blob: 1a3704e1e1a8c55f0e25ad5e72db94b8a9e40a3e [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;
Vishnu Nair04ab4392018-01-10 11:00:06 -080022import static android.view.SurfaceControl.Transaction;
Louis Chang7501e332018-08-20 13:08:39 +080023
Yi Jin6c6e9ca2018-03-20 16:53:35 -070024import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
25import static com.android.server.wm.WindowContainerProto.ORIENTATION;
26import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
27import static com.android.server.wm.WindowContainerProto.VISIBLE;
Louis Chang7501e332018-08-20 13:08:39 +080028import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
29import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
30import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Jorim Jaggi612bb882017-05-16 17:11:18 +020031
Wale Ogunwaled63594a2016-07-18 07:48:30 -070032import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020033import android.annotation.IntDef;
Garfield Tan90b04282018-12-11 14:04:42 -080034import android.annotation.Nullable;
Jorim Jaggi391790622018-04-18 15:30:44 +020035import android.app.WindowConfiguration;
Andrii Kulian441e4492016-09-29 15:25:00 -070036import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080037import android.graphics.Point;
38import android.graphics.Rect;
Garfield Tan90b04282018-12-11 14:04:42 -080039import android.os.IBinder;
Vishnu Nair04ab4392018-01-10 11:00:06 -080040import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010041import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080042import android.util.proto.ProtoOutputStream;
Robert Carrb1579c82017-09-05 14:54:47 -070043import android.view.MagnificationSpec;
44import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010045import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070046import android.view.SurfaceSession;
Garfield Tan2f145f22018-11-01 15:27:03 -070047
Evan Rosky65dffa62019-02-04 14:09:53 -080048import com.android.internal.annotations.VisibleForTesting;
Jorim Jaggia5e10572017-11-15 14:36:26 +010049import com.android.internal.util.ToBooleanFunction;
50import com.android.server.wm.SurfaceAnimator.Animatable;
Garfield Tan2f145f22018-11-01 15:27:03 -070051
Jorim Jaggia5e10572017-11-15 14:36:26 +010052import java.io.PrintWriter;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070053import java.util.Comparator;
54import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070055import java.util.function.Consumer;
Wale Ogunwaled1880962016-11-08 10:31:59 -080056import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070057
58/**
59 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070060 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -070061 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
62 * changes are made to this class.
63 */
Wale Ogunwale98d62312017-07-12 09:24:56 -070064class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Jorim Jaggia5e10572017-11-15 14:36:26 +010065 implements Comparable<WindowContainer>, Animatable {
66
67 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070068
Jorim Jaggi391790622018-04-18 15:30:44 +020069 /** Animation layer that happens above all animating {@link TaskStack}s. */
70 static final int ANIMATION_LAYER_STANDARD = 0;
71
72 /** Animation layer that happens above all {@link TaskStack}s. */
73 static final int ANIMATION_LAYER_BOOSTED = 1;
74
75 /**
76 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
Winson Chung732446a2018-09-19 13:15:17 -070077 * activities and all activities that are being controlled by the recents animation. This
78 * layer is generally below all {@link TaskStack}s.
Jorim Jaggi391790622018-04-18 15:30:44 +020079 */
80 static final int ANIMATION_LAYER_HOME = 2;
81
82 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
83 ANIMATION_LAYER_STANDARD,
84 ANIMATION_LAYER_BOOSTED,
85 ANIMATION_LAYER_HOME,
86 })
87 @interface AnimationLayer {}
88
Andrii Kuliand2765632016-12-12 22:26:34 -080089 static final int POSITION_TOP = Integer.MAX_VALUE;
90 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
91
Andrii Kulian441e4492016-09-29 15:25:00 -070092 /**
93 * The parent of this window container.
94 * For removing or setting new parent {@link #setParent} should be used, because it also
95 * performs configuration updates based on new parent's settings.
96 */
Jorim Jaggia5e10572017-11-15 14:36:26 +010097 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070098
99 // List of children for this window container. List is in z-order as the children appear on
100 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +0200101 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700102
Wale Ogunwale51362492016-09-08 17:49:17 -0700103 // The specified orientation for this window container.
104 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
105
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800106 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
107 new Pools.SynchronizedPool<>(3);
108
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800109 // The owner/creator for this container. No controller if null.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100110 WindowContainerController mController;
Robert Carrb1579c82017-09-05 14:54:47 -0700111
Tiger Huanged6794e2019-05-07 20:07:59 +0800112 // The display this window container is on.
113 protected DisplayContent mDisplayContent;
114
Robert Carrb1579c82017-09-05 14:54:47 -0700115 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100116 private int mLastLayer = 0;
117 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700118
Tiger Huanged6794e2019-05-07 20:07:59 +0800119 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
120 private final Transaction mPendingTransaction;
121
Robert Carrb1579c82017-09-05 14:54:47 -0700122 /**
123 * Applied as part of the animation pass in "prepareSurfaces".
124 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100125 protected final SurfaceAnimator mSurfaceAnimator;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800126 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100127
chaviwe07246a2017-12-12 16:18:29 -0800128 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800129 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800130
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100131 /** Total number of elements in this subtree, including our own hierarchy element. */
132 private int mTreeWeight = 1;
133
chaviw7f1fa992018-01-10 13:52:12 -0800134 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700135 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800136 * surface to the animation leash
137 */
138 private boolean mCommittedReparentToAnimationLeash;
139
Robert Carr32eef6b2019-07-17 13:16:21 -0700140 private MagnificationSpec mLastMagnificationSpec;
141
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800142 WindowContainer(WindowManagerService wms) {
143 mWmService = wms;
144 mPendingTransaction = wms.mTransactionFactory.make();
145 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100146 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800147
Wale Ogunwale98d62312017-07-12 09:24:56 -0700148 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700149 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700150 return mParent;
151 }
152
Wale Ogunwale98d62312017-07-12 09:24:56 -0700153 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700154 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700155 return mChildren.size();
156 }
157
158 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700159 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700160 return mChildren.get(index);
161 }
162
chaviwe07246a2017-12-12 16:18:29 -0800163 @Override
164 public void onConfigurationChanged(Configuration newParentConfig) {
165 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800166 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800167 scheduleAnimation();
168 }
169
Jorim Jaggia5e10572017-11-15 14:36:26 +0100170 final protected void setParent(WindowContainer<WindowContainer> parent) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700171 mParent = parent;
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800172 onParentChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800173 }
174
175 /**
176 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
177 * Supposed to be overridden and contain actions that should be executed after parent was set.
178 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800179 @Override
180 void onParentChanged() {
181 super.onParentChanged();
Robert Carrb1579c82017-09-05 14:54:47 -0700182 if (mParent == null) {
183 return;
184 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100185
Robert Carrb1579c82017-09-05 14:54:47 -0700186 if (mSurfaceControl == null) {
187 // If we don't yet have a surface, but we now have a parent, we should
188 // build a surface.
189 mSurfaceControl = makeSurface().build();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700190 getPendingTransaction().show(mSurfaceControl);
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700191 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700192 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100193 // If we have a surface but a new parent, we just need to perform a reparent. Go through
194 // surface animator such that hierarchy is preserved when animating, i.e.
195 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
196 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100197 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700198 }
199
200 // Either way we need to ask the parent to assign us a Z-order.
201 mParent.assignChildLayers();
202 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700203 }
204
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700205 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100206 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
207 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700208
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700209 /**
210 * Adds the input window container has a child of this container in order based on the input
211 * comparator.
212 * @param child The window container to add as a child of this window container.
213 * @param comparator Comparator to use in determining the position the child should be added to.
214 * If null, the child will be added to the top.
215 */
216 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700217 protected void addChild(E child, Comparator<E> comparator) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700218 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700219 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700220 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700221 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700222 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700223
Andrii Kulianb94292e2016-10-19 13:30:58 -0700224 int positionToAdd = -1;
225 if (comparator != null) {
226 final int count = mChildren.size();
227 for (int i = 0; i < count; i++) {
228 if (comparator.compare(child, mChildren.get(i)) < 0) {
229 positionToAdd = i;
230 break;
231 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700232 }
233 }
234
Andrii Kulianb94292e2016-10-19 13:30:58 -0700235 if (positionToAdd == -1) {
236 mChildren.add(child);
237 } else {
238 mChildren.add(positionToAdd, child);
239 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100240 onChildAdded(child);
241
Andrii Kulianb94292e2016-10-19 13:30:58 -0700242 // Set the parent after we've actually added a child in case a subclass depends on this.
243 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700244 }
245
Wale Ogunwalef6192862016-09-10 13:42:30 -0700246 /** Adds the input window container has a child of this container at the input index. */
247 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800248 void addChild(E child, int index) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700249 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700250 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700251 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700252 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700253 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900254
255 if ((index < 0 && index != POSITION_BOTTOM)
256 || (index > mChildren.size() && index != POSITION_TOP)) {
257 throw new IllegalArgumentException("addChild: invalid position=" + index
258 + ", children number=" + mChildren.size());
259 }
260
261 if (index == POSITION_TOP) {
262 index = mChildren.size();
263 } else if (index == POSITION_BOTTOM) {
264 index = 0;
265 }
266
Wale Ogunwalef6192862016-09-10 13:42:30 -0700267 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100268 onChildAdded(child);
269
Andrii Kulianb94292e2016-10-19 13:30:58 -0700270 // Set the parent after we've actually added a child in case a subclass depends on this.
271 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700272 }
273
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100274 private void onChildAdded(WindowContainer child) {
275 mTreeWeight += child.mTreeWeight;
276 WindowContainer parent = getParent();
277 while (parent != null) {
278 parent.mTreeWeight += child.mTreeWeight;
279 parent = parent.getParent();
280 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800281 onChildPositionChanged();
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100282 }
283
Wale Ogunwalef6192862016-09-10 13:42:30 -0700284 /**
285 * Removes the input child container from this container which is its parent.
286 *
287 * @return True if the container did contain the input child and it was detached.
288 */
289 @CallSuper
290 void removeChild(E child) {
291 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100292 onChildRemoved(child);
Andrii Kulian441e4492016-09-29 15:25:00 -0700293 child.setParent(null);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700294 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700295 throw new IllegalArgumentException("removeChild: container=" + child.getName()
296 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700297 }
298 }
299
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100300 private void onChildRemoved(WindowContainer child) {
301 mTreeWeight -= child.mTreeWeight;
302 WindowContainer parent = getParent();
303 while (parent != null) {
304 parent.mTreeWeight -= child.mTreeWeight;
305 parent = parent.getParent();
306 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800307 onChildPositionChanged();
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100308 }
309
Wale Ogunwale571771c2016-08-26 13:18:50 -0700310 /**
311 * Removes this window container and its children with no regard for what else might be going on
312 * in the system. For example, the container will be removed during animation if this method is
313 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
314 * which allows the system to defer removal until a suitable time.
315 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700316 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700317 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700318 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100319 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700320 child.removeImmediately();
321 // Need to do this after calling remove on the child because the child might try to
322 // remove/detach itself from its parent which will cause an exception if we remove
323 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100324 if (mChildren.remove(child)) {
325 onChildRemoved(child);
326 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700327 }
328
Robert Carrb1579c82017-09-05 14:54:47 -0700329 if (mSurfaceControl != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800330 getPendingTransaction().remove(mSurfaceControl);
chaviw6728e2f2018-03-19 15:58:04 -0700331
332 // Merge to parent transaction to ensure the transactions on this WindowContainer are
333 // applied in native even if WindowContainer is removed.
334 if (mParent != null) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800335 mParent.getPendingTransaction().merge(getPendingTransaction());
chaviw6728e2f2018-03-19 15:58:04 -0700336 }
337
Robert Carrb1579c82017-09-05 14:54:47 -0700338 mSurfaceControl = null;
Chavi Weingartenb736e322018-02-23 00:27:54 +0000339 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700340 }
341
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700342 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700343 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700344 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800345
346 if (mController != null) {
347 setController(null);
348 }
Robert Carrb1579c82017-09-05 14:54:47 -0700349
Wale Ogunwale571771c2016-08-26 13:18:50 -0700350 }
351
352 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100353 * @return The index of this element in the hierarchy tree in prefix order.
354 */
355 int getPrefixOrderIndex() {
356 if (mParent == null) {
357 return 0;
358 }
359 return mParent.getPrefixOrderIndex(this);
360 }
361
362 private int getPrefixOrderIndex(WindowContainer child) {
363 int order = 0;
364 for (int i = 0; i < mChildren.size(); i++) {
365 final WindowContainer childI = mChildren.get(i);
366 if (child == childI) {
367 break;
368 }
369 order += childI.mTreeWeight;
370 }
371 if (mParent != null) {
372 order += mParent.getPrefixOrderIndex(this);
373 }
374
375 // We also need to count ourselves.
376 order++;
377 return order;
378 }
379
380 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700381 * Removes this window container and its children taking care not to remove them during a
382 * critical stage in the system. For example, some containers will not be removed during
383 * animation if this method is called.
384 */
385 // TODO: figure-out implementation that works best for this.
386 // E.g. when do we remove from parent list? maybe not...
387 void removeIfPossible() {
388 for (int i = mChildren.size() - 1; i >= 0; --i) {
389 final WindowContainer wc = mChildren.get(i);
390 wc.removeIfPossible();
391 }
392 }
393
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700394 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000395 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700396 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000397 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700398 if (current == child || current.hasChild(child)) {
399 return true;
400 }
401 }
402 return false;
403 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700404
Andrii Kulian441e4492016-09-29 15:25:00 -0700405 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800406 * Move a child from it's current place in siblings list to the specified position,
407 * with an option to move all its parents to top.
408 * @param position Target position to move the child to.
409 * @param child Child to move to selected position.
410 * @param includingParents Flag indicating whether we need to move the entire branch of the
411 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
412 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
413 * this flag will do nothing.
414 */
415 @CallSuper
416 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800417
418 if (child.getParent() != this) {
419 throw new IllegalArgumentException("removeChild: container=" + child.getName()
420 + " is not a child of container=" + getName()
421 + " current parent=" + child.getParent());
422 }
423
Andrii Kuliand2765632016-12-12 22:26:34 -0800424 if ((position < 0 && position != POSITION_BOTTOM)
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800425 || (position > mChildren.size() && position != POSITION_TOP)) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800426 throw new IllegalArgumentException("positionAt: invalid position=" + position
427 + ", children number=" + mChildren.size());
428 }
429
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800430 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800431 position = POSITION_TOP;
432 } else if (position == 0) {
433 position = POSITION_BOTTOM;
434 }
435
436 switch (position) {
437 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800438 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800439 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200440 mChildren.add(child);
Tiger Huangdda14a72019-01-10 17:20:27 +0800441 onChildPositionChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800442 }
443 if (includingParents && getParent() != null) {
444 getParent().positionChildAt(POSITION_TOP, this /* child */,
445 true /* includingParents */);
446 }
447 break;
448 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800449 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800450 mChildren.remove(child);
451 mChildren.addFirst(child);
Tiger Huangdda14a72019-01-10 17:20:27 +0800452 onChildPositionChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800453 }
454 if (includingParents && getParent() != null) {
455 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
456 true /* includingParents */);
457 }
458 break;
459 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800460 // TODO: Removing the child before reinserting requires the caller to provide a
461 // position that takes into account the removed child (if the index of the
462 // child < position, then the position should be adjusted). We should consider
463 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800464 mChildren.remove(child);
465 mChildren.add(position, child);
Tiger Huangdda14a72019-01-10 17:20:27 +0800466 onChildPositionChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800467 }
468 }
469
470 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800471 * Notify that a child's position has changed. Possible changes are adding or removing a child.
472 */
473 void onChildPositionChanged() { }
474
475 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700476 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700477 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700478 * @see #mFullConfiguration
479 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700480 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700481 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800482 // We must diff before the configuration is applied so that we can capture the change
483 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700484 final int diff = diffRequestedOverrideBounds(
485 overrideConfiguration.windowConfiguration.getBounds());
486 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700487 if (mParent != null) {
488 mParent.onDescendantOverrideConfigurationChanged();
489 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800490
491 if (diff == BOUNDS_CHANGE_NONE) {
492 return;
493 }
494
495 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
496 onResize();
497 } else {
498 onMovedByResize();
499 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700500 }
501
502 /**
503 * Notify that a descendant's overrideConfiguration has changed.
504 */
505 void onDescendantOverrideConfigurationChanged() {
506 if (mParent != null) {
507 mParent.onDescendantOverrideConfigurationChanged();
508 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700509 }
510
511 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700512 * Notify that the display this container is on has changed. This could be either this container
513 * is moved to a new display, or some configurations on the display it is on changes.
514 *
515 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700516 */
517 void onDisplayChanged(DisplayContent dc) {
Tiger Huanged6794e2019-05-07 20:07:59 +0800518 mDisplayContent = dc;
519 if (dc != null && dc != this) {
520 dc.getPendingTransaction().merge(mPendingTransaction);
521 }
Wale Ogunwale02319a62016-09-26 15:21:22 -0700522 for (int i = mChildren.size() - 1; i >= 0; --i) {
523 final WindowContainer child = mChildren.get(i);
524 child.onDisplayChanged(dc);
525 }
526 }
527
Tiger Huanged6794e2019-05-07 20:07:59 +0800528 DisplayContent getDisplayContent() {
529 return mDisplayContent;
530 }
531
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700532 void setWaitingForDrawnIfResizingChanged() {
533 for (int i = mChildren.size() - 1; i >= 0; --i) {
534 final WindowContainer wc = mChildren.get(i);
535 wc.setWaitingForDrawnIfResizingChanged();
536 }
537 }
538
539 void onResize() {
540 for (int i = mChildren.size() - 1; i >= 0; --i) {
541 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800542 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700543 }
544 }
545
Bryce Leed92ae482018-01-22 13:56:23 -0800546 void onParentResize() {
547 // In the case this container has specified its own bounds, a parent resize will not
548 // affect its bounds. Any relevant changes will be propagated through changes to the
549 // Configuration override.
550 if (hasOverrideBounds()) {
551 return;
552 }
553
554 // Default implementation is to treat as resize on self.
555 onResize();
556 }
557
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700558 void onMovedByResize() {
559 for (int i = mChildren.size() - 1; i >= 0; --i) {
560 final WindowContainer wc = mChildren.get(i);
561 wc.onMovedByResize();
562 }
563 }
564
565 void resetDragResizingChangeReported() {
566 for (int i = mChildren.size() - 1; i >= 0; --i) {
567 final WindowContainer wc = mChildren.get(i);
568 wc.resetDragResizingChangeReported();
569 }
570 }
571
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700572 void forceWindowsScaleableInTransaction(boolean force) {
573 for (int i = mChildren.size() - 1; i >= 0; --i) {
574 final WindowContainer wc = mChildren.get(i);
575 wc.forceWindowsScaleableInTransaction(force);
576 }
577 }
578
Jorim Jaggia5e10572017-11-15 14:36:26 +0100579 /**
580 * @return Whether our own container is running an animation or any child, no matter how deep in
581 * the hierarchy, is animating.
582 */
583 boolean isSelfOrChildAnimating() {
584 if (isSelfAnimating()) {
585 return true;
586 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700587 for (int j = mChildren.size() - 1; j >= 0; j--) {
588 final WindowContainer wc = mChildren.get(j);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100589 if (wc.isSelfOrChildAnimating()) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700590 return true;
591 }
592 }
593 return false;
594 }
595
Jorim Jaggia5e10572017-11-15 14:36:26 +0100596 /**
597 * @return Whether our own container is running an animation or our parent is animating. This
598 * doesn't consider whether children are animating.
599 */
600 boolean isAnimating() {
601
602 // We are animating if we ourselves are animating or if our parent is animating.
603 return isSelfAnimating() || mParent != null && mParent.isAnimating();
604 }
605
606 /**
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200607 * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
608 * that is {@link #isSelfAnimating}; {@code false} otherwise.
609 */
610 boolean isAppAnimating() {
611 for (int j = mChildren.size() - 1; j >= 0; j--) {
612 final WindowContainer wc = mChildren.get(j);
613 if (wc.isAppAnimating()) {
614 return true;
615 }
616 }
617 return false;
618 }
619
620 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100621 * @return Whether our own container running an animation at the moment.
622 */
623 boolean isSelfAnimating() {
624 return mSurfaceAnimator.isAnimating();
625 }
626
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700627 void sendAppVisibilityToClients() {
628 for (int i = mChildren.size() - 1; i >= 0; --i) {
629 final WindowContainer wc = mChildren.get(i);
630 wc.sendAppVisibilityToClients();
631 }
632 }
633
Wale Ogunwale44f21802016-09-02 12:49:48 -0700634 /**
635 * Returns true if the container or one of its children as some content it can display or wants
636 * to display (e.g. app views or saved surface).
637 *
638 * NOTE: While this method will return true if the there is some content to display, it doesn't
639 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
640 * visible.
641 */
642 boolean hasContentToDisplay() {
643 for (int i = mChildren.size() - 1; i >= 0; --i) {
644 final WindowContainer wc = mChildren.get(i);
645 if (wc.hasContentToDisplay()) {
646 return true;
647 }
648 }
649 return false;
650 }
651
652 /**
653 * Returns true if the container or one of its children is considered visible from the
654 * WindowManager perspective which usually means valid surface and some other internal state
655 * are true.
656 *
657 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
658 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
659 * the container has any content to display.
660 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700661 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700662 // TODO: Will this be more correct if it checks the visibility of its parents?
663 // It depends...For example, Tasks and Stacks are only visible if there children are visible
664 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800665 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700666 for (int i = mChildren.size() - 1; i >= 0; --i) {
667 final WindowContainer wc = mChildren.get(i);
668 if (wc.isVisible()) {
669 return true;
670 }
671 }
672 return false;
673 }
674
Bryce Lee00d586d2017-07-28 20:48:43 -0700675 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700676 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700677 */
678 boolean isOnTop() {
679 return getParent().getTopChild() == this && getParent().isOnTop();
680 }
681
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100682 /** Returns the top child container. */
683 E getTopChild() {
684 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700685 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700686
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700687 /** Returns true if there is still a removal being deferred */
688 boolean checkCompleteDeferredRemoval() {
689 boolean stillDeferringRemoval = false;
690
691 for (int i = mChildren.size() - 1; i >= 0; --i) {
692 final WindowContainer wc = mChildren.get(i);
693 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
694 }
695
696 return stillDeferringRemoval;
697 }
698
699 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700700 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700701 for (int i = mChildren.size() - 1; i >= 0; --i) {
702 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700703 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700704 }
705 }
706
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700707 void onAppTransitionDone() {
708 for (int i = mChildren.size() - 1; i >= 0; --i) {
709 final WindowContainer wc = mChildren.get(i);
710 wc.onAppTransitionDone();
711 }
712 }
713
Garfield Tan90b04282018-12-11 14:04:42 -0800714 /**
715 * Called when this container or one of its descendants changed its requested orientation, and
716 * wants this container to handle it or pass it to its parent.
717 *
718 * @param freezeDisplayToken freeze this app window token if display needs to freeze
719 * @param requestingContainer the container which orientation request has changed
720 * @return {@code true} if handled; {@code false} otherwise.
721 */
722 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
723 @Nullable ConfigurationContainer requestingContainer) {
724 final WindowContainer parent = getParent();
725 if (parent == null) {
726 return false;
727 }
728 return parent.onDescendantOrientationChanged(freezeDisplayToken,
729 requestingContainer);
730 }
731
732 /**
Garfield Tan49dae102019-02-04 09:51:59 -0800733 * Check if this container or its parent will handle orientation changes from descendants. It's
734 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
735 * ConfigurationContainer)} in the sense that the return value of this method tells if this
736 * container or its parent will handle the request eventually, while the return value of the
737 * other method is if it handled the request synchronously.
738 *
739 * @return {@code true} if it handles or will handle orientation change in the future; {@code
740 * false} if it won't handle the change at anytime.
741 */
742 boolean handlesOrientationChangeFromDescendant() {
743 final WindowContainer parent = getParent();
744 return parent != null && parent.handlesOrientationChangeFromDescendant();
745 }
746
747 /**
Garfield Tan90b04282018-12-11 14:04:42 -0800748 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
749 * parameters.
750 *
751 * @param orientation the specified orientation.
752 */
Wale Ogunwale51362492016-09-08 17:49:17 -0700753 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -0800754 setOrientation(orientation, null /* freezeDisplayToken */,
755 null /* ActivityRecord */);
756 }
757
758 /**
759 * Sets the specified orientation of this container. It percolates this change upward along the
760 * hierarchy to let each level of the hierarchy a chance to respond to it.
761 *
762 * @param orientation the specified orientation. Needs to be one of {@link
763 * android.content.pm.ActivityInfo.ScreenOrientation}.
764 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
765 * done. Display will not be frozen if this is {@code null}, which
766 * should only happen in tests.
767 * @param requestingContainer the container which orientation request has changed. Mostly used
768 * to ensure it gets correct configuration.
769 */
770 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
771 @Nullable ConfigurationContainer requestingContainer) {
772 final boolean changed = mOrientation != orientation;
Wale Ogunwale51362492016-09-08 17:49:17 -0700773 mOrientation = orientation;
Garfield Tan90b04282018-12-11 14:04:42 -0800774 if (!changed) {
775 return;
776 }
777 final WindowContainer parent = getParent();
778 if (parent != null) {
779 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
780 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700781 }
782
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700783 int getOrientation() {
784 return getOrientation(mOrientation);
785 }
786
Wale Ogunwale51362492016-09-08 17:49:17 -0700787 /**
788 * Returns the specified orientation for this window container or one of its children is there
789 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
790 * specification is set.
791 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
792 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700793 *
794 * @param candidate The current orientation candidate that will be returned if we don't find a
795 * better match.
796 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -0700797 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700798 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -0800799 if (!fillsParent()) {
800 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -0700801 return SCREEN_ORIENTATION_UNSET;
802 }
803
Bryce Leea163b762017-01-24 11:05:01 -0800804 // The container fills its parent so we can use it orientation if it has one
805 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -0700806 // specified and fall back on this container's unset or unspecified value as a candidate
807 // if none of the children have a better candidate for the orientation.
808 if (mOrientation != SCREEN_ORIENTATION_UNSET
809 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
810 return mOrientation;
811 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700812
813 for (int i = mChildren.size() - 1; i >= 0; --i) {
814 final WindowContainer wc = mChildren.get(i);
815
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700816 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
817 // SCREEN_ORIENTATION_UNSPECIFIED?
818 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
819 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -0700820 if (orientation == SCREEN_ORIENTATION_BEHIND) {
821 // container wants us to use the orientation of the container behind it. See if we
822 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
823 // look behind this container.
824 candidate = orientation;
825 continue;
826 }
827
828 if (orientation == SCREEN_ORIENTATION_UNSET) {
829 continue;
830 }
831
832 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
833 // Use the orientation if the container fills its parent or requested an explicit
834 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
835 return orientation;
836 }
837 }
838
839 return candidate;
840 }
841
842 /**
843 * Returns true if this container is opaque and fills all the space made available by its parent
844 * container.
845 *
846 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
847 * this is just a signal from the client to window manager stating its intent, but not what it
848 * actually does.
849 */
850 boolean fillsParent() {
851 return false;
852 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700853
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000854 // TODO: Users would have their own window containers under the display container?
855 void switchUser() {
856 for (int i = mChildren.size() - 1; i >= 0; --i) {
857 mChildren.get(i).switchUser();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700858 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700859 }
860
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800861 /**
862 * For all windows at or below this container call the callback.
863 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
864 * stops the search if {@link ToBooleanFunction#apply} returns true.
865 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
866 * z-order, else from bottom-to-top.
867 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800868 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800869 */
870 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700871 if (traverseTopToBottom) {
872 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800873 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
874 return true;
875 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700876 }
877 } else {
878 final int count = mChildren.size();
879 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800880 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
881 return true;
882 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700883 }
884 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800885 return false;
886 }
887
888 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800889 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
890 forAllWindows(wrapper, traverseTopToBottom);
891 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700892 }
893
lumark588a3e82018-07-20 18:53:54 +0800894 void forAllAppWindows(Consumer<AppWindowToken> callback) {
895 for (int i = mChildren.size() - 1; i >= 0; --i) {
896 mChildren.get(i).forAllAppWindows(callback);
897 }
898 }
899
Jorim Jaggi51304d72017-05-17 17:25:32 +0200900 /**
901 * For all tasks at or below this container call the callback.
902 *
903 * @param callback Callback to be called for every task.
904 */
905 void forAllTasks(Consumer<Task> callback) {
906 for (int i = mChildren.size() - 1; i >= 0; --i) {
907 mChildren.get(i).forAllTasks(callback);
908 }
909 }
910
Wale Ogunwaled1880962016-11-08 10:31:59 -0800911 WindowState getWindow(Predicate<WindowState> callback) {
912 for (int i = mChildren.size() - 1; i >= 0; --i) {
913 final WindowState w = mChildren.get(i).getWindow(callback);
914 if (w != null) {
915 return w;
916 }
917 }
918
919 return null;
920 }
921
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700922 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -0700923 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
924 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700925 */
926 @Override
927 public int compareTo(WindowContainer other) {
928 if (this == other) {
929 return 0;
930 }
931
932 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200933 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700934 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
935 }
936
937 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
938 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200939 try {
940 getParents(thisParentChain);
941 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700942
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200943 // Find the common ancestor of both containers.
944 WindowContainer commonAncestor = null;
945 WindowContainer thisTop = thisParentChain.peekLast();
946 WindowContainer otherTop = otherParentChain.peekLast();
947 while (thisTop != null && otherTop != null && thisTop == otherTop) {
948 commonAncestor = thisParentChain.removeLast();
949 otherParentChain.removeLast();
950 thisTop = thisParentChain.peekLast();
951 otherTop = otherParentChain.peekLast();
952 }
953
954 // Containers don't belong to the same hierarchy???
955 if (commonAncestor == null) {
956 throw new IllegalArgumentException("No in the same hierarchy this="
957 + thisParentChain + " other=" + otherParentChain);
958 }
959
960 // Children are always considered greater than their parents, so if one of the containers
961 // we are comparing it the parent of the other then whichever is the child is greater.
962 if (commonAncestor == this) {
963 return -1;
964 } else if (commonAncestor == other) {
965 return 1;
966 }
967
968 // The position of the first non-common ancestor in the common ancestor list determines
969 // which is greater the which.
970 final WindowList<WindowContainer> list = commonAncestor.mChildren;
971 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
972 ? 1 : -1;
973 } finally {
974 mTmpChain1.clear();
975 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700976 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700977 }
978
979 private void getParents(LinkedList<WindowContainer> parents) {
980 parents.clear();
981 WindowContainer current = this;
982 do {
983 parents.addLast(current);
984 current = current.mParent;
985 } while (current != null);
986 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700987
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800988 WindowContainerController getController() {
989 return mController;
990 }
991
992 void setController(WindowContainerController controller) {
993 if (mController != null && controller != null) {
994 throw new IllegalArgumentException("Can't set controller=" + mController
995 + " for container=" + this + " Already set to=" + mController);
996 }
997 if (controller != null) {
998 controller.setContainer(this);
999 } else if (mController != null) {
1000 mController.setContainer(null);
1001 }
1002 mController = controller;
1003 }
1004
Robert Carrb1579c82017-09-05 14:54:47 -07001005 SurfaceControl.Builder makeSurface() {
1006 final WindowContainer p = getParent();
1007 return p.makeChildSurface(this);
1008 }
1009
Robert Carrf59b8dd2017-10-02 18:58:36 -07001010 /**
1011 * @param child The WindowContainer this child surface is for, or null if the Surface
1012 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1013 */
Robert Carrb1579c82017-09-05 14:54:47 -07001014 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1015 final WindowContainer p = getParent();
1016 // Give the parent a chance to set properties. In hierarchy v1 we rely
1017 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001018 return p.makeChildSurface(child)
1019 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001020 }
Robert Carrdea7bf42019-04-04 12:02:51 -07001021 /*
1022 * @return The SurfaceControl parent for this containers SurfaceControl.
1023 * The SurfaceControl must be valid if non-null.
1024 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001025 @Override
1026 public SurfaceControl getParentSurfaceControl() {
1027 final WindowContainer parent = getParent();
1028 if (parent == null) {
1029 return null;
1030 }
1031 return parent.getSurfaceControl();
1032 }
1033
Robert Carrb1579c82017-09-05 14:54:47 -07001034 /**
1035 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1036 */
1037 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001038 if (mSurfaceControl == null) {
1039 return false;
1040 }
1041
Robert Carrb1579c82017-09-05 14:54:47 -07001042 for (int i = 0; i < mChildren.size(); i++) {
1043 if (!mChildren.get(i).shouldMagnify()) {
1044 return false;
1045 }
1046 }
1047 return true;
1048 }
1049
1050 SurfaceSession getSession() {
1051 if (getParent() != null) {
1052 return getParent().getSession();
1053 }
1054 return null;
1055 }
1056
1057 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001058 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1059 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001060 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001061 mLastLayer = layer;
1062 mLastRelativeToLayer = null;
1063 }
1064 }
1065
1066 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1067 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1068 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001069 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001070 mLastLayer = layer;
1071 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001072 }
1073 }
1074
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001075 protected void setLayer(Transaction t, int layer) {
1076
1077 // Route through surface animator to accommodate that our surface control might be
1078 // attached to the leash, and leash is attached to parent container.
1079 mSurfaceAnimator.setLayer(t, layer);
1080 }
1081
1082 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1083
1084 // Route through surface animator to accommodate that our surface control might be
1085 // attached to the leash, and leash is attached to parent container.
1086 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1087 }
1088
1089 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1090 mSurfaceAnimator.reparent(t, newParent);
1091 }
1092
Robert Carrb1579c82017-09-05 14:54:47 -07001093 void assignChildLayers(Transaction t) {
1094 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001095
1096 // We use two passes as a way to promote children which
1097 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001098 for (int j = 0; j < mChildren.size(); ++j) {
1099 final WindowContainer wc = mChildren.get(j);
1100 wc.assignChildLayers(t);
1101 if (!wc.needsZBoost()) {
1102 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001103 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001104 }
1105 for (int j = 0; j < mChildren.size(); ++j) {
1106 final WindowContainer wc = mChildren.get(j);
1107 if (wc.needsZBoost()) {
1108 wc.assignLayer(t, layer++);
1109 }
Robert Carrb1579c82017-09-05 14:54:47 -07001110 }
1111 }
1112
1113 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001114 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001115 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001116 }
1117
1118 boolean needsZBoost() {
1119 for (int i = 0; i < mChildren.size(); i++) {
1120 if (mChildren.get(i).needsZBoost()) {
1121 return true;
1122 }
1123 }
1124 return false;
1125 }
1126
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001127 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001128 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001129 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001130 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001131 * @param proto Stream to write the WindowContainer object to.
1132 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001133 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001134 * @hide
1135 */
1136 @CallSuper
1137 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08001138 public void writeToProto(ProtoOutputStream proto, long fieldId,
1139 @WindowTraceLogLevel int logLevel) {
1140 boolean isVisible = isVisible();
1141 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1142 return;
1143 }
1144
Adrian Roos4921ccf2017-09-28 16:54:06 +02001145 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001146 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001147 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001148 proto.write(VISIBLE, isVisible);
1149 if (mSurfaceAnimator.isAnimating()) {
1150 mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
1151 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001152 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001153 }
1154
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001155 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1156 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1157 if (wrapper == null) {
1158 wrapper = new ForAllWindowsConsumerWrapper();
1159 }
1160 wrapper.setConsumer(consumer);
1161 return wrapper;
1162 }
1163
1164 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1165
1166 private Consumer<WindowState> mConsumer;
1167
1168 void setConsumer(Consumer<WindowState> consumer) {
1169 mConsumer = consumer;
1170 }
1171
1172 @Override
1173 public boolean apply(WindowState w) {
1174 mConsumer.accept(w);
1175 return false;
1176 }
1177
1178 void release() {
1179 mConsumer = null;
1180 mConsumerWrapperPool.release(this);
1181 }
1182 }
Robert Carrb1579c82017-09-05 14:54:47 -07001183
1184 // TODO(b/68336570): Should this really be on WindowContainer since it
1185 // can only be used on the top-level nodes that aren't animated?
1186 // (otherwise we would be fighting other callers of setMatrix).
1187 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1188 if (shouldMagnify()) {
1189 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1190 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
Robert Carr32eef6b2019-07-17 13:16:21 -07001191 mLastMagnificationSpec = spec;
Robert Carrb1579c82017-09-05 14:54:47 -07001192 } else {
Jackal Guoae2002a2019-12-16 15:24:58 +08001193 clearMagnificationSpec(t);
Robert Carrb1579c82017-09-05 14:54:47 -07001194 for (int i = 0; i < mChildren.size(); i++) {
1195 mChildren.get(i).applyMagnificationSpec(t, spec);
1196 }
1197 }
1198 }
1199
Robert Carr32eef6b2019-07-17 13:16:21 -07001200 void clearMagnificationSpec(Transaction t) {
1201 if (mLastMagnificationSpec != null) {
1202 t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
1203 .setPosition(mSurfaceControl, 0, 0);
1204 }
1205 mLastMagnificationSpec = null;
1206 for (int i = 0; i < mChildren.size(); i++) {
1207 mChildren.get(i).clearMagnificationSpec(t);
1208 }
1209 }
1210
Robert Carrb1579c82017-09-05 14:54:47 -07001211 void prepareSurfaces() {
chaviw7f1fa992018-01-10 13:52:12 -08001212 // If a leash has been set when the transaction was committed, then the leash reparent has
1213 // been committed.
1214 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001215 for (int i = 0; i < mChildren.size(); i++) {
1216 mChildren.get(i).prepareSurfaces();
1217 }
1218 }
1219
1220 /**
chaviw7f1fa992018-01-10 13:52:12 -08001221 * @return true if the reparent to animation leash transaction has been committed, false
1222 * otherwise.
1223 */
1224 boolean hasCommittedReparentToAnimationLeash() {
1225 return mCommittedReparentToAnimationLeash;
1226 }
1227
1228 /**
Tiger Huanged6794e2019-05-07 20:07:59 +08001229 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1230 * will be applied.
Robert Carrb1579c82017-09-05 14:54:47 -07001231 */
1232 void scheduleAnimation() {
1233 if (mParent != null) {
1234 mParent.scheduleAnimation();
1235 }
1236 }
1237
Robert Carrdea7bf42019-04-04 12:02:51 -07001238 /**
1239 * @return The SurfaceControl for this container.
1240 * The SurfaceControl must be valid if non-null.
1241 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001242 @Override
1243 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001244 return mSurfaceControl;
1245 }
1246
Jorim Jaggia5e10572017-11-15 14:36:26 +01001247 @Override
1248 public Transaction getPendingTransaction() {
Tiger Huanged6794e2019-05-07 20:07:59 +08001249 final DisplayContent displayContent = getDisplayContent();
1250 if (displayContent != null && displayContent != this) {
1251 return displayContent.getPendingTransaction();
1252 }
1253 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1254 // let the caller to save the surface operations within the local mPendingTransaction.
1255 // If this is not a DisplayContent, we will merge it to the pending transaction of its
1256 // display once it attaches to it.
Robert Carrf59b8dd2017-10-02 18:58:36 -07001257 return mPendingTransaction;
1258 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001259
1260 /**
1261 * Starts an animation on the container.
1262 *
1263 * @param anim The animation to run.
1264 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1265 * some point but the meaning is too weird to work for all containers.
1266 */
1267 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1268 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1269
1270 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1271 // the moment this doesn't work for all animatable window containers.
1272 mSurfaceAnimator.startAnimation(t, anim, hidden);
1273 }
1274
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001275 void transferAnimation(WindowContainer from) {
1276 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1277 }
1278
Jorim Jaggia5e10572017-11-15 14:36:26 +01001279 void cancelAnimation() {
1280 mSurfaceAnimator.cancelAnimation();
1281 }
1282
1283 @Override
1284 public Builder makeAnimationLeash() {
1285 return makeSurface();
1286 }
1287
Jorim Jaggi596a1992017-12-29 14:48:02 +01001288 @Override
1289 public SurfaceControl getAnimationLeashParent() {
1290 return getParentSurfaceControl();
1291 }
1292
chaviw23ee71c2017-12-18 11:29:41 -08001293 /**
1294 * @return The layer on which all app animations are happening.
1295 */
Jorim Jaggi391790622018-04-18 15:30:44 +02001296 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08001297 final WindowContainer parent = getParent();
1298 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02001299 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08001300 }
1301 return null;
1302 }
1303
Jorim Jaggia5e10572017-11-15 14:36:26 +01001304 @Override
1305 public void commitPendingTransaction() {
1306 scheduleAnimation();
1307 }
1308
Robert Carr2f8aa392018-01-31 14:46:51 -08001309 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001310 final WindowContainer parent = getParent();
1311 if (parent != null) {
1312 parent.assignChildLayers(t);
1313 }
1314 }
1315
1316 @Override
1317 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001318 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001319 reassignLayer(t);
1320 }
1321
1322 @Override
lumarkf6f34942019-04-29 16:56:50 +08001323 public void onAnimationLeashLost(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001324 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001325 reassignLayer(t);
1326 }
1327
1328 /**
1329 * Called when an animation has finished running.
1330 */
1331 protected void onAnimationFinished() {
chaviwccd5d502019-02-22 13:30:31 -08001332 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01001333 }
1334
1335 /**
1336 * @return The currently running animation, if any, or {@code null} otherwise.
1337 */
1338 AnimationAdapter getAnimation() {
1339 return mSurfaceAnimator.getAnimation();
1340 }
1341
1342 /**
1343 * @see SurfaceAnimator#startDelayingAnimationStart
1344 */
1345 void startDelayingAnimationStart() {
1346 mSurfaceAnimator.startDelayingAnimationStart();
1347 }
1348
1349 /**
1350 * @see SurfaceAnimator#endDelayingAnimationStart
1351 */
1352 void endDelayingAnimationStart() {
1353 mSurfaceAnimator.endDelayingAnimationStart();
1354 }
1355
1356 @Override
1357 public int getSurfaceWidth() {
1358 return mSurfaceControl.getWidth();
1359 }
1360
1361 @Override
1362 public int getSurfaceHeight() {
1363 return mSurfaceControl.getHeight();
1364 }
1365
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001366 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01001367 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1368 if (mSurfaceAnimator.isAnimating()) {
1369 pw.print(prefix); pw.println("ContainerAnimator:");
1370 mSurfaceAnimator.dump(pw, prefix + " ");
1371 }
1372 }
chaviwe07246a2017-12-12 16:18:29 -08001373
chaviw2f0567b2018-01-29 16:22:02 -08001374 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08001375 if (mSurfaceControl == null) {
1376 return;
1377 }
1378
Evan Roskyed6767f2018-10-26 17:21:06 -07001379 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08001380 if (mTmpPos.equals(mLastSurfacePosition)) {
1381 return;
1382 }
1383
chaviw2f0567b2018-01-29 16:22:02 -08001384 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08001385 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08001386 }
1387
Evan Rosky65dffa62019-02-04 14:09:53 -08001388 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08001389 Point getLastSurfacePosition() {
1390 return mLastSurfacePosition;
1391 }
1392
Evan Roskyed6767f2018-10-26 17:21:06 -07001393 /**
1394 * Displayed bounds specify where to display this container at. It differs from bounds during
1395 * certain operations (like animation or interactive dragging).
1396 *
1397 * @return the bounds to display this container at.
1398 */
1399 Rect getDisplayedBounds() {
1400 return getBounds();
1401 }
1402
1403 void getRelativeDisplayedPosition(Point outPos) {
1404 final Rect dispBounds = getDisplayedBounds();
1405 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08001406 final WindowContainer parent = getParent();
1407 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07001408 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08001409 outPos.offset(-parentBounds.left, -parentBounds.top);
1410 }
1411 }
chaviw2fb06bc2018-01-19 17:09:15 -08001412
1413 Dimmer getDimmer() {
1414 if (mParent == null) {
1415 return null;
1416 }
1417 return mParent.getDimmer();
1418 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001419}