blob: a1902bbd6764ceb2a22f53d0bede3dcebb70bf8f [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;
Vishnu Nairdddc9f52020-03-09 09:37:27 -070043import static com.android.server.wm.WindowContainerChildProto.WINDOW_CONTAINER;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070044import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
45import static com.android.server.wm.WindowContainerProto.ORIENTATION;
46import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
47import static com.android.server.wm.WindowContainerProto.VISIBLE;
Louis Chang7501e332018-08-20 13:08:39 +080048import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
49import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
50import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
lumark19a5d2e2019-10-11 16:19:30 +080051import static com.android.server.wm.WindowManagerService.logWithStack;
lumark85718662019-12-26 22:05:12 +080052import static com.android.server.wm.WindowManagerService.sHierarchicalAnimations;
lumark19a5d2e2019-10-11 16:19:30 +080053import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Jorim Jaggi612bb882017-05-16 17:11:18 +020054
Wale Ogunwaled63594a2016-07-18 07:48:30 -070055import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020056import android.annotation.IntDef;
Garfield Tan90b04282018-12-11 14:04:42 -080057import android.annotation.Nullable;
Jorim Jaggi391790622018-04-18 15:30:44 +020058import android.app.WindowConfiguration;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080059import android.content.pm.ActivityInfo;
Andrii Kulian441e4492016-09-29 15:25:00 -070060import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080061import android.graphics.Point;
62import android.graphics.Rect;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080063import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -080064import android.os.IBinder;
lumark19a5d2e2019-10-11 16:19:30 +080065import android.os.Trace;
66import android.util.Pair;
Vishnu Nair04ab4392018-01-10 11:00:06 -080067import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010068import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080069import android.util.proto.ProtoOutputStream;
lumark19a5d2e2019-10-11 16:19:30 +080070import android.view.DisplayInfo;
Evan Roskya80f11c2020-01-23 19:17:10 -080071import android.view.IWindowContainer;
Robert Carrb1579c82017-09-05 14:54:47 -070072import android.view.MagnificationSpec;
Evan Rosky55bddd82020-01-29 13:07:18 -080073import android.view.RemoteAnimationDefinition;
lumark19a5d2e2019-10-11 16:19:30 +080074import android.view.RemoteAnimationTarget;
Robert Carrb1579c82017-09-05 14:54:47 -070075import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010076import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070077import android.view.SurfaceSession;
lumark19a5d2e2019-10-11 16:19:30 +080078import android.view.WindowManager;
79import android.view.animation.Animation;
Garfield Tan2f145f22018-11-01 15:27:03 -070080
Evan Rosky65dffa62019-02-04 14:09:53 -080081import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010082import com.android.internal.util.ToBooleanFunction;
lumark19a5d2e2019-10-11 16:19:30 +080083import com.android.server.protolog.common.ProtoLog;
Jorim Jaggia5e10572017-11-15 14:36:26 +010084import com.android.server.wm.SurfaceAnimator.Animatable;
Issei Suzuki8b995df2020-01-08 12:23:04 +010085import com.android.server.wm.SurfaceAnimator.AnimationType;
86import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
Garfield Tan2f145f22018-11-01 15:27:03 -070087
Jorim Jaggia5e10572017-11-15 14:36:26 +010088import java.io.PrintWriter;
Evan Roskya80f11c2020-01-23 19:17:10 -080089import java.lang.ref.WeakReference;
Yunfan Chen87b5a242019-10-01 17:53:59 +090090import java.util.ArrayList;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070091import java.util.Comparator;
92import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070093import java.util.function.Consumer;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -080094import java.util.function.Function;
Wale Ogunwaled1880962016-11-08 10:31:59 -080095import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070096
97/**
98 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070099 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700100 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
101 * changes are made to this class.
102 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700103class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Evan Rosky55bddd82020-01-29 13:07:18 -0800104 implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable,
Robert Carre10ee3d2019-11-11 15:03:15 -0800105 BLASTSyncEngine.TransactionReadyListener {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100106
107 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700108
Louis Changdc077272019-11-12 16:52:56 +0800109 /** Animation layer that happens above all animating {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200110 static final int ANIMATION_LAYER_STANDARD = 0;
111
Louis Changdc077272019-11-12 16:52:56 +0800112 /** Animation layer that happens above all {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200113 static final int ANIMATION_LAYER_BOOSTED = 1;
114
115 /**
116 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -0700117 * activities and all activities that are being controlled by the recents animation. This
Louis Changdc077272019-11-12 16:52:56 +0800118 * layer is generally below all {@link ActivityStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +0200119 */
120 static final int ANIMATION_LAYER_HOME = 2;
121
122 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
123 ANIMATION_LAYER_STANDARD,
124 ANIMATION_LAYER_BOOSTED,
125 ANIMATION_LAYER_HOME,
126 })
127 @interface AnimationLayer {}
128
Andrii Kuliand2765632016-12-12 22:26:34 -0800129 static final int POSITION_TOP = Integer.MAX_VALUE;
130 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
131
Andrii Kulian441e4492016-09-29 15:25:00 -0700132 /**
133 * The parent of this window container.
134 * For removing or setting new parent {@link #setParent} should be used, because it also
135 * performs configuration updates based on new parent's settings.
136 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100137 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700138
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200139 // Set to true when we are performing a reparenting operation so we only send one
140 // onParentChanged() notification.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700141 boolean mReparenting;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200142
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700143 // List of children for this window container. List is in z-order as the children appear on
144 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200145 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700146
Wale Ogunwale51362492016-09-08 17:49:17 -0700147 // The specified orientation for this window container.
Vadim Caen1096f112019-12-18 11:44:26 +0100148 @ActivityInfo.ScreenOrientation
Wale Ogunwale51362492016-09-08 17:49:17 -0700149 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
150
Riddle Hsu6f548e92020-01-13 13:34:09 +0800151 /**
152 * The window container which decides its orientation since the last time
153 * {@link #getOrientation(int) was called.
154 */
155 protected WindowContainer mLastOrientationSource;
156
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800157 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
158 new Pools.SynchronizedPool<>(3);
159
Tiger Huanged6794e2019-05-07 20:07:59 +0800160 // The display this window container is on.
161 protected DisplayContent mDisplayContent;
162
Robert Carrb1579c82017-09-05 14:54:47 -0700163 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100164 private int mLastLayer = 0;
165 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700166
Tiger Huanged6794e2019-05-07 20:07:59 +0800167 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
168 private final Transaction mPendingTransaction;
169
Robert Carrb1579c82017-09-05 14:54:47 -0700170 /**
Yunfan Chen87b5a242019-10-01 17:53:59 +0900171 * Windows that clients are waiting to have drawn.
172 */
173 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
174
175 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700176 * Applied as part of the animation pass in "prepareSurfaces".
177 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100178 protected final SurfaceAnimator mSurfaceAnimator;
Evan Rosky55bddd82020-01-29 13:07:18 -0800179 final SurfaceFreezer mSurfaceFreezer;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800180 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100181
chaviwe07246a2017-12-12 16:18:29 -0800182 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800183 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800184
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100185 /** Total number of elements in this subtree, including our own hierarchy element. */
186 private int mTreeWeight = 1;
187
chaviw7f1fa992018-01-10 13:52:12 -0800188 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700189 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800190 * surface to the animation leash
191 */
192 private boolean mCommittedReparentToAnimationLeash;
193
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800194 private final Configuration mTmpConfig = new Configuration();
195
lumark9bca6b42019-10-17 18:35:22 +0800196 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
197 public interface AnimationFlags {
198 /**
199 * A bit flag indicates that {@link #isAnimating} should also return {@code true}
200 * even though the container is not yet animating, but the window container or its
201 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
202 * that is pending so an animation starts soon.
203 */
204 int TRANSITION = 1;
205
206 /**
207 * A bit flag indicates that {@link #isAnimating} should also check if one of the
208 * ancestors of the container are animating in addition to the container itself.
209 */
210 int PARENTS = 2;
211
212 /**
213 * A bit flag indicates that {@link #isAnimating} should also check if one of the
214 * descendants of the container are animating in addition to the container itself.
215 */
216 int CHILDREN = 4;
217 }
218
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200219 /**
220 * Callback which is triggered while changing the parent, after setting up the surface but
221 * before asking the parent to assign child layers.
222 */
223 interface PreAssignChildLayersCallback {
224 void onPreAssignChildLayers();
225 }
226
lumark19a5d2e2019-10-11 16:19:30 +0800227 /**
228 * True if this an AppWindowToken and the activity which created this was launched with
229 * ActivityOptions.setLaunchTaskBehind.
230 *
231 * TODO(b/142617871): We run a special animation when the activity was launched with that
232 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
233 * selected to suppress an animation, and remove this flag.
234 */
235 boolean mLaunchTaskBehind;
236
237 /**
238 * If we are running an animation, this determines the transition type. Must be one of
239 * {@link AppTransition#TransitionFlags}.
240 */
241 int mTransit;
242
243 /**
244 * If we are running an animation, this determines the flags during this animation. Must be a
245 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
246 */
247 int mTransitFlags;
248
249 /** Whether this container should be boosted at the top of all its siblings. */
250 @VisibleForTesting boolean mNeedsZBoost;
251
252 /** Layer used to constrain the animation to a container's stack bounds. */
253 SurfaceControl mAnimationBoundsLayer;
254
255 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
256 boolean mNeedsAnimationBoundsLayer;
257
258 /**
259 * This gets used during some open/close transitions as well as during a change transition
260 * where it represents the starting-state snapshot.
261 */
lumarkbc0032a2019-11-01 21:38:13 +0800262 WindowContainerThumbnail mThumbnail;
lumark19a5d2e2019-10-11 16:19:30 +0800263 final Point mTmpPoint = new Point();
264 protected final Rect mTmpRect = new Rect();
265 final Rect mTmpPrevBounds = new Rect();
266
Robert Carr7603dea2019-07-17 13:16:21 -0700267 private MagnificationSpec mLastMagnificationSpec;
268
Evan Rosky226de132020-01-03 18:00:29 -0800269 private boolean mIsFocusable = true;
270
Evan Roskya80f11c2020-01-23 19:17:10 -0800271 /**
272 * Used as a unique, cross-process identifier for this Container. It also serves a minimal
273 * interface to other processes.
274 */
275 RemoteToken mRemoteToken = null;
276
Robert Carre10ee3d2019-11-11 15:03:15 -0800277 BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine();
Rob Carrdb37d582020-03-10 12:31:07 -0700278 SurfaceControl.Transaction mBLASTSyncTransaction;
Robert Carre10ee3d2019-11-11 15:03:15 -0800279 boolean mUsingBLASTSyncTransaction = false;
280 BLASTSyncEngine.TransactionReadyListener mWaitingListener;
281 int mWaitingSyncId;
282
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800283 WindowContainer(WindowManagerService wms) {
284 mWmService = wms;
Vishnu Nair33197392019-08-30 10:29:37 -0700285 mPendingTransaction = wms.mTransactionFactory.get();
Rob Carrdb37d582020-03-10 12:31:07 -0700286 mBLASTSyncTransaction = wms.mTransactionFactory.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800287 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Evan Rosky55bddd82020-01-29 13:07:18 -0800288 mSurfaceFreezer = new SurfaceFreezer(this, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100289 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800290
Wale Ogunwale98d62312017-07-12 09:24:56 -0700291 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700292 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700293 return mParent;
294 }
295
Wale Ogunwale98d62312017-07-12 09:24:56 -0700296 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700297 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700298 return mChildren.size();
299 }
300
301 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700302 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700303 return mChildren.get(index);
304 }
305
chaviwe07246a2017-12-12 16:18:29 -0800306 @Override
307 public void onConfigurationChanged(Configuration newParentConfig) {
308 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800309 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800310 scheduleAnimation();
311 }
312
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200313 void reparent(WindowContainer newParent, int position) {
314 if (newParent == null) {
315 throw new IllegalArgumentException("reparent: can't reparent to null " + this);
316 }
317
318 final WindowContainer oldParent = mParent;
319 if (mParent == newParent) {
320 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
321 }
322
323 // The display object before reparenting as that might lead to old parent getting removed
324 // from the display if it no longer has any child.
325 final DisplayContent prevDc = oldParent.getDisplayContent();
326 final DisplayContent dc = newParent.getDisplayContent();
327
328 mReparenting = true;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700329 oldParent.removeChild(this);
Louis Chang2453d062019-11-19 22:30:48 +0800330 newParent.addChild(this, position);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200331 mReparenting = false;
332
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200333 // Relayout display(s)
334 dc.setLayoutNeeded();
335 if (prevDc != dc) {
336 onDisplayChanged(dc);
337 prevDc.setLayoutNeeded();
338 }
339 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700340
341 // Send onParentChanged notification here is we disabled sending it in setParent for
342 // reparenting case.
343 onParentChanged(newParent, oldParent);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200344 }
345
Jorim Jaggia5e10572017-11-15 14:36:26 +0100346 final protected void setParent(WindowContainer<WindowContainer> parent) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200347 final WindowContainer oldParent = mParent;
Andrii Kulian441e4492016-09-29 15:25:00 -0700348 mParent = parent;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800349
350 if (mParent != null) {
351 mParent.onChildAdded(this);
352 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200353 if (!mReparenting) {
lumarkbde15132019-12-18 22:29:43 +0800354 if (mParent != null && mParent.mDisplayContent != null
355 && mDisplayContent != mParent.mDisplayContent) {
356 onDisplayChanged(mParent.mDisplayContent);
357 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200358 onParentChanged(mParent, oldParent);
359 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800360 }
361
362 /**
363 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
364 * Supposed to be overridden and contain actions that should be executed after parent was set.
365 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800366 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200367 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
368 onParentChanged(newParent, oldParent, null);
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200369 }
370
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200371 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
372 PreAssignChildLayersCallback callback) {
373 super.onParentChanged(newParent, oldParent);
Robert Carrb1579c82017-09-05 14:54:47 -0700374 if (mParent == null) {
375 return;
376 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100377
Robert Carrb1579c82017-09-05 14:54:47 -0700378 if (mSurfaceControl == null) {
379 // If we don't yet have a surface, but we now have a parent, we should
380 // build a surface.
Robert Carr8a2f9132019-11-11 15:03:15 -0800381 setSurfaceControl(makeSurface().build());
Robert Carrf59b8dd2017-10-02 18:58:36 -0700382 getPendingTransaction().show(mSurfaceControl);
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800383 onSurfaceShown(getPendingTransaction());
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700384 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700385 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100386 // If we have a surface but a new parent, we just need to perform a reparent. Go through
387 // surface animator such that hierarchy is preserved when animating, i.e.
388 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
389 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100390 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700391 }
392
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200393 if (callback != null) {
394 callback.onPreAssignChildLayers();
395 }
396
Robert Carrb1579c82017-09-05 14:54:47 -0700397 // Either way we need to ask the parent to assign us a Z-order.
398 mParent.assignChildLayers();
399 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700400 }
401
Vishnu Nairfd6fb672020-02-14 12:56:37 -0800402 /**
403 * Called when the surface is shown for the first time.
404 */
405 void onSurfaceShown(Transaction t) {
406 // do nothing
407 }
408
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700409 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100410 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
411 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700412
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700413 /**
414 * Adds the input window container has a child of this container in order based on the input
415 * comparator.
416 * @param child The window container to add as a child of this window container.
417 * @param comparator Comparator to use in determining the position the child should be added to.
418 * If null, the child will be added to the top.
419 */
420 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700421 protected void addChild(E child, Comparator<E> comparator) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700422 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700423 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700424 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700425 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700426 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700427
Andrii Kulianb94292e2016-10-19 13:30:58 -0700428 int positionToAdd = -1;
429 if (comparator != null) {
430 final int count = mChildren.size();
431 for (int i = 0; i < count; i++) {
432 if (comparator.compare(child, mChildren.get(i)) < 0) {
433 positionToAdd = i;
434 break;
435 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700436 }
437 }
438
Andrii Kulianb94292e2016-10-19 13:30:58 -0700439 if (positionToAdd == -1) {
440 mChildren.add(child);
441 } else {
442 mChildren.add(positionToAdd, child);
443 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100444
Andrii Kulianb94292e2016-10-19 13:30:58 -0700445 // Set the parent after we've actually added a child in case a subclass depends on this.
446 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700447 }
448
Wale Ogunwalef6192862016-09-10 13:42:30 -0700449 /** Adds the input window container has a child of this container at the input index. */
450 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800451 void addChild(E child, int index) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700452 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700453 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700454 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800455 + " can't add to container=" + getName()
456 + "\n callers=" + Debug.getCallers(15, "\n"));
Wale Ogunwalef6192862016-09-10 13:42:30 -0700457 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900458
459 if ((index < 0 && index != POSITION_BOTTOM)
460 || (index > mChildren.size() && index != POSITION_TOP)) {
461 throw new IllegalArgumentException("addChild: invalid position=" + index
462 + ", children number=" + mChildren.size());
463 }
464
465 if (index == POSITION_TOP) {
466 index = mChildren.size();
467 } else if (index == POSITION_BOTTOM) {
468 index = 0;
469 }
470
Wale Ogunwalef6192862016-09-10 13:42:30 -0700471 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100472
Andrii Kulianb94292e2016-10-19 13:30:58 -0700473 // Set the parent after we've actually added a child in case a subclass depends on this.
474 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700475 }
476
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100477 private void onChildAdded(WindowContainer child) {
478 mTreeWeight += child.mTreeWeight;
479 WindowContainer parent = getParent();
480 while (parent != null) {
481 parent.mTreeWeight += child.mTreeWeight;
482 parent = parent.getParent();
483 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200484 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100485 }
486
Wale Ogunwalef6192862016-09-10 13:42:30 -0700487 /**
488 * Removes the input child container from this container which is its parent.
489 *
490 * @return True if the container did contain the input child and it was detached.
491 */
492 @CallSuper
493 void removeChild(E child) {
494 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100495 onChildRemoved(child);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700496 if (!child.mReparenting) {
497 child.setParent(null);
498 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700499 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700500 throw new IllegalArgumentException("removeChild: container=" + child.getName()
501 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700502 }
503 }
504
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100505 private void onChildRemoved(WindowContainer child) {
506 mTreeWeight -= child.mTreeWeight;
507 WindowContainer parent = getParent();
508 while (parent != null) {
509 parent.mTreeWeight -= child.mTreeWeight;
510 parent = parent.getParent();
511 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200512 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100513 }
514
Wale Ogunwale571771c2016-08-26 13:18:50 -0700515 /**
516 * Removes this window container and its children with no regard for what else might be going on
517 * in the system. For example, the container will be removed during animation if this method is
518 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
519 * which allows the system to defer removal until a suitable time.
520 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700521 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700522 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700523 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100524 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700525 child.removeImmediately();
526 // Need to do this after calling remove on the child because the child might try to
527 // remove/detach itself from its parent which will cause an exception if we remove
528 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100529 if (mChildren.remove(child)) {
530 onChildRemoved(child);
531 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700532 }
533
Robert Carrb1579c82017-09-05 14:54:47 -0700534 if (mSurfaceControl != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800535 getPendingTransaction().remove(mSurfaceControl);
Robert Carr8a2f9132019-11-11 15:03:15 -0800536 setSurfaceControl(null);
Garfield Tan265ab91a2019-11-12 16:30:49 -0800537 mLastSurfacePosition.set(0, 0);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000538 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700539 }
540
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700541 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700542 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700543 }
544 }
545
546 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100547 * @return The index of this element in the hierarchy tree in prefix order.
548 */
549 int getPrefixOrderIndex() {
550 if (mParent == null) {
551 return 0;
552 }
553 return mParent.getPrefixOrderIndex(this);
554 }
555
556 private int getPrefixOrderIndex(WindowContainer child) {
557 int order = 0;
558 for (int i = 0; i < mChildren.size(); i++) {
559 final WindowContainer childI = mChildren.get(i);
560 if (child == childI) {
561 break;
562 }
563 order += childI.mTreeWeight;
564 }
565 if (mParent != null) {
566 order += mParent.getPrefixOrderIndex(this);
567 }
568
569 // We also need to count ourselves.
570 order++;
571 return order;
572 }
573
574 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700575 * Removes this window container and its children taking care not to remove them during a
576 * critical stage in the system. For example, some containers will not be removed during
577 * animation if this method is called.
578 */
579 // TODO: figure-out implementation that works best for this.
580 // E.g. when do we remove from parent list? maybe not...
581 void removeIfPossible() {
582 for (int i = mChildren.size() - 1; i >= 0; --i) {
583 final WindowContainer wc = mChildren.get(i);
584 wc.removeIfPossible();
585 }
586 }
587
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700588 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000589 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700590 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000591 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700592 if (current == child || current.hasChild(child)) {
593 return true;
594 }
595 }
596 return false;
597 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700598
Issei Suzuki2f541842020-01-09 20:18:29 +0100599 /** @return true if this window container is a descendant of the input container. */
600 boolean isDescendantOf(WindowContainer ancestor) {
601 final WindowContainer parent = getParent();
602 if (parent == ancestor) return true;
603 return (parent != null) && parent.isDescendantOf(ancestor);
604 }
605
Andrii Kulian441e4492016-09-29 15:25:00 -0700606 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800607 * Move a child from it's current place in siblings list to the specified position,
608 * with an option to move all its parents to top.
609 * @param position Target position to move the child to.
610 * @param child Child to move to selected position.
611 * @param includingParents Flag indicating whether we need to move the entire branch of the
612 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
613 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
614 * this flag will do nothing.
615 */
616 @CallSuper
617 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800618
619 if (child.getParent() != this) {
Wale Ogunwale0d465192020-01-23 19:14:44 -0800620 throw new IllegalArgumentException("positionChildAt: container=" + child.getName()
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800621 + " is not a child of container=" + getName()
622 + " current parent=" + child.getParent());
623 }
624
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800625 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800626 position = POSITION_TOP;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700627 } else if (position <= 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800628 position = POSITION_BOTTOM;
629 }
630
631 switch (position) {
632 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800633 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800634 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200635 mChildren.add(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200636 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800637 }
638 if (includingParents && getParent() != null) {
639 getParent().positionChildAt(POSITION_TOP, this /* child */,
640 true /* includingParents */);
641 }
642 break;
643 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800644 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800645 mChildren.remove(child);
646 mChildren.addFirst(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200647 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800648 }
649 if (includingParents && getParent() != null) {
650 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
651 true /* includingParents */);
652 }
653 break;
654 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800655 // TODO: Removing the child before reinserting requires the caller to provide a
656 // position that takes into account the removed child (if the index of the
657 // child < position, then the position should be adjusted). We should consider
658 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800659 mChildren.remove(child);
660 mChildren.add(position, child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200661 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800662 }
663 }
664
665 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800666 * Notify that a child's position has changed. Possible changes are adding or removing a child.
667 */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200668 void onChildPositionChanged(WindowContainer child) { }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800669
670 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700671 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700672 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700673 * @see #mFullConfiguration
674 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700675 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700676 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800677 // We must diff before the configuration is applied so that we can capture the change
678 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700679 final int diff = diffRequestedOverrideBounds(
680 overrideConfiguration.windowConfiguration.getBounds());
681 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700682 if (mParent != null) {
683 mParent.onDescendantOverrideConfigurationChanged();
684 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800685
686 if (diff == BOUNDS_CHANGE_NONE) {
687 return;
688 }
689
690 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
691 onResize();
692 } else {
693 onMovedByResize();
694 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700695 }
696
697 /**
698 * Notify that a descendant's overrideConfiguration has changed.
699 */
700 void onDescendantOverrideConfigurationChanged() {
701 if (mParent != null) {
702 mParent.onDescendantOverrideConfigurationChanged();
703 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700704 }
705
706 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700707 * Notify that the display this container is on has changed. This could be either this container
708 * is moved to a new display, or some configurations on the display it is on changes.
709 *
710 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700711 */
712 void onDisplayChanged(DisplayContent dc) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800713 mDisplayContent = dc;
714 if (dc != null && dc != this) {
715 dc.getPendingTransaction().merge(mPendingTransaction);
716 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700717 for (int i = mChildren.size() - 1; i >= 0; --i) {
718 final WindowContainer child = mChildren.get(i);
719 child.onDisplayChanged(dc);
720 }
721 }
722
Tiger Huanged6794e2019-05-07 20:07:59 +0800723 DisplayContent getDisplayContent() {
724 return mDisplayContent;
725 }
726
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700727 void setWaitingForDrawnIfResizingChanged() {
728 for (int i = mChildren.size() - 1; i >= 0; --i) {
729 final WindowContainer wc = mChildren.get(i);
730 wc.setWaitingForDrawnIfResizingChanged();
731 }
732 }
733
734 void onResize() {
735 for (int i = mChildren.size() - 1; i >= 0; --i) {
736 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800737 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700738 }
739 }
740
Bryce Leed92ae482018-01-22 13:56:23 -0800741 void onParentResize() {
742 // In the case this container has specified its own bounds, a parent resize will not
743 // affect its bounds. Any relevant changes will be propagated through changes to the
744 // Configuration override.
745 if (hasOverrideBounds()) {
746 return;
747 }
748
749 // Default implementation is to treat as resize on self.
750 onResize();
751 }
752
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700753 void onMovedByResize() {
754 for (int i = mChildren.size() - 1; i >= 0; --i) {
755 final WindowContainer wc = mChildren.get(i);
756 wc.onMovedByResize();
757 }
758 }
759
760 void resetDragResizingChangeReported() {
761 for (int i = mChildren.size() - 1; i >= 0; --i) {
762 final WindowContainer wc = mChildren.get(i);
763 wc.resetDragResizingChangeReported();
764 }
765 }
766
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700767 void forceWindowsScaleableInTransaction(boolean force) {
768 for (int i = mChildren.size() - 1; i >= 0; --i) {
769 final WindowContainer wc = mChildren.get(i);
770 wc.forceWindowsScaleableInTransaction(force);
771 }
772 }
773
Jorim Jaggia5e10572017-11-15 14:36:26 +0100774 /**
lumark9bca6b42019-10-17 18:35:22 +0800775 * @return {@code true} when this container or its related containers are running an
776 * animation, {@code false} otherwise.
777 *
778 * By default this predicate only checks if this container itself is actually running an
779 * animation, but you can extend the check target over its relatives, or relax the condition
780 * so that this can return {@code true} if an animation starts soon by giving a combination
781 * of {@link #AnimationFlags}.
782 *
783 * Note that you can give a combination of bitmask flags to specify targets and condition for
784 * checking animating status.
785 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
786 * container itself or one of its parents is running an animation or waiting for an app
787 * transition.
788 *
789 * Note that TRANSITION propagates to parents and children as well.
790 *
791 * {@see AnimationFlags#TRANSITION}
792 * {@see AnimationFlags#PARENTS}
793 * {@see AnimationFlags#CHILDREN}
Jorim Jaggia5e10572017-11-15 14:36:26 +0100794 */
Jorim Jaggi924ef752020-01-29 17:26:55 +0100795 boolean isAnimating(int flags) {
lumark9bca6b42019-10-17 18:35:22 +0800796 if (mSurfaceAnimator.isAnimating()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100797 return true;
798 }
lumark9bca6b42019-10-17 18:35:22 +0800799 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
800 return true;
801 }
802 if ((flags & PARENTS) != 0) {
803 final WindowContainer parent = getParent();
804 if (parent != null && parent.isAnimating(flags & ~CHILDREN)) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700805 return true;
806 }
807 }
lumark9bca6b42019-10-17 18:35:22 +0800808 if ((flags & CHILDREN) != 0) {
809 for (int i = 0; i < mChildren.size(); ++i) {
810 final WindowContainer wc = mChildren.get(i);
811 if (wc.isAnimating(flags & ~PARENTS)) {
812 return true;
813 }
814 }
815 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700816 return false;
817 }
818
Jorim Jaggia5e10572017-11-15 14:36:26 +0100819 /**
lumark9bca6b42019-10-17 18:35:22 +0800820 * @return {@code true} when the container is waiting the app transition start, {@code false}
821 * otherwise.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100822 */
lumark9bca6b42019-10-17 18:35:22 +0800823 boolean isWaitingForTransitionStart() {
lumark52d5f422020-01-06 16:17:55 +0800824 return false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100825 }
826
827 /**
lumark9bca6b42019-10-17 18:35:22 +0800828 * @return {@code true} if in this subtree of the hierarchy we have an
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800829 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200830 */
lumark9bca6b42019-10-17 18:35:22 +0800831 boolean isAppTransitioning() {
lumark5341d1c2019-12-14 01:54:02 +0800832 return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200833 }
834
835 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100836 * @return Whether our own container running an animation at the moment.
837 */
lumark9bca6b42019-10-17 18:35:22 +0800838 final boolean isAnimating() {
839 return isAnimating(0 /* self only */);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100840 }
841
lumark19a5d2e2019-10-11 16:19:30 +0800842 /**
843 * @return {@code true} if the container is in changing app transition.
844 */
845 boolean isChangingAppTransition() {
Evan Rosky55bddd82020-01-29 13:07:18 -0800846 return mDisplayContent != null && mDisplayContent.mChangingContainers.contains(this);
lumark19a5d2e2019-10-11 16:19:30 +0800847 }
848
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700849 void sendAppVisibilityToClients() {
850 for (int i = mChildren.size() - 1; i >= 0; --i) {
851 final WindowContainer wc = mChildren.get(i);
852 wc.sendAppVisibilityToClients();
853 }
854 }
855
Wale Ogunwale44f21802016-09-02 12:49:48 -0700856 /**
857 * Returns true if the container or one of its children as some content it can display or wants
858 * to display (e.g. app views or saved surface).
859 *
860 * NOTE: While this method will return true if the there is some content to display, it doesn't
861 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
862 * visible.
863 */
864 boolean hasContentToDisplay() {
865 for (int i = mChildren.size() - 1; i >= 0; --i) {
866 final WindowContainer wc = mChildren.get(i);
867 if (wc.hasContentToDisplay()) {
868 return true;
869 }
870 }
871 return false;
872 }
873
874 /**
875 * Returns true if the container or one of its children is considered visible from the
876 * WindowManager perspective which usually means valid surface and some other internal state
877 * are true.
878 *
879 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
880 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
881 * the container has any content to display.
882 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700883 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700884 // TODO: Will this be more correct if it checks the visibility of its parents?
885 // It depends...For example, Tasks and Stacks are only visible if there children are visible
886 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800887 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700888 for (int i = mChildren.size() - 1; i >= 0; --i) {
889 final WindowContainer wc = mChildren.get(i);
890 if (wc.isVisible()) {
891 return true;
892 }
893 }
894 return false;
895 }
896
Evan Roskya80f11c2020-01-23 19:17:10 -0800897 /**
Evan Rosky55bddd82020-01-29 13:07:18 -0800898 * Called when the visibility of a child is asked to change. This is before visibility actually
899 * changes (eg. a transition animation might play out first).
900 */
901 void onChildVisibilityRequested(boolean visible) {
902 // If we are changing visibility, then a snapshot isn't necessary and we are no-longer
903 // part of a change transition.
904 mSurfaceFreezer.unfreeze(getPendingTransaction());
905 if (mDisplayContent != null) {
906 mDisplayContent.mChangingContainers.remove(this);
907 }
908 WindowContainer parent = getParent();
909 if (parent != null) {
910 parent.onChildVisibilityRequested(visible);
911 }
912 }
913
914 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) {
915 final long token = proto.start(fieldId);
916 proto.write(HASH_CODE, System.identityHashCode(this));
917 proto.write(USER_ID, USER_NULL);
918 proto.write(TITLE, "WindowContainer");
919 proto.end(token);
920 }
921
922 /**
Evan Roskya80f11c2020-01-23 19:17:10 -0800923 * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
924 * this will not be focusable either.
925 */
Evan Rosky226de132020-01-03 18:00:29 -0800926 boolean isFocusable() {
Evan Roskya80f11c2020-01-23 19:17:10 -0800927 final WindowContainer parent = getParent();
928 return (parent == null || parent.isFocusable()) && mIsFocusable;
Evan Rosky226de132020-01-03 18:00:29 -0800929 }
930
931 /** Set whether this container or its children can be focusable */
Evan Rosky226de132020-01-03 18:00:29 -0800932 boolean setFocusable(boolean focusable) {
933 if (mIsFocusable == focusable) {
934 return false;
935 }
936 mIsFocusable = focusable;
937 return true;
938 }
939
Bryce Lee00d586d2017-07-28 20:48:43 -0700940 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700941 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700942 */
943 boolean isOnTop() {
944 return getParent().getTopChild() == this && getParent().isOnTop();
945 }
946
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100947 /** Returns the top child container. */
948 E getTopChild() {
949 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700950 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700951
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700952 /** Returns true if there is still a removal being deferred */
953 boolean checkCompleteDeferredRemoval() {
954 boolean stillDeferringRemoval = false;
955
956 for (int i = mChildren.size() - 1; i >= 0; --i) {
957 final WindowContainer wc = mChildren.get(i);
958 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
959 }
960
961 return stillDeferringRemoval;
962 }
963
964 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700965 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700966 for (int i = mChildren.size() - 1; i >= 0; --i) {
967 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700968 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700969 }
970 }
971
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700972 void onAppTransitionDone() {
973 for (int i = mChildren.size() - 1; i >= 0; --i) {
974 final WindowContainer wc = mChildren.get(i);
975 wc.onAppTransitionDone();
976 }
977 }
978
Garfield Tan90b04282018-12-11 14:04:42 -0800979 /**
980 * Called when this container or one of its descendants changed its requested orientation, and
981 * wants this container to handle it or pass it to its parent.
982 *
983 * @param freezeDisplayToken freeze this app window token if display needs to freeze
984 * @param requestingContainer the container which orientation request has changed
985 * @return {@code true} if handled; {@code false} otherwise.
986 */
987 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
988 @Nullable ConfigurationContainer requestingContainer) {
989 final WindowContainer parent = getParent();
990 if (parent == null) {
991 return false;
992 }
993 return parent.onDescendantOrientationChanged(freezeDisplayToken,
994 requestingContainer);
995 }
996
997 /**
Garfield Tan49dae102019-02-04 09:51:59 -0800998 * Check if this container or its parent will handle orientation changes from descendants. It's
999 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
1000 * ConfigurationContainer)} in the sense that the return value of this method tells if this
1001 * container or its parent will handle the request eventually, while the return value of the
1002 * other method is if it handled the request synchronously.
1003 *
1004 * @return {@code true} if it handles or will handle orientation change in the future; {@code
1005 * false} if it won't handle the change at anytime.
1006 */
1007 boolean handlesOrientationChangeFromDescendant() {
1008 final WindowContainer parent = getParent();
1009 return parent != null && parent.handlesOrientationChangeFromDescendant();
1010 }
1011
1012 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001013 * Get the configuration orientation by the requested screen orientation
1014 * ({@link ActivityInfo.ScreenOrientation}) of this activity.
1015 *
1016 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
1017 * {@link Configuration#ORIENTATION_PORTRAIT},
1018 * {@link Configuration#ORIENTATION_UNDEFINED}).
1019 */
1020 int getRequestedConfigurationOrientation() {
1021 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
1022 // NOSENSOR means the display's "natural" orientation, so return that.
1023 if (mDisplayContent != null) {
1024 return mDisplayContent.getNaturalOrientation();
1025 }
1026 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
1027 // LOCKED means the activity's orientation remains unchanged, so return existing value.
1028 return getConfiguration().orientation;
1029 } else if (isFixedOrientationLandscape(mOrientation)) {
1030 return ORIENTATION_LANDSCAPE;
1031 } else if (isFixedOrientationPortrait(mOrientation)) {
1032 return ORIENTATION_PORTRAIT;
1033 }
1034 return ORIENTATION_UNDEFINED;
1035 }
1036
1037 /**
Garfield Tan90b04282018-12-11 14:04:42 -08001038 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
1039 * parameters.
1040 *
1041 * @param orientation the specified orientation.
1042 */
Wale Ogunwale51362492016-09-08 17:49:17 -07001043 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001044 setOrientation(orientation, null /* freezeDisplayToken */,
1045 null /* ActivityRecord */);
1046 }
1047
1048 /**
1049 * Sets the specified orientation of this container. It percolates this change upward along the
1050 * hierarchy to let each level of the hierarchy a chance to respond to it.
1051 *
1052 * @param orientation the specified orientation. Needs to be one of {@link
1053 * android.content.pm.ActivityInfo.ScreenOrientation}.
1054 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
1055 * done. Display will not be frozen if this is {@code null}, which
1056 * should only happen in tests.
1057 * @param requestingContainer the container which orientation request has changed. Mostly used
1058 * to ensure it gets correct configuration.
1059 */
1060 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
1061 @Nullable ConfigurationContainer requestingContainer) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001062 if (mOrientation == orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001063 return;
1064 }
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001065
1066 mOrientation = orientation;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001067 final int configOrientation = getRequestedConfigurationOrientation();
1068 if (getRequestedOverrideConfiguration().orientation != configOrientation) {
1069 mTmpConfig.setTo(getRequestedOverrideConfiguration());
1070 mTmpConfig.orientation = configOrientation;
1071 onRequestedOverrideConfigurationChanged(mTmpConfig);
1072 }
1073
Garfield Tan90b04282018-12-11 14:04:42 -08001074 final WindowContainer parent = getParent();
1075 if (parent != null) {
1076 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
1077 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001078 }
1079
Vadim Caen1096f112019-12-18 11:44:26 +01001080 @ActivityInfo.ScreenOrientation
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001081 int getOrientation() {
1082 return getOrientation(mOrientation);
1083 }
1084
Wale Ogunwale51362492016-09-08 17:49:17 -07001085 /**
1086 * Returns the specified orientation for this window container or one of its children is there
1087 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
1088 * specification is set.
1089 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
1090 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001091 *
1092 * @param candidate The current orientation candidate that will be returned if we don't find a
1093 * better match.
1094 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -07001095 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001096 int getOrientation(int candidate) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001097 mLastOrientationSource = null;
Bryce Leea163b762017-01-24 11:05:01 -08001098 if (!fillsParent()) {
1099 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -07001100 return SCREEN_ORIENTATION_UNSET;
1101 }
1102
Bryce Leea163b762017-01-24 11:05:01 -08001103 // The container fills its parent so we can use it orientation if it has one
1104 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -07001105 // specified and fall back on this container's unset or unspecified value as a candidate
1106 // if none of the children have a better candidate for the orientation.
1107 if (mOrientation != SCREEN_ORIENTATION_UNSET
1108 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
Riddle Hsu6f548e92020-01-13 13:34:09 +08001109 mLastOrientationSource = this;
Wale Ogunwale51362492016-09-08 17:49:17 -07001110 return mOrientation;
1111 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001112
1113 for (int i = mChildren.size() - 1; i >= 0; --i) {
1114 final WindowContainer wc = mChildren.get(i);
1115
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001116 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
1117 // SCREEN_ORIENTATION_UNSPECIFIED?
1118 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
1119 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -07001120 if (orientation == SCREEN_ORIENTATION_BEHIND) {
1121 // container wants us to use the orientation of the container behind it. See if we
1122 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
1123 // look behind this container.
1124 candidate = orientation;
Riddle Hsu6f548e92020-01-13 13:34:09 +08001125 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001126 continue;
1127 }
1128
1129 if (orientation == SCREEN_ORIENTATION_UNSET) {
1130 continue;
1131 }
1132
1133 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1134 // Use the orientation if the container fills its parent or requested an explicit
1135 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
Vadim Caenfc14c662020-01-20 16:00:31 +01001136 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
1137 wc.toString(), orientation,
1138 ActivityInfo.screenOrientationToString(orientation));
Riddle Hsu6f548e92020-01-13 13:34:09 +08001139 mLastOrientationSource = wc;
Wale Ogunwale51362492016-09-08 17:49:17 -07001140 return orientation;
1141 }
1142 }
1143
1144 return candidate;
1145 }
1146
1147 /**
Riddle Hsu6f548e92020-01-13 13:34:09 +08001148 * @return The deepest source which decides the orientation of this window container since the
1149 * last time {@link #getOrientation(int) was called.
1150 */
1151 @Nullable
1152 WindowContainer getLastOrientationSource() {
1153 final WindowContainer source = mLastOrientationSource;
1154 if (source != null && source != this) {
1155 final WindowContainer nextSource = source.getLastOrientationSource();
1156 if (nextSource != null) {
1157 return nextSource;
1158 }
1159 }
1160 return source;
1161 }
1162
1163 /**
Wale Ogunwale51362492016-09-08 17:49:17 -07001164 * Returns true if this container is opaque and fills all the space made available by its parent
1165 * container.
1166 *
1167 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
1168 * this is just a signal from the client to window manager stating its intent, but not what it
1169 * actually does.
1170 */
1171 boolean fillsParent() {
1172 return false;
1173 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001174
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001175 // TODO: Users would have their own window containers under the display container?
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001176 void switchUser(int userId) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001177 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001178 mChildren.get(i).switchUser(userId);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001179 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001180 }
1181
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08001182 boolean showToCurrentUser() {
1183 return true;
1184 }
1185
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001186 /**
1187 * For all windows at or below this container call the callback.
1188 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
1189 * stops the search if {@link ToBooleanFunction#apply} returns true.
1190 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
1191 * z-order, else from bottom-to-top.
1192 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -08001193 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001194 */
1195 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001196 if (traverseTopToBottom) {
1197 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001198 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1199 return true;
1200 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001201 }
1202 } else {
1203 final int count = mChildren.size();
1204 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001205 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1206 return true;
1207 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001208 }
1209 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001210 return false;
1211 }
1212
1213 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001214 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
1215 forAllWindows(wrapper, traverseTopToBottom);
1216 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001217 }
1218
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001219 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001220 return forAllActivities(callback, true /*traverseTopToBottom*/);
1221 }
1222
1223 boolean forAllActivities(
1224 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
1225 if (traverseTopToBottom) {
1226 for (int i = mChildren.size() - 1; i >= 0; --i) {
1227 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
1228 }
1229 } else {
1230 final int count = mChildren.size();
1231 for (int i = 0; i < count; i++) {
1232 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
lumark9bca6b42019-10-17 18:35:22 +08001233 }
lumark588a3e82018-07-20 18:53:54 +08001234 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001235
lumark9bca6b42019-10-17 18:35:22 +08001236 return false;
lumark588a3e82018-07-20 18:53:54 +08001237 }
1238
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001239 void forAllActivities(Consumer<ActivityRecord> callback) {
1240 forAllActivities(callback, true /*traverseTopToBottom*/);
1241 }
1242
1243 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
1244 if (traverseTopToBottom) {
1245 for (int i = mChildren.size() - 1; i >= 0; --i) {
1246 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1247 }
1248 } else {
1249 final int count = mChildren.size();
1250 for (int i = 0; i < count; i++) {
1251 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1252 }
1253 }
1254 }
1255
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001256 /**
1257 * Process all activities in this branch of the tree.
1258 *
1259 * @param callback Called for each activity found.
1260 * @param boundary We don't return activities via {@param callback} until we get to this node in
1261 * the tree.
1262 * @param includeBoundary If the boundary from be processed to return activities.
1263 * @param traverseTopToBottom direction to traverse the tree.
1264 * @return {@code true} if we ended the search before reaching the end of the tree.
1265 */
1266 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1267 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1268 return forAllActivities(
1269 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1270 }
1271
1272 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1273 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1274 boolean[] boundaryFound) {
1275 if (traverseTopToBottom) {
1276 for (int i = mChildren.size() - 1; i >= 0; --i) {
1277 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1278 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1279 return true;
1280 }
1281 }
1282 } else {
1283 final int count = mChildren.size();
1284 for (int i = 0; i < count; i++) {
1285 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1286 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1287 return true;
1288 }
1289 }
1290 }
1291
1292 return false;
1293 }
1294
1295 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
1296 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1297 boolean[] boundaryFound, WindowContainer wc) {
1298 if (wc == boundary) {
1299 boundaryFound[0] = true;
1300 if (!includeBoundary) return false;
1301 }
1302
1303 if (boundaryFound[0]) {
1304 return wc.forAllActivities(callback, traverseTopToBottom);
1305 }
1306
1307 return wc.forAllActivities(
1308 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1309 }
1310
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001311 /** @return {@code true} if this node or any of its children contains an activity. */
1312 boolean hasActivity() {
1313 for (int i = mChildren.size() - 1; i >= 0; --i) {
1314 if (mChildren.get(i).hasActivity()) {
1315 return true;
1316 }
1317 }
1318 return false;
1319 }
1320
1321 ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
1322 return getActivity(callback, true /*traverseTopToBottom*/);
1323 }
1324
1325 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001326 return getActivity(callback, traverseTopToBottom, null /*boundary*/);
1327 }
1328
1329 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
1330 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001331 if (traverseTopToBottom) {
1332 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001333 final WindowContainer wc = mChildren.get(i);
1334 if (wc == boundary) return null;
1335
1336 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001337 if (r != null) {
1338 return r;
1339 }
1340 }
1341 } else {
1342 final int count = mChildren.size();
1343 for (int i = 0; i < count; i++) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001344 final WindowContainer wc = mChildren.get(i);
1345 if (wc == boundary) return null;
1346
1347 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001348 if (r != null) {
1349 return r;
1350 }
1351 }
1352 }
1353
1354 return null;
1355 }
1356
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001357 /**
1358 * Gets an activity in a branch of the tree.
1359 *
1360 * @param callback called to test if this is the activity that should be returned.
1361 * @param boundary We don't return activities via {@param callback} until we get to this node in
1362 * the tree.
1363 * @param includeBoundary If the boundary from be processed to return activities.
1364 * @param traverseTopToBottom direction to traverse the tree.
1365 * @return The activity if found or null.
1366 */
1367 final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1368 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1369 return getActivity(
1370 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1371 }
1372
1373 private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1374 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1375 boolean[] boundaryFound) {
1376 if (traverseTopToBottom) {
1377 for (int i = mChildren.size() - 1; i >= 0; --i) {
1378 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1379 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1380 if (r != null) {
1381 return r;
1382 }
1383 }
1384 } else {
1385 final int count = mChildren.size();
1386 for (int i = 0; i < count; i++) {
1387 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1388 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1389 if (r != null) {
1390 return r;
1391 }
1392 }
1393 }
1394
1395 return null;
1396 }
1397
1398 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
1399 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1400 boolean[] boundaryFound, WindowContainer wc) {
1401 if (wc == boundary || boundary == null) {
1402 boundaryFound[0] = true;
1403 if (!includeBoundary) return null;
1404 }
1405
1406 if (boundaryFound[0]) {
1407 return wc.getActivity(callback, traverseTopToBottom);
1408 }
1409
1410 return wc.getActivity(
1411 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1412 }
1413
1414 ActivityRecord getActivityAbove(ActivityRecord r) {
1415 return getActivity((above) -> true, r,
1416 false /*includeBoundary*/, false /*traverseTopToBottom*/);
1417 }
1418
1419 ActivityRecord getActivityBelow(ActivityRecord r) {
1420 return getActivity((below) -> true, r,
1421 false /*includeBoundary*/, true /*traverseTopToBottom*/);
1422 }
1423
1424 ActivityRecord getBottomMostActivity() {
1425 return getActivity((r) -> true, false /*traverseTopToBottom*/);
1426 }
1427
1428 ActivityRecord getTopMostActivity() {
1429 return getActivity((r) -> true, true /*traverseTopToBottom*/);
1430 }
1431
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001432 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
1433 // Break down into 4 calls to avoid object creation due to capturing input params.
1434 if (includeFinishing) {
1435 if (includeOverlays) {
1436 return getActivity((r) -> true);
1437 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001438 return getActivity((r) -> !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001439 } else if (includeOverlays) {
1440 return getActivity((r) -> !r.finishing);
1441 }
1442
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001443 return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001444 }
1445
Winson Chungd5852192019-09-06 17:20:28 -07001446 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
1447 for (int i = mChildren.size() - 1; i >= 0; --i) {
1448 mChildren.get(i).forAllWallpaperWindows(callback);
1449 }
1450 }
1451
Jorim Jaggi51304d72017-05-17 17:25:32 +02001452 /**
1453 * For all tasks at or below this container call the callback.
1454 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001455 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
1456 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
1457 */
1458 boolean forAllTasks(Function<Task, Boolean> callback) {
1459 for (int i = mChildren.size() - 1; i >= 0; --i) {
1460 if (mChildren.get(i).forAllTasks(callback)) {
1461 return true;
1462 }
1463 }
1464 return false;
1465 }
1466
1467 /**
1468 * For all tasks at or below this container call the callback.
1469 *
Jorim Jaggi51304d72017-05-17 17:25:32 +02001470 * @param callback Callback to be called for every task.
1471 */
1472 void forAllTasks(Consumer<Task> callback) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001473 forAllTasks(callback, true /*traverseTopToBottom*/);
1474 }
1475
1476 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
1477 final int count = mChildren.size();
1478 if (traverseTopToBottom) {
1479 for (int i = count - 1; i >= 0; --i) {
1480 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1481 }
1482 } else {
1483 for (int i = 0; i < count; i++) {
1484 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1485 }
Jorim Jaggi51304d72017-05-17 17:25:32 +02001486 }
1487 }
1488
Wale Ogunwale0d465192020-01-23 19:14:44 -08001489 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
Jeff Changdc9c1d42020-02-11 14:57:34 +08001490 final int count = mChildren.size();
1491 if (traverseTopToBottom) {
1492 for (int i = count - 1; i >= 0; --i) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001493 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001494 }
1495 } else {
1496 for (int i = 0; i < count; i++) {
Wale Ogunwale0d465192020-01-23 19:14:44 -08001497 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom);
Jeff Changdc9c1d42020-02-11 14:57:34 +08001498 }
1499 }
1500 }
1501
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001502 Task getTaskAbove(Task t) {
1503 return getTask(
1504 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
1505 }
1506
1507 Task getTaskBelow(Task t) {
1508 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/);
1509 }
1510
1511 Task getBottomMostTask() {
1512 return getTask((t) -> true, false /*traverseTopToBottom*/);
1513 }
1514
1515 Task getTopMostTask() {
1516 return getTask((t) -> true, true /*traverseTopToBottom*/);
1517 }
1518
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001519 Task getTask(Predicate<Task> callback) {
1520 return getTask(callback, true /*traverseTopToBottom*/);
1521 }
1522
1523 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
1524 if (traverseTopToBottom) {
1525 for (int i = mChildren.size() - 1; i >= 0; --i) {
1526 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1527 if (t != null) {
1528 return t;
1529 }
1530 }
1531 } else {
1532 final int count = mChildren.size();
1533 for (int i = 0; i < count; i++) {
1534 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1535 if (t != null) {
1536 return t;
1537 }
1538 }
1539 }
1540
1541 return null;
1542 }
1543
lumarkbc0032a2019-11-01 21:38:13 +08001544 /**
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001545 * Gets an task in a branch of the tree.
lumarkbc0032a2019-11-01 21:38:13 +08001546 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001547 * @param callback called to test if this is the task that should be returned.
1548 * @param boundary We don't return tasks via {@param callback} until we get to this node in
1549 * the tree.
1550 * @param includeBoundary If the boundary from be processed to return tasks.
1551 * @param traverseTopToBottom direction to traverse the tree.
1552 * @return The task if found or null.
lumarkbc0032a2019-11-01 21:38:13 +08001553 */
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001554 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary,
1555 boolean traverseTopToBottom) {
1556 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1557 }
1558
1559 private Task getTask(Predicate<Task> callback,
1560 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1561 boolean[] boundaryFound) {
1562 if (traverseTopToBottom) {
1563 for (int i = mChildren.size() - 1; i >= 0; --i) {
1564 final Task t = processGetTaskWithBoundary(callback, boundary,
1565 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1566 if (t != null) {
1567 return t;
1568 }
1569 }
1570 } else {
1571 final int count = mChildren.size();
1572 for (int i = 0; i < count; i++) {
1573 final Task t = processGetTaskWithBoundary(callback, boundary,
1574 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1575 if (t != null) {
1576 return t;
1577 }
lumarkbc0032a2019-11-01 21:38:13 +08001578 }
1579 }
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001580
1581 return null;
1582 }
1583
1584 private Task processGetTaskWithBoundary(Predicate<Task> callback,
1585 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1586 boolean[] boundaryFound, WindowContainer wc) {
1587 if (wc == boundary || boundary == null) {
1588 boundaryFound[0] = true;
1589 if (!includeBoundary) return null;
1590 }
1591
1592 if (boundaryFound[0]) {
1593 return wc.getTask(callback, traverseTopToBottom);
1594 }
1595
1596 return wc.getTask(
1597 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
lumarkbc0032a2019-11-01 21:38:13 +08001598 }
1599
Wale Ogunwaled1880962016-11-08 10:31:59 -08001600 WindowState getWindow(Predicate<WindowState> callback) {
1601 for (int i = mChildren.size() - 1; i >= 0; --i) {
1602 final WindowState w = mChildren.get(i).getWindow(callback);
1603 if (w != null) {
1604 return w;
1605 }
1606 }
1607
1608 return null;
1609 }
1610
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001611 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -07001612 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
1613 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001614 */
1615 @Override
1616 public int compareTo(WindowContainer other) {
1617 if (this == other) {
1618 return 0;
1619 }
1620
1621 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +02001622 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001623 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
1624 }
1625
1626 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
1627 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001628 try {
1629 getParents(thisParentChain);
1630 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001631
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001632 // Find the common ancestor of both containers.
1633 WindowContainer commonAncestor = null;
1634 WindowContainer thisTop = thisParentChain.peekLast();
1635 WindowContainer otherTop = otherParentChain.peekLast();
1636 while (thisTop != null && otherTop != null && thisTop == otherTop) {
1637 commonAncestor = thisParentChain.removeLast();
1638 otherParentChain.removeLast();
1639 thisTop = thisParentChain.peekLast();
1640 otherTop = otherParentChain.peekLast();
1641 }
1642
1643 // Containers don't belong to the same hierarchy???
1644 if (commonAncestor == null) {
1645 throw new IllegalArgumentException("No in the same hierarchy this="
1646 + thisParentChain + " other=" + otherParentChain);
1647 }
1648
1649 // Children are always considered greater than their parents, so if one of the containers
1650 // we are comparing it the parent of the other then whichever is the child is greater.
1651 if (commonAncestor == this) {
1652 return -1;
1653 } else if (commonAncestor == other) {
1654 return 1;
1655 }
1656
1657 // The position of the first non-common ancestor in the common ancestor list determines
1658 // which is greater the which.
1659 final WindowList<WindowContainer> list = commonAncestor.mChildren;
1660 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
1661 ? 1 : -1;
1662 } finally {
1663 mTmpChain1.clear();
1664 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001665 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001666 }
1667
1668 private void getParents(LinkedList<WindowContainer> parents) {
1669 parents.clear();
1670 WindowContainer current = this;
1671 do {
1672 parents.addLast(current);
1673 current = current.mParent;
1674 } while (current != null);
1675 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001676
Robert Carrb1579c82017-09-05 14:54:47 -07001677 SurfaceControl.Builder makeSurface() {
1678 final WindowContainer p = getParent();
1679 return p.makeChildSurface(this);
1680 }
1681
Robert Carrf59b8dd2017-10-02 18:58:36 -07001682 /**
1683 * @param child The WindowContainer this child surface is for, or null if the Surface
1684 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1685 */
Robert Carrb1579c82017-09-05 14:54:47 -07001686 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1687 final WindowContainer p = getParent();
1688 // Give the parent a chance to set properties. In hierarchy v1 we rely
1689 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001690 return p.makeChildSurface(child)
1691 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001692 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001693 /*
1694 * @return The SurfaceControl parent for this containers SurfaceControl.
1695 * The SurfaceControl must be valid if non-null.
1696 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001697 @Override
1698 public SurfaceControl getParentSurfaceControl() {
1699 final WindowContainer parent = getParent();
1700 if (parent == null) {
1701 return null;
1702 }
1703 return parent.getSurfaceControl();
1704 }
1705
Robert Carrb1579c82017-09-05 14:54:47 -07001706 /**
1707 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1708 */
1709 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001710 if (mSurfaceControl == null) {
1711 return false;
1712 }
1713
Robert Carrb1579c82017-09-05 14:54:47 -07001714 for (int i = 0; i < mChildren.size(); i++) {
1715 if (!mChildren.get(i).shouldMagnify()) {
1716 return false;
1717 }
1718 }
1719 return true;
1720 }
1721
1722 SurfaceSession getSession() {
1723 if (getParent() != null) {
1724 return getParent().getSession();
1725 }
1726 return null;
1727 }
1728
1729 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001730 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1731 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001732 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001733 mLastLayer = layer;
1734 mLastRelativeToLayer = null;
1735 }
1736 }
1737
1738 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1739 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1740 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001741 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001742 mLastLayer = layer;
1743 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001744 }
1745 }
1746
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001747 protected void setLayer(Transaction t, int layer) {
1748
1749 // Route through surface animator to accommodate that our surface control might be
1750 // attached to the leash, and leash is attached to parent container.
1751 mSurfaceAnimator.setLayer(t, layer);
1752 }
1753
1754 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1755
1756 // Route through surface animator to accommodate that our surface control might be
1757 // attached to the leash, and leash is attached to parent container.
1758 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1759 }
1760
1761 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1762 mSurfaceAnimator.reparent(t, newParent);
1763 }
1764
Robert Carrb1579c82017-09-05 14:54:47 -07001765 void assignChildLayers(Transaction t) {
1766 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001767
1768 // We use two passes as a way to promote children which
1769 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001770 for (int j = 0; j < mChildren.size(); ++j) {
1771 final WindowContainer wc = mChildren.get(j);
1772 wc.assignChildLayers(t);
1773 if (!wc.needsZBoost()) {
1774 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001775 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001776 }
1777 for (int j = 0; j < mChildren.size(); ++j) {
1778 final WindowContainer wc = mChildren.get(j);
1779 if (wc.needsZBoost()) {
1780 wc.assignLayer(t, layer++);
1781 }
Robert Carrb1579c82017-09-05 14:54:47 -07001782 }
1783 }
1784
1785 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001786 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001787 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001788 }
1789
1790 boolean needsZBoost() {
1791 for (int i = 0; i < mChildren.size(); i++) {
1792 if (mChildren.get(i).needsZBoost()) {
1793 return true;
1794 }
1795 }
1796 return false;
1797 }
1798
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001799 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001800 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001801 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001802 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001803 * @param proto Stream to write the WindowContainer object to.
1804 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001805 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001806 * @hide
1807 */
1808 @CallSuper
1809 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08001810 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001811 @WindowTraceLogLevel int logLevel) {
1812 boolean isVisible = isVisible();
1813 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1814 return;
1815 }
1816
Adrian Roos4921ccf2017-09-28 16:54:06 +02001817 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001818 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001819 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001820 proto.write(VISIBLE, isVisible);
1821 if (mSurfaceAnimator.isAnimating()) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001822 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001823 }
Vishnu Nairdddc9f52020-03-09 09:37:27 -07001824
1825 // add children to proto
1826 for (int i = 0; i < getChildCount(); i++) {
1827 final long childToken = proto.start(WindowContainerProto.CHILDREN);
1828 final E child = getChildAt(i);
1829 child.dumpDebug(proto, child.getProtoFieldId(), logLevel);
1830 proto.end(childToken);
1831 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001832 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001833 }
1834
Vishnu Nairdddc9f52020-03-09 09:37:27 -07001835 /**
1836 * @return a proto field id to identify where to add the derived class to the generic window
1837 * container proto.
1838 */
1839 long getProtoFieldId() {
1840 return WINDOW_CONTAINER;
1841 }
1842
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001843 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1844 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1845 if (wrapper == null) {
1846 wrapper = new ForAllWindowsConsumerWrapper();
1847 }
1848 wrapper.setConsumer(consumer);
1849 return wrapper;
1850 }
1851
1852 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1853
1854 private Consumer<WindowState> mConsumer;
1855
1856 void setConsumer(Consumer<WindowState> consumer) {
1857 mConsumer = consumer;
1858 }
1859
1860 @Override
1861 public boolean apply(WindowState w) {
1862 mConsumer.accept(w);
1863 return false;
1864 }
1865
1866 void release() {
1867 mConsumer = null;
1868 mConsumerWrapperPool.release(this);
1869 }
1870 }
Robert Carrb1579c82017-09-05 14:54:47 -07001871
1872 // TODO(b/68336570): Should this really be on WindowContainer since it
1873 // can only be used on the top-level nodes that aren't animated?
1874 // (otherwise we would be fighting other callers of setMatrix).
1875 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1876 if (shouldMagnify()) {
1877 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1878 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
Robert Carr7603dea2019-07-17 13:16:21 -07001879 mLastMagnificationSpec = spec;
Robert Carrb1579c82017-09-05 14:54:47 -07001880 } else {
Jackal Guoa8b3a272019-12-16 15:24:58 +08001881 clearMagnificationSpec(t);
Robert Carrb1579c82017-09-05 14:54:47 -07001882 for (int i = 0; i < mChildren.size(); i++) {
1883 mChildren.get(i).applyMagnificationSpec(t, spec);
1884 }
1885 }
1886 }
1887
Robert Carr7603dea2019-07-17 13:16:21 -07001888 void clearMagnificationSpec(Transaction t) {
1889 if (mLastMagnificationSpec != null) {
1890 t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
1891 .setPosition(mSurfaceControl, 0, 0);
1892 }
1893 mLastMagnificationSpec = null;
1894 for (int i = 0; i < mChildren.size(); i++) {
1895 mChildren.get(i).clearMagnificationSpec(t);
1896 }
1897 }
1898
Robert Carrb1579c82017-09-05 14:54:47 -07001899 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08001900 // If a leash has been set when the transaction was committed, then the leash reparent has
1901 // been committed.
1902 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001903 for (int i = 0; i < mChildren.size(); i++) {
1904 mChildren.get(i).prepareSurfaces();
1905 }
1906 }
1907
1908 /**
chaviw7f1fa992018-01-10 13:52:12 -08001909 * @return true if the reparent to animation leash transaction has been committed, false
1910 * otherwise.
1911 */
1912 boolean hasCommittedReparentToAnimationLeash() {
1913 return mCommittedReparentToAnimationLeash;
1914 }
1915
1916 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08001917 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1918 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07001919 */
1920 void scheduleAnimation() {
1921 if (mParent != null) {
1922 mParent.scheduleAnimation();
1923 }
1924 }
1925
Robert Carrdea7bf42019-04-04 12:02:51 -07001926 /**
1927 * @return The SurfaceControl for this container.
1928 * The SurfaceControl must be valid if non-null.
1929 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001930 @Override
1931 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001932 return mSurfaceControl;
1933 }
1934
Jorim Jaggia5e10572017-11-15 14:36:26 +01001935 @Override
1936 public Transaction getPendingTransaction() {
Robert Carre10ee3d2019-11-11 15:03:15 -08001937 if (mUsingBLASTSyncTransaction) {
1938 return mBLASTSyncTransaction;
1939 }
1940
Tiger Huanged6794e2019-05-07 20:07:59 +08001941 final DisplayContent displayContent = getDisplayContent();
1942 if (displayContent != null && displayContent != this) {
1943 return displayContent.getPendingTransaction();
1944 }
1945 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1946 // let the caller to save the surface operations within the local mPendingTransaction.
1947 // If this is not a DisplayContent, we will merge it to the pending transaction of its
1948 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07001949 return mPendingTransaction;
1950 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001951
1952 /**
1953 * Starts an animation on the container.
1954 *
1955 * @param anim The animation to run.
1956 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1957 * some point but the meaning is too weird to work for all containers.
Issei Suzuki8b995df2020-01-08 12:23:04 +01001958 * @param type The type of animation defined as {@link AnimationType}.
Issei Suzuki2f541842020-01-09 20:18:29 +01001959 * @param animationFinishedCallback The callback being triggered when the animation finishes.
Jorim Jaggia5e10572017-11-15 14:36:26 +01001960 */
Issei Suzuki2f541842020-01-09 20:18:29 +01001961 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
Issei Suzuki8b995df2020-01-08 12:23:04 +01001962 @AnimationType int type,
1963 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
1964 if (DEBUG_ANIM) {
1965 Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim);
1966 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001967
1968 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1969 // the moment this doesn't work for all animatable window containers.
Evan Rosky55bddd82020-01-29 13:07:18 -08001970 mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback,
1971 mSurfaceFreezer);
Issei Suzuki2f541842020-01-09 20:18:29 +01001972 }
1973
Issei Suzuki8b995df2020-01-08 12:23:04 +01001974 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
1975 @AnimationType int type) {
1976 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01001977 }
1978
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001979 void transferAnimation(WindowContainer from) {
1980 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1981 }
1982
Jorim Jaggia5e10572017-11-15 14:36:26 +01001983 void cancelAnimation() {
1984 mSurfaceAnimator.cancelAnimation();
1985 }
1986
1987 @Override
Evan Rosky55bddd82020-01-29 13:07:18 -08001988 public SurfaceControl getFreezeSnapshotTarget() {
1989 return null;
1990 }
1991
1992 @Override
Jorim Jaggia5e10572017-11-15 14:36:26 +01001993 public Builder makeAnimationLeash() {
Vishnu Nairfd6fb672020-02-14 12:56:37 -08001994 return makeSurface().setContainerLayer();
Jorim Jaggia5e10572017-11-15 14:36:26 +01001995 }
1996
Jorim Jaggi596a1992017-12-29 14:48:02 +01001997 @Override
1998 public SurfaceControl getAnimationLeashParent() {
1999 return getParentSurfaceControl();
2000 }
2001
chaviw23ee71c2017-12-18 11:29:41 -08002002 /**
2003 * @return The layer on which all app animations are happening.
2004 */
Jorim Jaggi391790622018-04-18 15:30:44 +02002005 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08002006 final WindowContainer parent = getParent();
2007 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02002008 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08002009 }
2010 return null;
2011 }
2012
lumark19a5d2e2019-10-11 16:19:30 +08002013 // TODO: Remove this and use #getBounds() instead once we set an app transition animation
2014 // on TaskStack.
2015 Rect getAnimationBounds(int appStackClipMode) {
lumark85718662019-12-26 22:05:12 +08002016 return getDisplayedBounds();
lumark19a5d2e2019-10-11 16:19:30 +08002017 }
2018
2019 /**
2020 * Applies the app transition animation according the given the layout properties in the
2021 * window hierarchy.
2022 *
2023 * @param lp The layout parameters of the window.
2024 * @param transit The app transition type indicates what kind of transition to be applied.
2025 * @param enter Whether the app transition is entering transition or not.
2026 * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
2027 *
2028 * @return {@code true} when the container applied the app transition, {@code false} if the
2029 * app transition is disabled or skipped.
2030 *
2031 * @see #getAnimationAdapter
2032 */
2033 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Issei Suzuki8b995df2020-01-08 12:23:04 +01002034 boolean isVoiceInteraction,
2035 @Nullable OnAnimationFinishedCallback animationFinishedCallback) {
lumark19a5d2e2019-10-11 16:19:30 +08002036 if (mWmService.mDisableTransitionAnimation) {
2037 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
2038 "applyAnimation: transition animation is disabled or skipped. "
2039 + "container=%s", this);
2040 cancelAnimation();
2041 return false;
2042 }
2043
2044 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
2045 // to animate and it can cause strange artifacts when we unfreeze the display if some
2046 // different animation is running.
2047 try {
2048 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
2049 if (okToAnimate()) {
lumarkbc0032a2019-11-01 21:38:13 +08002050 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
2051 transit, enter, isVoiceInteraction);
lumark19a5d2e2019-10-11 16:19:30 +08002052 AnimationAdapter adapter = adapters.first;
2053 AnimationAdapter thumbnailAdapter = adapters.second;
2054 if (adapter != null) {
Issei Suzuki2f541842020-01-09 20:18:29 +01002055 startAnimation(getPendingTransaction(), adapter, !isVisible(),
Issei Suzuki8b995df2020-01-08 12:23:04 +01002056 ANIMATION_TYPE_APP_TRANSITION, animationFinishedCallback);
lumark19a5d2e2019-10-11 16:19:30 +08002057 if (adapter.getShowWallpaper()) {
lumark5341d1c2019-12-14 01:54:02 +08002058 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
lumark19a5d2e2019-10-11 16:19:30 +08002059 }
2060 if (thumbnailAdapter != null) {
Evan Rosky55bddd82020-01-29 13:07:18 -08002061 mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(),
2062 thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION,
2063 (type, anim) -> { });
lumark19a5d2e2019-10-11 16:19:30 +08002064 }
2065 }
2066 } else {
2067 cancelAnimation();
2068 }
2069 } finally {
2070 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
2071 }
2072
2073 return isAnimating();
2074 }
2075
2076 /**
2077 * Gets the {@link AnimationAdapter} according the given window layout properties in the window
2078 * hierarchy.
2079 *
2080 * @return The return value will always contain two elements, one for normal animations and the
2081 * other for thumbnail animation, both can be {@code null}.
2082 *
2083 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
2084 * @See LocalAnimationAdapter
2085 */
2086 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
2087 int transit, boolean enter, boolean isVoiceInteraction) {
2088 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
2089 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
2090
2091 // Separate position and size for use in animators.
2092 mTmpRect.set(getAnimationBounds(appStackClipMode));
lumark85718662019-12-26 22:05:12 +08002093 if (sHierarchicalAnimations) {
2094 getRelativeDisplayedPosition(mTmpPoint);
2095 } else {
2096 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
2097 }
lumark19a5d2e2019-10-11 16:19:30 +08002098 mTmpRect.offsetTo(0, 0);
2099
2100 final RemoteAnimationController controller =
2101 getDisplayContent().mAppTransition.getRemoteAnimationController();
2102 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
2103 && isChangingAppTransition();
2104
2105 // Delaying animation start isn't compatible with remote animations at all.
2106 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
lumark2ec19122020-01-23 00:09:04 +08002107 final Rect localBounds = new Rect(mTmpRect);
2108 localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y);
lumark19a5d2e2019-10-11 16:19:30 +08002109 final RemoteAnimationController.RemoteAnimationRecord adapters =
lumark2ec19122020-01-23 00:09:04 +08002110 controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds,
2111 mTmpRect, (isChanging ? mSurfaceFreezer.mFreezeBounds : null));
lumark19a5d2e2019-10-11 16:19:30 +08002112 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
2113 } else if (isChanging) {
2114 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
2115 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2116 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
2117
lumarkbc0032a2019-11-01 21:38:13 +08002118 final AnimationAdapter adapter = new LocalAnimationAdapter(
Evan Rosky55bddd82020-01-29 13:07:18 -08002119 new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect,
2120 displayInfo, durationScale, true /* isAppAnimation */,
2121 false /* isThumbnail */),
lumark19a5d2e2019-10-11 16:19:30 +08002122 getSurfaceAnimationRunner());
2123
Evan Rosky55bddd82020-01-29 13:07:18 -08002124 final AnimationAdapter thumbnailAdapter = mSurfaceFreezer.mSnapshot != null
2125 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(
2126 mSurfaceFreezer.mFreezeBounds, mTmpRect, displayInfo, durationScale,
2127 true /* isAppAnimation */, true /* isThumbnail */), getSurfaceAnimationRunner())
lumarkbc0032a2019-11-01 21:38:13 +08002128 : null;
lumark19a5d2e2019-10-11 16:19:30 +08002129 resultAdapters = new Pair<>(adapter, thumbnailAdapter);
2130 mTransit = transit;
2131 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2132 } else {
2133 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2134 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2135
2136 if (a != null) {
2137 // Only apply corner radius to animation if we're not in multi window mode.
2138 // We don't want rounded corners when in pip or split screen.
2139 final float windowCornerRadius = !inMultiWindowMode()
2140 ? getDisplayContent().getWindowCornerRadius()
2141 : 0;
2142 AnimationAdapter adapter = new LocalAnimationAdapter(
2143 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
2144 getDisplayContent().mAppTransition.canSkipFirstFrame(),
2145 appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
2146 getSurfaceAnimationRunner());
2147
2148 resultAdapters = new Pair<>(adapter, null);
2149 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP;
2150 mTransit = transit;
2151 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2152 } else {
2153 resultAdapters = new Pair<>(null, null);
2154 }
2155 }
2156 return resultAdapters;
2157 }
2158
2159 final SurfaceAnimationRunner getSurfaceAnimationRunner() {
2160 return mWmService.mSurfaceAnimationRunner;
2161 }
2162
2163 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2164 boolean isVoiceInteraction) {
2165 final DisplayContent displayContent = getDisplayContent();
2166 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2167 final int width = displayInfo.appWidth;
2168 final int height = displayInfo.appHeight;
2169 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
2170
2171 // Determine the visible rect to calculate the thumbnail clip with
2172 // getAnimationFrames.
2173 final Rect frame = new Rect(0, 0, width, height);
2174 final Rect displayFrame = new Rect(0, 0,
2175 displayInfo.logicalWidth, displayInfo.logicalHeight);
2176 final Rect insets = new Rect();
2177 final Rect stableInsets = new Rect();
2178 final Rect surfaceInsets = new Rect();
2179 getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
2180
2181 if (mLaunchTaskBehind) {
2182 // Differentiate the two animations. This one which is briefly on the screen
2183 // gets the !enter animation, and the other one which remains on the
2184 // screen gets the enter animation. Both appear in the mOpeningApps set.
2185 enter = false;
2186 }
2187 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2188 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2189 + "surfaceInsets=%s",
2190 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
2191 final Configuration displayConfig = displayContent.getConfiguration();
2192 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
2193 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2194 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
2195 if (a != null) {
lumark8669ef32020-02-10 18:41:57 +08002196 if (a != null) {
2197 // Setup the maximum app transition duration to prevent malicious app may set a long
2198 // animation duration or infinite repeat counts for the app transition through
2199 // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition.
2200 a.restrictDuration(MAX_APP_TRANSITION_DURATION);
2201 }
2202 if (DEBUG_ANIM) {
2203 logWithStack(TAG, "Loaded animation " + a + " for " + this
2204 + ", duration: " + ((a != null) ? a.getDuration() : 0));
2205 }
lumark19a5d2e2019-10-11 16:19:30 +08002206 final int containingWidth = frame.width();
2207 final int containingHeight = frame.height();
2208 a.initialize(containingWidth, containingHeight, width, height);
2209 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
2210 }
2211 return a;
2212 }
2213
2214 RemoteAnimationTarget createRemoteAnimationTarget(
2215 RemoteAnimationController.RemoteAnimationRecord record) {
2216 return null;
2217 }
2218
Daichi Hirono8ecfc6b2020-02-18 16:28:03 +09002219 boolean canCreateRemoteAnimationTarget() {
2220 return false;
2221 }
2222
lumark19a5d2e2019-10-11 16:19:30 +08002223 boolean okToDisplay() {
lumark5341d1c2019-12-14 01:54:02 +08002224 final DisplayContent dc = getDisplayContent();
2225 return dc != null && dc.okToDisplay();
lumark19a5d2e2019-10-11 16:19:30 +08002226 }
2227
2228 boolean okToAnimate() {
lumark3b8bbc82019-12-02 16:22:08 +08002229 return okToAnimate(false /* ignoreFrozen */);
2230 }
2231
2232 boolean okToAnimate(boolean ignoreFrozen) {
lumark5341d1c2019-12-14 01:54:02 +08002233 final DisplayContent dc = getDisplayContent();
2234 return dc != null && dc.okToAnimate(ignoreFrozen);
lumark19a5d2e2019-10-11 16:19:30 +08002235 }
2236
Jorim Jaggia5e10572017-11-15 14:36:26 +01002237 @Override
2238 public void commitPendingTransaction() {
2239 scheduleAnimation();
2240 }
2241
Robert Carr2f8aa392018-01-31 14:46:51 -08002242 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01002243 final WindowContainer parent = getParent();
2244 if (parent != null) {
2245 parent.assignChildLayers(t);
2246 }
2247 }
2248
2249 @Override
2250 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002251 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002252 reassignLayer(t);
2253 }
2254
2255 @Override
lumarkf6f34942019-04-29 16:56:50 +08002256 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002257 mLastLayer = -1;
Evan Rosky55bddd82020-01-29 13:07:18 -08002258 mSurfaceFreezer.unfreeze(t);
Jorim Jaggia5e10572017-11-15 14:36:26 +01002259 reassignLayer(t);
2260 }
2261
2262 /**
2263 * Called when an animation has finished running.
2264 */
Issei Suzuki8b995df2020-01-08 12:23:04 +01002265 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) {
chaviwccd5d502019-02-22 13:30:31 -08002266 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002267 }
2268
2269 /**
2270 * @return The currently running animation, if any, or {@code null} otherwise.
2271 */
2272 AnimationAdapter getAnimation() {
2273 return mSurfaceAnimator.getAnimation();
2274 }
2275
2276 /**
lumark5bd11af2019-12-21 01:52:28 +08002277 * @return The {@link WindowContainer} which is running an animation.
2278 *
2279 * It traverses from the current container to its parents recursively. If nothing is animating,
2280 * it will return {@code null}.
2281 */
2282 @Nullable
2283 WindowContainer getAnimatingContainer() {
2284 if (isAnimating()) {
2285 return this;
2286 }
2287 final WindowContainer parent = getParent();
2288 return (parent != null) ? parent.getAnimatingContainer() : null;
2289 }
2290
2291 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +01002292 * @see SurfaceAnimator#startDelayingAnimationStart
2293 */
2294 void startDelayingAnimationStart() {
2295 mSurfaceAnimator.startDelayingAnimationStart();
2296 }
2297
2298 /**
2299 * @see SurfaceAnimator#endDelayingAnimationStart
2300 */
2301 void endDelayingAnimationStart() {
2302 mSurfaceAnimator.endDelayingAnimationStart();
2303 }
2304
2305 @Override
2306 public int getSurfaceWidth() {
2307 return mSurfaceControl.getWidth();
2308 }
2309
2310 @Override
2311 public int getSurfaceHeight() {
2312 return mSurfaceControl.getHeight();
2313 }
2314
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002315 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01002316 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2317 if (mSurfaceAnimator.isAnimating()) {
2318 pw.print(prefix); pw.println("ContainerAnimator:");
2319 mSurfaceAnimator.dump(pw, prefix + " ");
2320 }
2321 }
chaviwe07246a2017-12-12 16:18:29 -08002322
chaviw2f0567b2018-01-29 16:22:02 -08002323 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08002324 if (mSurfaceControl == null) {
2325 return;
2326 }
2327
Evan Roskyed6767f2018-10-26 17:21:06 -07002328 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08002329 if (mTmpPos.equals(mLastSurfacePosition)) {
2330 return;
2331 }
2332
chaviw2f0567b2018-01-29 16:22:02 -08002333 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08002334 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08002335 }
2336
Evan Rosky65dffa62019-02-04 14:09:53 -08002337 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002338 Point getLastSurfacePosition() {
2339 return mLastSurfacePosition;
2340 }
2341
Evan Roskyed6767f2018-10-26 17:21:06 -07002342 /**
2343 * Displayed bounds specify where to display this container at. It differs from bounds during
2344 * certain operations (like animation or interactive dragging).
2345 *
2346 * @return the bounds to display this container at.
2347 */
2348 Rect getDisplayedBounds() {
2349 return getBounds();
2350 }
2351
lumark19a5d2e2019-10-11 16:19:30 +08002352 /**
2353 * The {@code outFrame} retrieved by this method specifies where the animation will finish
2354 * the entrance animation, as the next frame will display the window at these coordinates. In
2355 * case of exit animation, this is where the animation will start, as the frame before the
2356 * animation is displaying the window at these bounds.
2357 *
2358 * @param outFrame The bounds where entrance animation finishes or exit animation starts.
2359 * @param outInsets Insets that are covered by system windows.
2360 * @param outStableInsets Insets that determine the area covered by the stable system windows.
2361 * @param outSurfaceInsets Positive insets between the drawing surface and window content.
2362 */
2363 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2364 Rect outSurfaceInsets) {
2365 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2366 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
2367 outInsets.setEmpty();
2368 outStableInsets.setEmpty();
2369 outSurfaceInsets.setEmpty();
2370 }
2371
Evan Roskyed6767f2018-10-26 17:21:06 -07002372 void getRelativeDisplayedPosition(Point outPos) {
2373 final Rect dispBounds = getDisplayedBounds();
2374 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08002375 final WindowContainer parent = getParent();
2376 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002377 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08002378 outPos.offset(-parentBounds.left, -parentBounds.top);
2379 }
2380 }
chaviw2fb06bc2018-01-19 17:09:15 -08002381
Yunfan Chen87b5a242019-10-01 17:53:59 +09002382 void waitForAllWindowsDrawn() {
Yunfan Chen87b5a242019-10-01 17:53:59 +09002383 forAllWindows(w -> {
Riddle Hsu5df3b752019-12-16 13:27:37 -06002384 w.requestDrawIfNeeded(mWaitingForDrawn);
Yunfan Chen87b5a242019-10-01 17:53:59 +09002385 }, true /* traverseTopToBottom */);
2386 }
2387
chaviw2fb06bc2018-01-19 17:09:15 -08002388 Dimmer getDimmer() {
2389 if (mParent == null) {
2390 return null;
2391 }
2392 return mParent.getDimmer();
2393 }
Robert Carr8a2f9132019-11-11 15:03:15 -08002394
2395 void setSurfaceControl(SurfaceControl sc) {
2396 mSurfaceControl = sc;
2397 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002398
Evan Rosky55bddd82020-01-29 13:07:18 -08002399 RemoteAnimationDefinition getRemoteAnimationDefinition() {
2400 return null;
2401 }
2402
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002403 /** Cheap way of doing cast and instanceof. */
2404 Task asTask() {
2405 return null;
2406 }
2407
2408 /** Cheap way of doing cast and instanceof. */
2409 ActivityRecord asActivityRecord() {
2410 return null;
2411 }
Evan Roskya80f11c2020-01-23 19:17:10 -08002412
2413 RemoteToken getRemoteToken() {
2414 return mRemoteToken;
2415 }
2416
Evan Roskya8fde152020-01-07 19:09:13 -08002417 static WindowContainer fromBinder(IBinder binder) {
2418 return RemoteToken.fromBinder(binder).getContainer();
2419 }
2420
Evan Roskya80f11c2020-01-23 19:17:10 -08002421 static class RemoteToken extends IWindowContainer.Stub {
2422 final WeakReference<WindowContainer> mWeakRef;
2423
2424 RemoteToken(WindowContainer container) {
2425 mWeakRef = new WeakReference<>(container);
2426 }
2427
2428 WindowContainer getContainer() {
2429 return mWeakRef.get();
2430 }
2431
2432 static RemoteToken fromBinder(IBinder binder) {
2433 return (RemoteToken) binder;
2434 }
2435
2436 @Override
2437 public SurfaceControl getLeash() {
2438 throw new RuntimeException("Not implemented");
2439 }
2440
2441 @Override
2442 public String toString() {
2443 StringBuilder sb = new StringBuilder(128);
2444 sb.append("RemoteToken{");
2445 sb.append(Integer.toHexString(System.identityHashCode(this)));
2446 sb.append(' ');
2447 sb.append(mWeakRef.get());
2448 sb.append('}');
2449 return sb.toString();
2450 }
2451 }
Robert Carre10ee3d2019-11-11 15:03:15 -08002452
2453 @Override
2454 public void transactionReady(int mSyncId, SurfaceControl.Transaction mergedTransaction) {
2455 mergedTransaction.merge(mBLASTSyncTransaction);
2456 mUsingBLASTSyncTransaction = false;
2457
2458 mWaitingListener.transactionReady(mWaitingSyncId, mergedTransaction);
2459
2460 mWaitingListener = null;
2461 mWaitingSyncId = -1;
2462 }
2463
Rob Carr25376512020-03-09 15:23:19 -07002464 /**
2465 * Returns true if any of the children elected to participate in the Sync
2466 */
2467 boolean addChildrenToSyncSet(int localId) {
2468 boolean willSync = false;
2469
2470 for (int i = 0; i < mChildren.size(); i++) {
2471 final WindowContainer child = mChildren.get(i);
2472 willSync |= mBLASTSyncEngine.addToSyncSet(localId, child);
2473 }
2474 return willSync;
2475 }
2476
Robert Carre10ee3d2019-11-11 15:03:15 -08002477 boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener,
2478 int waitingId) {
Robert Carr8ccc4fc2020-03-13 10:48:49 -07002479 boolean willSync = true;
2480
2481 // If we are invisible, no need to sync, likewise if we are already engaged in a sync,
2482 // we can't support overlapping syncs on a single container yet.
2483 if (!isVisible() || mWaitingListener != null) {
2484 return false;
Robert Carre10ee3d2019-11-11 15:03:15 -08002485 }
2486 mUsingBLASTSyncTransaction = true;
2487
Robert Carre10ee3d2019-11-11 15:03:15 -08002488 // Make sure to set these before we call setReady in case the sync was a no-op
2489 mWaitingSyncId = waitingId;
2490 mWaitingListener = waitingListener;
2491
Rob Carr25376512020-03-09 15:23:19 -07002492 int localId = mBLASTSyncEngine.startSyncSet(this);
2493 willSync |= addChildrenToSyncSet(localId);
Robert Carre10ee3d2019-11-11 15:03:15 -08002494 mBLASTSyncEngine.setReady(localId);
2495
2496 return willSync;
2497 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07002498}