blob: 05d47609de4c3c1751941d9337037b5c7af155b6 [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
112 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100113 private int mLastLayer = 0;
114 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700115
116 /**
117 * Applied as part of the animation pass in "prepareSurfaces".
118 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100119 protected final Transaction mPendingTransaction;
120 protected final SurfaceAnimator mSurfaceAnimator;
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800121 protected final WindowManagerService mWmService;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100122
chaviwe07246a2017-12-12 16:18:29 -0800123 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800124 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800125
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100126 /** Total number of elements in this subtree, including our own hierarchy element. */
127 private int mTreeWeight = 1;
128
chaviw7f1fa992018-01-10 13:52:12 -0800129 /**
Vishnu Nairddd80742018-08-21 14:12:46 -0700130 * Indicates whether we are animating and have committed the transaction to reparent our
chaviw7f1fa992018-01-10 13:52:12 -0800131 * surface to the animation leash
132 */
133 private boolean mCommittedReparentToAnimationLeash;
134
Wale Ogunwale8b19de92018-11-29 19:58:26 -0800135 WindowContainer(WindowManagerService wms) {
136 mWmService = wms;
137 mPendingTransaction = wms.mTransactionFactory.make();
138 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100139 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800140
Wale Ogunwale98d62312017-07-12 09:24:56 -0700141 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700142 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700143 return mParent;
144 }
145
Wale Ogunwale98d62312017-07-12 09:24:56 -0700146 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700147 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700148 return mChildren.size();
149 }
150
151 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700152 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700153 return mChildren.get(index);
154 }
155
chaviwe07246a2017-12-12 16:18:29 -0800156 @Override
157 public void onConfigurationChanged(Configuration newParentConfig) {
158 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800159 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800160 scheduleAnimation();
161 }
162
Jorim Jaggia5e10572017-11-15 14:36:26 +0100163 final protected void setParent(WindowContainer<WindowContainer> parent) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700164 mParent = parent;
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800165 onParentChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800166 }
167
168 /**
169 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
170 * Supposed to be overridden and contain actions that should be executed after parent was set.
171 */
Riddle Hsu3a4bb612019-01-31 00:02:22 +0800172 @Override
173 void onParentChanged() {
174 super.onParentChanged();
Robert Carrb1579c82017-09-05 14:54:47 -0700175 if (mParent == null) {
176 return;
177 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100178
Robert Carrb1579c82017-09-05 14:54:47 -0700179 if (mSurfaceControl == null) {
180 // If we don't yet have a surface, but we now have a parent, we should
181 // build a surface.
182 mSurfaceControl = makeSurface().build();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700183 getPendingTransaction().show(mSurfaceControl);
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700184 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700185 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100186 // If we have a surface but a new parent, we just need to perform a reparent. Go through
187 // surface animator such that hierarchy is preserved when animating, i.e.
188 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
189 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100190 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700191 }
192
193 // Either way we need to ask the parent to assign us a Z-order.
194 mParent.assignChildLayers();
195 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700196 }
197
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700198 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100199 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
200 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700201
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700202 /**
203 * Adds the input window container has a child of this container in order based on the input
204 * comparator.
205 * @param child The window container to add as a child of this window container.
206 * @param comparator Comparator to use in determining the position the child should be added to.
207 * If null, the child will be added to the top.
208 */
209 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700210 protected void addChild(E child, Comparator<E> comparator) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700211 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700212 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700213 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700214 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700215 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700216
Andrii Kulianb94292e2016-10-19 13:30:58 -0700217 int positionToAdd = -1;
218 if (comparator != null) {
219 final int count = mChildren.size();
220 for (int i = 0; i < count; i++) {
221 if (comparator.compare(child, mChildren.get(i)) < 0) {
222 positionToAdd = i;
223 break;
224 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700225 }
226 }
227
Andrii Kulianb94292e2016-10-19 13:30:58 -0700228 if (positionToAdd == -1) {
229 mChildren.add(child);
230 } else {
231 mChildren.add(positionToAdd, child);
232 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100233 onChildAdded(child);
234
Andrii Kulianb94292e2016-10-19 13:30:58 -0700235 // Set the parent after we've actually added a child in case a subclass depends on this.
236 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700237 }
238
Wale Ogunwalef6192862016-09-10 13:42:30 -0700239 /** Adds the input window container has a child of this container at the input index. */
240 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800241 void addChild(E child, int index) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700242 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700243 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700244 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700245 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700246 }
Kazuki Takisef85197b2018-06-18 18:18:36 +0900247
248 if ((index < 0 && index != POSITION_BOTTOM)
249 || (index > mChildren.size() && index != POSITION_TOP)) {
250 throw new IllegalArgumentException("addChild: invalid position=" + index
251 + ", children number=" + mChildren.size());
252 }
253
254 if (index == POSITION_TOP) {
255 index = mChildren.size();
256 } else if (index == POSITION_BOTTOM) {
257 index = 0;
258 }
259
Wale Ogunwalef6192862016-09-10 13:42:30 -0700260 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100261 onChildAdded(child);
262
Andrii Kulianb94292e2016-10-19 13:30:58 -0700263 // Set the parent after we've actually added a child in case a subclass depends on this.
264 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700265 }
266
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100267 private void onChildAdded(WindowContainer child) {
268 mTreeWeight += child.mTreeWeight;
269 WindowContainer parent = getParent();
270 while (parent != null) {
271 parent.mTreeWeight += child.mTreeWeight;
272 parent = parent.getParent();
273 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800274 onChildPositionChanged();
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100275 }
276
Wale Ogunwalef6192862016-09-10 13:42:30 -0700277 /**
278 * Removes the input child container from this container which is its parent.
279 *
280 * @return True if the container did contain the input child and it was detached.
281 */
282 @CallSuper
283 void removeChild(E child) {
284 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100285 onChildRemoved(child);
Andrii Kulian441e4492016-09-29 15:25:00 -0700286 child.setParent(null);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700287 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700288 throw new IllegalArgumentException("removeChild: container=" + child.getName()
289 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700290 }
291 }
292
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100293 private void onChildRemoved(WindowContainer child) {
294 mTreeWeight -= child.mTreeWeight;
295 WindowContainer parent = getParent();
296 while (parent != null) {
297 parent.mTreeWeight -= child.mTreeWeight;
298 parent = parent.getParent();
299 }
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800300 onChildPositionChanged();
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100301 }
302
Wale Ogunwale571771c2016-08-26 13:18:50 -0700303 /**
304 * Removes this window container and its children with no regard for what else might be going on
305 * in the system. For example, the container will be removed during animation if this method is
306 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
307 * which allows the system to defer removal until a suitable time.
308 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700309 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700310 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700311 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100312 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700313 child.removeImmediately();
314 // Need to do this after calling remove on the child because the child might try to
315 // remove/detach itself from its parent which will cause an exception if we remove
316 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100317 if (mChildren.remove(child)) {
318 onChildRemoved(child);
319 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700320 }
321
Robert Carrb1579c82017-09-05 14:54:47 -0700322 if (mSurfaceControl != null) {
Robert Carr71200f22019-02-05 09:44:53 -0800323 mPendingTransaction.remove(mSurfaceControl);
chaviw6728e2f2018-03-19 15:58:04 -0700324
325 // Merge to parent transaction to ensure the transactions on this WindowContainer are
326 // applied in native even if WindowContainer is removed.
327 if (mParent != null) {
328 mParent.getPendingTransaction().merge(mPendingTransaction);
329 }
330
Robert Carrb1579c82017-09-05 14:54:47 -0700331 mSurfaceControl = null;
Chavi Weingartenb736e322018-02-23 00:27:54 +0000332 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700333 }
334
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700335 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700336 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700337 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800338
339 if (mController != null) {
340 setController(null);
341 }
Robert Carrb1579c82017-09-05 14:54:47 -0700342
Wale Ogunwale571771c2016-08-26 13:18:50 -0700343 }
344
345 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100346 * @return The index of this element in the hierarchy tree in prefix order.
347 */
348 int getPrefixOrderIndex() {
349 if (mParent == null) {
350 return 0;
351 }
352 return mParent.getPrefixOrderIndex(this);
353 }
354
355 private int getPrefixOrderIndex(WindowContainer child) {
356 int order = 0;
357 for (int i = 0; i < mChildren.size(); i++) {
358 final WindowContainer childI = mChildren.get(i);
359 if (child == childI) {
360 break;
361 }
362 order += childI.mTreeWeight;
363 }
364 if (mParent != null) {
365 order += mParent.getPrefixOrderIndex(this);
366 }
367
368 // We also need to count ourselves.
369 order++;
370 return order;
371 }
372
373 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700374 * Removes this window container and its children taking care not to remove them during a
375 * critical stage in the system. For example, some containers will not be removed during
376 * animation if this method is called.
377 */
378 // TODO: figure-out implementation that works best for this.
379 // E.g. when do we remove from parent list? maybe not...
380 void removeIfPossible() {
381 for (int i = mChildren.size() - 1; i >= 0; --i) {
382 final WindowContainer wc = mChildren.get(i);
383 wc.removeIfPossible();
384 }
385 }
386
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700387 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000388 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700389 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000390 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700391 if (current == child || current.hasChild(child)) {
392 return true;
393 }
394 }
395 return false;
396 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700397
Andrii Kulian441e4492016-09-29 15:25:00 -0700398 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800399 * Move a child from it's current place in siblings list to the specified position,
400 * with an option to move all its parents to top.
401 * @param position Target position to move the child to.
402 * @param child Child to move to selected position.
403 * @param includingParents Flag indicating whether we need to move the entire branch of the
404 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
405 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
406 * this flag will do nothing.
407 */
408 @CallSuper
409 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800410
411 if (child.getParent() != this) {
412 throw new IllegalArgumentException("removeChild: container=" + child.getName()
413 + " is not a child of container=" + getName()
414 + " current parent=" + child.getParent());
415 }
416
Andrii Kuliand2765632016-12-12 22:26:34 -0800417 if ((position < 0 && position != POSITION_BOTTOM)
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800418 || (position > mChildren.size() && position != POSITION_TOP)) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800419 throw new IllegalArgumentException("positionAt: invalid position=" + position
420 + ", children number=" + mChildren.size());
421 }
422
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800423 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800424 position = POSITION_TOP;
425 } else if (position == 0) {
426 position = POSITION_BOTTOM;
427 }
428
429 switch (position) {
430 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800431 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800432 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200433 mChildren.add(child);
Tiger Huangdda14a72019-01-10 17:20:27 +0800434 onChildPositionChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800435 }
436 if (includingParents && getParent() != null) {
437 getParent().positionChildAt(POSITION_TOP, this /* child */,
438 true /* includingParents */);
439 }
440 break;
441 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800442 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800443 mChildren.remove(child);
444 mChildren.addFirst(child);
Tiger Huangdda14a72019-01-10 17:20:27 +0800445 onChildPositionChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800446 }
447 if (includingParents && getParent() != null) {
448 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
449 true /* includingParents */);
450 }
451 break;
452 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800453 // TODO: Removing the child before reinserting requires the caller to provide a
454 // position that takes into account the removed child (if the index of the
455 // child < position, then the position should be adjusted). We should consider
456 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800457 mChildren.remove(child);
458 mChildren.add(position, child);
Tiger Huangdda14a72019-01-10 17:20:27 +0800459 onChildPositionChanged();
Andrii Kuliand2765632016-12-12 22:26:34 -0800460 }
461 }
462
463 /**
Tiger Huang1e5b10a2018-07-30 20:19:51 +0800464 * Notify that a child's position has changed. Possible changes are adding or removing a child.
465 */
466 void onChildPositionChanged() { }
467
468 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700469 * Update override configuration and recalculate full config.
Evan Roskydfe3da72018-10-26 17:21:06 -0700470 * @see #mRequestedOverrideConfiguration
Andrii Kulian441e4492016-09-29 15:25:00 -0700471 * @see #mFullConfiguration
472 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700473 @Override
Evan Roskydfe3da72018-10-26 17:21:06 -0700474 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
Bryce Leef3c6a472017-11-14 14:53:06 -0800475 // We must diff before the configuration is applied so that we can capture the change
476 // against the existing bounds.
Evan Roskydfe3da72018-10-26 17:21:06 -0700477 final int diff = diffRequestedOverrideBounds(
478 overrideConfiguration.windowConfiguration.getBounds());
479 super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700480 if (mParent != null) {
481 mParent.onDescendantOverrideConfigurationChanged();
482 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800483
484 if (diff == BOUNDS_CHANGE_NONE) {
485 return;
486 }
487
488 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
489 onResize();
490 } else {
491 onMovedByResize();
492 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700493 }
494
495 /**
496 * Notify that a descendant's overrideConfiguration has changed.
497 */
498 void onDescendantOverrideConfigurationChanged() {
499 if (mParent != null) {
500 mParent.onDescendantOverrideConfigurationChanged();
501 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700502 }
503
504 /**
Garfield Tan2f145f22018-11-01 15:27:03 -0700505 * Notify that the display this container is on has changed. This could be either this container
506 * is moved to a new display, or some configurations on the display it is on changes.
507 *
508 * @param dc The display this container is on after changes.
Wale Ogunwale02319a62016-09-26 15:21:22 -0700509 */
510 void onDisplayChanged(DisplayContent dc) {
511 for (int i = mChildren.size() - 1; i >= 0; --i) {
512 final WindowContainer child = mChildren.get(i);
513 child.onDisplayChanged(dc);
514 }
515 }
516
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700517 void setWaitingForDrawnIfResizingChanged() {
518 for (int i = mChildren.size() - 1; i >= 0; --i) {
519 final WindowContainer wc = mChildren.get(i);
520 wc.setWaitingForDrawnIfResizingChanged();
521 }
522 }
523
524 void onResize() {
525 for (int i = mChildren.size() - 1; i >= 0; --i) {
526 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800527 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700528 }
529 }
530
Bryce Leed92ae482018-01-22 13:56:23 -0800531 void onParentResize() {
532 // In the case this container has specified its own bounds, a parent resize will not
533 // affect its bounds. Any relevant changes will be propagated through changes to the
534 // Configuration override.
535 if (hasOverrideBounds()) {
536 return;
537 }
538
539 // Default implementation is to treat as resize on self.
540 onResize();
541 }
542
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700543 void onMovedByResize() {
544 for (int i = mChildren.size() - 1; i >= 0; --i) {
545 final WindowContainer wc = mChildren.get(i);
546 wc.onMovedByResize();
547 }
548 }
549
550 void resetDragResizingChangeReported() {
551 for (int i = mChildren.size() - 1; i >= 0; --i) {
552 final WindowContainer wc = mChildren.get(i);
553 wc.resetDragResizingChangeReported();
554 }
555 }
556
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700557 void forceWindowsScaleableInTransaction(boolean force) {
558 for (int i = mChildren.size() - 1; i >= 0; --i) {
559 final WindowContainer wc = mChildren.get(i);
560 wc.forceWindowsScaleableInTransaction(force);
561 }
562 }
563
Jorim Jaggia5e10572017-11-15 14:36:26 +0100564 /**
565 * @return Whether our own container is running an animation or any child, no matter how deep in
566 * the hierarchy, is animating.
567 */
568 boolean isSelfOrChildAnimating() {
569 if (isSelfAnimating()) {
570 return true;
571 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700572 for (int j = mChildren.size() - 1; j >= 0; j--) {
573 final WindowContainer wc = mChildren.get(j);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100574 if (wc.isSelfOrChildAnimating()) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700575 return true;
576 }
577 }
578 return false;
579 }
580
Jorim Jaggia5e10572017-11-15 14:36:26 +0100581 /**
582 * @return Whether our own container is running an animation or our parent is animating. This
583 * doesn't consider whether children are animating.
584 */
585 boolean isAnimating() {
586
587 // We are animating if we ourselves are animating or if our parent is animating.
588 return isSelfAnimating() || mParent != null && mParent.isAnimating();
589 }
590
591 /**
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200592 * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
593 * that is {@link #isSelfAnimating}; {@code false} otherwise.
594 */
595 boolean isAppAnimating() {
596 for (int j = mChildren.size() - 1; j >= 0; j--) {
597 final WindowContainer wc = mChildren.get(j);
598 if (wc.isAppAnimating()) {
599 return true;
600 }
601 }
602 return false;
603 }
604
605 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100606 * @return Whether our own container running an animation at the moment.
607 */
608 boolean isSelfAnimating() {
609 return mSurfaceAnimator.isAnimating();
610 }
611
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700612 void sendAppVisibilityToClients() {
613 for (int i = mChildren.size() - 1; i >= 0; --i) {
614 final WindowContainer wc = mChildren.get(i);
615 wc.sendAppVisibilityToClients();
616 }
617 }
618
Wale Ogunwale44f21802016-09-02 12:49:48 -0700619 /**
620 * Returns true if the container or one of its children as some content it can display or wants
621 * to display (e.g. app views or saved surface).
622 *
623 * NOTE: While this method will return true if the there is some content to display, it doesn't
624 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
625 * visible.
626 */
627 boolean hasContentToDisplay() {
628 for (int i = mChildren.size() - 1; i >= 0; --i) {
629 final WindowContainer wc = mChildren.get(i);
630 if (wc.hasContentToDisplay()) {
631 return true;
632 }
633 }
634 return false;
635 }
636
637 /**
638 * Returns true if the container or one of its children is considered visible from the
639 * WindowManager perspective which usually means valid surface and some other internal state
640 * are true.
641 *
642 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
643 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
644 * the container has any content to display.
645 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700646 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700647 // TODO: Will this be more correct if it checks the visibility of its parents?
648 // It depends...For example, Tasks and Stacks are only visible if there children are visible
649 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800650 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700651 for (int i = mChildren.size() - 1; i >= 0; --i) {
652 final WindowContainer wc = mChildren.get(i);
653 if (wc.isVisible()) {
654 return true;
655 }
656 }
657 return false;
658 }
659
Bryce Lee00d586d2017-07-28 20:48:43 -0700660 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700661 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700662 */
663 boolean isOnTop() {
664 return getParent().getTopChild() == this && getParent().isOnTop();
665 }
666
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100667 /** Returns the top child container. */
668 E getTopChild() {
669 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700670 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700671
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700672 /** Returns true if there is still a removal being deferred */
673 boolean checkCompleteDeferredRemoval() {
674 boolean stillDeferringRemoval = false;
675
676 for (int i = mChildren.size() - 1; i >= 0; --i) {
677 final WindowContainer wc = mChildren.get(i);
678 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
679 }
680
681 return stillDeferringRemoval;
682 }
683
684 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700685 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700686 for (int i = mChildren.size() - 1; i >= 0; --i) {
687 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700688 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700689 }
690 }
691
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700692 void onAppTransitionDone() {
693 for (int i = mChildren.size() - 1; i >= 0; --i) {
694 final WindowContainer wc = mChildren.get(i);
695 wc.onAppTransitionDone();
696 }
697 }
698
Garfield Tan90b04282018-12-11 14:04:42 -0800699 /**
700 * Called when this container or one of its descendants changed its requested orientation, and
701 * wants this container to handle it or pass it to its parent.
702 *
703 * @param freezeDisplayToken freeze this app window token if display needs to freeze
704 * @param requestingContainer the container which orientation request has changed
705 * @return {@code true} if handled; {@code false} otherwise.
706 */
707 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
708 @Nullable ConfigurationContainer requestingContainer) {
709 final WindowContainer parent = getParent();
710 if (parent == null) {
711 return false;
712 }
713 return parent.onDescendantOrientationChanged(freezeDisplayToken,
714 requestingContainer);
715 }
716
717 /**
Garfield Tan49dae102019-02-04 09:51:59 -0800718 * Check if this container or its parent will handle orientation changes from descendants. It's
719 * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
720 * ConfigurationContainer)} in the sense that the return value of this method tells if this
721 * container or its parent will handle the request eventually, while the return value of the
722 * other method is if it handled the request synchronously.
723 *
724 * @return {@code true} if it handles or will handle orientation change in the future; {@code
725 * false} if it won't handle the change at anytime.
726 */
727 boolean handlesOrientationChangeFromDescendant() {
728 final WindowContainer parent = getParent();
729 return parent != null && parent.handlesOrientationChangeFromDescendant();
730 }
731
732 /**
Garfield Tan90b04282018-12-11 14:04:42 -0800733 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
734 * parameters.
735 *
736 * @param orientation the specified orientation.
737 */
Wale Ogunwale51362492016-09-08 17:49:17 -0700738 void setOrientation(int orientation) {
Garfield Tan90b04282018-12-11 14:04:42 -0800739 setOrientation(orientation, null /* freezeDisplayToken */,
740 null /* ActivityRecord */);
741 }
742
743 /**
744 * Sets the specified orientation of this container. It percolates this change upward along the
745 * hierarchy to let each level of the hierarchy a chance to respond to it.
746 *
747 * @param orientation the specified orientation. Needs to be one of {@link
748 * android.content.pm.ActivityInfo.ScreenOrientation}.
749 * @param freezeDisplayToken uses this token to freeze display if orientation change is not
750 * done. Display will not be frozen if this is {@code null}, which
751 * should only happen in tests.
752 * @param requestingContainer the container which orientation request has changed. Mostly used
753 * to ensure it gets correct configuration.
754 */
755 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
756 @Nullable ConfigurationContainer requestingContainer) {
757 final boolean changed = mOrientation != orientation;
Wale Ogunwale51362492016-09-08 17:49:17 -0700758 mOrientation = orientation;
Garfield Tan90b04282018-12-11 14:04:42 -0800759 if (!changed) {
760 return;
761 }
762 final WindowContainer parent = getParent();
763 if (parent != null) {
764 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
765 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700766 }
767
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700768 int getOrientation() {
769 return getOrientation(mOrientation);
770 }
771
Wale Ogunwale51362492016-09-08 17:49:17 -0700772 /**
773 * Returns the specified orientation for this window container or one of its children is there
774 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
775 * specification is set.
776 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
777 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700778 *
779 * @param candidate The current orientation candidate that will be returned if we don't find a
780 * better match.
781 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -0700782 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700783 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -0800784 if (!fillsParent()) {
785 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -0700786 return SCREEN_ORIENTATION_UNSET;
787 }
788
Bryce Leea163b762017-01-24 11:05:01 -0800789 // The container fills its parent so we can use it orientation if it has one
790 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -0700791 // specified and fall back on this container's unset or unspecified value as a candidate
792 // if none of the children have a better candidate for the orientation.
793 if (mOrientation != SCREEN_ORIENTATION_UNSET
794 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
795 return mOrientation;
796 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700797
798 for (int i = mChildren.size() - 1; i >= 0; --i) {
799 final WindowContainer wc = mChildren.get(i);
800
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700801 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
802 // SCREEN_ORIENTATION_UNSPECIFIED?
803 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
804 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -0700805 if (orientation == SCREEN_ORIENTATION_BEHIND) {
806 // container wants us to use the orientation of the container behind it. See if we
807 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
808 // look behind this container.
809 candidate = orientation;
810 continue;
811 }
812
813 if (orientation == SCREEN_ORIENTATION_UNSET) {
814 continue;
815 }
816
817 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
818 // Use the orientation if the container fills its parent or requested an explicit
819 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
820 return orientation;
821 }
822 }
823
824 return candidate;
825 }
826
827 /**
828 * Returns true if this container is opaque and fills all the space made available by its parent
829 * container.
830 *
831 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
832 * this is just a signal from the client to window manager stating its intent, but not what it
833 * actually does.
834 */
835 boolean fillsParent() {
836 return false;
837 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700838
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000839 // TODO: Users would have their own window containers under the display container?
840 void switchUser() {
841 for (int i = mChildren.size() - 1; i >= 0; --i) {
842 mChildren.get(i).switchUser();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700843 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700844 }
845
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800846 /**
847 * For all windows at or below this container call the callback.
848 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
849 * stops the search if {@link ToBooleanFunction#apply} returns true.
850 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
851 * z-order, else from bottom-to-top.
852 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800853 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800854 */
855 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700856 if (traverseTopToBottom) {
857 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800858 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
859 return true;
860 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700861 }
862 } else {
863 final int count = mChildren.size();
864 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800865 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
866 return true;
867 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700868 }
869 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800870 return false;
871 }
872
873 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800874 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
875 forAllWindows(wrapper, traverseTopToBottom);
876 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700877 }
878
lumark588a3e82018-07-20 18:53:54 +0800879 void forAllAppWindows(Consumer<AppWindowToken> callback) {
880 for (int i = mChildren.size() - 1; i >= 0; --i) {
881 mChildren.get(i).forAllAppWindows(callback);
882 }
883 }
884
Jorim Jaggi51304d72017-05-17 17:25:32 +0200885 /**
886 * For all tasks at or below this container call the callback.
887 *
888 * @param callback Callback to be called for every task.
889 */
890 void forAllTasks(Consumer<Task> callback) {
891 for (int i = mChildren.size() - 1; i >= 0; --i) {
892 mChildren.get(i).forAllTasks(callback);
893 }
894 }
895
Wale Ogunwaled1880962016-11-08 10:31:59 -0800896 WindowState getWindow(Predicate<WindowState> callback) {
897 for (int i = mChildren.size() - 1; i >= 0; --i) {
898 final WindowState w = mChildren.get(i).getWindow(callback);
899 if (w != null) {
900 return w;
901 }
902 }
903
904 return null;
905 }
906
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700907 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -0700908 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
909 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700910 */
911 @Override
912 public int compareTo(WindowContainer other) {
913 if (this == other) {
914 return 0;
915 }
916
917 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200918 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700919 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
920 }
921
922 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
923 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200924 try {
925 getParents(thisParentChain);
926 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700927
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200928 // Find the common ancestor of both containers.
929 WindowContainer commonAncestor = null;
930 WindowContainer thisTop = thisParentChain.peekLast();
931 WindowContainer otherTop = otherParentChain.peekLast();
932 while (thisTop != null && otherTop != null && thisTop == otherTop) {
933 commonAncestor = thisParentChain.removeLast();
934 otherParentChain.removeLast();
935 thisTop = thisParentChain.peekLast();
936 otherTop = otherParentChain.peekLast();
937 }
938
939 // Containers don't belong to the same hierarchy???
940 if (commonAncestor == null) {
941 throw new IllegalArgumentException("No in the same hierarchy this="
942 + thisParentChain + " other=" + otherParentChain);
943 }
944
945 // Children are always considered greater than their parents, so if one of the containers
946 // we are comparing it the parent of the other then whichever is the child is greater.
947 if (commonAncestor == this) {
948 return -1;
949 } else if (commonAncestor == other) {
950 return 1;
951 }
952
953 // The position of the first non-common ancestor in the common ancestor list determines
954 // which is greater the which.
955 final WindowList<WindowContainer> list = commonAncestor.mChildren;
956 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
957 ? 1 : -1;
958 } finally {
959 mTmpChain1.clear();
960 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700961 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700962 }
963
964 private void getParents(LinkedList<WindowContainer> parents) {
965 parents.clear();
966 WindowContainer current = this;
967 do {
968 parents.addLast(current);
969 current = current.mParent;
970 } while (current != null);
971 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700972
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800973 WindowContainerController getController() {
974 return mController;
975 }
976
977 void setController(WindowContainerController controller) {
978 if (mController != null && controller != null) {
979 throw new IllegalArgumentException("Can't set controller=" + mController
980 + " for container=" + this + " Already set to=" + mController);
981 }
982 if (controller != null) {
983 controller.setContainer(this);
984 } else if (mController != null) {
985 mController.setContainer(null);
986 }
987 mController = controller;
988 }
989
Robert Carrb1579c82017-09-05 14:54:47 -0700990 SurfaceControl.Builder makeSurface() {
991 final WindowContainer p = getParent();
992 return p.makeChildSurface(this);
993 }
994
Robert Carrf59b8dd2017-10-02 18:58:36 -0700995 /**
996 * @param child The WindowContainer this child surface is for, or null if the Surface
997 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
998 */
Robert Carrb1579c82017-09-05 14:54:47 -0700999 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1000 final WindowContainer p = getParent();
1001 // Give the parent a chance to set properties. In hierarchy v1 we rely
1002 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -08001003 return p.makeChildSurface(child)
1004 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -07001005 }
1006
Jorim Jaggia5e10572017-11-15 14:36:26 +01001007 @Override
1008 public SurfaceControl getParentSurfaceControl() {
1009 final WindowContainer parent = getParent();
1010 if (parent == null) {
1011 return null;
1012 }
1013 return parent.getSurfaceControl();
1014 }
1015
Robert Carrb1579c82017-09-05 14:54:47 -07001016 /**
1017 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1018 */
1019 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +09001020 if (mSurfaceControl == null) {
1021 return false;
1022 }
1023
Robert Carrb1579c82017-09-05 14:54:47 -07001024 for (int i = 0; i < mChildren.size(); i++) {
1025 if (!mChildren.get(i).shouldMagnify()) {
1026 return false;
1027 }
1028 }
1029 return true;
1030 }
1031
1032 SurfaceSession getSession() {
1033 if (getParent() != null) {
1034 return getParent().getSession();
1035 }
1036 return null;
1037 }
1038
1039 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001040 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1041 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001042 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001043 mLastLayer = layer;
1044 mLastRelativeToLayer = null;
1045 }
1046 }
1047
1048 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1049 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1050 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001051 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001052 mLastLayer = layer;
1053 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -07001054 }
1055 }
1056
Jorim Jaggi619c9f72017-12-19 18:04:29 +01001057 protected void setLayer(Transaction t, int layer) {
1058
1059 // Route through surface animator to accommodate that our surface control might be
1060 // attached to the leash, and leash is attached to parent container.
1061 mSurfaceAnimator.setLayer(t, layer);
1062 }
1063
1064 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1065
1066 // Route through surface animator to accommodate that our surface control might be
1067 // attached to the leash, and leash is attached to parent container.
1068 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1069 }
1070
1071 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1072 mSurfaceAnimator.reparent(t, newParent);
1073 }
1074
Robert Carrb1579c82017-09-05 14:54:47 -07001075 void assignChildLayers(Transaction t) {
1076 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -07001077
1078 // We use two passes as a way to promote children which
1079 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001080 for (int j = 0; j < mChildren.size(); ++j) {
1081 final WindowContainer wc = mChildren.get(j);
1082 wc.assignChildLayers(t);
1083 if (!wc.needsZBoost()) {
1084 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001085 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001086 }
1087 for (int j = 0; j < mChildren.size(); ++j) {
1088 final WindowContainer wc = mChildren.get(j);
1089 if (wc.needsZBoost()) {
1090 wc.assignLayer(t, layer++);
1091 }
Robert Carrb1579c82017-09-05 14:54:47 -07001092 }
1093 }
1094
1095 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001096 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001097 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001098 }
1099
1100 boolean needsZBoost() {
1101 for (int i = 0; i < mChildren.size(); i++) {
1102 if (mChildren.get(i).needsZBoost()) {
1103 return true;
1104 }
1105 }
1106 return false;
1107 }
1108
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001109 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001110 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001111 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001112 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001113 * @param proto Stream to write the WindowContainer object to.
1114 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
Nataniel Borges023ecb52019-01-16 14:15:43 -08001115 * @param logLevel Determines the amount of data to be written to the Protobuf.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001116 * @hide
1117 */
1118 @CallSuper
1119 @Override
Nataniel Borges023ecb52019-01-16 14:15:43 -08001120 public void writeToProto(ProtoOutputStream proto, long fieldId,
1121 @WindowTraceLogLevel int logLevel) {
1122 boolean isVisible = isVisible();
1123 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1124 return;
1125 }
1126
Adrian Roos4921ccf2017-09-28 16:54:06 +02001127 final long token = proto.start(fieldId);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001128 super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001129 proto.write(ORIENTATION, mOrientation);
Nataniel Borges023ecb52019-01-16 14:15:43 -08001130 proto.write(VISIBLE, isVisible);
1131 if (mSurfaceAnimator.isAnimating()) {
1132 mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
1133 }
Adrian Roos4921ccf2017-09-28 16:54:06 +02001134 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001135 }
1136
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001137 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1138 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1139 if (wrapper == null) {
1140 wrapper = new ForAllWindowsConsumerWrapper();
1141 }
1142 wrapper.setConsumer(consumer);
1143 return wrapper;
1144 }
1145
1146 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1147
1148 private Consumer<WindowState> mConsumer;
1149
1150 void setConsumer(Consumer<WindowState> consumer) {
1151 mConsumer = consumer;
1152 }
1153
1154 @Override
1155 public boolean apply(WindowState w) {
1156 mConsumer.accept(w);
1157 return false;
1158 }
1159
1160 void release() {
1161 mConsumer = null;
1162 mConsumerWrapperPool.release(this);
1163 }
1164 }
Robert Carrb1579c82017-09-05 14:54:47 -07001165
1166 // TODO(b/68336570): Should this really be on WindowContainer since it
1167 // can only be used on the top-level nodes that aren't animated?
1168 // (otherwise we would be fighting other callers of setMatrix).
1169 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1170 if (shouldMagnify()) {
1171 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1172 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
1173 } else {
1174 for (int i = 0; i < mChildren.size(); i++) {
1175 mChildren.get(i).applyMagnificationSpec(t, spec);
1176 }
1177 }
1178 }
1179
1180 /**
1181 * TODO: Once we totally eliminate global transaction we will pass transaction in here
1182 * rather than merging to global.
1183 */
1184 void prepareSurfaces() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001185 SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
chaviw7f1fa992018-01-10 13:52:12 -08001186
1187 // If a leash has been set when the transaction was committed, then the leash reparent has
1188 // been committed.
1189 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001190 for (int i = 0; i < mChildren.size(); i++) {
1191 mChildren.get(i).prepareSurfaces();
1192 }
1193 }
1194
1195 /**
chaviw7f1fa992018-01-10 13:52:12 -08001196 * @return true if the reparent to animation leash transaction has been committed, false
1197 * otherwise.
1198 */
1199 boolean hasCommittedReparentToAnimationLeash() {
1200 return mCommittedReparentToAnimationLeash;
1201 }
1202
1203 /**
Robert Carrb1579c82017-09-05 14:54:47 -07001204 * Trigger a call to prepareSurfaces from the animation thread, such that
1205 * mPendingTransaction will be applied.
1206 */
1207 void scheduleAnimation() {
1208 if (mParent != null) {
1209 mParent.scheduleAnimation();
1210 }
1211 }
1212
Jorim Jaggia5e10572017-11-15 14:36:26 +01001213 @Override
1214 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001215 return mSurfaceControl;
1216 }
1217
Jorim Jaggia5e10572017-11-15 14:36:26 +01001218 @Override
1219 public Transaction getPendingTransaction() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001220 return mPendingTransaction;
1221 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001222
1223 /**
1224 * Starts an animation on the container.
1225 *
1226 * @param anim The animation to run.
1227 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1228 * some point but the meaning is too weird to work for all containers.
1229 */
1230 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1231 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1232
1233 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1234 // the moment this doesn't work for all animatable window containers.
1235 mSurfaceAnimator.startAnimation(t, anim, hidden);
1236 }
1237
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001238 void transferAnimation(WindowContainer from) {
1239 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1240 }
1241
Jorim Jaggia5e10572017-11-15 14:36:26 +01001242 void cancelAnimation() {
1243 mSurfaceAnimator.cancelAnimation();
1244 }
1245
1246 @Override
1247 public Builder makeAnimationLeash() {
1248 return makeSurface();
1249 }
1250
Jorim Jaggi596a1992017-12-29 14:48:02 +01001251 @Override
1252 public SurfaceControl getAnimationLeashParent() {
1253 return getParentSurfaceControl();
1254 }
1255
chaviw23ee71c2017-12-18 11:29:41 -08001256 /**
1257 * @return The layer on which all app animations are happening.
1258 */
Jorim Jaggi391790622018-04-18 15:30:44 +02001259 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08001260 final WindowContainer parent = getParent();
1261 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02001262 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08001263 }
1264 return null;
1265 }
1266
Jorim Jaggia5e10572017-11-15 14:36:26 +01001267 @Override
1268 public void commitPendingTransaction() {
1269 scheduleAnimation();
1270 }
1271
Robert Carr2f8aa392018-01-31 14:46:51 -08001272 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001273 final WindowContainer parent = getParent();
1274 if (parent != null) {
1275 parent.assignChildLayers(t);
1276 }
1277 }
1278
1279 @Override
1280 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001281 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001282 reassignLayer(t);
1283 }
1284
1285 @Override
1286 public void onAnimationLeashDestroyed(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001287 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001288 reassignLayer(t);
1289 }
1290
1291 /**
1292 * Called when an animation has finished running.
1293 */
1294 protected void onAnimationFinished() {
chaviwccd5d502019-02-22 13:30:31 -08001295 mWmService.onAnimationFinished();
Jorim Jaggia5e10572017-11-15 14:36:26 +01001296 }
1297
1298 /**
1299 * @return The currently running animation, if any, or {@code null} otherwise.
1300 */
1301 AnimationAdapter getAnimation() {
1302 return mSurfaceAnimator.getAnimation();
1303 }
1304
1305 /**
1306 * @see SurfaceAnimator#startDelayingAnimationStart
1307 */
1308 void startDelayingAnimationStart() {
1309 mSurfaceAnimator.startDelayingAnimationStart();
1310 }
1311
1312 /**
1313 * @see SurfaceAnimator#endDelayingAnimationStart
1314 */
1315 void endDelayingAnimationStart() {
1316 mSurfaceAnimator.endDelayingAnimationStart();
1317 }
1318
1319 @Override
1320 public int getSurfaceWidth() {
1321 return mSurfaceControl.getWidth();
1322 }
1323
1324 @Override
1325 public int getSurfaceHeight() {
1326 return mSurfaceControl.getHeight();
1327 }
1328
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001329 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01001330 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1331 if (mSurfaceAnimator.isAnimating()) {
1332 pw.print(prefix); pw.println("ContainerAnimator:");
1333 mSurfaceAnimator.dump(pw, prefix + " ");
1334 }
1335 }
chaviwe07246a2017-12-12 16:18:29 -08001336
chaviw2f0567b2018-01-29 16:22:02 -08001337 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08001338 if (mSurfaceControl == null) {
1339 return;
1340 }
1341
Evan Roskyed6767f2018-10-26 17:21:06 -07001342 getRelativeDisplayedPosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08001343 if (mTmpPos.equals(mLastSurfacePosition)) {
1344 return;
1345 }
1346
chaviw2f0567b2018-01-29 16:22:02 -08001347 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08001348 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08001349 }
1350
Evan Rosky65dffa62019-02-04 14:09:53 -08001351 @VisibleForTesting
Evan Rosky89f5c1d2019-01-29 10:04:05 -08001352 Point getLastSurfacePosition() {
1353 return mLastSurfacePosition;
1354 }
1355
Evan Roskyed6767f2018-10-26 17:21:06 -07001356 /**
1357 * Displayed bounds specify where to display this container at. It differs from bounds during
1358 * certain operations (like animation or interactive dragging).
1359 *
1360 * @return the bounds to display this container at.
1361 */
1362 Rect getDisplayedBounds() {
1363 return getBounds();
1364 }
1365
1366 void getRelativeDisplayedPosition(Point outPos) {
1367 final Rect dispBounds = getDisplayedBounds();
1368 outPos.set(dispBounds.left, dispBounds.top);
chaviwe07246a2017-12-12 16:18:29 -08001369 final WindowContainer parent = getParent();
1370 if (parent != null) {
Evan Roskyed6767f2018-10-26 17:21:06 -07001371 final Rect parentBounds = parent.getDisplayedBounds();
chaviwe07246a2017-12-12 16:18:29 -08001372 outPos.offset(-parentBounds.left, -parentBounds.top);
1373 }
1374 }
chaviw2fb06bc2018-01-19 17:09:15 -08001375
1376 Dimmer getDimmer() {
1377 if (mParent == null) {
1378 return null;
1379 }
1380 return mParent.getDimmer();
1381 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001382}