blob: b12c6980cccef11f0024c1e37d74ecc7f6b891cd [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;
Issei Suzuki8b995df2020-01-08 12:23:04 +010039import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
lumark9bca6b42019-10-17 18:35:22 +080040import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
41import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
42import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070043import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
44import static com.android.server.wm.WindowContainerProto.ORIENTATION;
45import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
46import static com.android.server.wm.WindowContainerProto.VISIBLE;
Louis Chang7501e332018-08-20 13:08:39 +080047import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
48import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
49import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
lumark19a5d2e2019-10-11 16:19:30 +080050import static com.android.server.wm.WindowManagerService.logWithStack;
lumark85718662019-12-26 22:05:12 +080051import static com.android.server.wm.WindowManagerService.sHierarchicalAnimations;
lumark19a5d2e2019-10-11 16:19:30 +080052import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Jorim Jaggi612bb882017-05-16 17:11:18 +020053
Wale Ogunwaled63594a2016-07-18 07:48:30 -070054import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020055import android.annotation.IntDef;
Garfield Tan90b04282018-12-11 14:04:42 -080056import android.annotation.Nullable;
Jorim Jaggi391790622018-04-18 15:30:44 +020057import android.app.WindowConfiguration;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080058import android.content.pm.ActivityInfo;
Andrii Kulian441e4492016-09-29 15:25:00 -070059import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080060import android.graphics.Point;
61import android.graphics.Rect;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080062import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -080063import android.os.IBinder;
lumark19a5d2e2019-10-11 16:19:30 +080064import android.os.Trace;
65import android.util.Pair;
Vishnu Nair04ab4392018-01-10 11:00:06 -080066import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010067import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080068import android.util.proto.ProtoOutputStream;
lumark19a5d2e2019-10-11 16:19:30 +080069import android.view.DisplayInfo;
Evan Roskya80f11c2020-01-23 19:17:10 -080070import android.view.IWindowContainer;
Robert Carrb1579c82017-09-05 14:54:47 -070071import android.view.MagnificationSpec;
Evan Rosky55bddd82020-01-29 13:07:18 -080072import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +080073import android.view.RemoteAnimationTarget;
Robert Carrb1579c82017-09-05 14:54:47 -070074import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010075import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070076import android.view.SurfaceSession;
lumark19a5d2e2019-10-11 16:19:30 +080077import android.view.WindowManager;
78import android.view.animation.Animation;
Garfield Tan2f145f22018-11-01 15:27:03 -070079
Evan Rosky65dffa62019-02-04 14:09:53 -080080import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010081import com.android.internal.util.ToBooleanFunction;
lumark19a5d2e2019-10-11 16:19:30 +080082import com.android.server.protolog.common.ProtoLog;
Jorim Jaggia5e10572017-11-15 14:36:26 +010083import com.android.server.wm.SurfaceAnimator.Animatable;
Issei Suzuki8b995df2020-01-08 12:23:04 +010084import com.android.server.wm.SurfaceAnimator.AnimationType;
85import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Garfield Tan2f145f22018-11-01 15:27:03 -070086
Jorim Jaggia5e10572017-11-15 14:36:26 +010087import java.io.PrintWriter;
Evan Roskya80f11c2020-01-23 19:17:10 -080088import java.lang.ref.WeakReference;
Yunfan Chen87b5a242019-10-01 17:53:59 +090089import java.util.ArrayList;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070090import java.util.Comparator;
91import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070092import java.util.function.Consumer;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -080093import java.util.function.Function;
Wale Ogunwaled1880962016-11-08 10:31:59 -080094import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070095
96/**
97 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070098 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -070099 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
100 * changes are made to this class.
101 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700102class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Evan Rosky55bddd82020-01-29 13:07:18 -0800103 implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
Robert Carre10ee3d2019-11-11 15:03:15 -0800104 BLASTSyncEngine.TransactionReadyListener {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100105
106 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700107
Louis Changdc077272019-11-12 16:52:56 +0800108 /** Animation layer that happens above all animating {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200109 static final int ANIMATION_LAYER_STANDARD = 0;
110
Louis Changdc077272019-11-12 16:52:56 +0800111 /** Animation layer that happens above all {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200112 static final int ANIMATION_LAYER_BOOSTED = 1;
113
114 /**
115 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -0700116 * activities and all activities that are being controlled by the recents animation. This
Louis Changdc077272019-11-12 16:52:56 +0800117 * layer is generally below all {@link ActivityStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +0200118 */
119 static final int ANIMATION_LAYER_HOME = 2;
120
121 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
122 ANIMATION_LAYER_STANDARD,
123 ANIMATION_LAYER_BOOSTED,
124 ANIMATION_LAYER_HOME,
125 })
126 @interface AnimationLayer {}
127
Andrii Kuliand2765632016-12-12 22:26:34 -0800128 static final int POSITION_TOP = Integer.MAX_VALUE;
129 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
130
Andrii Kulian441e4492016-09-29 15:25:00 -0700131 /**
132 * The parent of this window container.
133 * For removing or setting new parent {@link #setParent} should be used, because it also
134 * performs configuration updates based on new parent's settings.
135 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100136 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700137
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200138 // Set to true when we are performing a reparenting operation so we only send one
139 // onParentChanged() notification.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700140 boolean mReparenting;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200141
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700142 // List of children for this window container. List is in z-order as the children appear on
143 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200144 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700145
Wale Ogunwale51362492016-09-08 17:49:17 -0700146 // The specified orientation for this window container.
Vadim Caen1096f112019-12-18 11:44:26 +0100147 @ActivityInfo.ScreenOrientation
Wale Ogunwale51362492016-09-08 17:49:17 -0700148 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
149
Riddle Hsu6f548e92020-01-13 13:34:09 +0800150 /**
151 * The window container which decides its orientation since the last time
152 * {@link #getOrientation(int) was called.
153 */
154 protected WindowContainer mLastOrientationSource;
155
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800156 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
157 new Pools.SynchronizedPool<>(3);
158
Tiger Huanged6794e2019-05-07 20:07:59 +0800159 // The display this window container is on.
160 protected DisplayContent mDisplayContent;
161
Robert Carrb1579c82017-09-05 14:54:47 -0700162 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100163 private int mLastLayer = 0;
164 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700165
Tiger Huanged6794e2019-05-07 20:07:59 +0800166 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
167 private final Transaction mPendingTransaction;
168
Robert Carrb1579c82017-09-05 14:54:47 -0700169 /**
Yunfan Chen87b5a242019-10-01 17:53:59 +0900170 * Windows that clients are waiting to have drawn.
171 */
172 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
173
174 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700175 * Applied as part of the animation pass in "prepareSurfaces".
176 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100177 protected final SurfaceAnimator mSurfaceAnimator;
Evan Rosky55bddd82020-01-29 13:07:18 -0800178 final SurfaceFreezer mSurfaceFreezer;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800179 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100180
chaviwe07246a2017-12-12 16:18:29 -0800181 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800182 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800183
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100184 /** Total number of elements in this subtree, including our own hierarchy element. */
185 private int mTreeWeight = 1;
186
chaviw7f1fa992018-01-10 13:52:12 -0800187 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700188 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800189 * surface to the animation leash
190 */
191 private boolean mCommittedReparentToAnimationLeash;
192
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800193 private final Configuration mTmpConfig = new Configuration();
194
lumark9bca6b42019-10-17 18:35:22 +0800195 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
196 public interface AnimationFlags {
197 /**
198 * A bit flag indicates that {@link #isAnimating} should also return {@code true}
199 * even though the container is not yet animating, but the window container or its
200 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
201 * that is pending so an animation starts soon.
202 */
203 int TRANSITION = 1;
204
205 /**
206 * A bit flag indicates that {@link #isAnimating} should also check if one of the
207 * ancestors of the container are animating in addition to the container itself.
208 */
209 int PARENTS = 2;
210
211 /**
212 * A bit flag indicates that {@link #isAnimating} should also check if one of the
213 * descendants of the container are animating in addition to the container itself.
214 */
215 int CHILDREN = 4;
216 }
217
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200218 /**
219 * Callback which is triggered while changing the parent, after setting up the surface but
220 * before asking the parent to assign child layers.
221 */
222 interface PreAssignChildLayersCallback {
223 void onPreAssignChildLayers();
224 }
225
lumark19a5d2e2019-10-11 16:19:30 +0800226 /**
227 * True if this an AppWindowToken and the activity which created this was launched with
228 * ActivityOptions.setLaunchTaskBehind.
229 *
230 * TODO(b/142617871): We run a special animation when the activity was launched with that
231 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
232 * selected to suppress an animation, and remove this flag.
233 */
234 boolean mLaunchTaskBehind;
235
236 /**
237 * If we are running an animation, this determines the transition type. Must be one of
238 * {@link AppTransition#TransitionFlags}.
239 */
240 int mTransit;
241
242 /**
243 * If we are running an animation, this determines the flags during this animation. Must be a
244 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
245 */
246 int mTransitFlags;
247
248 /** Whether this container should be boosted at the top of all its siblings. */
249 @VisibleForTesting boolean mNeedsZBoost;
250
251 /** Layer used to constrain the animation to a container's stack bounds. */
252 SurfaceControl mAnimationBoundsLayer;
253
254 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
255 boolean mNeedsAnimationBoundsLayer;
256
257 /**
258 * This gets used during some open/close transitions as well as during a change transition
259 * where it represents the starting-state snapshot.
260 */
lumarkbc0032a2019-11-01 21:38:13 +0800261 WindowContainerThumbnail mThumbnail;
lumark19a5d2e2019-10-11 16:19:30 +0800262 final Point mTmpPoint = new Point();
263 protected final Rect mTmpRect = new Rect();
264 final Rect mTmpPrevBounds = new Rect();
265
Robert Carr7603dea2019-07-17 13:16:21 -0700266 private MagnificationSpec mLastMagnificationSpec;
267
Evan Rosky226de132020-01-03 18:00:29 -0800268 private boolean mIsFocusable = true;
269
Evan Roskya80f11c2020-01-23 19:17:10 -0800270 /**
271 * Used as a unique, cross-process identifier for this Container. It also serves a minimal
272 * interface to other processes.
273 */
274 RemoteToken mRemoteToken = null;
275
Robert Carre10ee3d2019-11-11 15:03:15 -0800276 BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
277 SurfaceControl.Transaction mBLASTSyncTransaction = new SurfaceControl.Transaction();
278 boolean mUsingBLASTSyncTransaction = false;
279 BLASTSyncEngine.TransactionReadyListener mWaitingListener;
280 int mWaitingSyncId;
281
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800282 WindowContainer(WindowManagerService wms) {
283 mWmService = wms;
Vishnu Nair33197392019-08-30 10:29:37 -0700284 mPendingTransaction = wms.mTransactionFactory.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800285 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Evan Rosky55bddd82020-01-29 13:07:18 -0800286 mSurfaceFreezer = new SurfaceFreezer(this, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100287 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800288
Wale Ogunwale98d62312017-07-12 09:24:56 -0700289 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700290 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700291 return mParent;
292 }
293
Wale Ogunwale98d62312017-07-12 09:24:56 -0700294 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700295 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700296 return mChildren.size();
297 }
298
299 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700300 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700301 return mChildren.get(index);
302 }
303
chaviwe07246a2017-12-12 16:18:29 -0800304 @Override
305 public void onConfigurationChanged(Configuration newParentConfig) {
306 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800307 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800308 scheduleAnimation();
309 }
310
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200311 void reparent(WindowContainer newParent, int position) {
312 if (newParent == null) {
313 throw new IllegalArgumentException("reparent: can't reparent to null " + this);
314 }
315
316 final WindowContainer oldParent = mParent;
317 if (mParent == newParent) {
318 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
319 }
320
321 // The display object before reparenting as that might lead to old parent getting removed
322 // from the display if it no longer has any child.
323 final DisplayContent prevDc = oldParent.getDisplayContent();
324 final DisplayContent dc = newParent.getDisplayContent();
325
326 mReparenting = true;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700327 oldParent.removeChild(this);
Louis Chang2453d062019-11-19 22:30:48 +0800328 newParent.addChild(this, position);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200329 mReparenting = false;
330
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200331 // Relayout display(s)
332 dc.setLayoutNeeded();
333 if (prevDc != dc) {
334 onDisplayChanged(dc);
335 prevDc.setLayoutNeeded();
336 }
337 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700338
339 // Send onParentChanged notification here is we disabled sending it in setParent for
340 // reparenting case.
341 onParentChanged(newParent, oldParent);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200342 }
343
Jorim Jaggia5e10572017-11-15 14:36:26 +0100344 final protected void setParent(WindowContainer<WindowContainer> parent) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200345 final WindowContainer oldParent = mParent;
Andrii Kulian441e4492016-09-29 15:25:00 -0700346 mParent = parent;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800347
348 if (mParent != null) {
349 mParent.onChildAdded(this);
350 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200351 if (!mReparenting) {
lumarkbde15132019-12-18 22:29:43 +0800352 if (mParent != null && mParent.mDisplayContent != null
353 && mDisplayContent != mParent.mDisplayContent) {
354 onDisplayChanged(mParent.mDisplayContent);
355 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200356 onParentChanged(mParent, oldParent);
357 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800358 }
359
360 /**
361 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
362 * Supposed to be overridden and contain actions that should be executed after parent was set.
363 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800364 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200365 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
366 onParentChanged(newParent, oldParent, null);
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200367 }
368
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200369 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
370 PreAssignChildLayersCallback callback) {
371 super.onParentChanged(newParent, oldParent);
Robert Carrb1579c82017-09-05 14:54:47 -0700372 if (mParent == null) {
373 return;
374 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100375
Robert Carrb1579c82017-09-05 14:54:47 -0700376 if (mSurfaceControl == null) {
377 // If we don't yet have a surface, but we now have a parent, we should
378 // build a surface.
Robert Carr8a2f9132019-11-11 15:03:15 -0800379 setSurfaceControl(makeSurface().build());
Robert Carrf59b8dd2017-10-02 18:58:36 -0700380 getPendingTransaction().show(mSurfaceControl);
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800381 onSurfaceShown(getPendingTransaction());
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700382 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700383 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100384 // If we have a surface but a new parent, we just need to perform a reparent. Go through
385 // surface animator such that hierarchy is preserved when animating, i.e.
386 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
387 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100388 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700389 }
390
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200391 if (callback != null) {
392 callback.onPreAssignChildLayers();
393 }
394
Robert Carrb1579c82017-09-05 14:54:47 -0700395 // Either way we need to ask the parent to assign us a Z-order.
396 mParent.assignChildLayers();
397 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700398 }
399
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800400 /**
401 * Called when the surface is shown for the first time.
402 */
403 void onSurfaceShown(Transaction t) {
404 // do nothing
405 }
406
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700407 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100408 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
409 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700410
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700411 /**
412 * Adds the input window container has a child of this container in order based on the input
413 * comparator.
414 * @param child The window container to add as a child of this window container.
415 * @param comparator Comparator to use in determining the position the child should be added to.
416 * If null, the child will be added to the top.
417 */
418 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700419 protected void addChild(E child, Comparator<E> comparator) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700420 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700421 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700422 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700423 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700424 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700425
Andrii Kulianb94292e2016-10-19 13:30:58 -0700426 int positionToAdd = -1;
427 if (comparator != null) {
428 final int count = mChildren.size();
429 for (int i = 0; i < count; i++) {
430 if (comparator.compare(child, mChildren.get(i)) < 0) {
431 positionToAdd = i;
432 break;
433 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700434 }
435 }
436
Andrii Kulianb94292e2016-10-19 13:30:58 -0700437 if (positionToAdd == -1) {
438 mChildren.add(child);
439 } else {
440 mChildren.add(positionToAdd, child);
441 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100442
Andrii Kulianb94292e2016-10-19 13:30:58 -0700443 // Set the parent after we've actually added a child in case a subclass depends on this.
444 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700445 }
446
Wale Ogunwalef6192862016-09-10 13:42:30 -0700447 /** Adds the input window container has a child of this container at the input index. */
448 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800449 void addChild(E child, int index) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700450 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700451 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700452 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800453 + " can't add to container=" + getName()
454 + "\n callers=" + Debug.getCallers(15, "\n"));
Wale Ogunwalef6192862016-09-10 13:42:30 -0700455 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900456
457 if ((index < 0 && index != POSITION_BOTTOM)
458 || (index > mChildren.size() && index != POSITION_TOP)) {
459 throw new IllegalArgumentException("addChild: invalid position=" + index
460 + ", children number=" + mChildren.size());
461 }
462
463 if (index == POSITION_TOP) {
464 index = mChildren.size();
465 } else if (index == POSITION_BOTTOM) {
466 index = 0;
467 }
468
Wale Ogunwalef6192862016-09-10 13:42:30 -0700469 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100470
Andrii Kulianb94292e2016-10-19 13:30:58 -0700471 // Set the parent after we've actually added a child in case a subclass depends on this.
472 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700473 }
474
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100475 private void onChildAdded(WindowContainer child) {
476 mTreeWeight += child.mTreeWeight;
477 WindowContainer parent = getParent();
478 while (parent != null) {
479 parent.mTreeWeight += child.mTreeWeight;
480 parent = parent.getParent();
481 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200482 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100483 }
484
Wale Ogunwalef6192862016-09-10 13:42:30 -0700485 /**
486 * Removes the input child container from this container which is its parent.
487 *
488 * @return True if the container did contain the input child and it was detached.
489 */
490 @CallSuper
491 void removeChild(E child) {
492 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100493 onChildRemoved(child);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700494 if (!child.mReparenting) {
495 child.setParent(null);
496 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700497 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700498 throw new IllegalArgumentException("removeChild: container=" + child.getName()
499 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700500 }
501 }
502
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100503 private void onChildRemoved(WindowContainer child) {
504 mTreeWeight -= child.mTreeWeight;
505 WindowContainer parent = getParent();
506 while (parent != null) {
507 parent.mTreeWeight -= child.mTreeWeight;
508 parent = parent.getParent();
509 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200510 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100511 }
512
Wale Ogunwale571771c2016-08-26 13:18:50 -0700513 /**
514 * Removes this window container and its children with no regard for what else might be going on
515 * in the system. For example, the container will be removed during animation if this method is
516 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
517 * which allows the system to defer removal until a suitable time.
518 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700519 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700520 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700521 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100522 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700523 child.removeImmediately();
524 // Need to do this after calling remove on the child because the child might try to
525 // remove/detach itself from its parent which will cause an exception if we remove
526 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100527 if (mChildren.remove(child)) {
528 onChildRemoved(child);
529 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700530 }
531
Robert Carrb1579c82017-09-05 14:54:47 -0700532 if (mSurfaceControl != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800533 getPendingTransaction().remove(mSurfaceControl);
Robert Carr8a2f9132019-11-11 15:03:15 -0800534 setSurfaceControl(null);
Garfield Tan265ab91a2019-11-12 16:30:49 -0800535 mLastSurfacePosition.set(0, 0);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000536 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700537 }
538
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700539 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700540 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700541 }
542 }
543
544 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100545 * @return The index of this element in the hierarchy tree in prefix order.
546 */
547 int getPrefixOrderIndex() {
548 if (mParent == null) {
549 return 0;
550 }
551 return mParent.getPrefixOrderIndex(this);
552 }
553
554 private int getPrefixOrderIndex(WindowContainer child) {
555 int order = 0;
556 for (int i = 0; i < mChildren.size(); i++) {
557 final WindowContainer childI = mChildren.get(i);
558 if (child == childI) {
559 break;
560 }
561 order += childI.mTreeWeight;
562 }
563 if (mParent != null) {
564 order += mParent.getPrefixOrderIndex(this);
565 }
566
567 // We also need to count ourselves.
568 order++;
569 return order;
570 }
571
572 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700573 * Removes this window container and its children taking care not to remove them during a
574 * critical stage in the system. For example, some containers will not be removed during
575 * animation if this method is called.
576 */
577 // TODO: figure-out implementation that works best for this.
578 // E.g. when do we remove from parent list? maybe not...
579 void removeIfPossible() {
580 for (int i = mChildren.size() - 1; i >= 0; --i) {
581 final WindowContainer wc = mChildren.get(i);
582 wc.removeIfPossible();
583 }
584 }
585
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700586 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000587 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700588 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000589 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700590 if (current == child || current.hasChild(child)) {
591 return true;
592 }
593 }
594 return false;
595 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700596
Issei Suzuki2f541842020-01-09 20:18:29 +0100597 /** @return true if this window container is a descendant of the input container. */
598 boolean isDescendantOf(WindowContainer ancestor) {
599 final WindowContainer parent = getParent();
600 if (parent == ancestor) return true;
601 return (parent != null) && parent.isDescendantOf(ancestor);
602 }
603
Andrii Kulian441e4492016-09-29 15:25:00 -0700604 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800605 * Move a child from it's current place in siblings list to the specified position,
606 * with an option to move all its parents to top.
607 * @param position Target position to move the child to.
608 * @param child Child to move to selected position.
609 * @param includingParents Flag indicating whether we need to move the entire branch of the
610 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
611 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
612 * this flag will do nothing.
613 */
614 @CallSuper
615 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800616
617 if (child.getParent() != this) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800618 throw new IllegalArgumentException("positionChildAt: container=" + child.getName()
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800619 + " is not a child of container=" + getName()
620 + " current parent=" + child.getParent());
621 }
622
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800623 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800624 position = POSITION_TOP;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700625 } else if (position <= 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800626 position = POSITION_BOTTOM;
627 }
628
629 switch (position) {
630 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800631 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800632 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200633 mChildren.add(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200634 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800635 }
636 if (includingParents && getParent() != null) {
637 getParent().positionChildAt(POSITION_TOP, this /* child */,
638 true /* includingParents */);
639 }
640 break;
641 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800642 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800643 mChildren.remove(child);
644 mChildren.addFirst(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200645 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800646 }
647 if (includingParents && getParent() != null) {
648 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
649 true /* includingParents */);
650 }
651 break;
652 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800653 // TODO: Removing the child before reinserting requires the caller to provide a
654 // position that takes into account the removed child (if the index of the
655 // child < position, then the position should be adjusted). We should consider
656 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800657 mChildren.remove(child);
658 mChildren.add(position, child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200659 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800660 }
661 }
662
663 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800664 * Notify that a child's position has changed. Possible changes are adding or removing a child.
665 */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200666 void onChildPositionChanged(WindowContainer child) { }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800667
668 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700669 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700670 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700671 * @see #mFullConfiguration
672 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700673 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700674 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800675 // We must diff before the configuration is applied so that we can capture the change
676 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700677 final int diff = diffRequestedOverrideBounds(
678 overrideConfiguration.windowConfiguration.getBounds());
679 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700680 if (mParent != null) {
681 mParent.onDescendantOverrideConfigurationChanged();
682 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800683
684 if (diff == BOUNDS_CHANGE_NONE) {
685 return;
686 }
687
688 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
689 onResize();
690 } else {
691 onMovedByResize();
692 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700693 }
694
695 /**
696 * Notify that a descendant's overrideConfiguration has changed.
697 */
698 void onDescendantOverrideConfigurationChanged() {
699 if (mParent != null) {
700 mParent.onDescendantOverrideConfigurationChanged();
701 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700702 }
703
704 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700705 * Notify that the display this container is on has changed. This could be either this container
706 * is moved to a new display, or some configurations on the display it is on changes.
707 *
708 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700709 */
710 void onDisplayChanged(DisplayContent dc) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800711 mDisplayContent = dc;
712 if (dc != null && dc != this) {
713 dc.getPendingTransaction().merge(mPendingTransaction);
714 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700715 for (int i = mChildren.size() - 1; i >= 0; --i) {
716 final WindowContainer child = mChildren.get(i);
717 child.onDisplayChanged(dc);
718 }
719 }
720
Tiger Huanged6794e2019-05-07 20:07:59 +0800721 DisplayContent getDisplayContent() {
722 return mDisplayContent;
723 }
724
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700725 void setWaitingForDrawnIfResizingChanged() {
726 for (int i = mChildren.size() - 1; i >= 0; --i) {
727 final WindowContainer wc = mChildren.get(i);
728 wc.setWaitingForDrawnIfResizingChanged();
729 }
730 }
731
732 void onResize() {
733 for (int i = mChildren.size() - 1; i >= 0; --i) {
734 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800735 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700736 }
737 }
738
Bryce Leed92ae482018-01-22 13:56:23 -0800739 void onParentResize() {
740 // In the case this container has specified its own bounds, a parent resize will not
741 // affect its bounds. Any relevant changes will be propagated through changes to the
742 // Configuration override.
743 if (hasOverrideBounds()) {
744 return;
745 }
746
747 // Default implementation is to treat as resize on self.
748 onResize();
749 }
750
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700751 void onMovedByResize() {
752 for (int i = mChildren.size() - 1; i >= 0; --i) {
753 final WindowContainer wc = mChildren.get(i);
754 wc.onMovedByResize();
755 }
756 }
757
758 void resetDragResizingChangeReported() {
759 for (int i = mChildren.size() - 1; i >= 0; --i) {
760 final WindowContainer wc = mChildren.get(i);
761 wc.resetDragResizingChangeReported();
762 }
763 }
764
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700765 void forceWindowsScaleableInTransaction(boolean force) {
766 for (int i = mChildren.size() - 1; i >= 0; --i) {
767 final WindowContainer wc = mChildren.get(i);
768 wc.forceWindowsScaleableInTransaction(force);
769 }
770 }
771
Jorim Jaggia5e10572017-11-15 14:36:26 +0100772 /**
lumark9bca6b42019-10-17 18:35:22 +0800773 * @return {@code true} when this container or its related containers are running an
774 * animation, {@code false} otherwise.
775 *
776 * By default this predicate only checks if this container itself is actually running an
777 * animation, but you can extend the check target over its relatives, or relax the condition
778 * so that this can return {@code true} if an animation starts soon by giving a combination
779 * of {@link #AnimationFlags}.
780 *
781 * Note that you can give a combination of bitmask flags to specify targets and condition for
782 * checking animating status.
783 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
784 * container itself or one of its parents is running an animation or waiting for an app
785 * transition.
786 *
787 * Note that TRANSITION propagates to parents and children as well.
788 *
789 * {@see AnimationFlags#TRANSITION}
790 * {@see AnimationFlags#PARENTS}
791 * {@see AnimationFlags#CHILDREN}
Jorim Jaggia5e10572017-11-15 14:36:26 +0100792 */
Jorim Jaggi924ef752020-01-29 17:26:55 +0100793 boolean isAnimating(int flags) {
lumark9bca6b42019-10-17 18:35:22 +0800794 if (mSurfaceAnimator.isAnimating()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100795 return true;
796 }
lumark9bca6b42019-10-17 18:35:22 +0800797 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
798 return true;
799 }
800 if ((flags & PARENTS) != 0) {
801 final WindowContainer parent = getParent();
802 if (parent != null && parent.isAnimating(flags & ~CHILDREN)) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700803 return true;
804 }
805 }
lumark9bca6b42019-10-17 18:35:22 +0800806 if ((flags & CHILDREN) != 0) {
807 for (int i = 0; i < mChildren.size(); ++i) {
808 final WindowContainer wc = mChildren.get(i);
809 if (wc.isAnimating(flags & ~PARENTS)) {
810 return true;
811 }
812 }
813 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700814 return false;
815 }
816
Jorim Jaggia5e10572017-11-15 14:36:26 +0100817 /**
lumark9bca6b42019-10-17 18:35:22 +0800818 * @return {@code true} when the container is waiting the app transition start, {@code false}
819 * otherwise.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100820 */
lumark9bca6b42019-10-17 18:35:22 +0800821 boolean isWaitingForTransitionStart() {
lumark52d5f422020-01-06 16:17:55 +0800822 return false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100823 }
824
825 /**
lumark9bca6b42019-10-17 18:35:22 +0800826 * @return {@code true} if in this subtree of the hierarchy we have an
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800827 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200828 */
lumark9bca6b42019-10-17 18:35:22 +0800829 boolean isAppTransitioning() {
lumark5341d1c2019-12-14 01:54:02 +0800830 return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200831 }
832
833 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100834 * @return Whether our own container running an animation at the moment.
835 */
lumark9bca6b42019-10-17 18:35:22 +0800836 final boolean isAnimating() {
837 return isAnimating(0 /* self only */);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100838 }
839
lumark19a5d2e2019-10-11 16:19:30 +0800840 /**
841 * @return {@code true} if the container is in changing app transition.
842 */
843 boolean isChangingAppTransition() {
Evan Rosky55bddd82020-01-29 13:07:18 -0800844 return mDisplayContent != null && mDisplayContent.mChangingContainers.contains(this);
lumark19a5d2e2019-10-11 16:19:30 +0800845 }
846
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700847 void sendAppVisibilityToClients() {
848 for (int i = mChildren.size() - 1; i >= 0; --i) {
849 final WindowContainer wc = mChildren.get(i);
850 wc.sendAppVisibilityToClients();
851 }
852 }
853
Wale Ogunwale44f21802016-09-02 12:49:48 -0700854 /**
855 * Returns true if the container or one of its children as some content it can display or wants
856 * to display (e.g. app views or saved surface).
857 *
858 * NOTE: While this method will return true if the there is some content to display, it doesn't
859 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
860 * visible.
861 */
862 boolean hasContentToDisplay() {
863 for (int i = mChildren.size() - 1; i >= 0; --i) {
864 final WindowContainer wc = mChildren.get(i);
865 if (wc.hasContentToDisplay()) {
866 return true;
867 }
868 }
869 return false;
870 }
871
872 /**
873 * Returns true if the container or one of its children is considered visible from the
874 * WindowManager perspective which usually means valid surface and some other internal state
875 * are true.
876 *
877 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
878 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
879 * the container has any content to display.
880 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700881 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700882 // TODO: Will this be more correct if it checks the visibility of its parents?
883 // It depends...For example, Tasks and Stacks are only visible if there children are visible
884 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800885 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700886 for (int i = mChildren.size() - 1; i >= 0; --i) {
887 final WindowContainer wc = mChildren.get(i);
888 if (wc.isVisible()) {
889 return true;
890 }
891 }
892 return false;
893 }
894
Evan Roskya80f11c2020-01-23 19:17:10 -0800895 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800896 * Called when the visibility of a child is asked to change. This is before visibility actually
897 * changes (eg. a transition animation might play out first).
898 */
899 void onChildVisibilityRequested(boolean visible) {
900 // If we are changing visibility, then a snapshot isn't necessary and we are no-longer
901 // part of a change transition.
902 mSurfaceFreezer.unfreeze(getPendingTransaction());
903 if (mDisplayContent != null) {
904 mDisplayContent.mChangingContainers.remove(this);
905 }
906 WindowContainer parent = getParent();
907 if (parent != null) {
908 parent.onChildVisibilityRequested(visible);
909 }
910 }
911
912 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
913 final long token = proto.start(fieldId);
914 proto.write(HASH_CODE, System.identityHashCode(this));
915 proto.write(USER_ID, USER_NULL);
916 proto.write(TITLE, "WindowContainer");
917 proto.end(token);
918 }
919
920 /**
Evan Roskya80f11c2020-01-23 19:17:10 -0800921 * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
922 * this will not be focusable either.
923 */
Evan Rosky226de132020-01-03 18:00:29 -0800924 boolean isFocusable() {
Evan Roskya80f11c2020-01-23 19:17:10 -0800925 final WindowContainer parent = getParent();
926 return (parent == null || parent.isFocusable()) && mIsFocusable;
Evan Rosky226de132020-01-03 18:00:29 -0800927 }
928
929 /** Set whether this container or its children can be focusable */
Evan Rosky226de132020-01-03 18:00:29 -0800930 boolean setFocusable(boolean focusable) {
931 if (mIsFocusable == focusable) {
932 return false;
933 }
934 mIsFocusable = focusable;
935 return true;
936 }
937
Bryce Lee00d586d2017-07-28 20:48:43 -0700938 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700939 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700940 */
941 boolean isOnTop() {
942 return getParent().getTopChild() == this && getParent().isOnTop();
943 }
944
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100945 /** Returns the top child container. */
946 E getTopChild() {
947 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700948 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700949
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700950 /** Returns true if there is still a removal being deferred */
951 boolean checkCompleteDeferredRemoval() {
952 boolean stillDeferringRemoval = false;
953
954 for (int i = mChildren.size() - 1; i >= 0; --i) {
955 final WindowContainer wc = mChildren.get(i);
956 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
957 }
958
959 return stillDeferringRemoval;
960 }
961
962 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700963 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700964 for (int i = mChildren.size() - 1; i >= 0; --i) {
965 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700966 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700967 }
968 }
969
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700970 void onAppTransitionDone() {
971 for (int i = mChildren.size() - 1; i >= 0; --i) {
972 final WindowContainer wc = mChildren.get(i);
973 wc.onAppTransitionDone();
974 }
975 }
976
Garfield Tan90b04282018-12-11 14:04:42 -0800977 /**
978 * Called when this container or one of its descendants changed its requested orientation, and
979 * wants this container to handle it or pass it to its parent.
980 *
981 * @param freezeDisplayToken freeze this app window token if display needs to freeze
982 * @param requestingContainer the container which orientation request has changed
983 * @return {@code true} if handled; {@code false} otherwise.
984 */
985 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
986 @Nullable ConfigurationContainer requestingContainer) {
987 final WindowContainer parent = getParent();
988 if (parent == null) {
989 return false;
990 }
991 return parent.onDescendantOrientationChanged(freezeDisplayToken,
992 requestingContainer);
993 }
994
995 /**
Garfield Tan49dae102019-02-04 09:51:59 -0800996 * Check if this container or its parent will handle orientation changes from descendants. It's
997 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
998 * ConfigurationContainer)} in the sense that the return value of this method tells if this
999 * container or its parent will handle the request eventually, while the return value of the
1000 * other method is if it handled the request synchronously.
1001 *
1002 * @return {@code true} if it handles or will handle orientation change in the future; {@code
1003 * false} if it won't handle the change at anytime.
1004 */
1005 boolean handlesOrientationChangeFromDescendant() {
1006 final WindowContainer parent = getParent();
1007 return parent != null && parent.handlesOrientationChangeFromDescendant();
1008 }
1009
1010 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001011 * Get the configuration orientation by the requested screen orientation
1012 * ({@link ActivityInfo.ScreenOrientation}) of this activity.
1013 *
1014 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
1015 * {@link Configuration#ORIENTATION_PORTRAIT},
1016 * {@link Configuration#ORIENTATION_UNDEFINED}).
1017 */
1018 int getRequestedConfigurationOrientation() {
1019 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
1020 // NOSENSOR means the display's "natural" orientation, so return that.
1021 if (mDisplayContent != null) {
1022 return mDisplayContent.getNaturalOrientation();
1023 }
1024 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
1025 // LOCKED means the activity's orientation remains unchanged, so return existing value.
1026 return getConfiguration().orientation;
1027 } else if (isFixedOrientationLandscape(mOrientation)) {
1028 return ORIENTATION_LANDSCAPE;
1029 } else if (isFixedOrientationPortrait(mOrientation)) {
1030 return ORIENTATION_PORTRAIT;
1031 }
1032 return ORIENTATION_UNDEFINED;
1033 }
1034
1035 /**
Garfield Tan90b04282018-12-11 14:04:42 -08001036 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
1037 * parameters.
1038 *
1039 * @param orientation the specified orientation.
1040 */
Wale Ogunwale51362492016-09-08 17:49:17 -07001041 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001042 setOrientation(orientation, null /* freezeDisplayToken */,
1043 null /* ActivityRecord */);
1044 }
1045
1046 /**
1047 * Sets the specified orientation of this container. It percolates this change upward along the
1048 * hierarchy to let each level of the hierarchy a chance to respond to it.
1049 *
1050 * @param orientation the specified orientation. Needs to be one of {@link
1051 * android.content.pm.ActivityInfo.ScreenOrientation}.
1052 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
1053 * done. Display will not be frozen if this is {@code null}, which
1054 * should only happen in tests.
1055 * @param requestingContainer the container which orientation request has changed. Mostly used
1056 * to ensure it gets correct configuration.
1057 */
1058 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
1059 @Nullable ConfigurationContainer requestingContainer) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001060 if (mOrientation == orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001061 return;
1062 }
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001063
1064 mOrientation = orientation;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001065 final int configOrientation = getRequestedConfigurationOrientation();
1066 if (getRequestedOverrideConfiguration().orientation != configOrientation) {
1067 mTmpConfig.setTo(getRequestedOverrideConfiguration());
1068 mTmpConfig.orientation = configOrientation;
1069 onRequestedOverrideConfigurationChanged(mTmpConfig);
1070 }
1071
Garfield Tan90b04282018-12-11 14:04:42 -08001072 final WindowContainer parent = getParent();
1073 if (parent != null) {
1074 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
1075 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001076 }
1077
Vadim Caen1096f112019-12-18 11:44:26 +01001078 @ActivityInfo.ScreenOrientation
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001079 int getOrientation() {
1080 return getOrientation(mOrientation);
1081 }
1082
Wale Ogunwale51362492016-09-08 17:49:17 -07001083 /**
1084 * Returns the specified orientation for this window container or one of its children is there
1085 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
1086 * specification is set.
1087 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
1088 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001089 *
1090 * @param candidate The current orientation candidate that will be returned if we don't find a
1091 * better match.
1092 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -07001093 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001094 int getOrientation(int candidate) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001095 mLastOrientationSource = null;
Bryce Leea163b762017-01-24 11:05:01 -08001096 if (!fillsParent()) {
1097 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -07001098 return SCREEN_ORIENTATION_UNSET;
1099 }
1100
Bryce Leea163b762017-01-24 11:05:01 -08001101 // The container fills its parent so we can use it orientation if it has one
1102 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -07001103 // specified and fall back on this container's unset or unspecified value as a candidate
1104 // if none of the children have a better candidate for the orientation.
1105 if (mOrientation != SCREEN_ORIENTATION_UNSET
1106 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001107 mLastOrientationSource = this;
Wale Ogunwale51362492016-09-08 17:49:17 -07001108 return mOrientation;
1109 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001110
1111 for (int i = mChildren.size() - 1; i >= 0; --i) {
1112 final WindowContainer wc = mChildren.get(i);
1113
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001114 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
1115 // SCREEN_ORIENTATION_UNSPECIFIED?
1116 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
1117 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -07001118 if (orientation == SCREEN_ORIENTATION_BEHIND) {
1119 // container wants us to use the orientation of the container behind it. See if we
1120 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
1121 // look behind this container.
1122 candidate = orientation;
Riddle Hsu6f548e92020-01-13 13:34:09 +08001123 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001124 continue;
1125 }
1126
1127 if (orientation == SCREEN_ORIENTATION_UNSET) {
1128 continue;
1129 }
1130
1131 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1132 // Use the orientation if the container fills its parent or requested an explicit
1133 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
Vadim Caenfc14c662020-01-20 16:00:31 +01001134 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
1135 wc.toString(), orientation,
1136 ActivityInfo.screenOrientationToString(orientation));
Riddle Hsu6f548e92020-01-13 13:34:09 +08001137 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001138 return orientation;
1139 }
1140 }
1141
1142 return candidate;
1143 }
1144
1145 /**
Riddle Hsu6f548e92020-01-13 13:34:09 +08001146 * @return The deepest source which decides the orientation of this window container since the
1147 * last time {@link #getOrientation(int) was called.
1148 */
1149 @Nullable
1150 WindowContainer getLastOrientationSource() {
1151 final WindowContainer source = mLastOrientationSource;
1152 if (source != null && source != this) {
1153 final WindowContainer nextSource = source.getLastOrientationSource();
1154 if (nextSource != null) {
1155 return nextSource;
1156 }
1157 }
1158 return source;
1159 }
1160
1161 /**
Wale Ogunwale51362492016-09-08 17:49:17 -07001162 * Returns true if this container is opaque and fills all the space made available by its parent
1163 * container.
1164 *
1165 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
1166 * this is just a signal from the client to window manager stating its intent, but not what it
1167 * actually does.
1168 */
1169 boolean fillsParent() {
1170 return false;
1171 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001172
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001173 // TODO: Users would have their own window containers under the display container?
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001174 void switchUser(int userId) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001175 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001176 mChildren.get(i).switchUser(userId);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001177 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001178 }
1179
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08001180 boolean showToCurrentUser() {
1181 return true;
1182 }
1183
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001184 /**
1185 * For all windows at or below this container call the callback.
1186 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
1187 * stops the search if {@link ToBooleanFunction#apply} returns true.
1188 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
1189 * z-order, else from bottom-to-top.
1190 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -08001191 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001192 */
1193 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001194 if (traverseTopToBottom) {
1195 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001196 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1197 return true;
1198 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001199 }
1200 } else {
1201 final int count = mChildren.size();
1202 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001203 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1204 return true;
1205 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001206 }
1207 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001208 return false;
1209 }
1210
1211 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001212 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
1213 forAllWindows(wrapper, traverseTopToBottom);
1214 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001215 }
1216
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001217 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001218 return forAllActivities(callback, true /*traverseTopToBottom*/);
1219 }
1220
1221 boolean forAllActivities(
1222 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
1223 if (traverseTopToBottom) {
1224 for (int i = mChildren.size() - 1; i >= 0; --i) {
1225 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
1226 }
1227 } else {
1228 final int count = mChildren.size();
1229 for (int i = 0; i < count; i++) {
1230 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
lumark9bca6b42019-10-17 18:35:22 +08001231 }
lumark588a3e82018-07-20 18:53:54 +08001232 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001233
lumark9bca6b42019-10-17 18:35:22 +08001234 return false;
lumark588a3e82018-07-20 18:53:54 +08001235 }
1236
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001237 void forAllActivities(Consumer<ActivityRecord> callback) {
1238 forAllActivities(callback, true /*traverseTopToBottom*/);
1239 }
1240
1241 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
1242 if (traverseTopToBottom) {
1243 for (int i = mChildren.size() - 1; i >= 0; --i) {
1244 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1245 }
1246 } else {
1247 final int count = mChildren.size();
1248 for (int i = 0; i < count; i++) {
1249 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1250 }
1251 }
1252 }
1253
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001254 /**
1255 * Process all activities in this branch of the tree.
1256 *
1257 * @param callback Called for each activity found.
1258 * @param boundary We don't return activities via {@param callback} until we get to this node in
1259 * the tree.
1260 * @param includeBoundary If the boundary from be processed to return activities.
1261 * @param traverseTopToBottom direction to traverse the tree.
1262 * @return {@code true} if we ended the search before reaching the end of the tree.
1263 */
1264 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1265 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1266 return forAllActivities(
1267 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1268 }
1269
1270 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1271 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1272 boolean[] boundaryFound) {
1273 if (traverseTopToBottom) {
1274 for (int i = mChildren.size() - 1; i >= 0; --i) {
1275 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1276 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1277 return true;
1278 }
1279 }
1280 } else {
1281 final int count = mChildren.size();
1282 for (int i = 0; i < count; i++) {
1283 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1284 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1285 return true;
1286 }
1287 }
1288 }
1289
1290 return false;
1291 }
1292
1293 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
1294 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1295 boolean[] boundaryFound, WindowContainer wc) {
1296 if (wc == boundary) {
1297 boundaryFound[0] = true;
1298 if (!includeBoundary) return false;
1299 }
1300
1301 if (boundaryFound[0]) {
1302 return wc.forAllActivities(callback, traverseTopToBottom);
1303 }
1304
1305 return wc.forAllActivities(
1306 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1307 }
1308
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001309 /** @return {@code true} if this node or any of its children contains an activity. */
1310 boolean hasActivity() {
1311 for (int i = mChildren.size() - 1; i >= 0; --i) {
1312 if (mChildren.get(i).hasActivity()) {
1313 return true;
1314 }
1315 }
1316 return false;
1317 }
1318
1319 ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
1320 return getActivity(callback, true /*traverseTopToBottom*/);
1321 }
1322
1323 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001324 return getActivity(callback, traverseTopToBottom, null /*boundary*/);
1325 }
1326
1327 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
1328 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001329 if (traverseTopToBottom) {
1330 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001331 final WindowContainer wc = mChildren.get(i);
1332 if (wc == boundary) return null;
1333
1334 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001335 if (r != null) {
1336 return r;
1337 }
1338 }
1339 } else {
1340 final int count = mChildren.size();
1341 for (int i = 0; i < count; i++) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001342 final WindowContainer wc = mChildren.get(i);
1343 if (wc == boundary) return null;
1344
1345 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001346 if (r != null) {
1347 return r;
1348 }
1349 }
1350 }
1351
1352 return null;
1353 }
1354
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001355 /**
1356 * Gets an activity in a branch of the tree.
1357 *
1358 * @param callback called to test if this is the activity that should be returned.
1359 * @param boundary We don't return activities via {@param callback} until we get to this node in
1360 * the tree.
1361 * @param includeBoundary If the boundary from be processed to return activities.
1362 * @param traverseTopToBottom direction to traverse the tree.
1363 * @return The activity if found or null.
1364 */
1365 final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1366 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1367 return getActivity(
1368 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1369 }
1370
1371 private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1372 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1373 boolean[] boundaryFound) {
1374 if (traverseTopToBottom) {
1375 for (int i = mChildren.size() - 1; i >= 0; --i) {
1376 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1377 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1378 if (r != null) {
1379 return r;
1380 }
1381 }
1382 } else {
1383 final int count = mChildren.size();
1384 for (int i = 0; i < count; i++) {
1385 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1386 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1387 if (r != null) {
1388 return r;
1389 }
1390 }
1391 }
1392
1393 return null;
1394 }
1395
1396 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
1397 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1398 boolean[] boundaryFound, WindowContainer wc) {
1399 if (wc == boundary || boundary == null) {
1400 boundaryFound[0] = true;
1401 if (!includeBoundary) return null;
1402 }
1403
1404 if (boundaryFound[0]) {
1405 return wc.getActivity(callback, traverseTopToBottom);
1406 }
1407
1408 return wc.getActivity(
1409 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1410 }
1411
1412 ActivityRecord getActivityAbove(ActivityRecord r) {
1413 return getActivity((above) -> true, r,
1414 false /*includeBoundary*/, false /*traverseTopToBottom*/);
1415 }
1416
1417 ActivityRecord getActivityBelow(ActivityRecord r) {
1418 return getActivity((below) -> true, r,
1419 false /*includeBoundary*/, true /*traverseTopToBottom*/);
1420 }
1421
1422 ActivityRecord getBottomMostActivity() {
1423 return getActivity((r) -> true, false /*traverseTopToBottom*/);
1424 }
1425
1426 ActivityRecord getTopMostActivity() {
1427 return getActivity((r) -> true, true /*traverseTopToBottom*/);
1428 }
1429
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001430 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
1431 // Break down into 4 calls to avoid object creation due to capturing input params.
1432 if (includeFinishing) {
1433 if (includeOverlays) {
1434 return getActivity((r) -> true);
1435 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001436 return getActivity((r) -> !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001437 } else if (includeOverlays) {
1438 return getActivity((r) -> !r.finishing);
1439 }
1440
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001441 return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001442 }
1443
Winson Chungd5852192019-09-06 17:20:28 -07001444 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
1445 for (int i = mChildren.size() - 1; i >= 0; --i) {
1446 mChildren.get(i).forAllWallpaperWindows(callback);
1447 }
1448 }
1449
Jorim Jaggi51304d72017-05-17 17:25:32 +02001450 /**
1451 * For all tasks at or below this container call the callback.
1452 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001453 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
1454 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
1455 */
1456 boolean forAllTasks(Function<Task, Boolean> callback) {
1457 for (int i = mChildren.size() - 1; i >= 0; --i) {
1458 if (mChildren.get(i).forAllTasks(callback)) {
1459 return true;
1460 }
1461 }
1462 return false;
1463 }
1464
1465 /**
1466 * For all tasks at or below this container call the callback.
1467 *
Jorim Jaggi51304d72017-05-17 17:25:32 +02001468 * @param callback Callback to be called for every task.
1469 */
1470 void forAllTasks(Consumer<Task> callback) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001471 forAllTasks(callback, true /*traverseTopToBottom*/);
1472 }
1473
1474 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
1475 final int count = mChildren.size();
1476 if (traverseTopToBottom) {
1477 for (int i = count - 1; i >= 0; --i) {
1478 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1479 }
1480 } else {
1481 for (int i = 0; i < count; i++) {
1482 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1483 }
Jorim Jaggi51304d72017-05-17 17:25:32 +02001484 }
1485 }
1486
Wale Ogunwale0d465192020-01-23 19:14:44 -08001487 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Jeff Changdc9c1d42020-02-11 14:57:34 +08001488 final int count = mChildren.size();
1489 if (traverseTopToBottom) {
1490 for (int i = count - 1; i >= 0; --i) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001491 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001492 }
1493 } else {
1494 for (int i = 0; i < count; i++) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001495 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001496 }
1497 }
1498 }
1499
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001500 Task getTaskAbove(Task t) {
1501 return getTask(
1502 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
1503 }
1504
1505 Task getTaskBelow(Task t) {
1506 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/);
1507 }
1508
1509 Task getBottomMostTask() {
1510 return getTask((t) -> true, false /*traverseTopToBottom*/);
1511 }
1512
1513 Task getTopMostTask() {
1514 return getTask((t) -> true, true /*traverseTopToBottom*/);
1515 }
1516
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001517 Task getTask(Predicate<Task> callback) {
1518 return getTask(callback, true /*traverseTopToBottom*/);
1519 }
1520
1521 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
1522 if (traverseTopToBottom) {
1523 for (int i = mChildren.size() - 1; i >= 0; --i) {
1524 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1525 if (t != null) {
1526 return t;
1527 }
1528 }
1529 } else {
1530 final int count = mChildren.size();
1531 for (int i = 0; i < count; i++) {
1532 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1533 if (t != null) {
1534 return t;
1535 }
1536 }
1537 }
1538
1539 return null;
1540 }
1541
lumarkbc0032a2019-11-01 21:38:13 +08001542 /**
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001543 * Gets an task in a branch of the tree.
lumarkbc0032a2019-11-01 21:38:13 +08001544 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001545 * @param callback called to test if this is the task that should be returned.
1546 * @param boundary We don't return tasks via {@param callback} until we get to this node in
1547 * the tree.
1548 * @param includeBoundary If the boundary from be processed to return tasks.
1549 * @param traverseTopToBottom direction to traverse the tree.
1550 * @return The task if found or null.
lumarkbc0032a2019-11-01 21:38:13 +08001551 */
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001552 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary,
1553 boolean traverseTopToBottom) {
1554 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1555 }
1556
1557 private Task getTask(Predicate<Task> callback,
1558 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1559 boolean[] boundaryFound) {
1560 if (traverseTopToBottom) {
1561 for (int i = mChildren.size() - 1; i >= 0; --i) {
1562 final Task t = processGetTaskWithBoundary(callback, boundary,
1563 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1564 if (t != null) {
1565 return t;
1566 }
1567 }
1568 } else {
1569 final int count = mChildren.size();
1570 for (int i = 0; i < count; i++) {
1571 final Task t = processGetTaskWithBoundary(callback, boundary,
1572 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1573 if (t != null) {
1574 return t;
1575 }
lumarkbc0032a2019-11-01 21:38:13 +08001576 }
1577 }
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001578
1579 return null;
1580 }
1581
1582 private Task processGetTaskWithBoundary(Predicate<Task> callback,
1583 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1584 boolean[] boundaryFound, WindowContainer wc) {
1585 if (wc == boundary || boundary == null) {
1586 boundaryFound[0] = true;
1587 if (!includeBoundary) return null;
1588 }
1589
1590 if (boundaryFound[0]) {
1591 return wc.getTask(callback, traverseTopToBottom);
1592 }
1593
1594 return wc.getTask(
1595 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
lumarkbc0032a2019-11-01 21:38:13 +08001596 }
1597
Wale Ogunwaled1880962016-11-08 10:31:59 -08001598 WindowState getWindow(Predicate<WindowState> callback) {
1599 for (int i = mChildren.size() - 1; i >= 0; --i) {
1600 final WindowState w = mChildren.get(i).getWindow(callback);
1601 if (w != null) {
1602 return w;
1603 }
1604 }
1605
1606 return null;
1607 }
1608
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001609 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -07001610 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
1611 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001612 */
1613 @Override
1614 public int compareTo(WindowContainer other) {
1615 if (this == other) {
1616 return 0;
1617 }
1618
1619 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +02001620 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001621 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
1622 }
1623
1624 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
1625 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001626 try {
1627 getParents(thisParentChain);
1628 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001629
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001630 // Find the common ancestor of both containers.
1631 WindowContainer commonAncestor = null;
1632 WindowContainer thisTop = thisParentChain.peekLast();
1633 WindowContainer otherTop = otherParentChain.peekLast();
1634 while (thisTop != null && otherTop != null && thisTop == otherTop) {
1635 commonAncestor = thisParentChain.removeLast();
1636 otherParentChain.removeLast();
1637 thisTop = thisParentChain.peekLast();
1638 otherTop = otherParentChain.peekLast();
1639 }
1640
1641 // Containers don't belong to the same hierarchy???
1642 if (commonAncestor == null) {
1643 throw new IllegalArgumentException("No in the same hierarchy this="
1644 + thisParentChain + " other=" + otherParentChain);
1645 }
1646
1647 // Children are always considered greater than their parents, so if one of the containers
1648 // we are comparing it the parent of the other then whichever is the child is greater.
1649 if (commonAncestor == this) {
1650 return -1;
1651 } else if (commonAncestor == other) {
1652 return 1;
1653 }
1654
1655 // The position of the first non-common ancestor in the common ancestor list determines
1656 // which is greater the which.
1657 final WindowList<WindowContainer> list = commonAncestor.mChildren;
1658 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
1659 ? 1 : -1;
1660 } finally {
1661 mTmpChain1.clear();
1662 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001663 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001664 }
1665
1666 private void getParents(LinkedList<WindowContainer> parents) {
1667 parents.clear();
1668 WindowContainer current = this;
1669 do {
1670 parents.addLast(current);
1671 current = current.mParent;
1672 } while (current != null);
1673 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001674
Robert Carrb1579c82017-09-05 14:54:47 -07001675 SurfaceControl.Builder makeSurface() {
1676 final WindowContainer p = getParent();
1677 return p.makeChildSurface(this);
1678 }
1679
Robert Carrf59b8dd2017-10-02 18:58:36 -07001680 /**
1681 * @param child The WindowContainer this child surface is for, or null if the Surface
1682 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1683 */
Robert Carrb1579c82017-09-05 14:54:47 -07001684 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1685 final WindowContainer p = getParent();
1686 // Give the parent a chance to set properties. In hierarchy v1 we rely
1687 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001688 return p.makeChildSurface(child)
1689 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001690 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001691 /*
1692 * @return The SurfaceControl parent for this containers SurfaceControl.
1693 * The SurfaceControl must be valid if non-null.
1694 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001695 @Override
1696 public SurfaceControl getParentSurfaceControl() {
1697 final WindowContainer parent = getParent();
1698 if (parent == null) {
1699 return null;
1700 }
1701 return parent.getSurfaceControl();
1702 }
1703
Robert Carrb1579c82017-09-05 14:54:47 -07001704 /**
1705 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1706 */
1707 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001708 if (mSurfaceControl == null) {
1709 return false;
1710 }
1711
Robert Carrb1579c82017-09-05 14:54:47 -07001712 for (int i = 0; i < mChildren.size(); i++) {
1713 if (!mChildren.get(i).shouldMagnify()) {
1714 return false;
1715 }
1716 }
1717 return true;
1718 }
1719
1720 SurfaceSession getSession() {
1721 if (getParent() != null) {
1722 return getParent().getSession();
1723 }
1724 return null;
1725 }
1726
1727 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001728 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1729 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001730 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001731 mLastLayer = layer;
1732 mLastRelativeToLayer = null;
1733 }
1734 }
1735
1736 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1737 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1738 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001739 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001740 mLastLayer = layer;
1741 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001742 }
1743 }
1744
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001745 protected void setLayer(Transaction t, int layer) {
1746
1747 // Route through surface animator to accommodate that our surface control might be
1748 // attached to the leash, and leash is attached to parent container.
1749 mSurfaceAnimator.setLayer(t, layer);
1750 }
1751
1752 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1753
1754 // Route through surface animator to accommodate that our surface control might be
1755 // attached to the leash, and leash is attached to parent container.
1756 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1757 }
1758
1759 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1760 mSurfaceAnimator.reparent(t, newParent);
1761 }
1762
Robert Carrb1579c82017-09-05 14:54:47 -07001763 void assignChildLayers(Transaction t) {
1764 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001765
1766 // We use two passes as a way to promote children which
1767 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001768 for (int j = 0; j < mChildren.size(); ++j) {
1769 final WindowContainer wc = mChildren.get(j);
1770 wc.assignChildLayers(t);
1771 if (!wc.needsZBoost()) {
1772 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001773 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001774 }
1775 for (int j = 0; j < mChildren.size(); ++j) {
1776 final WindowContainer wc = mChildren.get(j);
1777 if (wc.needsZBoost()) {
1778 wc.assignLayer(t, layer++);
1779 }
Robert Carrb1579c82017-09-05 14:54:47 -07001780 }
1781 }
1782
1783 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001784 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001785 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001786 }
1787
1788 boolean needsZBoost() {
1789 for (int i = 0; i < mChildren.size(); i++) {
1790 if (mChildren.get(i).needsZBoost()) {
1791 return true;
1792 }
1793 }
1794 return false;
1795 }
1796
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001797 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001798 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001799 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001800 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001801 * @param proto Stream to write the WindowContainer object to.
1802 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001803 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001804 * @hide
1805 */
1806 @CallSuper
1807 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08001808 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001809 @WindowTraceLogLevel int logLevel) {
1810 boolean isVisible = isVisible();
1811 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1812 return;
1813 }
1814
Adrian Roos4921ccf2017-09-28 16:54:06 +02001815 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001816 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001817 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001818 proto.write(VISIBLE, isVisible);
1819 if (mSurfaceAnimator.isAnimating()) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001820 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001821 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001822 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001823 }
1824
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001825 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1826 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1827 if (wrapper == null) {
1828 wrapper = new ForAllWindowsConsumerWrapper();
1829 }
1830 wrapper.setConsumer(consumer);
1831 return wrapper;
1832 }
1833
1834 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1835
1836 private Consumer<WindowState> mConsumer;
1837
1838 void setConsumer(Consumer<WindowState> consumer) {
1839 mConsumer = consumer;
1840 }
1841
1842 @Override
1843 public boolean apply(WindowState w) {
1844 mConsumer.accept(w);
1845 return false;
1846 }
1847
1848 void release() {
1849 mConsumer = null;
1850 mConsumerWrapperPool.release(this);
1851 }
1852 }
Robert Carrb1579c82017-09-05 14:54:47 -07001853
1854 // TODO(b/68336570): Should this really be on WindowContainer since it
1855 // can only be used on the top-level nodes that aren't animated?
1856 // (otherwise we would be fighting other callers of setMatrix).
1857 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1858 if (shouldMagnify()) {
1859 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1860 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
Robert Carr7603dea2019-07-17 13:16:21 -07001861 mLastMagnificationSpec = spec;
Robert Carrb1579c82017-09-05 14:54:47 -07001862 } else {
Jackal Guoa8b3a272019-12-16 15:24:58 +08001863 clearMagnificationSpec(t);
Robert Carrb1579c82017-09-05 14:54:47 -07001864 for (int i = 0; i < mChildren.size(); i++) {
1865 mChildren.get(i).applyMagnificationSpec(t, spec);
1866 }
1867 }
1868 }
1869
Robert Carr7603dea2019-07-17 13:16:21 -07001870 void clearMagnificationSpec(Transaction t) {
1871 if (mLastMagnificationSpec != null) {
1872 t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
1873 .setPosition(mSurfaceControl, 0, 0);
1874 }
1875 mLastMagnificationSpec = null;
1876 for (int i = 0; i < mChildren.size(); i++) {
1877 mChildren.get(i).clearMagnificationSpec(t);
1878 }
1879 }
1880
Robert Carrb1579c82017-09-05 14:54:47 -07001881 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08001882 // If a leash has been set when the transaction was committed, then the leash reparent has
1883 // been committed.
1884 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001885 for (int i = 0; i < mChildren.size(); i++) {
1886 mChildren.get(i).prepareSurfaces();
1887 }
1888 }
1889
1890 /**
chaviw7f1fa992018-01-10 13:52:12 -08001891 * @return true if the reparent to animation leash transaction has been committed, false
1892 * otherwise.
1893 */
1894 boolean hasCommittedReparentToAnimationLeash() {
1895 return mCommittedReparentToAnimationLeash;
1896 }
1897
1898 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08001899 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1900 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07001901 */
1902 void scheduleAnimation() {
1903 if (mParent != null) {
1904 mParent.scheduleAnimation();
1905 }
1906 }
1907
Robert Carrdea7bf42019-04-04 12:02:51 -07001908 /**
1909 * @return The SurfaceControl for this container.
1910 * The SurfaceControl must be valid if non-null.
1911 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001912 @Override
1913 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001914 return mSurfaceControl;
1915 }
1916
Jorim Jaggia5e10572017-11-15 14:36:26 +01001917 @Override
1918 public Transaction getPendingTransaction() {
Robert Carre10ee3d2019-11-11 15:03:15 -08001919 if (mUsingBLASTSyncTransaction) {
1920 return mBLASTSyncTransaction;
1921 }
1922
Tiger Huanged6794e2019-05-07 20:07:59 +08001923 final DisplayContent displayContent = getDisplayContent();
1924 if (displayContent != null && displayContent != this) {
1925 return displayContent.getPendingTransaction();
1926 }
1927 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1928 // let the caller to save the surface operations within the local mPendingTransaction.
1929 // If this is not a DisplayContent, we will merge it to the pending transaction of its
1930 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07001931 return mPendingTransaction;
1932 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001933
1934 /**
1935 * Starts an animation on the container.
1936 *
1937 * @param anim The animation to run.
1938 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1939 * some point but the meaning is too weird to work for all containers.
Issei Suzuki8b995df2020-01-08 12:23:04 +01001940 * @param type The type of animation defined as {@link AnimationType}.
Issei Suzuki2f541842020-01-09 20:18:29 +01001941 * @param animationFinishedCallback The callback being triggered when the animation finishes.
Jorim Jaggia5e10572017-11-15 14:36:26 +01001942 */
Issei Suzuki2f541842020-01-09 20:18:29 +01001943 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Issei Suzuki8b995df2020-01-08 12:23:04 +01001944 @AnimationType int type,
1945 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
1946 if (DEBUG_ANIM) {
1947 Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim);
1948 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001949
1950 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1951 // the moment this doesn't work for all animatable window containers.
Evan Rosky55bddd82020-01-29 13:07:18 -08001952 mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
1953 mSurfaceFreezer);
Issei Suzuki2f541842020-01-09 20:18:29 +01001954 }
1955
Issei Suzuki8b995df2020-01-08 12:23:04 +01001956 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
1957 @AnimationType int type) {
1958 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01001959 }
1960
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001961 void transferAnimation(WindowContainer from) {
1962 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1963 }
1964
Jorim Jaggia5e10572017-11-15 14:36:26 +01001965 void cancelAnimation() {
1966 mSurfaceAnimator.cancelAnimation();
1967 }
1968
1969 @Override
Evan Rosky55bddd82020-01-29 13:07:18 -08001970 public SurfaceControl getFreezeSnapshotTarget() {
1971 return null;
1972 }
1973
1974 @Override
Jorim Jaggia5e10572017-11-15 14:36:26 +01001975 public Builder makeAnimationLeash() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08001976 return makeSurface().setContainerLayer();
Jorim Jaggia5e10572017-11-15 14:36:26 +01001977 }
1978
Jorim Jaggi596a1992017-12-29 14:48:02 +01001979 @Override
1980 public SurfaceControl getAnimationLeashParent() {
1981 return getParentSurfaceControl();
1982 }
1983
chaviw23ee71c2017-12-18 11:29:41 -08001984 /**
1985 * @return The layer on which all app animations are happening.
1986 */
Jorim Jaggi391790622018-04-18 15:30:44 +02001987 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08001988 final WindowContainer parent = getParent();
1989 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02001990 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08001991 }
1992 return null;
1993 }
1994
lumark19a5d2e2019-10-11 16:19:30 +08001995 // TODO: Remove this and use #getBounds() instead once we set an app transition animation
1996 // on TaskStack.
1997 Rect getAnimationBounds(int appStackClipMode) {
lumark85718662019-12-26 22:05:12 +08001998 return getDisplayedBounds();
lumark19a5d2e2019-10-11 16:19:30 +08001999 }
2000
2001 /**
2002 * Applies the app transition animation according the given the layout properties in the
2003 * window hierarchy.
2004 *
2005 * @param lp The layout parameters of the window.
2006 * @param transit The app transition type indicates what kind of transition to be applied.
2007 * @param enter Whether the app transition is entering transition or not.
2008 * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
2009 *
2010 * @return {@code true} when the container applied the app transition, {@code false} if the
2011 * app transition is disabled or skipped.
2012 *
2013 * @see #getAnimationAdapter
2014 */
2015 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Issei Suzuki8b995df2020-01-08 12:23:04 +01002016 boolean isVoiceInteraction,
2017 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
lumark19a5d2e2019-10-11 16:19:30 +08002018 if (mWmService.mDisableTransitionAnimation) {
2019 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2020 "applyAnimation: transition animation is disabled or skipped. "
2021 + "container=%s", this);
2022 cancelAnimation();
2023 return false;
2024 }
2025
2026 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2027 // to animate and it can cause strange artifacts when we unfreeze the display if some
2028 // different animation is running.
2029 try {
2030 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
2031 if (okToAnimate()) {
lumarkbc0032a2019-11-01 21:38:13 +08002032 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
2033 transit, enter, isVoiceInteraction);
lumark19a5d2e2019-10-11 16:19:30 +08002034 AnimationAdapter adapter = adapters.first;
2035 AnimationAdapter thumbnailAdapter = adapters.second;
2036 if (adapter != null) {
Issei Suzuki2f541842020-01-09 20:18:29 +01002037 startAnimation(getPendingTransaction(), adapter, !isVisible(),
Issei Suzuki8b995df2020-01-08 12:23:04 +01002038 ANIMATION_TYPE_APP_TRANSITION, animationFinishedCallback);
lumark19a5d2e2019-10-11 16:19:30 +08002039 if (adapter.getShowWallpaper()) {
lumark5341d1c2019-12-14 01:54:02 +08002040 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
lumark19a5d2e2019-10-11 16:19:30 +08002041 }
2042 if (thumbnailAdapter != null) {
Evan Rosky55bddd82020-01-29 13:07:18 -08002043 mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
2044 thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION,
2045 (type, anim) -> { });
lumark19a5d2e2019-10-11 16:19:30 +08002046 }
2047 }
2048 } else {
2049 cancelAnimation();
2050 }
2051 } finally {
2052 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2053 }
2054
2055 return isAnimating();
2056 }
2057
2058 /**
2059 * Gets the {@link AnimationAdapter} according the given window layout properties in the window
2060 * hierarchy.
2061 *
2062 * @return The return value will always contain two elements, one for normal animations and the
2063 * other for thumbnail animation, both can be {@code null}.
2064 *
2065 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
2066 * @See LocalAnimationAdapter
2067 */
2068 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
2069 int transit, boolean enter, boolean isVoiceInteraction) {
2070 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
2071 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
2072
2073 // Separate position and size for use in animators.
2074 mTmpRect.set(getAnimationBounds(appStackClipMode));
lumark85718662019-12-26 22:05:12 +08002075 if (sHierarchicalAnimations) {
2076 getRelativeDisplayedPosition(mTmpPoint);
2077 } else {
2078 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2079 }
lumark19a5d2e2019-10-11 16:19:30 +08002080 mTmpRect.offsetTo(0, 0);
2081
2082 final RemoteAnimationController controller =
2083 getDisplayContent().mAppTransition.getRemoteAnimationController();
2084 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2085 && isChangingAppTransition();
2086
2087 // Delaying animation start isn't compatible with remote animations at all.
2088 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
2089 final RemoteAnimationController.RemoteAnimationRecord adapters =
2090 controller.createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
Evan Rosky55bddd82020-01-29 13:07:18 -08002091 (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
lumark19a5d2e2019-10-11 16:19:30 +08002092 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
2093 } else if (isChanging) {
2094 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
2095 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2096 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2097
lumarkbc0032a2019-11-01 21:38:13 +08002098 final AnimationAdapter adapter = new LocalAnimationAdapter(
Evan Rosky55bddd82020-01-29 13:07:18 -08002099 new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect,
2100 displayInfo, durationScale, true /* isAppAnimation */,
2101 false /* isThumbnail */),
lumark19a5d2e2019-10-11 16:19:30 +08002102 getSurfaceAnimationRunner());
2103
Evan Rosky55bddd82020-01-29 13:07:18 -08002104 final AnimationAdapter thumbnailAdapter = mSurfaceFreezer.mSnapshot != null
2105 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(
2106 mSurfaceFreezer.mFreezeBounds, mTmpRect, displayInfo, durationScale,
2107 true /* isAppAnimation */, true /* isThumbnail */), getSurfaceAnimationRunner())
lumarkbc0032a2019-11-01 21:38:13 +08002108 : null;
lumark19a5d2e2019-10-11 16:19:30 +08002109 resultAdapters = new Pair<>(adapter, thumbnailAdapter);
2110 mTransit = transit;
2111 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2112 } else {
2113 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2114 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2115
2116 if (a != null) {
2117 // Only apply corner radius to animation if we're not in multi window mode.
2118 // We don't want rounded corners when in pip or split screen.
2119 final float windowCornerRadius = !inMultiWindowMode()
2120 ? getDisplayContent().getWindowCornerRadius()
2121 : 0;
2122 AnimationAdapter adapter = new LocalAnimationAdapter(
2123 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
2124 getDisplayContent().mAppTransition.canSkipFirstFrame(),
2125 appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
2126 getSurfaceAnimationRunner());
2127
2128 resultAdapters = new Pair<>(adapter, null);
2129 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP;
2130 mTransit = transit;
2131 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2132 } else {
2133 resultAdapters = new Pair<>(null, null);
2134 }
2135 }
2136 return resultAdapters;
2137 }
2138
2139 final SurfaceAnimationRunner getSurfaceAnimationRunner() {
2140 return mWmService.mSurfaceAnimationRunner;
2141 }
2142
2143 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2144 boolean isVoiceInteraction) {
2145 final DisplayContent displayContent = getDisplayContent();
2146 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2147 final int width = displayInfo.appWidth;
2148 final int height = displayInfo.appHeight;
2149 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
2150
2151 // Determine the visible rect to calculate the thumbnail clip with
2152 // getAnimationFrames.
2153 final Rect frame = new Rect(0, 0, width, height);
2154 final Rect displayFrame = new Rect(0, 0,
2155 displayInfo.logicalWidth, displayInfo.logicalHeight);
2156 final Rect insets = new Rect();
2157 final Rect stableInsets = new Rect();
2158 final Rect surfaceInsets = new Rect();
2159 getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
2160
2161 if (mLaunchTaskBehind) {
2162 // Differentiate the two animations. This one which is briefly on the screen
2163 // gets the !enter animation, and the other one which remains on the
2164 // screen gets the enter animation. Both appear in the mOpeningApps set.
2165 enter = false;
2166 }
2167 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2168 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2169 + "surfaceInsets=%s",
2170 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
2171 final Configuration displayConfig = displayContent.getConfiguration();
2172 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
2173 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2174 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
2175 if (a != null) {
lumark8669ef32020-02-10 18:41:57 +08002176 if (a != null) {
2177 // Setup the maximum app transition duration to prevent malicious app may set a long
2178 // animation duration or infinite repeat counts for the app transition through
2179 // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
2180 a.restrictDuration(MAX_APP_TRANSITION_DURATION);
2181 }
2182 if (DEBUG_ANIM) {
2183 logWithStack(TAG, "Loaded animation " + a + " for " + this
2184 + ", duration: " + ((a != null) ? a.getDuration() : 0));
2185 }
lumark19a5d2e2019-10-11 16:19:30 +08002186 final int containingWidth = frame.width();
2187 final int containingHeight = frame.height();
2188 a.initialize(containingWidth, containingHeight, width, height);
2189 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
2190 }
2191 return a;
2192 }
2193
2194 RemoteAnimationTarget createRemoteAnimationTarget(
2195 RemoteAnimationController.RemoteAnimationRecord record) {
2196 return null;
2197 }
2198
2199 boolean okToDisplay() {
lumark5341d1c2019-12-14 01:54:02 +08002200 final DisplayContent dc = getDisplayContent();
2201 return dc != null && dc.okToDisplay();
lumark19a5d2e2019-10-11 16:19:30 +08002202 }
2203
2204 boolean okToAnimate() {
lumark3b8bbc82019-12-02 16:22:08 +08002205 return okToAnimate(false /* ignoreFrozen */);
2206 }
2207
2208 boolean okToAnimate(boolean ignoreFrozen) {
lumark5341d1c2019-12-14 01:54:02 +08002209 final DisplayContent dc = getDisplayContent();
2210 return dc != null && dc.okToAnimate(ignoreFrozen);
lumark19a5d2e2019-10-11 16:19:30 +08002211 }
2212
Jorim Jaggia5e10572017-11-15 14:36:26 +01002213 @Override
2214 public void commitPendingTransaction() {
2215 scheduleAnimation();
2216 }
2217
Robert Carr2f8aa392018-01-31 14:46:51 -08002218 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01002219 final WindowContainer parent = getParent();
2220 if (parent != null) {
2221 parent.assignChildLayers(t);
2222 }
2223 }
2224
2225 @Override
2226 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002227 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002228 reassignLayer(t);
2229 }
2230
2231 @Override
lumarkf6f34942019-04-29 16:56:50 +08002232 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002233 mLastLayer = -1;
Evan Rosky55bddd82020-01-29 13:07:18 -08002234 mSurfaceFreezer.unfreeze(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002235 reassignLayer(t);
2236 }
2237
2238 /**
2239 * Called when an animation has finished running.
2240 */
Issei Suzuki8b995df2020-01-08 12:23:04 +01002241 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
chaviwccd5d502019-02-22 13:30:31 -08002242 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002243 }
2244
2245 /**
2246 * @return The currently running animation, if any, or {@code null} otherwise.
2247 */
2248 AnimationAdapter getAnimation() {
2249 return mSurfaceAnimator.getAnimation();
2250 }
2251
2252 /**
lumark5bd11af2019-12-21 01:52:28 +08002253 * @return The {@link WindowContainer} which is running an animation.
2254 *
2255 * It traverses from the current container to its parents recursively. If nothing is animating,
2256 * it will return {@code null}.
2257 */
2258 @Nullable
2259 WindowContainer getAnimatingContainer() {
2260 if (isAnimating()) {
2261 return this;
2262 }
2263 final WindowContainer parent = getParent();
2264 return (parent != null) ? parent.getAnimatingContainer() : null;
2265 }
2266
2267 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +01002268 * @see SurfaceAnimator#startDelayingAnimationStart
2269 */
2270 void startDelayingAnimationStart() {
2271 mSurfaceAnimator.startDelayingAnimationStart();
2272 }
2273
2274 /**
2275 * @see SurfaceAnimator#endDelayingAnimationStart
2276 */
2277 void endDelayingAnimationStart() {
2278 mSurfaceAnimator.endDelayingAnimationStart();
2279 }
2280
2281 @Override
2282 public int getSurfaceWidth() {
2283 return mSurfaceControl.getWidth();
2284 }
2285
2286 @Override
2287 public int getSurfaceHeight() {
2288 return mSurfaceControl.getHeight();
2289 }
2290
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002291 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01002292 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2293 if (mSurfaceAnimator.isAnimating()) {
2294 pw.print(prefix); pw.println("ContainerAnimator:");
2295 mSurfaceAnimator.dump(pw, prefix + " ");
2296 }
2297 }
chaviwe07246a2017-12-12 16:18:29 -08002298
chaviw2f0567b2018-01-29 16:22:02 -08002299 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08002300 if (mSurfaceControl == null) {
2301 return;
2302 }
2303
Evan Roskyed6767f2018-10-26 17:21:06 -07002304 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08002305 if (mTmpPos.equals(mLastSurfacePosition)) {
2306 return;
2307 }
2308
chaviw2f0567b2018-01-29 16:22:02 -08002309 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08002310 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08002311 }
2312
Evan Rosky65dffa62019-02-04 14:09:53 -08002313 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002314 Point getLastSurfacePosition() {
2315 return mLastSurfacePosition;
2316 }
2317
Evan Roskyed6767f2018-10-26 17:21:06 -07002318 /**
2319 * Displayed bounds specify where to display this container at. It differs from bounds during
2320 * certain operations (like animation or interactive dragging).
2321 *
2322 * @return the bounds to display this container at.
2323 */
2324 Rect getDisplayedBounds() {
2325 return getBounds();
2326 }
2327
lumark19a5d2e2019-10-11 16:19:30 +08002328 /**
2329 * The {@code outFrame} retrieved by this method specifies where the animation will finish
2330 * the entrance animation, as the next frame will display the window at these coordinates. In
2331 * case of exit animation, this is where the animation will start, as the frame before the
2332 * animation is displaying the window at these bounds.
2333 *
2334 * @param outFrame The bounds where entrance animation finishes or exit animation starts.
2335 * @param outInsets Insets that are covered by system windows.
2336 * @param outStableInsets Insets that determine the area covered by the stable system windows.
2337 * @param outSurfaceInsets Positive insets between the drawing surface and window content.
2338 */
2339 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2340 Rect outSurfaceInsets) {
2341 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2342 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
2343 outInsets.setEmpty();
2344 outStableInsets.setEmpty();
2345 outSurfaceInsets.setEmpty();
2346 }
2347
Evan Roskyed6767f2018-10-26 17:21:06 -07002348 void getRelativeDisplayedPosition(Point outPos) {
2349 final Rect dispBounds = getDisplayedBounds();
2350 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08002351 final WindowContainer parent = getParent();
2352 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002353 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08002354 outPos.offset(-parentBounds.left, -parentBounds.top);
2355 }
2356 }
chaviw2fb06bc2018-01-19 17:09:15 -08002357
Yunfan Chen87b5a242019-10-01 17:53:59 +09002358 void waitForAllWindowsDrawn() {
Yunfan Chen87b5a242019-10-01 17:53:59 +09002359 forAllWindows(w -> {
Riddle Hsu5df3b752019-12-16 13:27:37 -06002360 w.requestDrawIfNeeded(mWaitingForDrawn);
Yunfan Chen87b5a242019-10-01 17:53:59 +09002361 }, true /* traverseTopToBottom */);
2362 }
2363
chaviw2fb06bc2018-01-19 17:09:15 -08002364 Dimmer getDimmer() {
2365 if (mParent == null) {
2366 return null;
2367 }
2368 return mParent.getDimmer();
2369 }
Robert Carr8a2f9132019-11-11 15:03:15 -08002370
2371 void setSurfaceControl(SurfaceControl sc) {
2372 mSurfaceControl = sc;
2373 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002374
Evan Rosky55bddd82020-01-29 13:07:18 -08002375 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2376 return null;
2377 }
2378
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002379 /** Cheap way of doing cast and instanceof. */
2380 Task asTask() {
2381 return null;
2382 }
2383
2384 /** Cheap way of doing cast and instanceof. */
2385 ActivityRecord asActivityRecord() {
2386 return null;
2387 }
Evan Roskya80f11c2020-01-23 19:17:10 -08002388
2389 RemoteToken getRemoteToken() {
2390 return mRemoteToken;
2391 }
2392
Evan Roskya8fde152020-01-07 19:09:13 -08002393 static WindowContainer fromBinder(IBinder binder) {
2394 return RemoteToken.fromBinder(binder).getContainer();
2395 }
2396
Evan Roskya80f11c2020-01-23 19:17:10 -08002397 static class RemoteToken extends IWindowContainer.Stub {
2398 final WeakReference<WindowContainer> mWeakRef;
2399
2400 RemoteToken(WindowContainer container) {
2401 mWeakRef = new WeakReference<>(container);
2402 }
2403
2404 WindowContainer getContainer() {
2405 return mWeakRef.get();
2406 }
2407
2408 static RemoteToken fromBinder(IBinder binder) {
2409 return (RemoteToken) binder;
2410 }
2411
2412 @Override
2413 public SurfaceControl getLeash() {
2414 throw new RuntimeException("Not implemented");
2415 }
2416
2417 @Override
2418 public String toString() {
2419 StringBuilder sb = new StringBuilder(128);
2420 sb.append("RemoteToken{");
2421 sb.append(Integer.toHexString(System.identityHashCode(this)));
2422 sb.append(' ');
2423 sb.append(mWeakRef.get());
2424 sb.append('}');
2425 return sb.toString();
2426 }
2427 }
Robert Carre10ee3d2019-11-11 15:03:15 -08002428
2429 @Override
2430 public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
2431 mergedTransaction.merge(mBLASTSyncTransaction);
2432 mUsingBLASTSyncTransaction = false;
2433
2434 mWaitingListener.transactionReady(mWaitingSyncId, mergedTransaction);
2435
2436 mWaitingListener = null;
2437 mWaitingSyncId = -1;
2438 }
2439
2440 boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
2441 int waitingId) {
2442 boolean willSync = false;
2443 if (!isVisible()) {
2444 return willSync;
2445 }
2446 mUsingBLASTSyncTransaction = true;
2447
2448 int localId = mBLASTSyncEngine.startSyncSet(this);
2449 for (int i = 0; i < mChildren.size(); i++) {
2450 final WindowContainer child = mChildren.get(i);
2451 willSync = mBLASTSyncEngine.addToSyncSet(localId, child) | willSync;
2452 }
2453
2454 // Make sure to set these before we call setReady in case the sync was a no-op
2455 mWaitingSyncId = waitingId;
2456 mWaitingListener = waitingListener;
2457
2458 mBLASTSyncEngine.setReady(localId);
2459
2460 return willSync;
2461 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07002462}