blob: 015b92c7cd034c56f54ea351b42417b2f3e7dc9c [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;
Vishnu Nair04ab4392018-01-10 11:00:06 -080028import static android.view.SurfaceControl.Transaction;
Louis Chang7501e332018-08-20 13:08:39 +080029
lumark19a5d2e2019-10-11 16:19:30 +080030import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
31import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
32import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
Vadim Caen1096f112019-12-18 11:44:26 +010033import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
lumark9bca6b42019-10-17 18:35:22 +080034import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
35import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
36import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070037import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
38import static com.android.server.wm.WindowContainerProto.ORIENTATION;
39import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
40import static com.android.server.wm.WindowContainerProto.VISIBLE;
Louis Chang7501e332018-08-20 13:08:39 +080041import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
42import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
43import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
lumark19a5d2e2019-10-11 16:19:30 +080044import static com.android.server.wm.WindowManagerService.logWithStack;
lumark85718662019-12-26 22:05:12 +080045import static com.android.server.wm.WindowManagerService.sHierarchicalAnimations;
lumark19a5d2e2019-10-11 16:19:30 +080046import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM;
Jorim Jaggi612bb882017-05-16 17:11:18 +020047
Wale Ogunwaled63594a2016-07-18 07:48:30 -070048import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020049import android.annotation.IntDef;
Garfield Tan90b04282018-12-11 14:04:42 -080050import android.annotation.Nullable;
Jorim Jaggi391790622018-04-18 15:30:44 +020051import android.app.WindowConfiguration;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080052import android.content.pm.ActivityInfo;
Andrii Kulian441e4492016-09-29 15:25:00 -070053import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080054import android.graphics.Point;
55import android.graphics.Rect;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -080056import android.os.Debug;
Garfield Tan90b04282018-12-11 14:04:42 -080057import android.os.IBinder;
lumark19a5d2e2019-10-11 16:19:30 +080058import android.os.Trace;
59import android.util.Pair;
Vishnu Nair04ab4392018-01-10 11:00:06 -080060import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010061import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080062import android.util.proto.ProtoOutputStream;
lumark19a5d2e2019-10-11 16:19:30 +080063import android.view.DisplayInfo;
Evan Roskya80f11c2020-01-23 19:17:10 -080064import android.view.IWindowContainer;
Robert Carrb1579c82017-09-05 14:54:47 -070065import android.view.MagnificationSpec;
lumark19a5d2e2019-10-11 16:19:30 +080066import android.view.RemoteAnimationTarget;
Robert Carrb1579c82017-09-05 14:54:47 -070067import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010068import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070069import android.view.SurfaceSession;
lumark19a5d2e2019-10-11 16:19:30 +080070import android.view.WindowManager;
71import android.view.animation.Animation;
Garfield Tan2f145f22018-11-01 15:27:03 -070072
Evan Rosky65dffa62019-02-04 14:09:53 -080073import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010074import com.android.internal.util.ToBooleanFunction;
lumark19a5d2e2019-10-11 16:19:30 +080075import com.android.server.protolog.common.ProtoLog;
Jorim Jaggia5e10572017-11-15 14:36:26 +010076import com.android.server.wm.SurfaceAnimator.Animatable;
Garfield Tan2f145f22018-11-01 15:27:03 -070077
Jorim Jaggia5e10572017-11-15 14:36:26 +010078import java.io.PrintWriter;
Evan Roskya80f11c2020-01-23 19:17:10 -080079import java.lang.ref.WeakReference;
Yunfan Chen87b5a242019-10-01 17:53:59 +090080import java.util.ArrayList;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070081import java.util.Comparator;
82import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070083import java.util.function.Consumer;
Wale Ogunwaledfbeed72019-11-20 08:57:39 -080084import java.util.function.Function;
Wale Ogunwaled1880962016-11-08 10:31:59 -080085import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070086
87/**
88 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070089 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -070090 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
91 * changes are made to this class.
92 */
Wale Ogunwale98d62312017-07-12 09:24:56 -070093class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Jorim Jaggia5e10572017-11-15 14:36:26 +010094 implements Comparable<WindowContainer>, Animatable {
95
96 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070097
Louis Changdc077272019-11-12 16:52:56 +080098 /** Animation layer that happens above all animating {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +020099 static final int ANIMATION_LAYER_STANDARD = 0;
100
Louis Changdc077272019-11-12 16:52:56 +0800101 /** Animation layer that happens above all {@link ActivityStack}s. */
Jorim Jaggi391790622018-04-18 15:30:44 +0200102 static final int ANIMATION_LAYER_BOOSTED = 1;
103
104 /**
105 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -0700106 * activities and all activities that are being controlled by the recents animation. This
Louis Changdc077272019-11-12 16:52:56 +0800107 * layer is generally below all {@link ActivityStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +0200108 */
109 static final int ANIMATION_LAYER_HOME = 2;
110
111 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
112 ANIMATION_LAYER_STANDARD,
113 ANIMATION_LAYER_BOOSTED,
114 ANIMATION_LAYER_HOME,
115 })
116 @interface AnimationLayer {}
117
Andrii Kuliand2765632016-12-12 22:26:34 -0800118 static final int POSITION_TOP = Integer.MAX_VALUE;
119 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
120
Andrii Kulian441e4492016-09-29 15:25:00 -0700121 /**
122 * The parent of this window container.
123 * For removing or setting new parent {@link #setParent} should be used, because it also
124 * performs configuration updates based on new parent's settings.
125 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100126 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700127
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200128 // Set to true when we are performing a reparenting operation so we only send one
129 // onParentChanged() notification.
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700130 boolean mReparenting;
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200131
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700132 // List of children for this window container. List is in z-order as the children appear on
133 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200134 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700135
Wale Ogunwale51362492016-09-08 17:49:17 -0700136 // The specified orientation for this window container.
Vadim Caen1096f112019-12-18 11:44:26 +0100137 @ActivityInfo.ScreenOrientation
Wale Ogunwale51362492016-09-08 17:49:17 -0700138 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
139
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800140 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
141 new Pools.SynchronizedPool<>(3);
142
Tiger Huanged6794e2019-05-07 20:07:59 +0800143 // The display this window container is on.
144 protected DisplayContent mDisplayContent;
145
Robert Carrb1579c82017-09-05 14:54:47 -0700146 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100147 private int mLastLayer = 0;
148 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700149
Tiger Huanged6794e2019-05-07 20:07:59 +0800150 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
151 private final Transaction mPendingTransaction;
152
Robert Carrb1579c82017-09-05 14:54:47 -0700153 /**
Yunfan Chen87b5a242019-10-01 17:53:59 +0900154 * Windows that clients are waiting to have drawn.
155 */
156 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>();
157
158 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700159 * Applied as part of the animation pass in "prepareSurfaces".
160 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100161 protected final SurfaceAnimator mSurfaceAnimator;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800162 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100163
chaviwe07246a2017-12-12 16:18:29 -0800164 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800165 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800166
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100167 /** Total number of elements in this subtree, including our own hierarchy element. */
168 private int mTreeWeight = 1;
169
chaviw7f1fa992018-01-10 13:52:12 -0800170 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700171 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800172 * surface to the animation leash
173 */
174 private boolean mCommittedReparentToAnimationLeash;
175
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800176 private final Configuration mTmpConfig = new Configuration();
177
lumark9bca6b42019-10-17 18:35:22 +0800178 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */
179 public interface AnimationFlags {
180 /**
181 * A bit flag indicates that {@link #isAnimating} should also return {@code true}
182 * even though the container is not yet animating, but the window container or its
183 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition}
184 * that is pending so an animation starts soon.
185 */
186 int TRANSITION = 1;
187
188 /**
189 * A bit flag indicates that {@link #isAnimating} should also check if one of the
190 * ancestors of the container are animating in addition to the container itself.
191 */
192 int PARENTS = 2;
193
194 /**
195 * A bit flag indicates that {@link #isAnimating} should also check if one of the
196 * descendants of the container are animating in addition to the container itself.
197 */
198 int CHILDREN = 4;
199 }
200
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200201 /**
202 * Callback which is triggered while changing the parent, after setting up the surface but
203 * before asking the parent to assign child layers.
204 */
205 interface PreAssignChildLayersCallback {
206 void onPreAssignChildLayers();
207 }
208
lumark19a5d2e2019-10-11 16:19:30 +0800209 /**
210 * True if this an AppWindowToken and the activity which created this was launched with
211 * ActivityOptions.setLaunchTaskBehind.
212 *
213 * TODO(b/142617871): We run a special animation when the activity was launched with that
214 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly
215 * selected to suppress an animation, and remove this flag.
216 */
217 boolean mLaunchTaskBehind;
218
219 /**
220 * If we are running an animation, this determines the transition type. Must be one of
221 * {@link AppTransition#TransitionFlags}.
222 */
223 int mTransit;
224
225 /**
226 * If we are running an animation, this determines the flags during this animation. Must be a
227 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants.
228 */
229 int mTransitFlags;
230
231 /** Whether this container should be boosted at the top of all its siblings. */
232 @VisibleForTesting boolean mNeedsZBoost;
233
234 /** Layer used to constrain the animation to a container's stack bounds. */
235 SurfaceControl mAnimationBoundsLayer;
236
237 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */
238 boolean mNeedsAnimationBoundsLayer;
239
240 /**
241 * This gets used during some open/close transitions as well as during a change transition
242 * where it represents the starting-state snapshot.
243 */
lumarkbc0032a2019-11-01 21:38:13 +0800244 WindowContainerThumbnail mThumbnail;
lumark19a5d2e2019-10-11 16:19:30 +0800245 final Rect mTransitStartRect = new Rect();
246 final Point mTmpPoint = new Point();
247 protected final Rect mTmpRect = new Rect();
248 final Rect mTmpPrevBounds = new Rect();
249
Robert Carr7603dea2019-07-17 13:16:21 -0700250 private MagnificationSpec mLastMagnificationSpec;
251
Evan Rosky226de132020-01-03 18:00:29 -0800252 private boolean mIsFocusable = true;
253
Evan Roskya80f11c2020-01-23 19:17:10 -0800254 /**
255 * Used as a unique, cross-process identifier for this Container. It also serves a minimal
256 * interface to other processes.
257 */
258 RemoteToken mRemoteToken = null;
259
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800260 WindowContainer(WindowManagerService wms) {
261 mWmService = wms;
Vishnu Nair33197392019-08-30 10:29:37 -0700262 mPendingTransaction = wms.mTransactionFactory.get();
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800263 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100264 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800265
Wale Ogunwale98d62312017-07-12 09:24:56 -0700266 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700267 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700268 return mParent;
269 }
270
Wale Ogunwale98d62312017-07-12 09:24:56 -0700271 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700272 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700273 return mChildren.size();
274 }
275
276 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700277 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700278 return mChildren.get(index);
279 }
280
chaviwe07246a2017-12-12 16:18:29 -0800281 @Override
282 public void onConfigurationChanged(Configuration newParentConfig) {
283 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800284 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800285 scheduleAnimation();
286 }
287
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200288 void reparent(WindowContainer newParent, int position) {
289 if (newParent == null) {
290 throw new IllegalArgumentException("reparent: can't reparent to null " + this);
291 }
292
293 final WindowContainer oldParent = mParent;
294 if (mParent == newParent) {
295 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent);
296 }
297
298 // The display object before reparenting as that might lead to old parent getting removed
299 // from the display if it no longer has any child.
300 final DisplayContent prevDc = oldParent.getDisplayContent();
301 final DisplayContent dc = newParent.getDisplayContent();
302
303 mReparenting = true;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700304 oldParent.removeChild(this);
Louis Chang2453d062019-11-19 22:30:48 +0800305 newParent.addChild(this, position);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200306 mReparenting = false;
307
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200308 // Relayout display(s)
309 dc.setLayoutNeeded();
310 if (prevDc != dc) {
311 onDisplayChanged(dc);
312 prevDc.setLayoutNeeded();
313 }
314 getDisplayContent().layoutAndAssignWindowLayersIfNeeded();
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700315
316 // Send onParentChanged notification here is we disabled sending it in setParent for
317 // reparenting case.
318 onParentChanged(newParent, oldParent);
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200319 }
320
Jorim Jaggia5e10572017-11-15 14:36:26 +0100321 final protected void setParent(WindowContainer<WindowContainer> parent) {
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200322 final WindowContainer oldParent = mParent;
Andrii Kulian441e4492016-09-29 15:25:00 -0700323 mParent = parent;
Wale Ogunwalea38654f2019-11-17 20:37:15 -0800324
325 if (mParent != null) {
326 mParent.onChildAdded(this);
327 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200328 if (!mReparenting) {
lumarkbde15132019-12-18 22:29:43 +0800329 if (mParent != null && mParent.mDisplayContent != null
330 && mDisplayContent != mParent.mDisplayContent) {
331 onDisplayChanged(mParent.mDisplayContent);
332 }
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200333 onParentChanged(mParent, oldParent);
334 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800335 }
336
337 /**
338 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
339 * Supposed to be overridden and contain actions that should be executed after parent was set.
340 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800341 @Override
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200342 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) {
343 onParentChanged(newParent, oldParent, null);
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200344 }
345
Wale Ogunwalec17418e2019-10-13 23:00:40 +0200346 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent,
347 PreAssignChildLayersCallback callback) {
348 super.onParentChanged(newParent, oldParent);
Robert Carrb1579c82017-09-05 14:54:47 -0700349 if (mParent == null) {
350 return;
351 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100352
Robert Carrb1579c82017-09-05 14:54:47 -0700353 if (mSurfaceControl == null) {
354 // If we don't yet have a surface, but we now have a parent, we should
355 // build a surface.
Robert Carr8a2f9132019-11-11 15:03:15 -0800356 setSurfaceControl(makeSurface().build());
Robert Carrf59b8dd2017-10-02 18:58:36 -0700357 getPendingTransaction().show(mSurfaceControl);
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700358 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700359 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100360 // If we have a surface but a new parent, we just need to perform a reparent. Go through
361 // surface animator such that hierarchy is preserved when animating, i.e.
362 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
363 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100364 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700365 }
366
Issei Suzuki25a9e2b2019-08-14 16:46:26 +0200367 if (callback != null) {
368 callback.onPreAssignChildLayers();
369 }
370
Robert Carrb1579c82017-09-05 14:54:47 -0700371 // Either way we need to ask the parent to assign us a Z-order.
372 mParent.assignChildLayers();
373 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700374 }
375
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700376 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100377 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
378 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700379
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700380 /**
381 * Adds the input window container has a child of this container in order based on the input
382 * comparator.
383 * @param child The window container to add as a child of this window container.
384 * @param comparator Comparator to use in determining the position the child should be added to.
385 * If null, the child will be added to the top.
386 */
387 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700388 protected void addChild(E child, Comparator<E> comparator) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700389 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700390 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700391 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700392 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700393 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700394
Andrii Kulianb94292e2016-10-19 13:30:58 -0700395 int positionToAdd = -1;
396 if (comparator != null) {
397 final int count = mChildren.size();
398 for (int i = 0; i < count; i++) {
399 if (comparator.compare(child, mChildren.get(i)) < 0) {
400 positionToAdd = i;
401 break;
402 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700403 }
404 }
405
Andrii Kulianb94292e2016-10-19 13:30:58 -0700406 if (positionToAdd == -1) {
407 mChildren.add(child);
408 } else {
409 mChildren.add(positionToAdd, child);
410 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100411
Andrii Kulianb94292e2016-10-19 13:30:58 -0700412 // Set the parent after we've actually added a child in case a subclass depends on this.
413 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700414 }
415
Wale Ogunwalef6192862016-09-10 13:42:30 -0700416 /** Adds the input window container has a child of this container at the input index. */
417 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800418 void addChild(E child, int index) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700419 if (!child.mReparenting && child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700420 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700421 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800422 + " can't add to container=" + getName()
423 + "\n callers=" + Debug.getCallers(15, "\n"));
Wale Ogunwalef6192862016-09-10 13:42:30 -0700424 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900425
426 if ((index < 0 && index != POSITION_BOTTOM)
427 || (index > mChildren.size() && index != POSITION_TOP)) {
428 throw new IllegalArgumentException("addChild: invalid position=" + index
429 + ", children number=" + mChildren.size());
430 }
431
432 if (index == POSITION_TOP) {
433 index = mChildren.size();
434 } else if (index == POSITION_BOTTOM) {
435 index = 0;
436 }
437
Wale Ogunwalef6192862016-09-10 13:42:30 -0700438 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100439
Andrii Kulianb94292e2016-10-19 13:30:58 -0700440 // Set the parent after we've actually added a child in case a subclass depends on this.
441 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700442 }
443
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100444 private void onChildAdded(WindowContainer child) {
445 mTreeWeight += child.mTreeWeight;
446 WindowContainer parent = getParent();
447 while (parent != null) {
448 parent.mTreeWeight += child.mTreeWeight;
449 parent = parent.getParent();
450 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200451 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100452 }
453
Wale Ogunwalef6192862016-09-10 13:42:30 -0700454 /**
455 * Removes the input child container from this container which is its parent.
456 *
457 * @return True if the container did contain the input child and it was detached.
458 */
459 @CallSuper
460 void removeChild(E child) {
461 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100462 onChildRemoved(child);
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700463 if (!child.mReparenting) {
464 child.setParent(null);
465 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700466 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700467 throw new IllegalArgumentException("removeChild: container=" + child.getName()
468 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700469 }
470 }
471
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100472 private void onChildRemoved(WindowContainer child) {
473 mTreeWeight -= child.mTreeWeight;
474 WindowContainer parent = getParent();
475 while (parent != null) {
476 parent.mTreeWeight -= child.mTreeWeight;
477 parent = parent.getParent();
478 }
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200479 onChildPositionChanged(child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100480 }
481
Wale Ogunwale571771c2016-08-26 13:18:50 -0700482 /**
483 * Removes this window container and its children with no regard for what else might be going on
484 * in the system. For example, the container will be removed during animation if this method is
485 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
486 * which allows the system to defer removal until a suitable time.
487 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700488 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700489 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700490 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100491 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700492 child.removeImmediately();
493 // Need to do this after calling remove on the child because the child might try to
494 // remove/detach itself from its parent which will cause an exception if we remove
495 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100496 if (mChildren.remove(child)) {
497 onChildRemoved(child);
498 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700499 }
500
Robert Carrb1579c82017-09-05 14:54:47 -0700501 if (mSurfaceControl != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800502 getPendingTransaction().remove(mSurfaceControl);
chaviw6728e2f2018-03-19 15:58:04 -0700503
504 // Merge to parent transaction to ensure the transactions on this WindowContainer are
505 // applied in native even if WindowContainer is removed.
506 if (mParent != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800507 mParent.getPendingTransaction().merge(getPendingTransaction());
chaviw6728e2f2018-03-19 15:58:04 -0700508 }
509
Robert Carr8a2f9132019-11-11 15:03:15 -0800510 setSurfaceControl(null);
Garfield Tan265ab91a2019-11-12 16:30:49 -0800511 mLastSurfacePosition.set(0, 0);
Chavi Weingartenb736e322018-02-23 00:27:54 +0000512 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700513 }
514
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700515 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700516 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700517 }
518 }
519
520 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100521 * @return The index of this element in the hierarchy tree in prefix order.
522 */
523 int getPrefixOrderIndex() {
524 if (mParent == null) {
525 return 0;
526 }
527 return mParent.getPrefixOrderIndex(this);
528 }
529
530 private int getPrefixOrderIndex(WindowContainer child) {
531 int order = 0;
532 for (int i = 0; i < mChildren.size(); i++) {
533 final WindowContainer childI = mChildren.get(i);
534 if (child == childI) {
535 break;
536 }
537 order += childI.mTreeWeight;
538 }
539 if (mParent != null) {
540 order += mParent.getPrefixOrderIndex(this);
541 }
542
543 // We also need to count ourselves.
544 order++;
545 return order;
546 }
547
548 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700549 * Removes this window container and its children taking care not to remove them during a
550 * critical stage in the system. For example, some containers will not be removed during
551 * animation if this method is called.
552 */
553 // TODO: figure-out implementation that works best for this.
554 // E.g. when do we remove from parent list? maybe not...
555 void removeIfPossible() {
556 for (int i = mChildren.size() - 1; i >= 0; --i) {
557 final WindowContainer wc = mChildren.get(i);
558 wc.removeIfPossible();
559 }
560 }
561
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700562 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000563 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700564 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000565 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700566 if (current == child || current.hasChild(child)) {
567 return true;
568 }
569 }
570 return false;
571 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700572
Issei Suzuki2f541842020-01-09 20:18:29 +0100573 /** @return true if this window container is a descendant of the input container. */
574 boolean isDescendantOf(WindowContainer ancestor) {
575 final WindowContainer parent = getParent();
576 if (parent == ancestor) return true;
577 return (parent != null) && parent.isDescendantOf(ancestor);
578 }
579
Andrii Kulian441e4492016-09-29 15:25:00 -0700580 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800581 * Move a child from it's current place in siblings list to the specified position,
582 * with an option to move all its parents to top.
583 * @param position Target position to move the child to.
584 * @param child Child to move to selected position.
585 * @param includingParents Flag indicating whether we need to move the entire branch of the
586 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
587 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
588 * this flag will do nothing.
589 */
590 @CallSuper
591 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800592
593 if (child.getParent() != this) {
594 throw new IllegalArgumentException("removeChild: container=" + child.getName()
595 + " is not a child of container=" + getName()
596 + " current parent=" + child.getParent());
597 }
598
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800599 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800600 position = POSITION_TOP;
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -0700601 } else if (position <= 0) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800602 position = POSITION_BOTTOM;
603 }
604
605 switch (position) {
606 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800607 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800608 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200609 mChildren.add(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200610 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800611 }
612 if (includingParents && getParent() != null) {
613 getParent().positionChildAt(POSITION_TOP, this /* child */,
614 true /* includingParents */);
615 }
616 break;
617 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800618 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800619 mChildren.remove(child);
620 mChildren.addFirst(child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200621 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800622 }
623 if (includingParents && getParent() != null) {
624 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
625 true /* includingParents */);
626 }
627 break;
628 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800629 // TODO: Removing the child before reinserting requires the caller to provide a
630 // position that takes into account the removed child (if the index of the
631 // child < position, then the position should be adjusted). We should consider
632 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800633 mChildren.remove(child);
634 mChildren.add(position, child);
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200635 onChildPositionChanged(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800636 }
637 }
638
639 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800640 * Notify that a child's position has changed. Possible changes are adding or removing a child.
641 */
Wale Ogunwale2322bed2019-10-10 17:24:19 +0200642 void onChildPositionChanged(WindowContainer child) { }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800643
644 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700645 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700646 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700647 * @see #mFullConfiguration
648 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700649 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700650 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800651 // We must diff before the configuration is applied so that we can capture the change
652 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700653 final int diff = diffRequestedOverrideBounds(
654 overrideConfiguration.windowConfiguration.getBounds());
655 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700656 if (mParent != null) {
657 mParent.onDescendantOverrideConfigurationChanged();
658 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800659
660 if (diff == BOUNDS_CHANGE_NONE) {
661 return;
662 }
663
664 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
665 onResize();
666 } else {
667 onMovedByResize();
668 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700669 }
670
671 /**
672 * Notify that a descendant's overrideConfiguration has changed.
673 */
674 void onDescendantOverrideConfigurationChanged() {
675 if (mParent != null) {
676 mParent.onDescendantOverrideConfigurationChanged();
677 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700678 }
679
680 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700681 * Notify that the display this container is on has changed. This could be either this container
682 * is moved to a new display, or some configurations on the display it is on changes.
683 *
684 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700685 */
686 void onDisplayChanged(DisplayContent dc) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800687 mDisplayContent = dc;
688 if (dc != null && dc != this) {
689 dc.getPendingTransaction().merge(mPendingTransaction);
690 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700691 for (int i = mChildren.size() - 1; i >= 0; --i) {
692 final WindowContainer child = mChildren.get(i);
693 child.onDisplayChanged(dc);
694 }
695 }
696
Tiger Huanged6794e2019-05-07 20:07:59 +0800697 DisplayContent getDisplayContent() {
698 return mDisplayContent;
699 }
700
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700701 void setWaitingForDrawnIfResizingChanged() {
702 for (int i = mChildren.size() - 1; i >= 0; --i) {
703 final WindowContainer wc = mChildren.get(i);
704 wc.setWaitingForDrawnIfResizingChanged();
705 }
706 }
707
708 void onResize() {
709 for (int i = mChildren.size() - 1; i >= 0; --i) {
710 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800711 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700712 }
713 }
714
Bryce Leed92ae482018-01-22 13:56:23 -0800715 void onParentResize() {
716 // In the case this container has specified its own bounds, a parent resize will not
717 // affect its bounds. Any relevant changes will be propagated through changes to the
718 // Configuration override.
719 if (hasOverrideBounds()) {
720 return;
721 }
722
723 // Default implementation is to treat as resize on self.
724 onResize();
725 }
726
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700727 void onMovedByResize() {
728 for (int i = mChildren.size() - 1; i >= 0; --i) {
729 final WindowContainer wc = mChildren.get(i);
730 wc.onMovedByResize();
731 }
732 }
733
734 void resetDragResizingChangeReported() {
735 for (int i = mChildren.size() - 1; i >= 0; --i) {
736 final WindowContainer wc = mChildren.get(i);
737 wc.resetDragResizingChangeReported();
738 }
739 }
740
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700741 void forceWindowsScaleableInTransaction(boolean force) {
742 for (int i = mChildren.size() - 1; i >= 0; --i) {
743 final WindowContainer wc = mChildren.get(i);
744 wc.forceWindowsScaleableInTransaction(force);
745 }
746 }
747
Jorim Jaggia5e10572017-11-15 14:36:26 +0100748 /**
lumark9bca6b42019-10-17 18:35:22 +0800749 * @return {@code true} when this container or its related containers are running an
750 * animation, {@code false} otherwise.
751 *
752 * By default this predicate only checks if this container itself is actually running an
753 * animation, but you can extend the check target over its relatives, or relax the condition
754 * so that this can return {@code true} if an animation starts soon by giving a combination
755 * of {@link #AnimationFlags}.
756 *
757 * Note that you can give a combination of bitmask flags to specify targets and condition for
758 * checking animating status.
759 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this
760 * container itself or one of its parents is running an animation or waiting for an app
761 * transition.
762 *
763 * Note that TRANSITION propagates to parents and children as well.
764 *
765 * {@see AnimationFlags#TRANSITION}
766 * {@see AnimationFlags#PARENTS}
767 * {@see AnimationFlags#CHILDREN}
Jorim Jaggia5e10572017-11-15 14:36:26 +0100768 */
lumark9bca6b42019-10-17 18:35:22 +0800769 final boolean isAnimating(int flags) {
770 if (mSurfaceAnimator.isAnimating()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100771 return true;
772 }
lumark9bca6b42019-10-17 18:35:22 +0800773 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) {
774 return true;
775 }
776 if ((flags & PARENTS) != 0) {
777 final WindowContainer parent = getParent();
778 if (parent != null && parent.isAnimating(flags & ~CHILDREN)) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700779 return true;
780 }
781 }
lumark9bca6b42019-10-17 18:35:22 +0800782 if ((flags & CHILDREN) != 0) {
783 for (int i = 0; i < mChildren.size(); ++i) {
784 final WindowContainer wc = mChildren.get(i);
785 if (wc.isAnimating(flags & ~PARENTS)) {
786 return true;
787 }
788 }
789 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700790 return false;
791 }
792
Jorim Jaggia5e10572017-11-15 14:36:26 +0100793 /**
lumark9bca6b42019-10-17 18:35:22 +0800794 * @return {@code true} when the container is waiting the app transition start, {@code false}
795 * otherwise.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100796 */
lumark9bca6b42019-10-17 18:35:22 +0800797 boolean isWaitingForTransitionStart() {
lumark52d5f422020-01-06 16:17:55 +0800798 return false;
Jorim Jaggia5e10572017-11-15 14:36:26 +0100799 }
800
801 /**
lumark9bca6b42019-10-17 18:35:22 +0800802 * @return {@code true} if in this subtree of the hierarchy we have an
Wale Ogunwaledfbeed72019-11-20 08:57:39 -0800803 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise.
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200804 */
lumark9bca6b42019-10-17 18:35:22 +0800805 boolean isAppTransitioning() {
lumark5341d1c2019-12-14 01:54:02 +0800806 return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null;
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200807 }
808
809 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100810 * @return Whether our own container running an animation at the moment.
811 */
lumark9bca6b42019-10-17 18:35:22 +0800812 final boolean isAnimating() {
813 return isAnimating(0 /* self only */);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100814 }
815
lumark19a5d2e2019-10-11 16:19:30 +0800816 /**
817 * @return {@code true} if the container is in changing app transition.
818 */
819 boolean isChangingAppTransition() {
820 return false;
821 }
822
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700823 void sendAppVisibilityToClients() {
824 for (int i = mChildren.size() - 1; i >= 0; --i) {
825 final WindowContainer wc = mChildren.get(i);
826 wc.sendAppVisibilityToClients();
827 }
828 }
829
Wale Ogunwale44f21802016-09-02 12:49:48 -0700830 /**
831 * Returns true if the container or one of its children as some content it can display or wants
832 * to display (e.g. app views or saved surface).
833 *
834 * NOTE: While this method will return true if the there is some content to display, it doesn't
835 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
836 * visible.
837 */
838 boolean hasContentToDisplay() {
839 for (int i = mChildren.size() - 1; i >= 0; --i) {
840 final WindowContainer wc = mChildren.get(i);
841 if (wc.hasContentToDisplay()) {
842 return true;
843 }
844 }
845 return false;
846 }
847
848 /**
849 * Returns true if the container or one of its children is considered visible from the
850 * WindowManager perspective which usually means valid surface and some other internal state
851 * are true.
852 *
853 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
854 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
855 * the container has any content to display.
856 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700857 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700858 // TODO: Will this be more correct if it checks the visibility of its parents?
859 // It depends...For example, Tasks and Stacks are only visible if there children are visible
860 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800861 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700862 for (int i = mChildren.size() - 1; i >= 0; --i) {
863 final WindowContainer wc = mChildren.get(i);
864 if (wc.isVisible()) {
865 return true;
866 }
867 }
868 return false;
869 }
870
Evan Roskya80f11c2020-01-23 19:17:10 -0800871 /**
872 * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable,
873 * this will not be focusable either.
874 */
Evan Rosky226de132020-01-03 18:00:29 -0800875 boolean isFocusable() {
Evan Roskya80f11c2020-01-23 19:17:10 -0800876 final WindowContainer parent = getParent();
877 return (parent == null || parent.isFocusable()) && mIsFocusable;
Evan Rosky226de132020-01-03 18:00:29 -0800878 }
879
880 /** Set whether this container or its children can be focusable */
Evan Rosky226de132020-01-03 18:00:29 -0800881 boolean setFocusable(boolean focusable) {
882 if (mIsFocusable == focusable) {
883 return false;
884 }
885 mIsFocusable = focusable;
886 return true;
887 }
888
Bryce Lee00d586d2017-07-28 20:48:43 -0700889 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700890 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700891 */
892 boolean isOnTop() {
893 return getParent().getTopChild() == this && getParent().isOnTop();
894 }
895
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100896 /** Returns the top child container. */
897 E getTopChild() {
898 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700899 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700900
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700901 /** Returns true if there is still a removal being deferred */
902 boolean checkCompleteDeferredRemoval() {
903 boolean stillDeferringRemoval = false;
904
905 for (int i = mChildren.size() - 1; i >= 0; --i) {
906 final WindowContainer wc = mChildren.get(i);
907 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
908 }
909
910 return stillDeferringRemoval;
911 }
912
913 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700914 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700915 for (int i = mChildren.size() - 1; i >= 0; --i) {
916 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700917 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700918 }
919 }
920
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700921 void onAppTransitionDone() {
922 for (int i = mChildren.size() - 1; i >= 0; --i) {
923 final WindowContainer wc = mChildren.get(i);
924 wc.onAppTransitionDone();
925 }
926 }
927
Garfield Tan90b04282018-12-11 14:04:42 -0800928 /**
929 * Called when this container or one of its descendants changed its requested orientation, and
930 * wants this container to handle it or pass it to its parent.
931 *
932 * @param freezeDisplayToken freeze this app window token if display needs to freeze
933 * @param requestingContainer the container which orientation request has changed
934 * @return {@code true} if handled; {@code false} otherwise.
935 */
936 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
937 @Nullable ConfigurationContainer requestingContainer) {
938 final WindowContainer parent = getParent();
939 if (parent == null) {
940 return false;
941 }
942 return parent.onDescendantOrientationChanged(freezeDisplayToken,
943 requestingContainer);
944 }
945
946 /**
Garfield Tan49dae102019-02-04 09:51:59 -0800947 * Check if this container or its parent will handle orientation changes from descendants. It's
948 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
949 * ConfigurationContainer)} in the sense that the return value of this method tells if this
950 * container or its parent will handle the request eventually, while the return value of the
951 * other method is if it handled the request synchronously.
952 *
953 * @return {@code true} if it handles or will handle orientation change in the future; {@code
954 * false} if it won't handle the change at anytime.
955 */
956 boolean handlesOrientationChangeFromDescendant() {
957 final WindowContainer parent = getParent();
958 return parent != null && parent.handlesOrientationChangeFromDescendant();
959 }
960
961 /**
Wale Ogunwaleda8b8272018-11-29 19:37:37 -0800962 * Get the configuration orientation by the requested screen orientation
963 * ({@link ActivityInfo.ScreenOrientation}) of this activity.
964 *
965 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE},
966 * {@link Configuration#ORIENTATION_PORTRAIT},
967 * {@link Configuration#ORIENTATION_UNDEFINED}).
968 */
969 int getRequestedConfigurationOrientation() {
970 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) {
971 // NOSENSOR means the display's "natural" orientation, so return that.
972 if (mDisplayContent != null) {
973 return mDisplayContent.getNaturalOrientation();
974 }
975 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
976 // LOCKED means the activity's orientation remains unchanged, so return existing value.
977 return getConfiguration().orientation;
978 } else if (isFixedOrientationLandscape(mOrientation)) {
979 return ORIENTATION_LANDSCAPE;
980 } else if (isFixedOrientationPortrait(mOrientation)) {
981 return ORIENTATION_PORTRAIT;
982 }
983 return ORIENTATION_UNDEFINED;
984 }
985
986 /**
Garfield Tan90b04282018-12-11 14:04:42 -0800987 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
988 * parameters.
989 *
990 * @param orientation the specified orientation.
991 */
Wale Ogunwale51362492016-09-08 17:49:17 -0700992 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -0800993 setOrientation(orientation, null /* freezeDisplayToken */,
994 null /* ActivityRecord */);
995 }
996
997 /**
998 * Sets the specified orientation of this container. It percolates this change upward along the
999 * hierarchy to let each level of the hierarchy a chance to respond to it.
1000 *
1001 * @param orientation the specified orientation. Needs to be one of {@link
1002 * android.content.pm.ActivityInfo.ScreenOrientation}.
1003 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
1004 * done. Display will not be frozen if this is {@code null}, which
1005 * should only happen in tests.
1006 * @param requestingContainer the container which orientation request has changed. Mostly used
1007 * to ensure it gets correct configuration.
1008 */
1009 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
1010 @Nullable ConfigurationContainer requestingContainer) {
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001011 if (mOrientation == orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -08001012 return;
1013 }
Wale Ogunwale8a1860a2019-06-05 08:57:19 -07001014
1015 mOrientation = orientation;
Wale Ogunwaleda8b8272018-11-29 19:37:37 -08001016 final int configOrientation = getRequestedConfigurationOrientation();
1017 if (getRequestedOverrideConfiguration().orientation != configOrientation) {
1018 mTmpConfig.setTo(getRequestedOverrideConfiguration());
1019 mTmpConfig.orientation = configOrientation;
1020 onRequestedOverrideConfigurationChanged(mTmpConfig);
1021 }
1022
Garfield Tan90b04282018-12-11 14:04:42 -08001023 final WindowContainer parent = getParent();
1024 if (parent != null) {
1025 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
1026 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001027 }
1028
Vadim Caen1096f112019-12-18 11:44:26 +01001029 @ActivityInfo.ScreenOrientation
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001030 int getOrientation() {
1031 return getOrientation(mOrientation);
1032 }
1033
Wale Ogunwale51362492016-09-08 17:49:17 -07001034 /**
1035 * Returns the specified orientation for this window container or one of its children is there
1036 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
1037 * specification is set.
1038 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
1039 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001040 *
1041 * @param candidate The current orientation candidate that will be returned if we don't find a
1042 * better match.
1043 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -07001044 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001045 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -08001046 if (!fillsParent()) {
1047 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -07001048 return SCREEN_ORIENTATION_UNSET;
1049 }
1050
Bryce Leea163b762017-01-24 11:05:01 -08001051 // The container fills its parent so we can use it orientation if it has one
1052 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -07001053 // specified and fall back on this container's unset or unspecified value as a candidate
1054 // if none of the children have a better candidate for the orientation.
1055 if (mOrientation != SCREEN_ORIENTATION_UNSET
1056 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1057 return mOrientation;
1058 }
Wale Ogunwale51362492016-09-08 17:49:17 -07001059
1060 for (int i = mChildren.size() - 1; i >= 0; --i) {
1061 final WindowContainer wc = mChildren.get(i);
1062
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -07001063 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
1064 // SCREEN_ORIENTATION_UNSPECIFIED?
1065 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
1066 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -07001067 if (orientation == SCREEN_ORIENTATION_BEHIND) {
1068 // container wants us to use the orientation of the container behind it. See if we
1069 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
1070 // look behind this container.
1071 candidate = orientation;
1072 continue;
1073 }
1074
1075 if (orientation == SCREEN_ORIENTATION_UNSET) {
1076 continue;
1077 }
1078
1079 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
1080 // Use the orientation if the container fills its parent or requested an explicit
1081 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
Vadim Caenfc14c662020-01-20 16:00:31 +01001082 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)",
1083 wc.toString(), orientation,
1084 ActivityInfo.screenOrientationToString(orientation));
Wale Ogunwale51362492016-09-08 17:49:17 -07001085 return orientation;
1086 }
1087 }
1088
1089 return candidate;
1090 }
1091
1092 /**
1093 * Returns true if this container is opaque and fills all the space made available by its parent
1094 * container.
1095 *
1096 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
1097 * this is just a signal from the client to window manager stating its intent, but not what it
1098 * actually does.
1099 */
1100 boolean fillsParent() {
1101 return false;
1102 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001103
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001104 // TODO: Users would have their own window containers under the display container?
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001105 void switchUser(int userId) {
Wale Ogunwale6213caa2016-12-02 16:47:15 +00001106 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalebebd8cd2019-10-28 15:53:31 -07001107 mChildren.get(i).switchUser(userId);
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001108 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001109 }
1110
Wale Ogunwale9bb1a1e2019-12-30 11:29:52 -08001111 boolean showToCurrentUser() {
1112 return true;
1113 }
1114
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001115 /**
1116 * For all windows at or below this container call the callback.
1117 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
1118 * stops the search if {@link ToBooleanFunction#apply} returns true.
1119 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
1120 * z-order, else from bottom-to-top.
1121 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -08001122 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001123 */
1124 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001125 if (traverseTopToBottom) {
1126 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001127 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1128 return true;
1129 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001130 }
1131 } else {
1132 final int count = mChildren.size();
1133 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001134 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
1135 return true;
1136 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001137 }
1138 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -08001139 return false;
1140 }
1141
1142 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001143 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
1144 forAllWindows(wrapper, traverseTopToBottom);
1145 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -07001146 }
1147
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001148 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) {
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001149 return forAllActivities(callback, true /*traverseTopToBottom*/);
1150 }
1151
1152 boolean forAllActivities(
1153 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) {
1154 if (traverseTopToBottom) {
1155 for (int i = mChildren.size() - 1; i >= 0; --i) {
1156 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
1157 }
1158 } else {
1159 final int count = mChildren.size();
1160 for (int i = 0; i < count; i++) {
1161 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true;
lumark9bca6b42019-10-17 18:35:22 +08001162 }
lumark588a3e82018-07-20 18:53:54 +08001163 }
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001164
lumark9bca6b42019-10-17 18:35:22 +08001165 return false;
lumark588a3e82018-07-20 18:53:54 +08001166 }
1167
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001168 void forAllActivities(Consumer<ActivityRecord> callback) {
1169 forAllActivities(callback, true /*traverseTopToBottom*/);
1170 }
1171
1172 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) {
1173 if (traverseTopToBottom) {
1174 for (int i = mChildren.size() - 1; i >= 0; --i) {
1175 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1176 }
1177 } else {
1178 final int count = mChildren.size();
1179 for (int i = 0; i < count; i++) {
1180 mChildren.get(i).forAllActivities(callback, traverseTopToBottom);
1181 }
1182 }
1183 }
1184
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001185 /**
1186 * Process all activities in this branch of the tree.
1187 *
1188 * @param callback Called for each activity found.
1189 * @param boundary We don't return activities via {@param callback} until we get to this node in
1190 * the tree.
1191 * @param includeBoundary If the boundary from be processed to return activities.
1192 * @param traverseTopToBottom direction to traverse the tree.
1193 * @return {@code true} if we ended the search before reaching the end of the tree.
1194 */
1195 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1196 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1197 return forAllActivities(
1198 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1199 }
1200
1201 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback,
1202 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1203 boolean[] boundaryFound) {
1204 if (traverseTopToBottom) {
1205 for (int i = mChildren.size() - 1; i >= 0; --i) {
1206 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1207 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1208 return true;
1209 }
1210 }
1211 } else {
1212 final int count = mChildren.size();
1213 for (int i = 0; i < count; i++) {
1214 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary,
1215 traverseTopToBottom, boundaryFound, mChildren.get(i))) {
1216 return true;
1217 }
1218 }
1219 }
1220
1221 return false;
1222 }
1223
1224 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback,
1225 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1226 boolean[] boundaryFound, WindowContainer wc) {
1227 if (wc == boundary) {
1228 boundaryFound[0] = true;
1229 if (!includeBoundary) return false;
1230 }
1231
1232 if (boundaryFound[0]) {
1233 return wc.forAllActivities(callback, traverseTopToBottom);
1234 }
1235
1236 return wc.forAllActivities(
1237 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1238 }
1239
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001240 /** @return {@code true} if this node or any of its children contains an activity. */
1241 boolean hasActivity() {
1242 for (int i = mChildren.size() - 1; i >= 0; --i) {
1243 if (mChildren.get(i).hasActivity()) {
1244 return true;
1245 }
1246 }
1247 return false;
1248 }
1249
1250 ActivityRecord getActivity(Predicate<ActivityRecord> callback) {
1251 return getActivity(callback, true /*traverseTopToBottom*/);
1252 }
1253
1254 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001255 return getActivity(callback, traverseTopToBottom, null /*boundary*/);
1256 }
1257
1258 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom,
1259 WindowContainer boundary) {
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001260 if (traverseTopToBottom) {
1261 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001262 final WindowContainer wc = mChildren.get(i);
1263 if (wc == boundary) return null;
1264
1265 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001266 if (r != null) {
1267 return r;
1268 }
1269 }
1270 } else {
1271 final int count = mChildren.size();
1272 for (int i = 0; i < count; i++) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001273 final WindowContainer wc = mChildren.get(i);
1274 if (wc == boundary) return null;
1275
1276 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary);
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001277 if (r != null) {
1278 return r;
1279 }
1280 }
1281 }
1282
1283 return null;
1284 }
1285
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001286 /**
1287 * Gets an activity in a branch of the tree.
1288 *
1289 * @param callback called to test if this is the activity that should be returned.
1290 * @param boundary We don't return activities via {@param callback} until we get to this node in
1291 * the tree.
1292 * @param includeBoundary If the boundary from be processed to return activities.
1293 * @param traverseTopToBottom direction to traverse the tree.
1294 * @return The activity if found or null.
1295 */
1296 final ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1297 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) {
1298 return getActivity(
1299 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1300 }
1301
1302 private ActivityRecord getActivity(Predicate<ActivityRecord> callback,
1303 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1304 boolean[] boundaryFound) {
1305 if (traverseTopToBottom) {
1306 for (int i = mChildren.size() - 1; i >= 0; --i) {
1307 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1308 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1309 if (r != null) {
1310 return r;
1311 }
1312 }
1313 } else {
1314 final int count = mChildren.size();
1315 for (int i = 0; i < count; i++) {
1316 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary,
1317 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1318 if (r != null) {
1319 return r;
1320 }
1321 }
1322 }
1323
1324 return null;
1325 }
1326
1327 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback,
1328 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1329 boolean[] boundaryFound, WindowContainer wc) {
1330 if (wc == boundary || boundary == null) {
1331 boundaryFound[0] = true;
1332 if (!includeBoundary) return null;
1333 }
1334
1335 if (boundaryFound[0]) {
1336 return wc.getActivity(callback, traverseTopToBottom);
1337 }
1338
1339 return wc.getActivity(
1340 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
1341 }
1342
1343 ActivityRecord getActivityAbove(ActivityRecord r) {
1344 return getActivity((above) -> true, r,
1345 false /*includeBoundary*/, false /*traverseTopToBottom*/);
1346 }
1347
1348 ActivityRecord getActivityBelow(ActivityRecord r) {
1349 return getActivity((below) -> true, r,
1350 false /*includeBoundary*/, true /*traverseTopToBottom*/);
1351 }
1352
1353 ActivityRecord getBottomMostActivity() {
1354 return getActivity((r) -> true, false /*traverseTopToBottom*/);
1355 }
1356
1357 ActivityRecord getTopMostActivity() {
1358 return getActivity((r) -> true, true /*traverseTopToBottom*/);
1359 }
1360
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001361 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) {
1362 // Break down into 4 calls to avoid object creation due to capturing input params.
1363 if (includeFinishing) {
1364 if (includeOverlays) {
1365 return getActivity((r) -> true);
1366 }
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001367 return getActivity((r) -> !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001368 } else if (includeOverlays) {
1369 return getActivity((r) -> !r.finishing);
1370 }
1371
Wale Ogunwale0b3d2922019-12-30 08:55:07 -08001372 return getActivity((r) -> !r.finishing && !r.isTaskOverlay());
Wale Ogunwaledfbeed72019-11-20 08:57:39 -08001373 }
1374
Winson Chungd5852192019-09-06 17:20:28 -07001375 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) {
1376 for (int i = mChildren.size() - 1; i >= 0; --i) {
1377 mChildren.get(i).forAllWallpaperWindows(callback);
1378 }
1379 }
1380
Jorim Jaggi51304d72017-05-17 17:25:32 +02001381 /**
1382 * For all tasks at or below this container call the callback.
1383 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001384 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and
1385 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}.
1386 */
1387 boolean forAllTasks(Function<Task, Boolean> callback) {
1388 for (int i = mChildren.size() - 1; i >= 0; --i) {
1389 if (mChildren.get(i).forAllTasks(callback)) {
1390 return true;
1391 }
1392 }
1393 return false;
1394 }
1395
1396 /**
1397 * For all tasks at or below this container call the callback.
1398 *
Jorim Jaggi51304d72017-05-17 17:25:32 +02001399 * @param callback Callback to be called for every task.
1400 */
1401 void forAllTasks(Consumer<Task> callback) {
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001402 forAllTasks(callback, true /*traverseTopToBottom*/);
1403 }
1404
1405 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
1406 final int count = mChildren.size();
1407 if (traverseTopToBottom) {
1408 for (int i = count - 1; i >= 0; --i) {
1409 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1410 }
1411 } else {
1412 for (int i = 0; i < count; i++) {
1413 mChildren.get(i).forAllTasks(callback, traverseTopToBottom);
1414 }
Jorim Jaggi51304d72017-05-17 17:25:32 +02001415 }
1416 }
1417
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001418 Task getTaskAbove(Task t) {
1419 return getTask(
1420 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/);
1421 }
1422
1423 Task getTaskBelow(Task t) {
1424 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/);
1425 }
1426
1427 Task getBottomMostTask() {
1428 return getTask((t) -> true, false /*traverseTopToBottom*/);
1429 }
1430
1431 Task getTopMostTask() {
1432 return getTask((t) -> true, true /*traverseTopToBottom*/);
1433 }
1434
Wale Ogunwalea38654f2019-11-17 20:37:15 -08001435 Task getTask(Predicate<Task> callback) {
1436 return getTask(callback, true /*traverseTopToBottom*/);
1437 }
1438
1439 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) {
1440 if (traverseTopToBottom) {
1441 for (int i = mChildren.size() - 1; i >= 0; --i) {
1442 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1443 if (t != null) {
1444 return t;
1445 }
1446 }
1447 } else {
1448 final int count = mChildren.size();
1449 for (int i = 0; i < count; i++) {
1450 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom);
1451 if (t != null) {
1452 return t;
1453 }
1454 }
1455 }
1456
1457 return null;
1458 }
1459
lumarkbc0032a2019-11-01 21:38:13 +08001460 /**
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001461 * Gets an task in a branch of the tree.
lumarkbc0032a2019-11-01 21:38:13 +08001462 *
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001463 * @param callback called to test if this is the task that should be returned.
1464 * @param boundary We don't return tasks via {@param callback} until we get to this node in
1465 * the tree.
1466 * @param includeBoundary If the boundary from be processed to return tasks.
1467 * @param traverseTopToBottom direction to traverse the tree.
1468 * @return The task if found or null.
lumarkbc0032a2019-11-01 21:38:13 +08001469 */
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001470 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary,
1471 boolean traverseTopToBottom) {
1472 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]);
1473 }
1474
1475 private Task getTask(Predicate<Task> callback,
1476 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1477 boolean[] boundaryFound) {
1478 if (traverseTopToBottom) {
1479 for (int i = mChildren.size() - 1; i >= 0; --i) {
1480 final Task t = processGetTaskWithBoundary(callback, boundary,
1481 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1482 if (t != null) {
1483 return t;
1484 }
1485 }
1486 } else {
1487 final int count = mChildren.size();
1488 for (int i = 0; i < count; i++) {
1489 final Task t = processGetTaskWithBoundary(callback, boundary,
1490 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i));
1491 if (t != null) {
1492 return t;
1493 }
lumarkbc0032a2019-11-01 21:38:13 +08001494 }
1495 }
Wale Ogunwale85fb19a2019-12-05 10:41:05 +09001496
1497 return null;
1498 }
1499
1500 private Task processGetTaskWithBoundary(Predicate<Task> callback,
1501 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom,
1502 boolean[] boundaryFound, WindowContainer wc) {
1503 if (wc == boundary || boundary == null) {
1504 boundaryFound[0] = true;
1505 if (!includeBoundary) return null;
1506 }
1507
1508 if (boundaryFound[0]) {
1509 return wc.getTask(callback, traverseTopToBottom);
1510 }
1511
1512 return wc.getTask(
1513 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound);
lumarkbc0032a2019-11-01 21:38:13 +08001514 }
1515
Wale Ogunwaled1880962016-11-08 10:31:59 -08001516 WindowState getWindow(Predicate<WindowState> callback) {
1517 for (int i = mChildren.size() - 1; i >= 0; --i) {
1518 final WindowState w = mChildren.get(i).getWindow(callback);
1519 if (w != null) {
1520 return w;
1521 }
1522 }
1523
1524 return null;
1525 }
1526
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001527 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -07001528 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
1529 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001530 */
1531 @Override
1532 public int compareTo(WindowContainer other) {
1533 if (this == other) {
1534 return 0;
1535 }
1536
1537 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +02001538 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001539 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
1540 }
1541
1542 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
1543 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001544 try {
1545 getParents(thisParentChain);
1546 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001547
Jorim Jaggi4448e1e2017-05-16 22:26:02 +02001548 // Find the common ancestor of both containers.
1549 WindowContainer commonAncestor = null;
1550 WindowContainer thisTop = thisParentChain.peekLast();
1551 WindowContainer otherTop = otherParentChain.peekLast();
1552 while (thisTop != null && otherTop != null && thisTop == otherTop) {
1553 commonAncestor = thisParentChain.removeLast();
1554 otherParentChain.removeLast();
1555 thisTop = thisParentChain.peekLast();
1556 otherTop = otherParentChain.peekLast();
1557 }
1558
1559 // Containers don't belong to the same hierarchy???
1560 if (commonAncestor == null) {
1561 throw new IllegalArgumentException("No in the same hierarchy this="
1562 + thisParentChain + " other=" + otherParentChain);
1563 }
1564
1565 // Children are always considered greater than their parents, so if one of the containers
1566 // we are comparing it the parent of the other then whichever is the child is greater.
1567 if (commonAncestor == this) {
1568 return -1;
1569 } else if (commonAncestor == other) {
1570 return 1;
1571 }
1572
1573 // The position of the first non-common ancestor in the common ancestor list determines
1574 // which is greater the which.
1575 final WindowList<WindowContainer> list = commonAncestor.mChildren;
1576 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
1577 ? 1 : -1;
1578 } finally {
1579 mTmpChain1.clear();
1580 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001581 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -07001582 }
1583
1584 private void getParents(LinkedList<WindowContainer> parents) {
1585 parents.clear();
1586 WindowContainer current = this;
1587 do {
1588 parents.addLast(current);
1589 current = current.mParent;
1590 } while (current != null);
1591 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001592
Robert Carrb1579c82017-09-05 14:54:47 -07001593 SurfaceControl.Builder makeSurface() {
1594 final WindowContainer p = getParent();
1595 return p.makeChildSurface(this);
1596 }
1597
Robert Carrf59b8dd2017-10-02 18:58:36 -07001598 /**
1599 * @param child The WindowContainer this child surface is for, or null if the Surface
1600 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1601 */
Robert Carrb1579c82017-09-05 14:54:47 -07001602 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1603 final WindowContainer p = getParent();
1604 // Give the parent a chance to set properties. In hierarchy v1 we rely
1605 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001606 return p.makeChildSurface(child)
1607 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001608 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001609 /*
1610 * @return The SurfaceControl parent for this containers SurfaceControl.
1611 * The SurfaceControl must be valid if non-null.
1612 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001613 @Override
1614 public SurfaceControl getParentSurfaceControl() {
1615 final WindowContainer parent = getParent();
1616 if (parent == null) {
1617 return null;
1618 }
1619 return parent.getSurfaceControl();
1620 }
1621
Robert Carrb1579c82017-09-05 14:54:47 -07001622 /**
1623 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1624 */
1625 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001626 if (mSurfaceControl == null) {
1627 return false;
1628 }
1629
Robert Carrb1579c82017-09-05 14:54:47 -07001630 for (int i = 0; i < mChildren.size(); i++) {
1631 if (!mChildren.get(i).shouldMagnify()) {
1632 return false;
1633 }
1634 }
1635 return true;
1636 }
1637
1638 SurfaceSession getSession() {
1639 if (getParent() != null) {
1640 return getParent().getSession();
1641 }
1642 return null;
1643 }
1644
1645 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001646 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1647 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001648 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001649 mLastLayer = layer;
1650 mLastRelativeToLayer = null;
1651 }
1652 }
1653
1654 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1655 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1656 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001657 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001658 mLastLayer = layer;
1659 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001660 }
1661 }
1662
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001663 protected void setLayer(Transaction t, int layer) {
1664
1665 // Route through surface animator to accommodate that our surface control might be
1666 // attached to the leash, and leash is attached to parent container.
1667 mSurfaceAnimator.setLayer(t, layer);
1668 }
1669
1670 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1671
1672 // Route through surface animator to accommodate that our surface control might be
1673 // attached to the leash, and leash is attached to parent container.
1674 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1675 }
1676
1677 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1678 mSurfaceAnimator.reparent(t, newParent);
1679 }
1680
Robert Carrb1579c82017-09-05 14:54:47 -07001681 void assignChildLayers(Transaction t) {
1682 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001683
1684 // We use two passes as a way to promote children which
1685 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001686 for (int j = 0; j < mChildren.size(); ++j) {
1687 final WindowContainer wc = mChildren.get(j);
1688 wc.assignChildLayers(t);
1689 if (!wc.needsZBoost()) {
1690 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001691 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001692 }
1693 for (int j = 0; j < mChildren.size(); ++j) {
1694 final WindowContainer wc = mChildren.get(j);
1695 if (wc.needsZBoost()) {
1696 wc.assignLayer(t, layer++);
1697 }
Robert Carrb1579c82017-09-05 14:54:47 -07001698 }
1699 }
1700
1701 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001702 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001703 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001704 }
1705
1706 boolean needsZBoost() {
1707 for (int i = 0; i < mChildren.size(); i++) {
1708 if (mChildren.get(i).needsZBoost()) {
1709 return true;
1710 }
1711 }
1712 return false;
1713 }
1714
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001715 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001716 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001717 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001718 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001719 * @param proto Stream to write the WindowContainer object to.
1720 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001721 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001722 * @hide
1723 */
1724 @CallSuper
1725 @Override
Jeffrey Huangcb782852019-12-05 11:28:11 -08001726 public void dumpDebug(ProtoOutputStream proto, long fieldId,
Nataniel Borges023ecb52019-01-16 14:15:43 -08001727 @WindowTraceLogLevel int logLevel) {
1728 boolean isVisible = isVisible();
1729 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1730 return;
1731 }
1732
Adrian Roos4921ccf2017-09-28 16:54:06 +02001733 final long token = proto.start(fieldId);
Jeffrey Huangcb782852019-12-05 11:28:11 -08001734 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001735 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001736 proto.write(VISIBLE, isVisible);
1737 if (mSurfaceAnimator.isAnimating()) {
Jeffrey Huangcb782852019-12-05 11:28:11 -08001738 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001739 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001740 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001741 }
1742
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001743 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1744 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1745 if (wrapper == null) {
1746 wrapper = new ForAllWindowsConsumerWrapper();
1747 }
1748 wrapper.setConsumer(consumer);
1749 return wrapper;
1750 }
1751
1752 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1753
1754 private Consumer<WindowState> mConsumer;
1755
1756 void setConsumer(Consumer<WindowState> consumer) {
1757 mConsumer = consumer;
1758 }
1759
1760 @Override
1761 public boolean apply(WindowState w) {
1762 mConsumer.accept(w);
1763 return false;
1764 }
1765
1766 void release() {
1767 mConsumer = null;
1768 mConsumerWrapperPool.release(this);
1769 }
1770 }
Robert Carrb1579c82017-09-05 14:54:47 -07001771
1772 // TODO(b/68336570): Should this really be on WindowContainer since it
1773 // can only be used on the top-level nodes that aren't animated?
1774 // (otherwise we would be fighting other callers of setMatrix).
1775 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1776 if (shouldMagnify()) {
1777 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1778 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
Robert Carr7603dea2019-07-17 13:16:21 -07001779 mLastMagnificationSpec = spec;
Robert Carrb1579c82017-09-05 14:54:47 -07001780 } else {
Jackal Guoa8b3a272019-12-16 15:24:58 +08001781 clearMagnificationSpec(t);
Robert Carrb1579c82017-09-05 14:54:47 -07001782 for (int i = 0; i < mChildren.size(); i++) {
1783 mChildren.get(i).applyMagnificationSpec(t, spec);
1784 }
1785 }
1786 }
1787
Robert Carr7603dea2019-07-17 13:16:21 -07001788 void clearMagnificationSpec(Transaction t) {
1789 if (mLastMagnificationSpec != null) {
1790 t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
1791 .setPosition(mSurfaceControl, 0, 0);
1792 }
1793 mLastMagnificationSpec = null;
1794 for (int i = 0; i < mChildren.size(); i++) {
1795 mChildren.get(i).clearMagnificationSpec(t);
1796 }
1797 }
1798
Robert Carrb1579c82017-09-05 14:54:47 -07001799 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08001800 // If a leash has been set when the transaction was committed, then the leash reparent has
1801 // been committed.
1802 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001803 for (int i = 0; i < mChildren.size(); i++) {
1804 mChildren.get(i).prepareSurfaces();
1805 }
1806 }
1807
1808 /**
chaviw7f1fa992018-01-10 13:52:12 -08001809 * @return true if the reparent to animation leash transaction has been committed, false
1810 * otherwise.
1811 */
1812 boolean hasCommittedReparentToAnimationLeash() {
1813 return mCommittedReparentToAnimationLeash;
1814 }
1815
1816 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08001817 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1818 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07001819 */
1820 void scheduleAnimation() {
1821 if (mParent != null) {
1822 mParent.scheduleAnimation();
1823 }
1824 }
1825
Robert Carrdea7bf42019-04-04 12:02:51 -07001826 /**
1827 * @return The SurfaceControl for this container.
1828 * The SurfaceControl must be valid if non-null.
1829 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001830 @Override
1831 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001832 return mSurfaceControl;
1833 }
1834
Jorim Jaggia5e10572017-11-15 14:36:26 +01001835 @Override
1836 public Transaction getPendingTransaction() {
Tiger Huanged6794e2019-05-07 20:07:59 +08001837 final DisplayContent displayContent = getDisplayContent();
1838 if (displayContent != null && displayContent != this) {
1839 return displayContent.getPendingTransaction();
1840 }
1841 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1842 // let the caller to save the surface operations within the local mPendingTransaction.
1843 // If this is not a DisplayContent, we will merge it to the pending transaction of its
1844 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07001845 return mPendingTransaction;
1846 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001847
1848 /**
1849 * Starts an animation on the container.
1850 *
1851 * @param anim The animation to run.
1852 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1853 * some point but the meaning is too weird to work for all containers.
Issei Suzuki2f541842020-01-09 20:18:29 +01001854 * @param animationFinishedCallback The callback being triggered when the animation finishes.
Jorim Jaggia5e10572017-11-15 14:36:26 +01001855 */
Issei Suzuki2f541842020-01-09 20:18:29 +01001856 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
1857 @Nullable Runnable animationFinishedCallback) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001858 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1859
1860 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1861 // the moment this doesn't work for all animatable window containers.
Issei Suzuki2f541842020-01-09 20:18:29 +01001862 mSurfaceAnimator.startAnimation(t, anim, hidden, animationFinishedCallback);
1863 }
1864
1865 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1866 startAnimation(t, anim, hidden, null /* animationFinishedCallback */);
Jorim Jaggia5e10572017-11-15 14:36:26 +01001867 }
1868
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001869 void transferAnimation(WindowContainer from) {
1870 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1871 }
1872
Jorim Jaggia5e10572017-11-15 14:36:26 +01001873 void cancelAnimation() {
1874 mSurfaceAnimator.cancelAnimation();
1875 }
1876
1877 @Override
1878 public Builder makeAnimationLeash() {
1879 return makeSurface();
1880 }
1881
Jorim Jaggi596a1992017-12-29 14:48:02 +01001882 @Override
1883 public SurfaceControl getAnimationLeashParent() {
1884 return getParentSurfaceControl();
1885 }
1886
chaviw23ee71c2017-12-18 11:29:41 -08001887 /**
1888 * @return The layer on which all app animations are happening.
1889 */
Jorim Jaggi391790622018-04-18 15:30:44 +02001890 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08001891 final WindowContainer parent = getParent();
1892 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02001893 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08001894 }
1895 return null;
1896 }
1897
lumark19a5d2e2019-10-11 16:19:30 +08001898 // TODO: Remove this and use #getBounds() instead once we set an app transition animation
1899 // on TaskStack.
1900 Rect getAnimationBounds(int appStackClipMode) {
lumark85718662019-12-26 22:05:12 +08001901 return getDisplayedBounds();
lumark19a5d2e2019-10-11 16:19:30 +08001902 }
1903
1904 /**
1905 * Applies the app transition animation according the given the layout properties in the
1906 * window hierarchy.
1907 *
1908 * @param lp The layout parameters of the window.
1909 * @param transit The app transition type indicates what kind of transition to be applied.
1910 * @param enter Whether the app transition is entering transition or not.
1911 * @param isVoiceInteraction Whether the container is participating in voice interaction or not.
1912 *
1913 * @return {@code true} when the container applied the app transition, {@code false} if the
1914 * app transition is disabled or skipped.
1915 *
1916 * @see #getAnimationAdapter
1917 */
1918 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
Issei Suzuki2f541842020-01-09 20:18:29 +01001919 boolean isVoiceInteraction, @Nullable Runnable animationFinishedCallback) {
lumark19a5d2e2019-10-11 16:19:30 +08001920 if (mWmService.mDisableTransitionAnimation) {
1921 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
1922 "applyAnimation: transition animation is disabled or skipped. "
1923 + "container=%s", this);
1924 cancelAnimation();
1925 return false;
1926 }
1927
1928 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason
1929 // to animate and it can cause strange artifacts when we unfreeze the display if some
1930 // different animation is running.
1931 try {
1932 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation");
1933 if (okToAnimate()) {
lumarkbc0032a2019-11-01 21:38:13 +08001934 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp,
1935 transit, enter, isVoiceInteraction);
lumark19a5d2e2019-10-11 16:19:30 +08001936 AnimationAdapter adapter = adapters.first;
1937 AnimationAdapter thumbnailAdapter = adapters.second;
1938 if (adapter != null) {
Issei Suzuki2f541842020-01-09 20:18:29 +01001939 startAnimation(getPendingTransaction(), adapter, !isVisible(),
1940 animationFinishedCallback);
lumark19a5d2e2019-10-11 16:19:30 +08001941 if (adapter.getShowWallpaper()) {
lumark5341d1c2019-12-14 01:54:02 +08001942 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
lumark19a5d2e2019-10-11 16:19:30 +08001943 }
1944 if (thumbnailAdapter != null) {
1945 mThumbnail.startAnimation(
1946 getPendingTransaction(), thumbnailAdapter, !isVisible());
1947 }
1948 }
1949 } else {
1950 cancelAnimation();
1951 }
1952 } finally {
1953 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
1954 }
1955
1956 return isAnimating();
1957 }
1958
1959 /**
1960 * Gets the {@link AnimationAdapter} according the given window layout properties in the window
1961 * hierarchy.
1962 *
1963 * @return The return value will always contain two elements, one for normal animations and the
1964 * other for thumbnail animation, both can be {@code null}.
1965 *
1966 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord
1967 * @See LocalAnimationAdapter
1968 */
1969 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp,
1970 int transit, boolean enter, boolean isVoiceInteraction) {
1971 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters;
1972 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode();
1973
1974 // Separate position and size for use in animators.
1975 mTmpRect.set(getAnimationBounds(appStackClipMode));
lumark85718662019-12-26 22:05:12 +08001976 if (sHierarchicalAnimations) {
1977 getRelativeDisplayedPosition(mTmpPoint);
1978 } else {
1979 mTmpPoint.set(mTmpRect.left, mTmpRect.top);
1980 }
lumark19a5d2e2019-10-11 16:19:30 +08001981 mTmpRect.offsetTo(0, 0);
1982
1983 final RemoteAnimationController controller =
1984 getDisplayContent().mAppTransition.getRemoteAnimationController();
1985 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter
1986 && isChangingAppTransition();
1987
1988 // Delaying animation start isn't compatible with remote animations at all.
1989 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) {
1990 final RemoteAnimationController.RemoteAnimationRecord adapters =
1991 controller.createRemoteAnimationRecord(this, mTmpPoint, mTmpRect,
1992 (isChanging ? mTransitStartRect : null));
1993 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter);
1994 } else if (isChanging) {
1995 final float durationScale = mWmService.getTransitionAnimationScaleLocked();
1996 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
1997 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y);
1998
lumarkbc0032a2019-11-01 21:38:13 +08001999 final AnimationAdapter adapter = new LocalAnimationAdapter(
lumark19a5d2e2019-10-11 16:19:30 +08002000 new WindowChangeAnimationSpec(mTransitStartRect, mTmpRect, displayInfo,
2001 durationScale, true /* isAppAnimation */, false /* isThumbnail */),
2002 getSurfaceAnimationRunner());
2003
lumarkbc0032a2019-11-01 21:38:13 +08002004 final AnimationAdapter thumbnailAdapter = mThumbnail != null
2005 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec(mTransitStartRect,
2006 mTmpRect, displayInfo, durationScale, true /* isAppAnimation */,
2007 true /* isThumbnail */), getSurfaceAnimationRunner())
2008 : null;
lumark19a5d2e2019-10-11 16:19:30 +08002009 resultAdapters = new Pair<>(adapter, thumbnailAdapter);
2010 mTransit = transit;
2011 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2012 } else {
2013 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM);
2014 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction);
2015
2016 if (a != null) {
2017 // Only apply corner radius to animation if we're not in multi window mode.
2018 // We don't want rounded corners when in pip or split screen.
2019 final float windowCornerRadius = !inMultiWindowMode()
2020 ? getDisplayContent().getWindowCornerRadius()
2021 : 0;
2022 AnimationAdapter adapter = new LocalAnimationAdapter(
2023 new WindowAnimationSpec(a, mTmpPoint, mTmpRect,
2024 getDisplayContent().mAppTransition.canSkipFirstFrame(),
2025 appStackClipMode, true /* isAppAnimation */, windowCornerRadius),
2026 getSurfaceAnimationRunner());
2027
2028 resultAdapters = new Pair<>(adapter, null);
2029 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP;
2030 mTransit = transit;
2031 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags();
2032 } else {
2033 resultAdapters = new Pair<>(null, null);
2034 }
2035 }
2036 return resultAdapters;
2037 }
2038
2039 final SurfaceAnimationRunner getSurfaceAnimationRunner() {
2040 return mWmService.mSurfaceAnimationRunner;
2041 }
2042
2043 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter,
2044 boolean isVoiceInteraction) {
2045 final DisplayContent displayContent = getDisplayContent();
2046 final DisplayInfo displayInfo = displayContent.getDisplayInfo();
2047 final int width = displayInfo.appWidth;
2048 final int height = displayInfo.appHeight;
2049 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this);
2050
2051 // Determine the visible rect to calculate the thumbnail clip with
2052 // getAnimationFrames.
2053 final Rect frame = new Rect(0, 0, width, height);
2054 final Rect displayFrame = new Rect(0, 0,
2055 displayInfo.logicalWidth, displayInfo.logicalHeight);
2056 final Rect insets = new Rect();
2057 final Rect stableInsets = new Rect();
2058 final Rect surfaceInsets = new Rect();
2059 getAnimationFrames(frame, insets, stableInsets, surfaceInsets);
2060
2061 if (mLaunchTaskBehind) {
2062 // Differentiate the two animations. This one which is briefly on the screen
2063 // gets the !enter animation, and the other one which remains on the
2064 // screen gets the enter animation. Both appear in the mOpeningApps set.
2065 enter = false;
2066 }
2067 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS,
2068 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s "
2069 + "surfaceInsets=%s",
2070 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets);
2071 final Configuration displayConfig = displayContent.getConfiguration();
2072 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter,
2073 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets,
2074 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this);
2075 if (a != null) {
2076 if (DEBUG_ANIM) logWithStack(TAG, "Loaded animation " + a + " for " + this);
2077 final int containingWidth = frame.width();
2078 final int containingHeight = frame.height();
2079 a.initialize(containingWidth, containingHeight, width, height);
2080 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked());
2081 }
2082 return a;
2083 }
2084
2085 RemoteAnimationTarget createRemoteAnimationTarget(
2086 RemoteAnimationController.RemoteAnimationRecord record) {
2087 return null;
2088 }
2089
2090 boolean okToDisplay() {
lumark5341d1c2019-12-14 01:54:02 +08002091 final DisplayContent dc = getDisplayContent();
2092 return dc != null && dc.okToDisplay();
lumark19a5d2e2019-10-11 16:19:30 +08002093 }
2094
2095 boolean okToAnimate() {
lumark3b8bbc82019-12-02 16:22:08 +08002096 return okToAnimate(false /* ignoreFrozen */);
2097 }
2098
2099 boolean okToAnimate(boolean ignoreFrozen) {
lumark5341d1c2019-12-14 01:54:02 +08002100 final DisplayContent dc = getDisplayContent();
2101 return dc != null && dc.okToAnimate(ignoreFrozen);
lumark19a5d2e2019-10-11 16:19:30 +08002102 }
2103
Jorim Jaggia5e10572017-11-15 14:36:26 +01002104 @Override
2105 public void commitPendingTransaction() {
2106 scheduleAnimation();
2107 }
2108
Robert Carr2f8aa392018-01-31 14:46:51 -08002109 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01002110 final WindowContainer parent = getParent();
2111 if (parent != null) {
2112 parent.assignChildLayers(t);
2113 }
2114 }
2115
2116 @Override
2117 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002118 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002119 reassignLayer(t);
2120 }
2121
2122 @Override
lumarkf6f34942019-04-29 16:56:50 +08002123 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08002124 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01002125 reassignLayer(t);
2126 }
2127
2128 /**
2129 * Called when an animation has finished running.
2130 */
2131 protected void onAnimationFinished() {
chaviwccd5d502019-02-22 13:30:31 -08002132 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01002133 }
2134
2135 /**
2136 * @return The currently running animation, if any, or {@code null} otherwise.
2137 */
2138 AnimationAdapter getAnimation() {
2139 return mSurfaceAnimator.getAnimation();
2140 }
2141
2142 /**
lumark5bd11af2019-12-21 01:52:28 +08002143 * @return The {@link WindowContainer} which is running an animation.
2144 *
2145 * It traverses from the current container to its parents recursively. If nothing is animating,
2146 * it will return {@code null}.
2147 */
2148 @Nullable
2149 WindowContainer getAnimatingContainer() {
2150 if (isAnimating()) {
2151 return this;
2152 }
2153 final WindowContainer parent = getParent();
2154 return (parent != null) ? parent.getAnimatingContainer() : null;
2155 }
2156
2157 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +01002158 * @see SurfaceAnimator#startDelayingAnimationStart
2159 */
2160 void startDelayingAnimationStart() {
2161 mSurfaceAnimator.startDelayingAnimationStart();
2162 }
2163
2164 /**
2165 * @see SurfaceAnimator#endDelayingAnimationStart
2166 */
2167 void endDelayingAnimationStart() {
2168 mSurfaceAnimator.endDelayingAnimationStart();
2169 }
2170
2171 @Override
2172 public int getSurfaceWidth() {
2173 return mSurfaceControl.getWidth();
2174 }
2175
2176 @Override
2177 public int getSurfaceHeight() {
2178 return mSurfaceControl.getHeight();
2179 }
2180
Jorim Jaggif5f9e122017-10-24 18:21:09 +02002181 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01002182 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
2183 if (mSurfaceAnimator.isAnimating()) {
2184 pw.print(prefix); pw.println("ContainerAnimator:");
2185 mSurfaceAnimator.dump(pw, prefix + " ");
2186 }
2187 }
chaviwe07246a2017-12-12 16:18:29 -08002188
chaviw2f0567b2018-01-29 16:22:02 -08002189 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08002190 if (mSurfaceControl == null) {
2191 return;
2192 }
2193
Evan Roskyed6767f2018-10-26 17:21:06 -07002194 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08002195 if (mTmpPos.equals(mLastSurfacePosition)) {
2196 return;
2197 }
2198
chaviw2f0567b2018-01-29 16:22:02 -08002199 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08002200 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08002201 }
2202
Evan Rosky65dffa62019-02-04 14:09:53 -08002203 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08002204 Point getLastSurfacePosition() {
2205 return mLastSurfacePosition;
2206 }
2207
Evan Roskyed6767f2018-10-26 17:21:06 -07002208 /**
2209 * Displayed bounds specify where to display this container at. It differs from bounds during
2210 * certain operations (like animation or interactive dragging).
2211 *
2212 * @return the bounds to display this container at.
2213 */
2214 Rect getDisplayedBounds() {
2215 return getBounds();
2216 }
2217
lumark19a5d2e2019-10-11 16:19:30 +08002218 /**
2219 * The {@code outFrame} retrieved by this method specifies where the animation will finish
2220 * the entrance animation, as the next frame will display the window at these coordinates. In
2221 * case of exit animation, this is where the animation will start, as the frame before the
2222 * animation is displaying the window at these bounds.
2223 *
2224 * @param outFrame The bounds where entrance animation finishes or exit animation starts.
2225 * @param outInsets Insets that are covered by system windows.
2226 * @param outStableInsets Insets that determine the area covered by the stable system windows.
2227 * @param outSurfaceInsets Positive insets between the drawing surface and window content.
2228 */
2229 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets,
2230 Rect outSurfaceInsets) {
2231 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo();
2232 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight);
2233 outInsets.setEmpty();
2234 outStableInsets.setEmpty();
2235 outSurfaceInsets.setEmpty();
2236 }
2237
Evan Roskyed6767f2018-10-26 17:21:06 -07002238 void getRelativeDisplayedPosition(Point outPos) {
2239 final Rect dispBounds = getDisplayedBounds();
2240 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08002241 final WindowContainer parent = getParent();
2242 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07002243 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08002244 outPos.offset(-parentBounds.left, -parentBounds.top);
2245 }
2246 }
chaviw2fb06bc2018-01-19 17:09:15 -08002247
Yunfan Chen87b5a242019-10-01 17:53:59 +09002248 void waitForAllWindowsDrawn() {
Yunfan Chen87b5a242019-10-01 17:53:59 +09002249 forAllWindows(w -> {
Riddle Hsu5df3b752019-12-16 13:27:37 -06002250 w.requestDrawIfNeeded(mWaitingForDrawn);
Yunfan Chen87b5a242019-10-01 17:53:59 +09002251 }, true /* traverseTopToBottom */);
2252 }
2253
chaviw2fb06bc2018-01-19 17:09:15 -08002254 Dimmer getDimmer() {
2255 if (mParent == null) {
2256 return null;
2257 }
2258 return mParent.getDimmer();
2259 }
Robert Carr8a2f9132019-11-11 15:03:15 -08002260
2261 void setSurfaceControl(SurfaceControl sc) {
2262 mSurfaceControl = sc;
2263 }
Wale Ogunwale8f93b642019-12-26 12:10:52 -08002264
2265 /** Cheap way of doing cast and instanceof. */
2266 Task asTask() {
2267 return null;
2268 }
2269
2270 /** Cheap way of doing cast and instanceof. */
2271 ActivityRecord asActivityRecord() {
2272 return null;
2273 }
Evan Roskya80f11c2020-01-23 19:17:10 -08002274
2275 RemoteToken getRemoteToken() {
2276 return mRemoteToken;
2277 }
2278
2279 static class RemoteToken extends IWindowContainer.Stub {
2280 final WeakReference<WindowContainer> mWeakRef;
2281
2282 RemoteToken(WindowContainer container) {
2283 mWeakRef = new WeakReference<>(container);
2284 }
2285
2286 WindowContainer getContainer() {
2287 return mWeakRef.get();
2288 }
2289
2290 static RemoteToken fromBinder(IBinder binder) {
2291 return (RemoteToken) binder;
2292 }
2293
2294 @Override
2295 public SurfaceControl getLeash() {
2296 throw new RuntimeException("Not implemented");
2297 }
2298
2299 @Override
2300 public String toString() {
2301 StringBuilder sb = new StringBuilder(128);
2302 sb.append("RemoteToken{");
2303 sb.append(Integer.toHexString(System.identityHashCode(this)));
2304 sb.append(' ');
2305 sb.append(mWeakRef.get());
2306 sb.append('}');
2307 return sb.toString();
2308 }
2309 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07002310}