blob: 3a1619ba11a15a25400ea2d4eb8324ebd2bfb41a [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;
Issei Suzuki737b7f12020-05-25 14:54:06 +020067import android.util.ArraySet;
lumark19a5d2e2019-10-11 16:19:30 +080068import android.util.Pair;
Vishnu Nair04ab4392018-01-10 11:00:06 -080069import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010070import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080071import android.util.proto.ProtoOutputStream;
lumark19a5d2e2019-10-11 16:19:30 +080072import android.view.DisplayInfo;
Robert Carrb1579c82017-09-05 14:54:47 -070073import android.view.MagnificationSpec;
Evan Rosky55bddd82020-01-29 13:07:18 -080074import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +080075import android.view.RemoteAnimationTarget;
Robert Carrb1579c82017-09-05 14:54:47 -070076import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010077import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070078import android.view.SurfaceSession;
lumark19a5d2e2019-10-11 16:19:30 +080079import android.view.WindowManager;
80import android.view.animation.Animation;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -070081import android.window.IWindowContainerToken;
82import android.window.WindowContainerToken;
Garfield Tan2f145f22018-11-01 15:27:03 -070083
Evan Rosky65dffa62019-02-04 14:09:53 -080084import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010085import com.android.internal.util.ToBooleanFunction;
lumark19a5d2e2019-10-11 16:19:30 +080086import com.android.server.protolog.common.ProtoLog;
Jorim Jaggia5e10572017-11-15 14:36:26 +010087import com.android.server.wm.SurfaceAnimator.Animatable;
Issei Suzuki8b995df2020-01-08 12:23:04 +010088import com.android.server.wm.SurfaceAnimator.AnimationType;
89import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Garfield Tan2f145f22018-11-01 15:27:03 -070090
Jorim Jaggia5e10572017-11-15 14:36:26 +010091import java.io.PrintWriter;
Evan Roskya80f11c2020-01-23 19:17:10 -080092import java.lang.ref.WeakReference;
Yunfan Chen87b5a242019-10-01 17:53:59 +090093import java.util.ArrayList;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070094import java.util.Comparator;
95import java.util.LinkedList;
chaviw54521692020-06-12 14:34:30 -070096import java.util.Set;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070097import java.util.function.Consumer;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -080098import java.util.function.Function;
Wale Ogunwaled1880962016-11-08 10:31:59 -080099import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700100
101/**
102 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -0700103 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700104 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
105 * changes are made to this class.
106 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700107class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Evan Rosky55bddd82020-01-29 13:07:18 -0800108 implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
Robert Carre10ee3d2019-11-11 15:03:15 -0800109 BLASTSyncEngine.TransactionReadyListener {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100110
111 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700112
Louis Changdc077272019-11-12 16:52:56 +0800113 /** Animation layer that happens above all animating {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200114 static final int ANIMATION_LAYER_STANDARD = 0;
115
Louis Changdc077272019-11-12 16:52:56 +0800116 /** Animation layer that happens above all {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200117 static final int ANIMATION_LAYER_BOOSTED = 1;
118
119 /**
120 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -0700121 * activities and all activities that are being controlled by the recents animation. This
Louis Changdc077272019-11-12 16:52:56 +0800122 * layer is generally below all {@link ActivityStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +0200123 */
124 static final int ANIMATION_LAYER_HOME = 2;
125
126 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
127 ANIMATION_LAYER_STANDARD,
128 ANIMATION_LAYER_BOOSTED,
129 ANIMATION_LAYER_HOME,
130 })
131 @interface AnimationLayer {}
132
Andrii Kuliand2765632016-12-12 22:26:34 -0800133 static final int POSITION_TOP = Integer.MAX_VALUE;
134 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
135
Andrii Kulian441e4492016-09-29 15:25:00 -0700136 /**
137 * The parent of this window container.
138 * For removing or setting new parent {@link #setParent} should be used, because it also
139 * performs configuration updates based on new parent's settings.
140 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100141 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700142
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200143 // Set to true when we are performing a reparenting operation so we only send one
144 // onParentChanged() notification.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700145 boolean mReparenting;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200146
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700147 // List of children for this window container. List is in z-order as the children appear on
148 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200149 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700150
Wale Ogunwale51362492016-09-08 17:49:17 -0700151 // The specified orientation for this window container.
Vadim Caen1096f112019-12-18 11:44:26 +0100152 @ActivityInfo.ScreenOrientation
Wale Ogunwale51362492016-09-08 17:49:17 -0700153 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
154
Riddle Hsu6f548e92020-01-13 13:34:09 +0800155 /**
156 * The window container which decides its orientation since the last time
157 * {@link #getOrientation(int) was called.
158 */
159 protected WindowContainer mLastOrientationSource;
160
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800161 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
162 new Pools.SynchronizedPool<>(3);
163
Tiger Huanged6794e2019-05-07 20:07:59 +0800164 // The display this window container is on.
165 protected DisplayContent mDisplayContent;
166
Robert Carrb1579c82017-09-05 14:54:47 -0700167 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100168 private int mLastLayer = 0;
169 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700170
Tiger Huanged6794e2019-05-07 20:07:59 +0800171 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
172 private final Transaction mPendingTransaction;
173
Robert Carrb1579c82017-09-05 14:54:47 -0700174 /**
Yunfan Chen87b5a242019-10-01 17:53:59 +0900175 * Windows that clients are waiting to have drawn.
176 */
177 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
178
179 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700180 * Applied as part of the animation pass in "prepareSurfaces".
181 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100182 protected final SurfaceAnimator mSurfaceAnimator;
Jorim Jaggi268bf6882020-06-18 23:44:02 +0200183 private boolean mAnyParentAnimating;
184
Evan Rosky55bddd82020-01-29 13:07:18 -0800185 final SurfaceFreezer mSurfaceFreezer;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800186 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100187
Issei Suzuki737b7f12020-05-25 14:54:06 +0200188 /**
189 * Sources which triggered a surface animation on this container. An animation target can be
190 * promoted to higher level, for example, from a set of {@link ActivityRecord}s to
191 * {@link ActivityStack}. In this case, {@link ActivityRecord}s are set on this variable while
192 * the animation is running, and reset after finishing it.
193 */
194 private final ArraySet<WindowContainer> mSurfaceAnimationSources = new ArraySet<>();
195
chaviwe07246a2017-12-12 16:18:29 -0800196 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800197 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800198
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100199 /** Total number of elements in this subtree, including our own hierarchy element. */
200 private int mTreeWeight = 1;
201
chaviw7f1fa992018-01-10 13:52:12 -0800202 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700203 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800204 * surface to the animation leash
205 */
206 private boolean mCommittedReparentToAnimationLeash;
207
lumark9bca6b42019-10-17 18:35:22 +0800208 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
209 public interface AnimationFlags {
210 /**
211 * A bit flag indicates that {@link #isAnimating} should also return {@code true}
212 * even though the container is not yet animating, but the window container or its
213 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
214 * that is pending so an animation starts soon.
215 */
216 int TRANSITION = 1;
217
218 /**
219 * A bit flag indicates that {@link #isAnimating} should also check if one of the
220 * ancestors of the container are animating in addition to the container itself.
221 */
222 int PARENTS = 2;
223
224 /**
225 * A bit flag indicates that {@link #isAnimating} should also check if one of the
226 * descendants of the container are animating in addition to the container itself.
227 */
228 int CHILDREN = 4;
229 }
230
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200231 /**
232 * Callback which is triggered while changing the parent, after setting up the surface but
233 * before asking the parent to assign child layers.
234 */
235 interface PreAssignChildLayersCallback {
236 void onPreAssignChildLayers();
237 }
238
lumark19a5d2e2019-10-11 16:19:30 +0800239 /**
240 * True if this an AppWindowToken and the activity which created this was launched with
241 * ActivityOptions.setLaunchTaskBehind.
242 *
243 * TODO(b/142617871): We run a special animation when the activity was launched with that
244 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
245 * selected to suppress an animation, and remove this flag.
246 */
247 boolean mLaunchTaskBehind;
248
249 /**
250 * If we are running an animation, this determines the transition type. Must be one of
251 * {@link AppTransition#TransitionFlags}.
252 */
253 int mTransit;
254
255 /**
256 * If we are running an animation, this determines the flags during this animation. Must be a
257 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
258 */
259 int mTransitFlags;
260
261 /** Whether this container should be boosted at the top of all its siblings. */
262 @VisibleForTesting boolean mNeedsZBoost;
263
264 /** Layer used to constrain the animation to a container's stack bounds. */
265 SurfaceControl mAnimationBoundsLayer;
266
267 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
268 boolean mNeedsAnimationBoundsLayer;
269
270 /**
271 * This gets used during some open/close transitions as well as during a change transition
272 * where it represents the starting-state snapshot.
273 */
lumarkbc0032a2019-11-01 21:38:13 +0800274 WindowContainerThumbnail mThumbnail;
lumark19a5d2e2019-10-11 16:19:30 +0800275 final Point mTmpPoint = new Point();
276 protected final Rect mTmpRect = new Rect();
277 final Rect mTmpPrevBounds = new Rect();
278
Robert Carr7603dea2019-07-17 13:16:21 -0700279 private MagnificationSpec mLastMagnificationSpec;
280
Evan Rosky226de132020-01-03 18:00:29 -0800281 private boolean mIsFocusable = true;
282
Evan Roskya80f11c2020-01-23 19:17:10 -0800283 /**
284 * Used as a unique, cross-process identifier for this Container. It also serves a minimal
285 * interface to other processes.
286 */
287 RemoteToken mRemoteToken = null;
288
Robert Carre10ee3d2019-11-11 15:03:15 -0800289 BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
Rob Carrdb37d582020-03-10 12:31:07 -0700290 SurfaceControl.Transaction mBLASTSyncTransaction;
Robert Carre10ee3d2019-11-11 15:03:15 -0800291 boolean mUsingBLASTSyncTransaction = false;
292 BLASTSyncEngine.TransactionReadyListener mWaitingListener;
293 int mWaitingSyncId;
294
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800295 WindowContainer(WindowManagerService wms) {
296 mWmService = wms;
Vishnu Nair33197392019-08-30 10:29:37 -0700297 mPendingTransaction = wms.mTransactionFactory.get();
Rob Carrdb37d582020-03-10 12:31:07 -0700298 mBLASTSyncTransaction = wms.mTransactionFactory.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800299 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Evan Rosky55bddd82020-01-29 13:07:18 -0800300 mSurfaceFreezer = new SurfaceFreezer(this, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100301 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800302
Wale Ogunwale98d62312017-07-12 09:24:56 -0700303 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700304 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700305 return mParent;
306 }
307
Wale Ogunwale98d62312017-07-12 09:24:56 -0700308 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700309 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700310 return mChildren.size();
311 }
312
313 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700314 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700315 return mChildren.get(index);
316 }
317
chaviwe07246a2017-12-12 16:18:29 -0800318 @Override
319 public void onConfigurationChanged(Configuration newParentConfig) {
320 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800321 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800322 scheduleAnimation();
323 }
324
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200325 void reparent(WindowContainer newParent, int position) {
326 if (newParent == null) {
327 throw new IllegalArgumentException("reparent: can't reparent to null " + this);
328 }
329
330 final WindowContainer oldParent = mParent;
331 if (mParent == newParent) {
332 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
333 }
334
335 // The display object before reparenting as that might lead to old parent getting removed
336 // from the display if it no longer has any child.
337 final DisplayContent prevDc = oldParent.getDisplayContent();
338 final DisplayContent dc = newParent.getDisplayContent();
339
340 mReparenting = true;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700341 oldParent.removeChild(this);
Louis Chang2453d062019-11-19 22:30:48 +0800342 newParent.addChild(this, position);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200343 mReparenting = false;
344
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200345 // Relayout display(s)
346 dc.setLayoutNeeded();
347 if (prevDc != dc) {
348 onDisplayChanged(dc);
349 prevDc.setLayoutNeeded();
350 }
351 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700352
353 // Send onParentChanged notification here is we disabled sending it in setParent for
354 // reparenting case.
355 onParentChanged(newParent, oldParent);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200356 }
357
Jorim Jaggia5e10572017-11-15 14:36:26 +0100358 final protected void setParent(WindowContainer<WindowContainer> parent) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200359 final WindowContainer oldParent = mParent;
Andrii Kulian441e4492016-09-29 15:25:00 -0700360 mParent = parent;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800361
362 if (mParent != null) {
363 mParent.onChildAdded(this);
364 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200365 if (!mReparenting) {
lumarkbde15132019-12-18 22:29:43 +0800366 if (mParent != null && mParent.mDisplayContent != null
367 && mDisplayContent != mParent.mDisplayContent) {
368 onDisplayChanged(mParent.mDisplayContent);
369 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200370 onParentChanged(mParent, oldParent);
371 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800372 }
373
374 /**
375 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
376 * Supposed to be overridden and contain actions that should be executed after parent was set.
377 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800378 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200379 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
380 onParentChanged(newParent, oldParent, null);
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200381 }
382
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200383 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
384 PreAssignChildLayersCallback callback) {
385 super.onParentChanged(newParent, oldParent);
Robert Carrb1579c82017-09-05 14:54:47 -0700386 if (mParent == null) {
387 return;
388 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100389
Robert Carrb1579c82017-09-05 14:54:47 -0700390 if (mSurfaceControl == null) {
391 // If we don't yet have a surface, but we now have a parent, we should
392 // build a surface.
wilsonshih07cb2722020-03-16 23:19:24 +0800393 createSurfaceControl(false /*force*/);
Robert Carrb1579c82017-09-05 14:54:47 -0700394 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100395 // If we have a surface but a new parent, we just need to perform a reparent. Go through
396 // surface animator such that hierarchy is preserved when animating, i.e.
397 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
398 // new parent.
chaviw89cc30e2020-05-19 10:36:27 -0700399 reparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700400 }
401
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200402 if (callback != null) {
403 callback.onPreAssignChildLayers();
404 }
405
Robert Carrb1579c82017-09-05 14:54:47 -0700406 // Either way we need to ask the parent to assign us a Z-order.
407 mParent.assignChildLayers();
408 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700409 }
410
wilsonshih07cb2722020-03-16 23:19:24 +0800411 void createSurfaceControl(boolean force) {
chaviw21ea1872020-05-28 17:26:38 -0700412 setInitialSurfaceControlProperties(makeSurface());
chaviw0a947d92020-05-27 10:09:10 -0700413 }
414
chaviw21ea1872020-05-28 17:26:38 -0700415 void setInitialSurfaceControlProperties(SurfaceControl.Builder b) {
416 setSurfaceControl(b.build());
chaviw89cc30e2020-05-19 10:36:27 -0700417 getSyncTransaction().show(mSurfaceControl);
418 onSurfaceShown(getSyncTransaction());
wilsonshih07cb2722020-03-16 23:19:24 +0800419 updateSurfacePosition();
420 }
421
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800422 /**
chaviwda7b3c22020-04-24 11:25:08 -0700423 * Create a new SurfaceControl for this WindowContainer and migrate all properties to the new
424 * SurfaceControl. Properties include:
425 * 1. Children
426 * 2. Position
427 * 3. Z order
428 *
429 * Remove the old SurfaceControl since it's no longer needed.
430 *
431 * This is used to revoke control of the SurfaceControl from a client process that was
432 * previously organizing this WindowContainer.
433 */
434 void migrateToNewSurfaceControl() {
435 SurfaceControl.Transaction t = getPendingTransaction();
436 t.remove(mSurfaceControl);
437 // Clear the last position so the new SurfaceControl will get correct position
438 mLastSurfacePosition.set(0, 0);
439
chaviw0a947d92020-05-27 10:09:10 -0700440 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(null)
441 .setContainerLayer()
442 .setName(getName());
443
chaviw21ea1872020-05-28 17:26:38 -0700444 setInitialSurfaceControlProperties(b);
chaviw0a947d92020-05-27 10:09:10 -0700445
446 // If parent is null, the layer should be placed offscreen so reparent to null. Otherwise,
447 // set to the available parent.
448 t.reparent(mSurfaceControl, mParent == null ? null : mParent.getSurfaceControl());
449
chaviwda7b3c22020-04-24 11:25:08 -0700450 if (mLastRelativeToLayer != null) {
451 t.setRelativeLayer(mSurfaceControl, mLastRelativeToLayer, mLastLayer);
452 } else {
453 t.setLayer(mSurfaceControl, mLastLayer);
454 }
455
456 for (int i = 0; i < mChildren.size(); i++) {
457 SurfaceControl sc = mChildren.get(i).getSurfaceControl();
458 if (sc != null) {
459 t.reparent(sc, mSurfaceControl);
460 }
461 }
462 scheduleAnimation();
463 }
464
465 /**
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800466 * Called when the surface is shown for the first time.
467 */
468 void onSurfaceShown(Transaction t) {
469 // do nothing
470 }
471
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700472 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100473 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
474 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700475
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700476 /**
477 * Adds the input window container has a child of this container in order based on the input
478 * comparator.
479 * @param child The window container to add as a child of this window container.
480 * @param comparator Comparator to use in determining the position the child should be added to.
481 * If null, the child will be added to the top.
482 */
483 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700484 protected void addChild(E child, Comparator<E> comparator) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700485 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700486 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700487 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700488 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700489 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700490
Andrii Kulianb94292e2016-10-19 13:30:58 -0700491 int positionToAdd = -1;
492 if (comparator != null) {
493 final int count = mChildren.size();
494 for (int i = 0; i < count; i++) {
495 if (comparator.compare(child, mChildren.get(i)) < 0) {
496 positionToAdd = i;
497 break;
498 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700499 }
500 }
501
Andrii Kulianb94292e2016-10-19 13:30:58 -0700502 if (positionToAdd == -1) {
503 mChildren.add(child);
504 } else {
505 mChildren.add(positionToAdd, child);
506 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100507
Andrii Kulianb94292e2016-10-19 13:30:58 -0700508 // Set the parent after we've actually added a child in case a subclass depends on this.
509 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700510 }
511
Wale Ogunwalef6192862016-09-10 13:42:30 -0700512 /** Adds the input window container has a child of this container at the input index. */
513 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800514 void addChild(E child, int index) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700515 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700516 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700517 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800518 + " can't add to container=" + getName()
519 + "\n callers=" + Debug.getCallers(15, "\n"));
Wale Ogunwalef6192862016-09-10 13:42:30 -0700520 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900521
522 if ((index < 0 && index != POSITION_BOTTOM)
523 || (index > mChildren.size() && index != POSITION_TOP)) {
524 throw new IllegalArgumentException("addChild: invalid position=" + index
525 + ", children number=" + mChildren.size());
526 }
527
528 if (index == POSITION_TOP) {
529 index = mChildren.size();
530 } else if (index == POSITION_BOTTOM) {
531 index = 0;
532 }
533
Wale Ogunwalef6192862016-09-10 13:42:30 -0700534 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100535
Andrii Kulianb94292e2016-10-19 13:30:58 -0700536 // Set the parent after we've actually added a child in case a subclass depends on this.
537 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700538 }
539
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100540 private void onChildAdded(WindowContainer child) {
541 mTreeWeight += child.mTreeWeight;
542 WindowContainer parent = getParent();
543 while (parent != null) {
544 parent.mTreeWeight += child.mTreeWeight;
545 parent = parent.getParent();
546 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200547 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100548 }
549
Wale Ogunwalef6192862016-09-10 13:42:30 -0700550 /**
551 * Removes the input child container from this container which is its parent.
552 *
553 * @return True if the container did contain the input child and it was detached.
554 */
555 @CallSuper
556 void removeChild(E child) {
557 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100558 onChildRemoved(child);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700559 if (!child.mReparenting) {
560 child.setParent(null);
561 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700562 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700563 throw new IllegalArgumentException("removeChild: container=" + child.getName()
564 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700565 }
566 }
567
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100568 private void onChildRemoved(WindowContainer child) {
569 mTreeWeight -= child.mTreeWeight;
570 WindowContainer parent = getParent();
571 while (parent != null) {
572 parent.mTreeWeight -= child.mTreeWeight;
573 parent = parent.getParent();
574 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200575 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100576 }
577
Wale Ogunwale571771c2016-08-26 13:18:50 -0700578 /**
579 * Removes this window container and its children with no regard for what else might be going on
580 * in the system. For example, the container will be removed during animation if this method is
581 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
582 * which allows the system to defer removal until a suitable time.
583 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700584 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700585 void removeImmediately() {
Evan Rosky8d4ee722020-04-21 17:28:31 -0700586 final DisplayContent dc = getDisplayContent();
587 if (dc != null) {
chaviw89cc30e2020-05-19 10:36:27 -0700588 mSurfaceFreezer.unfreeze(getSyncTransaction());
Evan Rosky8d4ee722020-04-21 17:28:31 -0700589 dc.mChangingContainers.remove(this);
590 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700591 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100592 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700593 child.removeImmediately();
594 // Need to do this after calling remove on the child because the child might try to
595 // remove/detach itself from its parent which will cause an exception if we remove
596 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100597 if (mChildren.remove(child)) {
598 onChildRemoved(child);
599 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700600 }
601
Robert Carrb1579c82017-09-05 14:54:47 -0700602 if (mSurfaceControl != null) {
chaviw89cc30e2020-05-19 10:36:27 -0700603 getSyncTransaction().remove(mSurfaceControl);
Robert Carr8a2f9132019-11-11 15:03:15 -0800604 setSurfaceControl(null);
Garfield Tan265ab91a2019-11-12 16:30:49 -0800605 mLastSurfacePosition.set(0, 0);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000606 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700607 }
608
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700609 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700610 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700611 }
612 }
613
614 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100615 * @return The index of this element in the hierarchy tree in prefix order.
616 */
617 int getPrefixOrderIndex() {
618 if (mParent == null) {
619 return 0;
620 }
621 return mParent.getPrefixOrderIndex(this);
622 }
623
624 private int getPrefixOrderIndex(WindowContainer child) {
625 int order = 0;
626 for (int i = 0; i < mChildren.size(); i++) {
627 final WindowContainer childI = mChildren.get(i);
628 if (child == childI) {
629 break;
630 }
631 order += childI.mTreeWeight;
632 }
633 if (mParent != null) {
634 order += mParent.getPrefixOrderIndex(this);
635 }
636
637 // We also need to count ourselves.
638 order++;
639 return order;
640 }
641
642 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700643 * Removes this window container and its children taking care not to remove them during a
644 * critical stage in the system. For example, some containers will not be removed during
645 * animation if this method is called.
646 */
647 // TODO: figure-out implementation that works best for this.
648 // E.g. when do we remove from parent list? maybe not...
649 void removeIfPossible() {
650 for (int i = mChildren.size() - 1; i >= 0; --i) {
651 final WindowContainer wc = mChildren.get(i);
652 wc.removeIfPossible();
653 }
654 }
655
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700656 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000657 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700658 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000659 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700660 if (current == child || current.hasChild(child)) {
661 return true;
662 }
663 }
664 return false;
665 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700666
Issei Suzuki2f541842020-01-09 20:18:29 +0100667 /** @return true if this window container is a descendant of the input container. */
668 boolean isDescendantOf(WindowContainer ancestor) {
669 final WindowContainer parent = getParent();
670 if (parent == ancestor) return true;
671 return (parent != null) && parent.isDescendantOf(ancestor);
672 }
673
Andrii Kulian441e4492016-09-29 15:25:00 -0700674 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800675 * Move a child from it's current place in siblings list to the specified position,
676 * with an option to move all its parents to top.
677 * @param position Target position to move the child to.
678 * @param child Child to move to selected position.
679 * @param includingParents Flag indicating whether we need to move the entire branch of the
680 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
681 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
682 * this flag will do nothing.
683 */
684 @CallSuper
685 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800686
687 if (child.getParent() != this) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800688 throw new IllegalArgumentException("positionChildAt: container=" + child.getName()
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800689 + " is not a child of container=" + getName()
690 + " current parent=" + child.getParent());
691 }
692
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800693 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800694 position = POSITION_TOP;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700695 } else if (position <= 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800696 position = POSITION_BOTTOM;
697 }
698
699 switch (position) {
700 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800701 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800702 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200703 mChildren.add(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200704 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800705 }
706 if (includingParents && getParent() != null) {
707 getParent().positionChildAt(POSITION_TOP, this /* child */,
708 true /* includingParents */);
709 }
710 break;
711 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800712 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800713 mChildren.remove(child);
714 mChildren.addFirst(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200715 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800716 }
717 if (includingParents && getParent() != null) {
718 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
719 true /* includingParents */);
720 }
721 break;
722 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800723 // TODO: Removing the child before reinserting requires the caller to provide a
724 // position that takes into account the removed child (if the index of the
725 // child < position, then the position should be adjusted). We should consider
726 // doing this adjustment here and remove any adjustments in the callers.
Vishnu Nair7c8a2472020-04-17 16:08:29 -0700727 if (mChildren.indexOf(child) != position) {
728 mChildren.remove(child);
729 mChildren.add(position, child);
730 onChildPositionChanged(child);
731 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800732 }
733 }
734
735 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800736 * Notify that a child's position has changed. Possible changes are adding or removing a child.
737 */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200738 void onChildPositionChanged(WindowContainer child) { }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800739
740 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700741 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700742 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700743 * @see #mFullConfiguration
744 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700745 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700746 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800747 // We must diff before the configuration is applied so that we can capture the change
748 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700749 final int diff = diffRequestedOverrideBounds(
750 overrideConfiguration.windowConfiguration.getBounds());
751 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700752 if (mParent != null) {
753 mParent.onDescendantOverrideConfigurationChanged();
754 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800755
756 if (diff == BOUNDS_CHANGE_NONE) {
757 return;
758 }
759
760 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
761 onResize();
762 } else {
763 onMovedByResize();
764 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700765 }
766
767 /**
768 * Notify that a descendant's overrideConfiguration has changed.
769 */
770 void onDescendantOverrideConfigurationChanged() {
771 if (mParent != null) {
772 mParent.onDescendantOverrideConfigurationChanged();
773 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700774 }
775
776 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700777 * Notify that the display this container is on has changed. This could be either this container
778 * is moved to a new display, or some configurations on the display it is on changes.
779 *
780 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700781 */
782 void onDisplayChanged(DisplayContent dc) {
Evan Rosky8d4ee722020-04-21 17:28:31 -0700783 if (mDisplayContent != null && mDisplayContent.mChangingContainers.remove(this)) {
784 // Cancel any change transition queued-up for this container on the old display.
785 mSurfaceFreezer.unfreeze(getPendingTransaction());
786 }
Tiger Huanged6794e2019-05-07 20:07:59 +0800787 mDisplayContent = dc;
788 if (dc != null && dc != this) {
789 dc.getPendingTransaction().merge(mPendingTransaction);
790 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700791 for (int i = mChildren.size() - 1; i >= 0; --i) {
792 final WindowContainer child = mChildren.get(i);
793 child.onDisplayChanged(dc);
794 }
795 }
796
Tiger Huanged6794e2019-05-07 20:07:59 +0800797 DisplayContent getDisplayContent() {
798 return mDisplayContent;
799 }
800
Andrii Kulian86d676c2020-03-27 19:34:54 -0700801 /** Get the first node of type {@link DisplayArea} above or at this node. */
802 @Nullable
803 DisplayArea getDisplayArea() {
804 WindowContainer parent = getParent();
805 return parent != null ? parent.getDisplayArea() : null;
806 }
807
Evan Rosky688c8382020-04-03 17:27:08 -0700808 boolean isAttached() {
809 return getDisplayArea() != null;
810 }
811
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700812 void setWaitingForDrawnIfResizingChanged() {
813 for (int i = mChildren.size() - 1; i >= 0; --i) {
814 final WindowContainer wc = mChildren.get(i);
815 wc.setWaitingForDrawnIfResizingChanged();
816 }
817 }
818
819 void onResize() {
820 for (int i = mChildren.size() - 1; i >= 0; --i) {
821 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800822 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700823 }
824 }
825
Bryce Leed92ae482018-01-22 13:56:23 -0800826 void onParentResize() {
827 // In the case this container has specified its own bounds, a parent resize will not
828 // affect its bounds. Any relevant changes will be propagated through changes to the
829 // Configuration override.
830 if (hasOverrideBounds()) {
831 return;
832 }
833
834 // Default implementation is to treat as resize on self.
835 onResize();
836 }
837
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700838 void onMovedByResize() {
839 for (int i = mChildren.size() - 1; i >= 0; --i) {
840 final WindowContainer wc = mChildren.get(i);
841 wc.onMovedByResize();
842 }
843 }
844
845 void resetDragResizingChangeReported() {
846 for (int i = mChildren.size() - 1; i >= 0; --i) {
847 final WindowContainer wc = mChildren.get(i);
848 wc.resetDragResizingChangeReported();
849 }
850 }
851
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700852 void forceWindowsScaleableInTransaction(boolean force) {
853 for (int i = mChildren.size() - 1; i >= 0; --i) {
854 final WindowContainer wc = mChildren.get(i);
855 wc.forceWindowsScaleableInTransaction(force);
856 }
857 }
858
Jorim Jaggia5e10572017-11-15 14:36:26 +0100859 /**
lumark9bca6b42019-10-17 18:35:22 +0800860 * @return {@code true} when this container or its related containers are running an
861 * animation, {@code false} otherwise.
862 *
863 * By default this predicate only checks if this container itself is actually running an
864 * animation, but you can extend the check target over its relatives, or relax the condition
865 * so that this can return {@code true} if an animation starts soon by giving a combination
chaviw9177c772020-03-24 11:35:22 -0700866 * of {@link AnimationFlags}.
lumark9bca6b42019-10-17 18:35:22 +0800867 *
868 * Note that you can give a combination of bitmask flags to specify targets and condition for
869 * checking animating status.
870 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
871 * container itself or one of its parents is running an animation or waiting for an app
872 * transition.
873 *
874 * Note that TRANSITION propagates to parents and children as well.
875 *
chaviw9177c772020-03-24 11:35:22 -0700876 * @param flags The combination of bitmask flags to specify targets and condition for
877 * checking animating status.
878 * @param typesToCheck The combination of bitmask {@link AnimationType} to compare when
879 * determining if animating.
880 *
881 * @see AnimationFlags#TRANSITION
882 * @see AnimationFlags#PARENTS
883 * @see AnimationFlags#CHILDREN
Jorim Jaggia5e10572017-11-15 14:36:26 +0100884 */
Issei Suzuki737b7f12020-05-25 14:54:06 +0200885 final boolean isAnimating(int flags, int typesToCheck) {
886 return getAnimatingContainer(flags, typesToCheck) != null;
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700887 }
888
Jorim Jaggia5e10572017-11-15 14:36:26 +0100889 /**
chaviw9177c772020-03-24 11:35:22 -0700890 * Similar to {@link #isAnimating(int, int)} except provide a bitmask of
891 * {@link AnimationType} to exclude, rather than include
892 * @param flags The combination of bitmask flags to specify targets and condition for
893 * checking animating status.
894 * @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when
895 * checking if animating.
Issei Suzuki737b7f12020-05-25 14:54:06 +0200896 *
897 * @deprecated Use {@link #isAnimating(int, int)}
chaviw9177c772020-03-24 11:35:22 -0700898 */
Issei Suzuki737b7f12020-05-25 14:54:06 +0200899 @Deprecated
900 final boolean isAnimatingExcluding(int flags, int typesToExclude) {
chaviw9177c772020-03-24 11:35:22 -0700901 return isAnimating(flags, ANIMATION_TYPE_ALL & ~typesToExclude);
902 }
903
904 /**
Issei Suzuki737b7f12020-05-25 14:54:06 +0200905 * @deprecated Use {@link #isAnimating(int, int)}
chaviw9177c772020-03-24 11:35:22 -0700906 * TODO (b/152333373): Migrate calls to use isAnimating with specified animation type
907 */
Issei Suzuki737b7f12020-05-25 14:54:06 +0200908 @Deprecated
909 final boolean isAnimating(int flags) {
chaviw9177c772020-03-24 11:35:22 -0700910 return isAnimating(flags, ANIMATION_TYPE_ALL);
911 }
912
913 /**
lumark9bca6b42019-10-17 18:35:22 +0800914 * @return {@code true} when the container is waiting the app transition start, {@code false}
915 * otherwise.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100916 */
lumark9bca6b42019-10-17 18:35:22 +0800917 boolean isWaitingForTransitionStart() {
lumark52d5f422020-01-06 16:17:55 +0800918 return false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100919 }
920
921 /**
lumark9bca6b42019-10-17 18:35:22 +0800922 * @return {@code true} if in this subtree of the hierarchy we have an
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800923 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200924 */
lumark9bca6b42019-10-17 18:35:22 +0800925 boolean isAppTransitioning() {
lumark5341d1c2019-12-14 01:54:02 +0800926 return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200927 }
928
929 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100930 * @return Whether our own container running an animation at the moment.
931 */
lumark9bca6b42019-10-17 18:35:22 +0800932 final boolean isAnimating() {
933 return isAnimating(0 /* self only */);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100934 }
935
lumark19a5d2e2019-10-11 16:19:30 +0800936 /**
937 * @return {@code true} if the container is in changing app transition.
938 */
939 boolean isChangingAppTransition() {
Evan Rosky55bddd82020-01-29 13:07:18 -0800940 return mDisplayContent != null && mDisplayContent.mChangingContainers.contains(this);
lumark19a5d2e2019-10-11 16:19:30 +0800941 }
942
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700943 void sendAppVisibilityToClients() {
944 for (int i = mChildren.size() - 1; i >= 0; --i) {
945 final WindowContainer wc = mChildren.get(i);
946 wc.sendAppVisibilityToClients();
947 }
948 }
949
Wale Ogunwale44f21802016-09-02 12:49:48 -0700950 /**
951 * Returns true if the container or one of its children as some content it can display or wants
952 * to display (e.g. app views or saved surface).
953 *
954 * NOTE: While this method will return true if the there is some content to display, it doesn't
955 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
956 * visible.
957 */
958 boolean hasContentToDisplay() {
959 for (int i = mChildren.size() - 1; i >= 0; --i) {
960 final WindowContainer wc = mChildren.get(i);
961 if (wc.hasContentToDisplay()) {
962 return true;
963 }
964 }
965 return false;
966 }
967
968 /**
969 * Returns true if the container or one of its children is considered visible from the
970 * WindowManager perspective which usually means valid surface and some other internal state
971 * are true.
972 *
973 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
974 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
975 * the container has any content to display.
976 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700977 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700978 // TODO: Will this be more correct if it checks the visibility of its parents?
979 // It depends...For example, Tasks and Stacks are only visible if there children are visible
980 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800981 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700982 for (int i = mChildren.size() - 1; i >= 0; --i) {
983 final WindowContainer wc = mChildren.get(i);
984 if (wc.isVisible()) {
985 return true;
986 }
987 }
988 return false;
989 }
990
Evan Roskya80f11c2020-01-23 19:17:10 -0800991 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800992 * Called when the visibility of a child is asked to change. This is before visibility actually
993 * changes (eg. a transition animation might play out first).
994 */
995 void onChildVisibilityRequested(boolean visible) {
996 // If we are changing visibility, then a snapshot isn't necessary and we are no-longer
997 // part of a change transition.
chaviw89cc30e2020-05-19 10:36:27 -0700998 mSurfaceFreezer.unfreeze(getSyncTransaction());
Evan Rosky55bddd82020-01-29 13:07:18 -0800999 if (mDisplayContent != null) {
1000 mDisplayContent.mChangingContainers.remove(this);
1001 }
1002 WindowContainer parent = getParent();
1003 if (parent != null) {
1004 parent.onChildVisibilityRequested(visible);
1005 }
1006 }
1007
1008 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
1009 final long token = proto.start(fieldId);
1010 proto.write(HASH_CODE, System.identityHashCode(this));
1011 proto.write(USER_ID, USER_NULL);
1012 proto.write(TITLE, "WindowContainer");
1013 proto.end(token);
1014 }
1015
1016 /**
Evan Roskya80f11c2020-01-23 19:17:10 -08001017 * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
1018 * this will not be focusable either.
1019 */
Evan Rosky226de132020-01-03 18:00:29 -08001020 boolean isFocusable() {
Evan Roskya80f11c2020-01-23 19:17:10 -08001021 final WindowContainer parent = getParent();
1022 return (parent == null || parent.isFocusable()) && mIsFocusable;
Evan Rosky226de132020-01-03 18:00:29 -08001023 }
1024
1025 /** Set whether this container or its children can be focusable */
Evan Rosky226de132020-01-03 18:00:29 -08001026 boolean setFocusable(boolean focusable) {
1027 if (mIsFocusable == focusable) {
1028 return false;
1029 }
1030 mIsFocusable = focusable;
1031 return true;
1032 }
1033
Bryce Lee00d586d2017-07-28 20:48:43 -07001034 /**
Robert Carrb1579c82017-09-05 14:54:47 -07001035 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -07001036 */
1037 boolean isOnTop() {
Ming-Shin Lu1a9f7382020-06-17 16:02:25 +08001038 final WindowContainer parent = getParent();
1039 return parent != null && parent.getTopChild() == this && parent.isOnTop();
Bryce Lee00d586d2017-07-28 20:48:43 -07001040 }
1041
Jorim Jaggi10abe2f2017-01-03 16:44:46 +01001042 /** Returns the top child container. */
1043 E getTopChild() {
1044 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -07001045 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001046
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001047 /** Returns true if there is still a removal being deferred */
1048 boolean checkCompleteDeferredRemoval() {
1049 boolean stillDeferringRemoval = false;
1050
1051 for (int i = mChildren.size() - 1; i >= 0; --i) {
1052 final WindowContainer wc = mChildren.get(i);
1053 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
1054 }
1055
1056 return stillDeferringRemoval;
1057 }
1058
1059 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001060 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001061 for (int i = mChildren.size() - 1; i >= 0; --i) {
1062 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -07001063 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -07001064 }
1065 }
1066
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001067 void onAppTransitionDone() {
1068 for (int i = mChildren.size() - 1; i >= 0; --i) {
1069 final WindowContainer wc = mChildren.get(i);
1070 wc.onAppTransitionDone();
1071 }
1072 }
1073
Garfield Tan90b04282018-12-11 14:04:42 -08001074 /**
1075 * Called when this container or one of its descendants changed its requested orientation, and
1076 * wants this container to handle it or pass it to its parent.
1077 *
1078 * @param freezeDisplayToken freeze this app window token if display needs to freeze
1079 * @param requestingContainer the container which orientation request has changed
1080 * @return {@code true} if handled; {@code false} otherwise.
1081 */
1082 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
1083 @Nullable ConfigurationContainer requestingContainer) {
1084 final WindowContainer parent = getParent();
1085 if (parent == null) {
1086 return false;
1087 }
1088 return parent.onDescendantOrientationChanged(freezeDisplayToken,
1089 requestingContainer);
1090 }
1091
1092 /**
Garfield Tan49dae102019-02-04 09:51:59 -08001093 * Check if this container or its parent will handle orientation changes from descendants. It's
1094 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
1095 * ConfigurationContainer)} in the sense that the return value of this method tells if this
1096 * container or its parent will handle the request eventually, while the return value of the
1097 * other method is if it handled the request synchronously.
1098 *
1099 * @return {@code true} if it handles or will handle orientation change in the future; {@code
1100 * false} if it won't handle the change at anytime.
1101 */
1102 boolean handlesOrientationChangeFromDescendant() {
1103 final WindowContainer parent = getParent();
1104 return parent != null && parent.handlesOrientationChangeFromDescendant();
1105 }
1106
1107 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001108 * Get the configuration orientation by the requested screen orientation
1109 * ({@link ActivityInfo.ScreenOrientation}) of this activity.
1110 *
1111 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
1112 * {@link Configuration#ORIENTATION_PORTRAIT},
1113 * {@link Configuration#ORIENTATION_UNDEFINED}).
1114 */
1115 int getRequestedConfigurationOrientation() {
1116 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
1117 // NOSENSOR means the display's "natural" orientation, so return that.
1118 if (mDisplayContent != null) {
1119 return mDisplayContent.getNaturalOrientation();
1120 }
1121 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
1122 // LOCKED means the activity's orientation remains unchanged, so return existing value.
1123 return getConfiguration().orientation;
1124 } else if (isFixedOrientationLandscape(mOrientation)) {
1125 return ORIENTATION_LANDSCAPE;
1126 } else if (isFixedOrientationPortrait(mOrientation)) {
1127 return ORIENTATION_PORTRAIT;
1128 }
1129 return ORIENTATION_UNDEFINED;
1130 }
1131
1132 /**
Garfield Tan90b04282018-12-11 14:04:42 -08001133 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
1134 * parameters.
1135 *
1136 * @param orientation the specified orientation.
1137 */
Wale Ogunwale51362492016-09-08 17:49:17 -07001138 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001139 setOrientation(orientation, null /* freezeDisplayToken */,
1140 null /* ActivityRecord */);
1141 }
1142
1143 /**
1144 * Sets the specified orientation of this container. It percolates this change upward along the
1145 * hierarchy to let each level of the hierarchy a chance to respond to it.
1146 *
1147 * @param orientation the specified orientation. Needs to be one of {@link
1148 * android.content.pm.ActivityInfo.ScreenOrientation}.
1149 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
1150 * done. Display will not be frozen if this is {@code null}, which
1151 * should only happen in tests.
1152 * @param requestingContainer the container which orientation request has changed. Mostly used
1153 * to ensure it gets correct configuration.
1154 */
1155 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
1156 @Nullable ConfigurationContainer requestingContainer) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001157 if (mOrientation == orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001158 return;
1159 }
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001160
1161 mOrientation = orientation;
Garfield Tan90b04282018-12-11 14:04:42 -08001162 final WindowContainer parent = getParent();
1163 if (parent != null) {
Riddle Hsu0c1b0d12020-05-27 23:15:39 +08001164 if (getConfiguration().orientation != getRequestedConfigurationOrientation()) {
1165 // Resolve the requested orientation.
1166 onConfigurationChanged(parent.getConfiguration());
1167 }
Garfield Tan90b04282018-12-11 14:04:42 -08001168 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
1169 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001170 }
1171
Vadim Caen1096f112019-12-18 11:44:26 +01001172 @ActivityInfo.ScreenOrientation
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001173 int getOrientation() {
1174 return getOrientation(mOrientation);
1175 }
1176
Wale Ogunwale51362492016-09-08 17:49:17 -07001177 /**
1178 * Returns the specified orientation for this window container or one of its children is there
1179 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
1180 * specification is set.
1181 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
1182 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001183 *
1184 * @param candidate The current orientation candidate that will be returned if we don't find a
1185 * better match.
1186 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -07001187 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001188 int getOrientation(int candidate) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001189 mLastOrientationSource = null;
Bryce Leea163b762017-01-24 11:05:01 -08001190 if (!fillsParent()) {
1191 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -07001192 return SCREEN_ORIENTATION_UNSET;
1193 }
1194
Bryce Leea163b762017-01-24 11:05:01 -08001195 // The container fills its parent so we can use it orientation if it has one
1196 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -07001197 // specified and fall back on this container's unset or unspecified value as a candidate
1198 // if none of the children have a better candidate for the orientation.
1199 if (mOrientation != SCREEN_ORIENTATION_UNSET
1200 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001201 mLastOrientationSource = this;
Wale Ogunwale51362492016-09-08 17:49:17 -07001202 return mOrientation;
1203 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001204
1205 for (int i = mChildren.size() - 1; i >= 0; --i) {
1206 final WindowContainer wc = mChildren.get(i);
1207
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001208 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
1209 // SCREEN_ORIENTATION_UNSPECIFIED?
1210 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
1211 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -07001212 if (orientation == SCREEN_ORIENTATION_BEHIND) {
1213 // container wants us to use the orientation of the container behind it. See if we
1214 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
1215 // look behind this container.
1216 candidate = orientation;
Riddle Hsu6f548e92020-01-13 13:34:09 +08001217 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001218 continue;
1219 }
1220
1221 if (orientation == SCREEN_ORIENTATION_UNSET) {
1222 continue;
1223 }
1224
1225 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1226 // Use the orientation if the container fills its parent or requested an explicit
1227 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
Vadim Caenfc14c662020-01-20 16:00:31 +01001228 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
1229 wc.toString(), orientation,
1230 ActivityInfo.screenOrientationToString(orientation));
Riddle Hsu6f548e92020-01-13 13:34:09 +08001231 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001232 return orientation;
1233 }
1234 }
1235
1236 return candidate;
1237 }
1238
1239 /**
Riddle Hsu6f548e92020-01-13 13:34:09 +08001240 * @return The deepest source which decides the orientation of this window container since the
1241 * last time {@link #getOrientation(int) was called.
1242 */
1243 @Nullable
1244 WindowContainer getLastOrientationSource() {
1245 final WindowContainer source = mLastOrientationSource;
1246 if (source != null && source != this) {
1247 final WindowContainer nextSource = source.getLastOrientationSource();
1248 if (nextSource != null) {
1249 return nextSource;
1250 }
1251 }
1252 return source;
1253 }
1254
1255 /**
Wale Ogunwale51362492016-09-08 17:49:17 -07001256 * Returns true if this container is opaque and fills all the space made available by its parent
1257 * container.
1258 *
1259 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
1260 * this is just a signal from the client to window manager stating its intent, but not what it
1261 * actually does.
1262 */
1263 boolean fillsParent() {
1264 return false;
1265 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001266
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001267 // TODO: Users would have their own window containers under the display container?
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001268 void switchUser(int userId) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001269 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001270 mChildren.get(i).switchUser(userId);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001271 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001272 }
1273
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08001274 boolean showToCurrentUser() {
1275 return true;
1276 }
1277
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001278 /**
1279 * For all windows at or below this container call the callback.
1280 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
1281 * stops the search if {@link ToBooleanFunction#apply} returns true.
1282 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
1283 * z-order, else from bottom-to-top.
1284 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -08001285 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001286 */
1287 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001288 if (traverseTopToBottom) {
1289 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001290 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1291 return true;
1292 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001293 }
1294 } else {
1295 final int count = mChildren.size();
1296 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001297 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1298 return true;
1299 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001300 }
1301 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001302 return false;
1303 }
1304
1305 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001306 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
1307 forAllWindows(wrapper, traverseTopToBottom);
1308 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001309 }
1310
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001311 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001312 return forAllActivities(callback, true /*traverseTopToBottom*/);
1313 }
1314
1315 boolean forAllActivities(
1316 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
1317 if (traverseTopToBottom) {
1318 for (int i = mChildren.size() - 1; i >= 0; --i) {
1319 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
1320 }
1321 } else {
1322 final int count = mChildren.size();
1323 for (int i = 0; i < count; i++) {
1324 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
lumark9bca6b42019-10-17 18:35:22 +08001325 }
lumark588a3e82018-07-20 18:53:54 +08001326 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001327
lumark9bca6b42019-10-17 18:35:22 +08001328 return false;
lumark588a3e82018-07-20 18:53:54 +08001329 }
1330
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001331 void forAllActivities(Consumer<ActivityRecord> callback) {
1332 forAllActivities(callback, true /*traverseTopToBottom*/);
1333 }
1334
1335 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
1336 if (traverseTopToBottom) {
1337 for (int i = mChildren.size() - 1; i >= 0; --i) {
1338 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1339 }
1340 } else {
1341 final int count = mChildren.size();
1342 for (int i = 0; i < count; i++) {
1343 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1344 }
1345 }
1346 }
1347
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001348 /**
1349 * Process all activities in this branch of the tree.
1350 *
1351 * @param callback Called for each activity found.
1352 * @param boundary We don't return activities via {@param callback} until we get to this node in
1353 * the tree.
1354 * @param includeBoundary If the boundary from be processed to return activities.
1355 * @param traverseTopToBottom direction to traverse the tree.
1356 * @return {@code true} if we ended the search before reaching the end of the tree.
1357 */
1358 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1359 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1360 return forAllActivities(
1361 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1362 }
1363
1364 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1365 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1366 boolean[] boundaryFound) {
1367 if (traverseTopToBottom) {
1368 for (int i = mChildren.size() - 1; i >= 0; --i) {
1369 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1370 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1371 return true;
1372 }
1373 }
1374 } else {
1375 final int count = mChildren.size();
1376 for (int i = 0; i < count; i++) {
1377 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1378 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1379 return true;
1380 }
1381 }
1382 }
1383
1384 return false;
1385 }
1386
1387 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
1388 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1389 boolean[] boundaryFound, WindowContainer wc) {
1390 if (wc == boundary) {
1391 boundaryFound[0] = true;
1392 if (!includeBoundary) return false;
1393 }
1394
1395 if (boundaryFound[0]) {
1396 return wc.forAllActivities(callback, traverseTopToBottom);
1397 }
1398
1399 return wc.forAllActivities(
1400 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1401 }
1402
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001403 /** @return {@code true} if this node or any of its children contains an activity. */
1404 boolean hasActivity() {
1405 for (int i = mChildren.size() - 1; i >= 0; --i) {
1406 if (mChildren.get(i).hasActivity()) {
1407 return true;
1408 }
1409 }
1410 return false;
1411 }
1412
1413 ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
1414 return getActivity(callback, true /*traverseTopToBottom*/);
1415 }
1416
1417 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001418 return getActivity(callback, traverseTopToBottom, null /*boundary*/);
1419 }
1420
1421 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
Louis Chang62cdfe72020-05-13 17:25:35 +08001422 ActivityRecord boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001423 if (traverseTopToBottom) {
1424 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001425 final WindowContainer wc = mChildren.get(i);
Louis Chang62cdfe72020-05-13 17:25:35 +08001426 // TODO(b/156986561): Improve the correctness of the boundary check.
1427 if (wc == boundary) return boundary;
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001428
1429 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001430 if (r != null) {
1431 return r;
1432 }
1433 }
1434 } else {
1435 final int count = mChildren.size();
1436 for (int i = 0; i < count; i++) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001437 final WindowContainer wc = mChildren.get(i);
Louis Chang62cdfe72020-05-13 17:25:35 +08001438 // TODO(b/156986561): Improve the correctness of the boundary check.
1439 if (wc == boundary) return boundary;
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001440
1441 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001442 if (r != null) {
1443 return r;
1444 }
1445 }
1446 }
1447
1448 return null;
1449 }
1450
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001451 /**
1452 * Gets an activity in a branch of the tree.
1453 *
1454 * @param callback called to test if this is the activity that should be returned.
1455 * @param boundary We don't return activities via {@param callback} until we get to this node in
1456 * the tree.
1457 * @param includeBoundary If the boundary from be processed to return activities.
1458 * @param traverseTopToBottom direction to traverse the tree.
1459 * @return The activity if found or null.
1460 */
1461 final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1462 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1463 return getActivity(
1464 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1465 }
1466
1467 private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1468 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1469 boolean[] boundaryFound) {
1470 if (traverseTopToBottom) {
1471 for (int i = mChildren.size() - 1; i >= 0; --i) {
1472 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1473 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1474 if (r != null) {
1475 return r;
1476 }
1477 }
1478 } else {
1479 final int count = mChildren.size();
1480 for (int i = 0; i < count; i++) {
1481 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1482 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1483 if (r != null) {
1484 return r;
1485 }
1486 }
1487 }
1488
1489 return null;
1490 }
1491
1492 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
1493 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1494 boolean[] boundaryFound, WindowContainer wc) {
1495 if (wc == boundary || boundary == null) {
1496 boundaryFound[0] = true;
1497 if (!includeBoundary) return null;
1498 }
1499
1500 if (boundaryFound[0]) {
1501 return wc.getActivity(callback, traverseTopToBottom);
1502 }
1503
1504 return wc.getActivity(
1505 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1506 }
1507
1508 ActivityRecord getActivityAbove(ActivityRecord r) {
1509 return getActivity((above) -> true, r,
1510 false /*includeBoundary*/, false /*traverseTopToBottom*/);
1511 }
1512
1513 ActivityRecord getActivityBelow(ActivityRecord r) {
1514 return getActivity((below) -> true, r,
1515 false /*includeBoundary*/, true /*traverseTopToBottom*/);
1516 }
1517
1518 ActivityRecord getBottomMostActivity() {
1519 return getActivity((r) -> true, false /*traverseTopToBottom*/);
1520 }
1521
1522 ActivityRecord getTopMostActivity() {
1523 return getActivity((r) -> true, true /*traverseTopToBottom*/);
1524 }
1525
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001526 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
1527 // Break down into 4 calls to avoid object creation due to capturing input params.
1528 if (includeFinishing) {
1529 if (includeOverlays) {
1530 return getActivity((r) -> true);
1531 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001532 return getActivity((r) -> !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001533 } else if (includeOverlays) {
1534 return getActivity((r) -> !r.finishing);
1535 }
1536
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001537 return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001538 }
1539
Winson Chungd5852192019-09-06 17:20:28 -07001540 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
1541 for (int i = mChildren.size() - 1; i >= 0; --i) {
1542 mChildren.get(i).forAllWallpaperWindows(callback);
1543 }
1544 }
1545
Jorim Jaggi51304d72017-05-17 17:25:32 +02001546 /**
1547 * For all tasks at or below this container call the callback.
1548 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001549 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
1550 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
1551 */
1552 boolean forAllTasks(Function<Task, Boolean> callback) {
1553 for (int i = mChildren.size() - 1; i >= 0; --i) {
1554 if (mChildren.get(i).forAllTasks(callback)) {
1555 return true;
1556 }
1557 }
1558 return false;
1559 }
1560
Louis Chang87ca32e2020-05-14 13:40:16 +08001561 boolean forAllLeafTasks(Function<Task, Boolean> callback) {
1562 for (int i = mChildren.size() - 1; i >= 0; --i) {
1563 if (mChildren.get(i).forAllLeafTasks(callback)) {
1564 return true;
1565 }
1566 }
1567 return false;
1568 }
1569
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001570 /**
1571 * For all tasks at or below this container call the callback.
1572 *
Jorim Jaggi51304d72017-05-17 17:25:32 +02001573 * @param callback Callback to be called for every task.
1574 */
1575 void forAllTasks(Consumer<Task> callback) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001576 forAllTasks(callback, true /*traverseTopToBottom*/);
1577 }
1578
1579 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
1580 final int count = mChildren.size();
1581 if (traverseTopToBottom) {
1582 for (int i = count - 1; i >= 0; --i) {
1583 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1584 }
1585 } else {
1586 for (int i = 0; i < count; i++) {
1587 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1588 }
Jorim Jaggi51304d72017-05-17 17:25:32 +02001589 }
1590 }
1591
Wale Ogunwale0d465192020-01-23 19:14:44 -08001592 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Jeff Changdc9c1d42020-02-11 14:57:34 +08001593 final int count = mChildren.size();
1594 if (traverseTopToBottom) {
1595 for (int i = count - 1; i >= 0; --i) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001596 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001597 }
1598 } else {
1599 for (int i = 0; i < count; i++) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001600 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001601 }
1602 }
1603 }
1604
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001605 Task getTaskAbove(Task t) {
1606 return getTask(
1607 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
1608 }
1609
1610 Task getTaskBelow(Task t) {
1611 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/);
1612 }
1613
1614 Task getBottomMostTask() {
1615 return getTask((t) -> true, false /*traverseTopToBottom*/);
1616 }
1617
1618 Task getTopMostTask() {
1619 return getTask((t) -> true, true /*traverseTopToBottom*/);
1620 }
1621
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001622 Task getTask(Predicate<Task> callback) {
1623 return getTask(callback, true /*traverseTopToBottom*/);
1624 }
1625
1626 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
1627 if (traverseTopToBottom) {
1628 for (int i = mChildren.size() - 1; i >= 0; --i) {
1629 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1630 if (t != null) {
1631 return t;
1632 }
1633 }
1634 } else {
1635 final int count = mChildren.size();
1636 for (int i = 0; i < count; i++) {
1637 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1638 if (t != null) {
1639 return t;
1640 }
1641 }
1642 }
1643
1644 return null;
1645 }
1646
lumarkbc0032a2019-11-01 21:38:13 +08001647 /**
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001648 * Gets an task in a branch of the tree.
lumarkbc0032a2019-11-01 21:38:13 +08001649 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001650 * @param callback called to test if this is the task that should be returned.
1651 * @param boundary We don't return tasks via {@param callback} until we get to this node in
1652 * the tree.
1653 * @param includeBoundary If the boundary from be processed to return tasks.
1654 * @param traverseTopToBottom direction to traverse the tree.
1655 * @return The task if found or null.
lumarkbc0032a2019-11-01 21:38:13 +08001656 */
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001657 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary,
1658 boolean traverseTopToBottom) {
1659 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1660 }
1661
1662 private Task getTask(Predicate<Task> callback,
1663 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1664 boolean[] boundaryFound) {
1665 if (traverseTopToBottom) {
1666 for (int i = mChildren.size() - 1; i >= 0; --i) {
1667 final Task t = processGetTaskWithBoundary(callback, boundary,
1668 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1669 if (t != null) {
1670 return t;
1671 }
1672 }
1673 } else {
1674 final int count = mChildren.size();
1675 for (int i = 0; i < count; i++) {
1676 final Task t = processGetTaskWithBoundary(callback, boundary,
1677 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1678 if (t != null) {
1679 return t;
1680 }
lumarkbc0032a2019-11-01 21:38:13 +08001681 }
1682 }
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001683
1684 return null;
1685 }
1686
1687 private Task processGetTaskWithBoundary(Predicate<Task> callback,
1688 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1689 boolean[] boundaryFound, WindowContainer wc) {
1690 if (wc == boundary || boundary == null) {
1691 boundaryFound[0] = true;
1692 if (!includeBoundary) return null;
1693 }
1694
1695 if (boundaryFound[0]) {
1696 return wc.getTask(callback, traverseTopToBottom);
1697 }
1698
1699 return wc.getTask(
1700 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
lumarkbc0032a2019-11-01 21:38:13 +08001701 }
1702
Wale Ogunwaled1880962016-11-08 10:31:59 -08001703 WindowState getWindow(Predicate<WindowState> callback) {
1704 for (int i = mChildren.size() - 1; i >= 0; --i) {
1705 final WindowState w = mChildren.get(i).getWindow(callback);
1706 if (w != null) {
1707 return w;
1708 }
1709 }
1710
1711 return null;
1712 }
1713
Wale Ogunwaledec34082020-03-22 09:45:00 -07001714 void forAllDisplayAreas(Consumer<DisplayArea> callback) {
1715 for (int i = mChildren.size() - 1; i >= 0; --i) {
1716 mChildren.get(i).forAllDisplayAreas(callback);
1717 }
1718 }
1719
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001720 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -07001721 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
1722 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001723 */
1724 @Override
1725 public int compareTo(WindowContainer other) {
1726 if (this == other) {
1727 return 0;
1728 }
1729
1730 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +02001731 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001732 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
1733 }
1734
1735 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
1736 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001737 try {
1738 getParents(thisParentChain);
1739 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001740
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001741 // Find the common ancestor of both containers.
1742 WindowContainer commonAncestor = null;
1743 WindowContainer thisTop = thisParentChain.peekLast();
1744 WindowContainer otherTop = otherParentChain.peekLast();
1745 while (thisTop != null && otherTop != null && thisTop == otherTop) {
1746 commonAncestor = thisParentChain.removeLast();
1747 otherParentChain.removeLast();
1748 thisTop = thisParentChain.peekLast();
1749 otherTop = otherParentChain.peekLast();
1750 }
1751
1752 // Containers don't belong to the same hierarchy???
1753 if (commonAncestor == null) {
1754 throw new IllegalArgumentException("No in the same hierarchy this="
1755 + thisParentChain + " other=" + otherParentChain);
1756 }
1757
1758 // Children are always considered greater than their parents, so if one of the containers
1759 // we are comparing it the parent of the other then whichever is the child is greater.
1760 if (commonAncestor == this) {
1761 return -1;
1762 } else if (commonAncestor == other) {
1763 return 1;
1764 }
1765
1766 // The position of the first non-common ancestor in the common ancestor list determines
1767 // which is greater the which.
1768 final WindowList<WindowContainer> list = commonAncestor.mChildren;
1769 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
1770 ? 1 : -1;
1771 } finally {
1772 mTmpChain1.clear();
1773 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001774 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001775 }
1776
1777 private void getParents(LinkedList<WindowContainer> parents) {
1778 parents.clear();
1779 WindowContainer current = this;
1780 do {
1781 parents.addLast(current);
1782 current = current.mParent;
1783 } while (current != null);
1784 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001785
Robert Carrb1579c82017-09-05 14:54:47 -07001786 SurfaceControl.Builder makeSurface() {
1787 final WindowContainer p = getParent();
1788 return p.makeChildSurface(this);
1789 }
1790
Robert Carrf59b8dd2017-10-02 18:58:36 -07001791 /**
1792 * @param child The WindowContainer this child surface is for, or null if the Surface
1793 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1794 */
Robert Carrb1579c82017-09-05 14:54:47 -07001795 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1796 final WindowContainer p = getParent();
1797 // Give the parent a chance to set properties. In hierarchy v1 we rely
1798 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001799 return p.makeChildSurface(child)
1800 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001801 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001802 /*
1803 * @return The SurfaceControl parent for this containers SurfaceControl.
1804 * The SurfaceControl must be valid if non-null.
1805 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001806 @Override
1807 public SurfaceControl getParentSurfaceControl() {
1808 final WindowContainer parent = getParent();
1809 if (parent == null) {
1810 return null;
1811 }
1812 return parent.getSurfaceControl();
1813 }
1814
Robert Carrb1579c82017-09-05 14:54:47 -07001815 /**
1816 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1817 */
1818 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001819 if (mSurfaceControl == null) {
1820 return false;
1821 }
1822
Robert Carrb1579c82017-09-05 14:54:47 -07001823 for (int i = 0; i < mChildren.size(); i++) {
1824 if (!mChildren.get(i).shouldMagnify()) {
1825 return false;
1826 }
1827 }
1828 return true;
1829 }
1830
1831 SurfaceSession getSession() {
1832 if (getParent() != null) {
1833 return getParent().getSession();
1834 }
1835 return null;
1836 }
1837
1838 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001839 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1840 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001841 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001842 mLastLayer = layer;
1843 mLastRelativeToLayer = null;
1844 }
1845 }
1846
1847 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1848 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1849 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001850 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001851 mLastLayer = layer;
1852 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001853 }
1854 }
1855
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001856 protected void setLayer(Transaction t, int layer) {
1857
1858 // Route through surface animator to accommodate that our surface control might be
1859 // attached to the leash, and leash is attached to parent container.
1860 mSurfaceAnimator.setLayer(t, layer);
1861 }
1862
1863 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1864
1865 // Route through surface animator to accommodate that our surface control might be
1866 // attached to the leash, and leash is attached to parent container.
1867 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1868 }
1869
1870 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1871 mSurfaceAnimator.reparent(t, newParent);
1872 }
1873
Robert Carrb1579c82017-09-05 14:54:47 -07001874 void assignChildLayers(Transaction t) {
1875 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001876
1877 // We use two passes as a way to promote children which
1878 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001879 for (int j = 0; j < mChildren.size(); ++j) {
1880 final WindowContainer wc = mChildren.get(j);
1881 wc.assignChildLayers(t);
1882 if (!wc.needsZBoost()) {
1883 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001884 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001885 }
1886 for (int j = 0; j < mChildren.size(); ++j) {
1887 final WindowContainer wc = mChildren.get(j);
1888 if (wc.needsZBoost()) {
1889 wc.assignLayer(t, layer++);
1890 }
Robert Carrb1579c82017-09-05 14:54:47 -07001891 }
1892 }
1893
1894 void assignChildLayers() {
chaviw89cc30e2020-05-19 10:36:27 -07001895 assignChildLayers(getSyncTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001896 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001897 }
1898
1899 boolean needsZBoost() {
1900 for (int i = 0; i < mChildren.size(); i++) {
1901 if (mChildren.get(i).needsZBoost()) {
1902 return true;
1903 }
1904 }
1905 return false;
1906 }
1907
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001908 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001909 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001910 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001911 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001912 * @param proto Stream to write the WindowContainer object to.
1913 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001914 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001915 * @hide
1916 */
1917 @CallSuper
1918 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08001919 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001920 @WindowTraceLogLevel int logLevel) {
1921 boolean isVisible = isVisible();
1922 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1923 return;
1924 }
1925
Adrian Roos4921ccf2017-09-28 16:54:06 +02001926 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001927 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001928 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001929 proto.write(VISIBLE, isVisible);
1930 if (mSurfaceAnimator.isAnimating()) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001931 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001932 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07001933
1934 // add children to proto
1935 for (int i = 0; i < getChildCount(); i++) {
1936 final long childToken = proto.start(WindowContainerProto.CHILDREN);
1937 final E child = getChildAt(i);
1938 child.dumpDebug(proto, child.getProtoFieldId(), logLevel);
1939 proto.end(childToken);
1940 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001941 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001942 }
1943
Vishnu Nairdddc9f52020-03-09 09:37:27 -07001944 /**
1945 * @return a proto field id to identify where to add the derived class to the generic window
1946 * container proto.
1947 */
1948 long getProtoFieldId() {
1949 return WINDOW_CONTAINER;
1950 }
1951
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001952 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1953 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1954 if (wrapper == null) {
1955 wrapper = new ForAllWindowsConsumerWrapper();
1956 }
1957 wrapper.setConsumer(consumer);
1958 return wrapper;
1959 }
1960
1961 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1962
1963 private Consumer<WindowState> mConsumer;
1964
1965 void setConsumer(Consumer<WindowState> consumer) {
1966 mConsumer = consumer;
1967 }
1968
1969 @Override
1970 public boolean apply(WindowState w) {
1971 mConsumer.accept(w);
1972 return false;
1973 }
1974
1975 void release() {
1976 mConsumer = null;
1977 mConsumerWrapperPool.release(this);
1978 }
1979 }
Robert Carrb1579c82017-09-05 14:54:47 -07001980
1981 // TODO(b/68336570): Should this really be on WindowContainer since it
1982 // can only be used on the top-level nodes that aren't animated?
1983 // (otherwise we would be fighting other callers of setMatrix).
1984 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1985 if (shouldMagnify()) {
1986 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1987 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
Robert Carr7603dea2019-07-17 13:16:21 -07001988 mLastMagnificationSpec = spec;
Robert Carrb1579c82017-09-05 14:54:47 -07001989 } else {
Jackal Guoa8b3a272019-12-16 15:24:58 +08001990 clearMagnificationSpec(t);
Robert Carrb1579c82017-09-05 14:54:47 -07001991 for (int i = 0; i < mChildren.size(); i++) {
1992 mChildren.get(i).applyMagnificationSpec(t, spec);
1993 }
1994 }
1995 }
1996
Robert Carr7603dea2019-07-17 13:16:21 -07001997 void clearMagnificationSpec(Transaction t) {
1998 if (mLastMagnificationSpec != null) {
1999 t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
2000 .setPosition(mSurfaceControl, 0, 0);
2001 }
2002 mLastMagnificationSpec = null;
2003 for (int i = 0; i < mChildren.size(); i++) {
2004 mChildren.get(i).clearMagnificationSpec(t);
2005 }
2006 }
2007
Robert Carrb1579c82017-09-05 14:54:47 -07002008 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08002009 // If a leash has been set when the transaction was committed, then the leash reparent has
2010 // been committed.
2011 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07002012 for (int i = 0; i < mChildren.size(); i++) {
2013 mChildren.get(i).prepareSurfaces();
2014 }
2015 }
2016
2017 /**
chaviw7f1fa992018-01-10 13:52:12 -08002018 * @return true if the reparent to animation leash transaction has been committed, false
2019 * otherwise.
2020 */
2021 boolean hasCommittedReparentToAnimationLeash() {
2022 return mCommittedReparentToAnimationLeash;
2023 }
2024
2025 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08002026 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
2027 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07002028 */
2029 void scheduleAnimation() {
2030 if (mParent != null) {
2031 mParent.scheduleAnimation();
2032 }
2033 }
2034
Robert Carrdea7bf42019-04-04 12:02:51 -07002035 /**
2036 * @return The SurfaceControl for this container.
2037 * The SurfaceControl must be valid if non-null.
2038 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01002039 @Override
2040 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07002041 return mSurfaceControl;
2042 }
2043
chaviw89cc30e2020-05-19 10:36:27 -07002044 /**
2045 * Use this method instead of {@link #getPendingTransaction()} if the Transaction should be
2046 * synchronized with the client.
2047 *
2048 * @return {@link #mBLASTSyncTransaction} if available. Otherwise, returns
2049 * {@link #getPendingTransaction()}
2050 */
2051 public Transaction getSyncTransaction() {
Robert Carre10ee3d2019-11-11 15:03:15 -08002052 if (mUsingBLASTSyncTransaction) {
2053 return mBLASTSyncTransaction;
2054 }
2055
chaviw89cc30e2020-05-19 10:36:27 -07002056 return getPendingTransaction();
2057 }
2058
2059 @Override
2060 public Transaction getPendingTransaction() {
Tiger Huanged6794e2019-05-07 20:07:59 +08002061 final DisplayContent displayContent = getDisplayContent();
2062 if (displayContent != null && displayContent != this) {
2063 return displayContent.getPendingTransaction();
2064 }
2065 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
2066 // let the caller to save the surface operations within the local mPendingTransaction.
2067 // If this is not a DisplayContent, we will merge it to the pending transaction of its
2068 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07002069 return mPendingTransaction;
2070 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01002071
2072 /**
2073 * Starts an animation on the container.
2074 *
2075 * @param anim The animation to run.
2076 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
2077 * some point but the meaning is too weird to work for all containers.
Issei Suzuki8b995df2020-01-08 12:23:04 +01002078 * @param type The type of animation defined as {@link AnimationType}.
Issei Suzuki2f541842020-01-09 20:18:29 +01002079 * @param animationFinishedCallback The callback being triggered when the animation finishes.
Jorim Jaggia5e10572017-11-15 14:36:26 +01002080 */
Issei Suzuki2f541842020-01-09 20:18:29 +01002081 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Issei Suzuki8b995df2020-01-08 12:23:04 +01002082 @AnimationType int type,
2083 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
2084 if (DEBUG_ANIM) {
2085 Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim);
2086 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01002087
2088 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
2089 // the moment this doesn't work for all animatable window containers.
Evan Rosky55bddd82020-01-29 13:07:18 -08002090 mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
2091 mSurfaceFreezer);
Issei Suzuki2f541842020-01-09 20:18:29 +01002092 }
2093
Issei Suzuki8b995df2020-01-08 12:23:04 +01002094 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
2095 @AnimationType int type) {
2096 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002097 }
2098
Jorim Jaggi980c9de2017-11-17 01:41:37 +01002099 void transferAnimation(WindowContainer from) {
2100 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
2101 }
2102
Jorim Jaggia5e10572017-11-15 14:36:26 +01002103 void cancelAnimation() {
Issei Suzuki737b7f12020-05-25 14:54:06 +02002104 doAnimationFinished(mSurfaceAnimator.getAnimationType(), mSurfaceAnimator.getAnimation());
Jorim Jaggia5e10572017-11-15 14:36:26 +01002105 mSurfaceAnimator.cancelAnimation();
Evan Rosky8d4ee722020-04-21 17:28:31 -07002106 mSurfaceFreezer.unfreeze(getPendingTransaction());
Jorim Jaggia5e10572017-11-15 14:36:26 +01002107 }
2108
Issei Suzuki737b7f12020-05-25 14:54:06 +02002109 ArraySet<WindowContainer> getAnimationSources() {
2110 return mSurfaceAnimationSources;
2111 }
2112
Jorim Jaggia5e10572017-11-15 14:36:26 +01002113 @Override
Evan Rosky55bddd82020-01-29 13:07:18 -08002114 public SurfaceControl getFreezeSnapshotTarget() {
2115 return null;
2116 }
2117
2118 @Override
Jorim Jaggia5e10572017-11-15 14:36:26 +01002119 public Builder makeAnimationLeash() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08002120 return makeSurface().setContainerLayer();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002121 }
2122
Jorim Jaggi596a1992017-12-29 14:48:02 +01002123 @Override
2124 public SurfaceControl getAnimationLeashParent() {
2125 return getParentSurfaceControl();
2126 }
2127
chaviw23ee71c2017-12-18 11:29:41 -08002128 /**
2129 * @return The layer on which all app animations are happening.
2130 */
Jorim Jaggi391790622018-04-18 15:30:44 +02002131 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08002132 final WindowContainer parent = getParent();
2133 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02002134 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08002135 }
2136 return null;
2137 }
2138
lumark19a5d2e2019-10-11 16:19:30 +08002139 // TODO: Remove this and use #getBounds() instead once we set an app transition animation
2140 // on TaskStack.
2141 Rect getAnimationBounds(int appStackClipMode) {
Evan Rosky6ecd67c2020-04-14 11:50:43 -07002142 return getBounds();
lumark19a5d2e2019-10-11 16:19:30 +08002143 }
2144
Riddle Hsua71f8e02020-05-05 23:07:59 +08002145 /** Gets the position relative to parent for animation. */
2146 void getAnimationPosition(Point outPosition) {
2147 getRelativePosition(outPosition);
2148 }
2149
lumark19a5d2e2019-10-11 16:19:30 +08002150 /**
2151 * Applies the app transition animation according the given the layout properties in the
2152 * window hierarchy.
2153 *
2154 * @param lp The layout parameters of the window.
2155 * @param transit The app transition type indicates what kind of transition to be applied.
2156 * @param enter Whether the app transition is entering transition or not.
2157 * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
Issei Suzuki737b7f12020-05-25 14:54:06 +02002158 * @param sources {@link ActivityRecord}s which causes this app transition animation.
lumark19a5d2e2019-10-11 16:19:30 +08002159 *
2160 * @return {@code true} when the container applied the app transition, {@code false} if the
2161 * app transition is disabled or skipped.
2162 *
2163 * @see #getAnimationAdapter
2164 */
2165 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Issei Suzuki737b7f12020-05-25 14:54:06 +02002166 boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) {
lumark19a5d2e2019-10-11 16:19:30 +08002167 if (mWmService.mDisableTransitionAnimation) {
2168 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2169 "applyAnimation: transition animation is disabled or skipped. "
2170 + "container=%s", this);
2171 cancelAnimation();
2172 return false;
2173 }
2174
2175 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2176 // to animate and it can cause strange artifacts when we unfreeze the display if some
2177 // different animation is running.
2178 try {
2179 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
2180 if (okToAnimate()) {
Issei Suzuki737b7f12020-05-25 14:54:06 +02002181 applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources);
lumark19a5d2e2019-10-11 16:19:30 +08002182 } else {
2183 cancelAnimation();
2184 }
2185 } finally {
2186 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2187 }
2188
2189 return isAnimating();
2190 }
2191
2192 /**
2193 * Gets the {@link AnimationAdapter} according the given window layout properties in the window
2194 * hierarchy.
2195 *
2196 * @return The return value will always contain two elements, one for normal animations and the
2197 * other for thumbnail animation, both can be {@code null}.
2198 *
2199 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
2200 * @See LocalAnimationAdapter
2201 */
2202 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
2203 int transit, boolean enter, boolean isVoiceInteraction) {
2204 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
2205 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
2206
2207 // Separate position and size for use in animators.
Ming-Shin Lue54dbef2020-05-18 10:19:20 +08002208 final Rect screenBounds = getAnimationBounds(appStackClipMode);
2209 mTmpRect.set(screenBounds);
Riddle Hsua71f8e02020-05-05 23:07:59 +08002210 getAnimationPosition(mTmpPoint);
2211 if (!sHierarchicalAnimations) {
2212 // Non-hierarchical animation uses position in global coordinates.
lumark85718662019-12-26 22:05:12 +08002213 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2214 }
lumark19a5d2e2019-10-11 16:19:30 +08002215 mTmpRect.offsetTo(0, 0);
2216
2217 final RemoteAnimationController controller =
2218 getDisplayContent().mAppTransition.getRemoteAnimationController();
2219 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2220 && isChangingAppTransition();
2221
2222 // Delaying animation start isn't compatible with remote animations at all.
2223 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
lumark2ec19122020-01-23 00:09:04 +08002224 final Rect localBounds = new Rect(mTmpRect);
2225 localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
lumark19a5d2e2019-10-11 16:19:30 +08002226 final RemoteAnimationController.RemoteAnimationRecord adapters =
lumark2ec19122020-01-23 00:09:04 +08002227 controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,
Ming-Shin Lue54dbef2020-05-18 10:19:20 +08002228 screenBounds, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
lumark19a5d2e2019-10-11 16:19:30 +08002229 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
2230 } else if (isChanging) {
2231 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
2232 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2233 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2234
lumarkbc0032a2019-11-01 21:38:13 +08002235 final AnimationAdapter adapter = new LocalAnimationAdapter(
Evan Rosky55bddd82020-01-29 13:07:18 -08002236 new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect,
2237 displayInfo, durationScale, true /* isAppAnimation */,
2238 false /* isThumbnail */),
lumark19a5d2e2019-10-11 16:19:30 +08002239 getSurfaceAnimationRunner());
2240
Evan Rosky55bddd82020-01-29 13:07:18 -08002241 final AnimationAdapter thumbnailAdapter = mSurfaceFreezer.mSnapshot != null
2242 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(
2243 mSurfaceFreezer.mFreezeBounds, mTmpRect, displayInfo, durationScale,
2244 true /* isAppAnimation */, true /* isThumbnail */), getSurfaceAnimationRunner())
lumarkbc0032a2019-11-01 21:38:13 +08002245 : null;
lumark19a5d2e2019-10-11 16:19:30 +08002246 resultAdapters = new Pair<>(adapter, thumbnailAdapter);
2247 mTransit = transit;
2248 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2249 } else {
2250 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2251 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2252
2253 if (a != null) {
2254 // Only apply corner radius to animation if we're not in multi window mode.
2255 // We don't want rounded corners when in pip or split screen.
2256 final float windowCornerRadius = !inMultiWindowMode()
2257 ? getDisplayContent().getWindowCornerRadius()
2258 : 0;
2259 AnimationAdapter adapter = new LocalAnimationAdapter(
2260 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
2261 getDisplayContent().mAppTransition.canSkipFirstFrame(),
2262 appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
2263 getSurfaceAnimationRunner());
2264
2265 resultAdapters = new Pair<>(adapter, null);
Ming-Shin Lu1ef1fba2020-04-22 21:37:13 +08002266 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP
2267 || AppTransition.isClosingTransit(transit);
lumark19a5d2e2019-10-11 16:19:30 +08002268 mTransit = transit;
2269 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2270 } else {
2271 resultAdapters = new Pair<>(null, null);
2272 }
2273 }
2274 return resultAdapters;
2275 }
2276
lumark04bceb92020-03-07 00:03:33 +08002277 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter,
2278 int transit, boolean isVoiceInteraction,
Issei Suzuki737b7f12020-05-25 14:54:06 +02002279 @Nullable ArrayList<WindowContainer> sources) {
lumark04bceb92020-03-07 00:03:33 +08002280 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
2281 transit, enter, isVoiceInteraction);
2282 AnimationAdapter adapter = adapters.first;
2283 AnimationAdapter thumbnailAdapter = adapters.second;
2284 if (adapter != null) {
Issei Suzuki737b7f12020-05-25 14:54:06 +02002285 if (sources != null) {
2286 mSurfaceAnimationSources.addAll(sources);
2287 }
lumark04bceb92020-03-07 00:03:33 +08002288 startAnimation(getPendingTransaction(), adapter, !isVisible(),
Issei Suzuki737b7f12020-05-25 14:54:06 +02002289 ANIMATION_TYPE_APP_TRANSITION);
lumark04bceb92020-03-07 00:03:33 +08002290 if (adapter.getShowWallpaper()) {
2291 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
2292 }
2293 if (thumbnailAdapter != null) {
2294 mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
2295 thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> { });
2296 }
2297 }
2298 }
2299
lumark19a5d2e2019-10-11 16:19:30 +08002300 final SurfaceAnimationRunner getSurfaceAnimationRunner() {
2301 return mWmService.mSurfaceAnimationRunner;
2302 }
2303
2304 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2305 boolean isVoiceInteraction) {
Winson Chung1b5d0552020-04-06 19:28:49 -07002306 if (isOrganized()) {
2307 // Defer to the task organizer to run animations
2308 return null;
2309 }
2310
lumark19a5d2e2019-10-11 16:19:30 +08002311 final DisplayContent displayContent = getDisplayContent();
2312 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2313 final int width = displayInfo.appWidth;
2314 final int height = displayInfo.appHeight;
2315 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
2316
2317 // Determine the visible rect to calculate the thumbnail clip with
2318 // getAnimationFrames.
2319 final Rect frame = new Rect(0, 0, width, height);
2320 final Rect displayFrame = new Rect(0, 0,
2321 displayInfo.logicalWidth, displayInfo.logicalHeight);
2322 final Rect insets = new Rect();
2323 final Rect stableInsets = new Rect();
2324 final Rect surfaceInsets = new Rect();
2325 getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
2326
2327 if (mLaunchTaskBehind) {
2328 // Differentiate the two animations. This one which is briefly on the screen
2329 // gets the !enter animation, and the other one which remains on the
2330 // screen gets the enter animation. Both appear in the mOpeningApps set.
2331 enter = false;
2332 }
2333 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2334 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2335 + "surfaceInsets=%s",
2336 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
2337 final Configuration displayConfig = displayContent.getConfiguration();
2338 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
2339 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2340 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
2341 if (a != null) {
lumark8669ef32020-02-10 18:41:57 +08002342 if (a != null) {
2343 // Setup the maximum app transition duration to prevent malicious app may set a long
2344 // animation duration or infinite repeat counts for the app transition through
2345 // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
2346 a.restrictDuration(MAX_APP_TRANSITION_DURATION);
2347 }
2348 if (DEBUG_ANIM) {
2349 logWithStack(TAG, "Loaded animation " + a + " for " + this
2350 + ", duration: " + ((a != null) ? a.getDuration() : 0));
2351 }
lumark19a5d2e2019-10-11 16:19:30 +08002352 final int containingWidth = frame.width();
2353 final int containingHeight = frame.height();
2354 a.initialize(containingWidth, containingHeight, width, height);
2355 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
2356 }
2357 return a;
2358 }
2359
2360 RemoteAnimationTarget createRemoteAnimationTarget(
2361 RemoteAnimationController.RemoteAnimationRecord record) {
2362 return null;
2363 }
2364
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09002365 boolean canCreateRemoteAnimationTarget() {
2366 return false;
2367 }
2368
lumark19a5d2e2019-10-11 16:19:30 +08002369 boolean okToDisplay() {
lumark5341d1c2019-12-14 01:54:02 +08002370 final DisplayContent dc = getDisplayContent();
2371 return dc != null && dc.okToDisplay();
lumark19a5d2e2019-10-11 16:19:30 +08002372 }
2373
2374 boolean okToAnimate() {
lumark3b8bbc82019-12-02 16:22:08 +08002375 return okToAnimate(false /* ignoreFrozen */);
2376 }
2377
2378 boolean okToAnimate(boolean ignoreFrozen) {
lumark5341d1c2019-12-14 01:54:02 +08002379 final DisplayContent dc = getDisplayContent();
2380 return dc != null && dc.okToAnimate(ignoreFrozen);
lumark19a5d2e2019-10-11 16:19:30 +08002381 }
2382
Jorim Jaggia5e10572017-11-15 14:36:26 +01002383 @Override
2384 public void commitPendingTransaction() {
2385 scheduleAnimation();
2386 }
2387
Robert Carr2f8aa392018-01-31 14:46:51 -08002388 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01002389 final WindowContainer parent = getParent();
2390 if (parent != null) {
2391 parent.assignChildLayers(t);
2392 }
2393 }
2394
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08002395 void resetSurfacePositionForAnimationLeash(Transaction t) {
2396 t.setPosition(mSurfaceControl, 0, 0);
2397 mLastSurfacePosition.set(0, 0);
2398 }
2399
Jorim Jaggia5e10572017-11-15 14:36:26 +01002400 @Override
2401 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002402 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002403 reassignLayer(t);
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002404
2405 // Leash is now responsible for position, so set our position to 0.
Riddle Hsu3d0aa4f2020-04-09 17:58:50 +08002406 resetSurfacePositionForAnimationLeash(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002407 }
2408
2409 @Override
lumarkf6f34942019-04-29 16:56:50 +08002410 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002411 mLastLayer = -1;
Evan Rosky55bddd82020-01-29 13:07:18 -08002412 mSurfaceFreezer.unfreeze(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002413 reassignLayer(t);
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002414 updateSurfacePosition(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002415 }
2416
Issei Suzuki737b7f12020-05-25 14:54:06 +02002417 private void doAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
2418 for (int i = 0; i < mSurfaceAnimationSources.size(); ++i) {
2419 mSurfaceAnimationSources.valueAt(i).onAnimationFinished(type, anim);
2420 }
2421 mSurfaceAnimationSources.clear();
2422 }
2423
Jorim Jaggia5e10572017-11-15 14:36:26 +01002424 /**
2425 * Called when an animation has finished running.
2426 */
Issei Suzuki8b995df2020-01-08 12:23:04 +01002427 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
Issei Suzuki737b7f12020-05-25 14:54:06 +02002428 doAnimationFinished(type, anim);
chaviwccd5d502019-02-22 13:30:31 -08002429 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002430 }
2431
2432 /**
2433 * @return The currently running animation, if any, or {@code null} otherwise.
2434 */
2435 AnimationAdapter getAnimation() {
2436 return mSurfaceAnimator.getAnimation();
2437 }
2438
2439 /**
lumark5bd11af2019-12-21 01:52:28 +08002440 * @return The {@link WindowContainer} which is running an animation.
2441 *
Issei Suzuki737b7f12020-05-25 14:54:06 +02002442 * By default this only checks if this container itself is actually running an animation, but
2443 * you can extend the check target over its relatives, or relax the condition so that this can
2444 * return {@code WindowContainer} if an animation starts soon by giving a combination
2445 * of {@link AnimationFlags}.
2446 *
2447 * Note that you can give a combination of bitmask flags to specify targets and condition for
2448 * checking animating status.
2449 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
2450 * container itself or one of its parents is running an animation or waiting for an app
2451 * transition.
2452 *
2453 * Note that TRANSITION propagates to parents and children as well.
2454 *
2455 * @param flags The combination of bitmask flags to specify targets and condition for
2456 * checking animating status.
2457 * @param typesToCheck The combination of bitmask {@link AnimationType} to compare when
2458 * determining if animating.
2459 *
2460 * @see AnimationFlags#TRANSITION
2461 * @see AnimationFlags#PARENTS
2462 * @see AnimationFlags#CHILDREN
lumark5bd11af2019-12-21 01:52:28 +08002463 */
2464 @Nullable
Issei Suzuki737b7f12020-05-25 14:54:06 +02002465 WindowContainer getAnimatingContainer(int flags, int typesToCheck) {
Jorim Jaggi268bf6882020-06-18 23:44:02 +02002466 if (isSelfAnimating(flags, typesToCheck)) {
Issei Suzuki737b7f12020-05-25 14:54:06 +02002467 return this;
2468 }
2469 if ((flags & PARENTS) != 0) {
Jorim Jaggi268bf6882020-06-18 23:44:02 +02002470 WindowContainer parent = getParent();
2471 while (parent != null) {
2472 if (parent.isSelfAnimating(flags, typesToCheck)) {
2473 return parent;
Issei Suzuki737b7f12020-05-25 14:54:06 +02002474 }
Jorim Jaggi268bf6882020-06-18 23:44:02 +02002475 parent = parent.getParent();
Issei Suzuki737b7f12020-05-25 14:54:06 +02002476 }
2477 }
2478 if ((flags & CHILDREN) != 0) {
2479 for (int i = 0; i < mChildren.size(); ++i) {
2480 final WindowContainer wc = mChildren.get(i).getAnimatingContainer(
2481 flags & ~PARENTS, typesToCheck);
2482 if (wc != null) {
2483 return wc;
2484 }
2485 }
2486 }
2487 return null;
2488 }
2489
2490 /**
Jorim Jaggi268bf6882020-06-18 23:44:02 +02002491 * Internal method only to be used during {@link #getAnimatingContainer(int, int)}.DO NOT CALL
2492 * FROM OUTSIDE.
2493 */
2494 protected boolean isSelfAnimating(int flags, int typesToCheck) {
2495 if (mSurfaceAnimator.isAnimating()
2496 && (mSurfaceAnimator.getAnimationType() & typesToCheck) > 0) {
2497 return true;
2498 }
2499 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
2500 return true;
2501 }
2502 return false;
2503 }
2504
2505 /**
Issei Suzuki737b7f12020-05-25 14:54:06 +02002506 * @deprecated Use {@link #getAnimatingContainer(int, int)} instead.
2507 */
2508 @Nullable
2509 @Deprecated
2510 final WindowContainer getAnimatingContainer() {
2511 return getAnimatingContainer(PARENTS, ANIMATION_TYPE_ALL);
lumark5bd11af2019-12-21 01:52:28 +08002512 }
2513
2514 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +01002515 * @see SurfaceAnimator#startDelayingAnimationStart
2516 */
2517 void startDelayingAnimationStart() {
2518 mSurfaceAnimator.startDelayingAnimationStart();
2519 }
2520
2521 /**
2522 * @see SurfaceAnimator#endDelayingAnimationStart
2523 */
2524 void endDelayingAnimationStart() {
2525 mSurfaceAnimator.endDelayingAnimationStart();
2526 }
2527
2528 @Override
2529 public int getSurfaceWidth() {
2530 return mSurfaceControl.getWidth();
2531 }
2532
2533 @Override
2534 public int getSurfaceHeight() {
2535 return mSurfaceControl.getHeight();
2536 }
2537
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002538 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01002539 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2540 if (mSurfaceAnimator.isAnimating()) {
2541 pw.print(prefix); pw.println("ContainerAnimator:");
2542 mSurfaceAnimator.dump(pw, prefix + " ");
2543 }
2544 }
chaviwe07246a2017-12-12 16:18:29 -08002545
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002546 final void updateSurfacePosition() {
chaviw89cc30e2020-05-19 10:36:27 -07002547 updateSurfacePosition(getSyncTransaction());
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002548 }
2549
2550 void updateSurfacePosition(Transaction t) {
Wale Ogunwaledec34082020-03-22 09:45:00 -07002551 // Avoid fighting with the organizer over Surface position.
2552 if (isOrganized()) return;
2553
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002554 if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) {
chaviwe07246a2017-12-12 16:18:29 -08002555 return;
2556 }
2557
Evan Rosky6ecd67c2020-04-14 11:50:43 -07002558 getRelativePosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08002559 if (mTmpPos.equals(mLastSurfacePosition)) {
2560 return;
2561 }
2562
Evan Rosky0ad8d2c2020-03-16 12:09:58 -07002563 t.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08002564 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08002565 }
2566
Evan Rosky65dffa62019-02-04 14:09:53 -08002567 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002568 Point getLastSurfacePosition() {
2569 return mLastSurfacePosition;
2570 }
2571
Evan Roskyed6767f2018-10-26 17:21:06 -07002572 /**
lumark19a5d2e2019-10-11 16:19:30 +08002573 * The {@code outFrame} retrieved by this method specifies where the animation will finish
2574 * the entrance animation, as the next frame will display the window at these coordinates. In
2575 * case of exit animation, this is where the animation will start, as the frame before the
2576 * animation is displaying the window at these bounds.
2577 *
2578 * @param outFrame The bounds where entrance animation finishes or exit animation starts.
2579 * @param outInsets Insets that are covered by system windows.
2580 * @param outStableInsets Insets that determine the area covered by the stable system windows.
2581 * @param outSurfaceInsets Positive insets between the drawing surface and window content.
2582 */
2583 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2584 Rect outSurfaceInsets) {
2585 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2586 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
2587 outInsets.setEmpty();
2588 outStableInsets.setEmpty();
2589 outSurfaceInsets.setEmpty();
2590 }
2591
Evan Rosky6ecd67c2020-04-14 11:50:43 -07002592 void getRelativePosition(Point outPos) {
Wale Ogunwaledec34082020-03-22 09:45:00 -07002593 // In addition to updateSurfacePosition, we keep other code that sets
2594 // position from fighting with the organizer
2595 if (isOrganized()) {
2596 outPos.set(0, 0);
2597 return;
2598 }
2599
Evan Rosky6ecd67c2020-04-14 11:50:43 -07002600 final Rect dispBounds = getBounds();
Evan Roskyed6767f2018-10-26 17:21:06 -07002601 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08002602 final WindowContainer parent = getParent();
2603 if (parent != null) {
Evan Rosky6ecd67c2020-04-14 11:50:43 -07002604 final Rect parentBounds = parent.getBounds();
chaviwe07246a2017-12-12 16:18:29 -08002605 outPos.offset(-parentBounds.left, -parentBounds.top);
2606 }
2607 }
chaviw2fb06bc2018-01-19 17:09:15 -08002608
Yunfan Chen87b5a242019-10-01 17:53:59 +09002609 void waitForAllWindowsDrawn() {
Yunfan Chen87b5a242019-10-01 17:53:59 +09002610 forAllWindows(w -> {
Riddle Hsu5df3b752019-12-16 13:27:37 -06002611 w.requestDrawIfNeeded(mWaitingForDrawn);
Yunfan Chen87b5a242019-10-01 17:53:59 +09002612 }, true /* traverseTopToBottom */);
2613 }
2614
chaviw2fb06bc2018-01-19 17:09:15 -08002615 Dimmer getDimmer() {
2616 if (mParent == null) {
2617 return null;
2618 }
2619 return mParent.getDimmer();
2620 }
Robert Carr8a2f9132019-11-11 15:03:15 -08002621
2622 void setSurfaceControl(SurfaceControl sc) {
2623 mSurfaceControl = sc;
2624 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002625
Evan Rosky55bddd82020-01-29 13:07:18 -08002626 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2627 return null;
2628 }
2629
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002630 /** Cheap way of doing cast and instanceof. */
2631 Task asTask() {
2632 return null;
2633 }
2634
2635 /** Cheap way of doing cast and instanceof. */
2636 ActivityRecord asActivityRecord() {
2637 return null;
2638 }
Evan Roskya80f11c2020-01-23 19:17:10 -08002639
Wale Ogunwaledec34082020-03-22 09:45:00 -07002640 /**
2641 * @return {@code true} if window container is manage by a
2642 * {@link android.window.WindowOrganizer}
2643 */
2644 boolean isOrganized() {
2645 return false;
Evan Roskya80f11c2020-01-23 19:17:10 -08002646 }
2647
Evan Roskya8fde152020-01-07 19:09:13 -08002648 static WindowContainer fromBinder(IBinder binder) {
2649 return RemoteToken.fromBinder(binder).getContainer();
2650 }
2651
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002652 static class RemoteToken extends IWindowContainerToken.Stub {
2653
Evan Roskya80f11c2020-01-23 19:17:10 -08002654 final WeakReference<WindowContainer> mWeakRef;
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002655 private WindowContainerToken mWindowContainerToken;
Evan Roskya80f11c2020-01-23 19:17:10 -08002656
2657 RemoteToken(WindowContainer container) {
2658 mWeakRef = new WeakReference<>(container);
2659 }
2660
2661 WindowContainer getContainer() {
2662 return mWeakRef.get();
2663 }
2664
2665 static RemoteToken fromBinder(IBinder binder) {
2666 return (RemoteToken) binder;
2667 }
2668
Wale Ogunwaleadf116e2020-03-27 16:36:01 -07002669 WindowContainerToken toWindowContainerToken() {
2670 if (mWindowContainerToken == null) {
2671 mWindowContainerToken = new WindowContainerToken(this);
2672 }
2673 return mWindowContainerToken;
2674 }
2675
Evan Roskya80f11c2020-01-23 19:17:10 -08002676 @Override
2677 public String toString() {
2678 StringBuilder sb = new StringBuilder(128);
2679 sb.append("RemoteToken{");
2680 sb.append(Integer.toHexString(System.identityHashCode(this)));
2681 sb.append(' ');
2682 sb.append(mWeakRef.get());
2683 sb.append('}');
2684 return sb.toString();
2685 }
2686 }
Robert Carre10ee3d2019-11-11 15:03:15 -08002687
2688 @Override
chaviw54521692020-06-12 14:34:30 -07002689 public void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady) {
2690 if (mWaitingListener == null) {
2691 return;
2692 }
Robert Carre10ee3d2019-11-11 15:03:15 -08002693
chaviw54521692020-06-12 14:34:30 -07002694 windowContainersReady.add(this);
2695 mWaitingListener.onTransactionReady(mWaitingSyncId, windowContainersReady);
Robert Carre10ee3d2019-11-11 15:03:15 -08002696
2697 mWaitingListener = null;
2698 mWaitingSyncId = -1;
2699 }
2700
Rob Carr25376512020-03-09 15:23:19 -07002701 /**
2702 * Returns true if any of the children elected to participate in the Sync
2703 */
2704 boolean addChildrenToSyncSet(int localId) {
2705 boolean willSync = false;
2706
2707 for (int i = 0; i < mChildren.size(); i++) {
2708 final WindowContainer child = mChildren.get(i);
2709 willSync |= mBLASTSyncEngine.addToSyncSet(localId, child);
2710 }
2711 return willSync;
2712 }
2713
Robert Carr6a08d322020-05-19 10:21:55 -07002714 boolean setPendingListener(BLASTSyncEngine.TransactionReadyListener waitingListener,
2715 int waitingId) {
Robert Carr8ccc4fc2020-03-13 10:48:49 -07002716 // If we are invisible, no need to sync, likewise if we are already engaged in a sync,
2717 // we can't support overlapping syncs on a single container yet.
2718 if (!isVisible() || mWaitingListener != null) {
2719 return false;
Robert Carre10ee3d2019-11-11 15:03:15 -08002720 }
2721 mUsingBLASTSyncTransaction = true;
2722
Robert Carre10ee3d2019-11-11 15:03:15 -08002723 // Make sure to set these before we call setReady in case the sync was a no-op
2724 mWaitingSyncId = waitingId;
2725 mWaitingListener = waitingListener;
Robert Carr6a08d322020-05-19 10:21:55 -07002726 return true;
2727 }
2728
2729 boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
2730 int waitingId) {
2731 boolean willSync = setPendingListener(waitingListener, waitingId);
2732 if (!willSync) {
2733 return false;
2734 }
Robert Carre10ee3d2019-11-11 15:03:15 -08002735
Rob Carr25376512020-03-09 15:23:19 -07002736 int localId = mBLASTSyncEngine.startSyncSet(this);
2737 willSync |= addChildrenToSyncSet(localId);
Robert Carre10ee3d2019-11-11 15:03:15 -08002738 mBLASTSyncEngine.setReady(localId);
2739
2740 return willSync;
2741 }
Robert Carr6cc720b2020-04-06 13:45:31 -07002742
2743 boolean useBLASTSync() {
2744 return mUsingBLASTSyncTransaction;
2745 }
chaviw54521692020-06-12 14:34:30 -07002746
2747 void mergeBlastSyncTransaction(Transaction t) {
2748 t.merge(mBLASTSyncTransaction);
2749 mUsingBLASTSyncTransaction = false;
2750 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07002751}