blob: 27c0b3b39dfc2bb25a1c8844d77ee13f56edfcc5 [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;
Jorim Jaggia5e10572017-11-15 14:36:26 +010023import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
24import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
25import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070026import static com.android.server.wm.proto.WindowContainerProto.CONFIGURATION_CONTAINER;
27import static com.android.server.wm.proto.WindowContainerProto.ORIENTATION;
Vishnu Nair04ab4392018-01-10 11:00:06 -080028import static com.android.server.wm.proto.WindowContainerProto.SURFACE_ANIMATOR;
Wale Ogunwaledf262f52017-12-07 18:17:12 -080029import static com.android.server.wm.proto.WindowContainerProto.VISIBLE;
Jorim Jaggi612bb882017-05-16 17:11:18 +020030
Wale Ogunwaled63594a2016-07-18 07:48:30 -070031import android.annotation.CallSuper;
Andrii Kulian441e4492016-09-29 15:25:00 -070032import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080033import android.graphics.Point;
34import android.graphics.Rect;
Vishnu Nair04ab4392018-01-10 11:00:06 -080035import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010036import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080037import android.util.proto.ProtoOutputStream;
Robert Carrb1579c82017-09-05 14:54:47 -070038import android.view.MagnificationSpec;
39import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010040import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070041import android.view.SurfaceSession;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070042
Jorim Jaggia5e10572017-11-15 14:36:26 +010043import com.android.internal.util.ToBooleanFunction;
44import com.android.server.wm.SurfaceAnimator.Animatable;
45
46import java.io.PrintWriter;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070047import java.util.Comparator;
48import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070049import java.util.function.Consumer;
Wale Ogunwaled1880962016-11-08 10:31:59 -080050import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070051
52/**
53 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070054 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -070055 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
56 * changes are made to this class.
57 */
Wale Ogunwale98d62312017-07-12 09:24:56 -070058class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Jorim Jaggia5e10572017-11-15 14:36:26 +010059 implements Comparable<WindowContainer>, Animatable {
60
61 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070062
Andrii Kuliand2765632016-12-12 22:26:34 -080063 static final int POSITION_TOP = Integer.MAX_VALUE;
64 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
65
Andrii Kulian441e4492016-09-29 15:25:00 -070066 /**
67 * The parent of this window container.
68 * For removing or setting new parent {@link #setParent} should be used, because it also
69 * performs configuration updates based on new parent's settings.
70 */
Jorim Jaggia5e10572017-11-15 14:36:26 +010071 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070072
73 // List of children for this window container. List is in z-order as the children appear on
74 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +020075 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -070076
Wale Ogunwale51362492016-09-08 17:49:17 -070077 // The specified orientation for this window container.
78 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
79
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -080080 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
81 new Pools.SynchronizedPool<>(3);
82
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -080083 // The owner/creator for this container. No controller if null.
Jorim Jaggia5e10572017-11-15 14:36:26 +010084 WindowContainerController mController;
Robert Carrb1579c82017-09-05 14:54:47 -070085
86 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +010087 private int mLastLayer = 0;
88 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -070089
90 /**
91 * Applied as part of the animation pass in "prepareSurfaces".
92 */
Jorim Jaggia5e10572017-11-15 14:36:26 +010093 protected final Transaction mPendingTransaction;
94 protected final SurfaceAnimator mSurfaceAnimator;
Jorim Jaggiffe128d2017-11-30 13:54:36 +010095 protected final WindowManagerService mService;
96
chaviwe07246a2017-12-12 16:18:29 -080097 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -080098 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -080099
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100100 /** Total number of elements in this subtree, including our own hierarchy element. */
101 private int mTreeWeight = 1;
102
chaviw7f1fa992018-01-10 13:52:12 -0800103 /**
104 * Indicates whether we are animating and have committed the transaction to reparent our
105 * surface to the animation leash
106 */
107 private boolean mCommittedReparentToAnimationLeash;
108
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100109 WindowContainer(WindowManagerService service) {
110 mService = service;
111 mPendingTransaction = service.mTransactionFactory.make();
Chavi Weingartenb736e322018-02-23 00:27:54 +0000112 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100113 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800114
Wale Ogunwale98d62312017-07-12 09:24:56 -0700115 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700116 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700117 return mParent;
118 }
119
Wale Ogunwale98d62312017-07-12 09:24:56 -0700120 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700121 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700122 return mChildren.size();
123 }
124
125 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700126 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700127 return mChildren.get(index);
128 }
129
chaviwe07246a2017-12-12 16:18:29 -0800130 @Override
131 public void onConfigurationChanged(Configuration newParentConfig) {
132 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800133 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800134 scheduleAnimation();
135 }
136
Jorim Jaggia5e10572017-11-15 14:36:26 +0100137 final protected void setParent(WindowContainer<WindowContainer> parent) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700138 mParent = parent;
Andrii Kulianb94292e2016-10-19 13:30:58 -0700139 // Removing parent usually means that we've detached this entity to destroy it or to attach
140 // to another parent. In both cases we don't need to update the configuration now.
141 if (mParent != null) {
142 // Update full configuration of this container and all its children.
Wale Ogunwale98d62312017-07-12 09:24:56 -0700143 onConfigurationChanged(mParent.getConfiguration());
Andrii Kulianb94292e2016-10-19 13:30:58 -0700144 // Update merged override configuration of this container and all its children.
145 onMergedOverrideConfigurationChanged();
146 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800147
148 onParentSet();
149 }
150
151 /**
152 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
153 * Supposed to be overridden and contain actions that should be executed after parent was set.
154 */
155 void onParentSet() {
Robert Carrb1579c82017-09-05 14:54:47 -0700156 if (mParent == null) {
157 return;
158 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100159
Robert Carrb1579c82017-09-05 14:54:47 -0700160 if (mSurfaceControl == null) {
161 // If we don't yet have a surface, but we now have a parent, we should
162 // build a surface.
163 mSurfaceControl = makeSurface().build();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700164 getPendingTransaction().show(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700165 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100166 // If we have a surface but a new parent, we just need to perform a reparent. Go through
167 // surface animator such that hierarchy is preserved when animating, i.e.
168 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
169 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100170 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700171 }
172
173 // Either way we need to ask the parent to assign us a Z-order.
174 mParent.assignChildLayers();
175 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700176 }
177
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700178 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100179 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
180 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700181
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700182 /**
183 * Adds the input window container has a child of this container in order based on the input
184 * comparator.
185 * @param child The window container to add as a child of this window container.
186 * @param comparator Comparator to use in determining the position the child should be added to.
187 * If null, the child will be added to the top.
188 */
189 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700190 protected void addChild(E child, Comparator<E> comparator) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700191 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700192 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700193 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700194 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700195 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700196
Andrii Kulianb94292e2016-10-19 13:30:58 -0700197 int positionToAdd = -1;
198 if (comparator != null) {
199 final int count = mChildren.size();
200 for (int i = 0; i < count; i++) {
201 if (comparator.compare(child, mChildren.get(i)) < 0) {
202 positionToAdd = i;
203 break;
204 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700205 }
206 }
207
Andrii Kulianb94292e2016-10-19 13:30:58 -0700208 if (positionToAdd == -1) {
209 mChildren.add(child);
210 } else {
211 mChildren.add(positionToAdd, child);
212 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100213 onChildAdded(child);
214
Andrii Kulianb94292e2016-10-19 13:30:58 -0700215 // Set the parent after we've actually added a child in case a subclass depends on this.
216 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700217 }
218
Wale Ogunwalef6192862016-09-10 13:42:30 -0700219 /** Adds the input window container has a child of this container at the input index. */
220 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800221 void addChild(E child, int index) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700222 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700223 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700224 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700225 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700226 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700227 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100228 onChildAdded(child);
229
Andrii Kulianb94292e2016-10-19 13:30:58 -0700230 // Set the parent after we've actually added a child in case a subclass depends on this.
231 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700232 }
233
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100234 private void onChildAdded(WindowContainer child) {
235 mTreeWeight += child.mTreeWeight;
236 WindowContainer parent = getParent();
237 while (parent != null) {
238 parent.mTreeWeight += child.mTreeWeight;
239 parent = parent.getParent();
240 }
241 }
242
Wale Ogunwalef6192862016-09-10 13:42:30 -0700243 /**
244 * Removes the input child container from this container which is its parent.
245 *
246 * @return True if the container did contain the input child and it was detached.
247 */
248 @CallSuper
249 void removeChild(E child) {
250 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100251 onChildRemoved(child);
Andrii Kulian441e4492016-09-29 15:25:00 -0700252 child.setParent(null);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700253 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700254 throw new IllegalArgumentException("removeChild: container=" + child.getName()
255 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700256 }
257 }
258
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100259 private void onChildRemoved(WindowContainer child) {
260 mTreeWeight -= child.mTreeWeight;
261 WindowContainer parent = getParent();
262 while (parent != null) {
263 parent.mTreeWeight -= child.mTreeWeight;
264 parent = parent.getParent();
265 }
266 }
267
Wale Ogunwale571771c2016-08-26 13:18:50 -0700268 /**
269 * Removes this window container and its children with no regard for what else might be going on
270 * in the system. For example, the container will be removed during animation if this method is
271 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
272 * which allows the system to defer removal until a suitable time.
273 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700274 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700275 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700276 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100277 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700278 child.removeImmediately();
279 // Need to do this after calling remove on the child because the child might try to
280 // remove/detach itself from its parent which will cause an exception if we remove
281 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100282 if (mChildren.remove(child)) {
283 onChildRemoved(child);
284 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700285 }
286
Robert Carrb1579c82017-09-05 14:54:47 -0700287 if (mSurfaceControl != null) {
chaviw6728e2f2018-03-19 15:58:04 -0700288 mPendingTransaction.destroy(mSurfaceControl);
289
290 // Merge to parent transaction to ensure the transactions on this WindowContainer are
291 // applied in native even if WindowContainer is removed.
292 if (mParent != null) {
293 mParent.getPendingTransaction().merge(mPendingTransaction);
294 }
295
Robert Carrb1579c82017-09-05 14:54:47 -0700296 mSurfaceControl = null;
Chavi Weingartenb736e322018-02-23 00:27:54 +0000297 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700298 }
299
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700300 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700301 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700302 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800303
304 if (mController != null) {
305 setController(null);
306 }
Robert Carrb1579c82017-09-05 14:54:47 -0700307
Wale Ogunwale571771c2016-08-26 13:18:50 -0700308 }
309
310 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100311 * @return The index of this element in the hierarchy tree in prefix order.
312 */
313 int getPrefixOrderIndex() {
314 if (mParent == null) {
315 return 0;
316 }
317 return mParent.getPrefixOrderIndex(this);
318 }
319
320 private int getPrefixOrderIndex(WindowContainer child) {
321 int order = 0;
322 for (int i = 0; i < mChildren.size(); i++) {
323 final WindowContainer childI = mChildren.get(i);
324 if (child == childI) {
325 break;
326 }
327 order += childI.mTreeWeight;
328 }
329 if (mParent != null) {
330 order += mParent.getPrefixOrderIndex(this);
331 }
332
333 // We also need to count ourselves.
334 order++;
335 return order;
336 }
337
338 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700339 * Removes this window container and its children taking care not to remove them during a
340 * critical stage in the system. For example, some containers will not be removed during
341 * animation if this method is called.
342 */
343 // TODO: figure-out implementation that works best for this.
344 // E.g. when do we remove from parent list? maybe not...
345 void removeIfPossible() {
346 for (int i = mChildren.size() - 1; i >= 0; --i) {
347 final WindowContainer wc = mChildren.get(i);
348 wc.removeIfPossible();
349 }
350 }
351
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700352 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000353 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700354 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000355 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700356 if (current == child || current.hasChild(child)) {
357 return true;
358 }
359 }
360 return false;
361 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700362
Andrii Kulian441e4492016-09-29 15:25:00 -0700363 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800364 * Move a child from it's current place in siblings list to the specified position,
365 * with an option to move all its parents to top.
366 * @param position Target position to move the child to.
367 * @param child Child to move to selected position.
368 * @param includingParents Flag indicating whether we need to move the entire branch of the
369 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
370 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
371 * this flag will do nothing.
372 */
373 @CallSuper
374 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800375
376 if (child.getParent() != this) {
377 throw new IllegalArgumentException("removeChild: container=" + child.getName()
378 + " is not a child of container=" + getName()
379 + " current parent=" + child.getParent());
380 }
381
Andrii Kuliand2765632016-12-12 22:26:34 -0800382 if ((position < 0 && position != POSITION_BOTTOM)
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800383 || (position > mChildren.size() && position != POSITION_TOP)) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800384 throw new IllegalArgumentException("positionAt: invalid position=" + position
385 + ", children number=" + mChildren.size());
386 }
387
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800388 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800389 position = POSITION_TOP;
390 } else if (position == 0) {
391 position = POSITION_BOTTOM;
392 }
393
394 switch (position) {
395 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800396 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800397 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200398 mChildren.add(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800399 }
400 if (includingParents && getParent() != null) {
401 getParent().positionChildAt(POSITION_TOP, this /* child */,
402 true /* includingParents */);
403 }
404 break;
405 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800406 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800407 mChildren.remove(child);
408 mChildren.addFirst(child);
409 }
410 if (includingParents && getParent() != null) {
411 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
412 true /* includingParents */);
413 }
414 break;
415 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800416 // TODO: Removing the child before reinserting requires the caller to provide a
417 // position that takes into account the removed child (if the index of the
418 // child < position, then the position should be adjusted). We should consider
419 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800420 mChildren.remove(child);
421 mChildren.add(position, child);
422 }
423 }
424
425 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700426 * Update override configuration and recalculate full config.
427 * @see #mOverrideConfiguration
428 * @see #mFullConfiguration
429 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700430 @Override
Bryce Leef3c6a472017-11-14 14:53:06 -0800431 public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
432 // We must diff before the configuration is applied so that we can capture the change
433 // against the existing bounds.
434 final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds());
Wale Ogunwale98d62312017-07-12 09:24:56 -0700435 super.onOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700436 if (mParent != null) {
437 mParent.onDescendantOverrideConfigurationChanged();
438 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800439
440 if (diff == BOUNDS_CHANGE_NONE) {
441 return;
442 }
443
444 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
445 onResize();
446 } else {
447 onMovedByResize();
448 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700449 }
450
451 /**
452 * Notify that a descendant's overrideConfiguration has changed.
453 */
454 void onDescendantOverrideConfigurationChanged() {
455 if (mParent != null) {
456 mParent.onDescendantOverrideConfigurationChanged();
457 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700458 }
459
460 /**
Wale Ogunwale02319a62016-09-26 15:21:22 -0700461 * Notify that the display this container is on has changed.
462 * @param dc The new display this container is on.
463 */
464 void onDisplayChanged(DisplayContent dc) {
465 for (int i = mChildren.size() - 1; i >= 0; --i) {
466 final WindowContainer child = mChildren.get(i);
467 child.onDisplayChanged(dc);
468 }
469 }
470
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700471 void setWaitingForDrawnIfResizingChanged() {
472 for (int i = mChildren.size() - 1; i >= 0; --i) {
473 final WindowContainer wc = mChildren.get(i);
474 wc.setWaitingForDrawnIfResizingChanged();
475 }
476 }
477
478 void onResize() {
479 for (int i = mChildren.size() - 1; i >= 0; --i) {
480 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800481 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700482 }
483 }
484
Bryce Leed92ae482018-01-22 13:56:23 -0800485 void onParentResize() {
486 // In the case this container has specified its own bounds, a parent resize will not
487 // affect its bounds. Any relevant changes will be propagated through changes to the
488 // Configuration override.
489 if (hasOverrideBounds()) {
490 return;
491 }
492
493 // Default implementation is to treat as resize on self.
494 onResize();
495 }
496
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700497 void onMovedByResize() {
498 for (int i = mChildren.size() - 1; i >= 0; --i) {
499 final WindowContainer wc = mChildren.get(i);
500 wc.onMovedByResize();
501 }
502 }
503
504 void resetDragResizingChangeReported() {
505 for (int i = mChildren.size() - 1; i >= 0; --i) {
506 final WindowContainer wc = mChildren.get(i);
507 wc.resetDragResizingChangeReported();
508 }
509 }
510
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700511 void forceWindowsScaleableInTransaction(boolean force) {
512 for (int i = mChildren.size() - 1; i >= 0; --i) {
513 final WindowContainer wc = mChildren.get(i);
514 wc.forceWindowsScaleableInTransaction(force);
515 }
516 }
517
Jorim Jaggia5e10572017-11-15 14:36:26 +0100518 /**
519 * @return Whether our own container is running an animation or any child, no matter how deep in
520 * the hierarchy, is animating.
521 */
522 boolean isSelfOrChildAnimating() {
523 if (isSelfAnimating()) {
524 return true;
525 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700526 for (int j = mChildren.size() - 1; j >= 0; j--) {
527 final WindowContainer wc = mChildren.get(j);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100528 if (wc.isSelfOrChildAnimating()) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700529 return true;
530 }
531 }
532 return false;
533 }
534
Jorim Jaggia5e10572017-11-15 14:36:26 +0100535 /**
536 * @return Whether our own container is running an animation or our parent is animating. This
537 * doesn't consider whether children are animating.
538 */
539 boolean isAnimating() {
540
541 // We are animating if we ourselves are animating or if our parent is animating.
542 return isSelfAnimating() || mParent != null && mParent.isAnimating();
543 }
544
545 /**
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200546 * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
547 * that is {@link #isSelfAnimating}; {@code false} otherwise.
548 */
549 boolean isAppAnimating() {
550 for (int j = mChildren.size() - 1; j >= 0; j--) {
551 final WindowContainer wc = mChildren.get(j);
552 if (wc.isAppAnimating()) {
553 return true;
554 }
555 }
556 return false;
557 }
558
559 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100560 * @return Whether our own container running an animation at the moment.
561 */
562 boolean isSelfAnimating() {
563 return mSurfaceAnimator.isAnimating();
564 }
565
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700566 void sendAppVisibilityToClients() {
567 for (int i = mChildren.size() - 1; i >= 0; --i) {
568 final WindowContainer wc = mChildren.get(i);
569 wc.sendAppVisibilityToClients();
570 }
571 }
572
Wale Ogunwale44f21802016-09-02 12:49:48 -0700573 /**
574 * Returns true if the container or one of its children as some content it can display or wants
575 * to display (e.g. app views or saved surface).
576 *
577 * NOTE: While this method will return true if the there is some content to display, it doesn't
578 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
579 * visible.
580 */
581 boolean hasContentToDisplay() {
582 for (int i = mChildren.size() - 1; i >= 0; --i) {
583 final WindowContainer wc = mChildren.get(i);
584 if (wc.hasContentToDisplay()) {
585 return true;
586 }
587 }
588 return false;
589 }
590
591 /**
592 * Returns true if the container or one of its children is considered visible from the
593 * WindowManager perspective which usually means valid surface and some other internal state
594 * are true.
595 *
596 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
597 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
598 * the container has any content to display.
599 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700600 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700601 // TODO: Will this be more correct if it checks the visibility of its parents?
602 // It depends...For example, Tasks and Stacks are only visible if there children are visible
603 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800604 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700605 for (int i = mChildren.size() - 1; i >= 0; --i) {
606 final WindowContainer wc = mChildren.get(i);
607 if (wc.isVisible()) {
608 return true;
609 }
610 }
611 return false;
612 }
613
Bryce Lee00d586d2017-07-28 20:48:43 -0700614 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700615 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700616 */
617 boolean isOnTop() {
618 return getParent().getTopChild() == this && getParent().isOnTop();
619 }
620
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100621 /** Returns the top child container. */
622 E getTopChild() {
623 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700624 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700625
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700626 /** Returns true if there is still a removal being deferred */
627 boolean checkCompleteDeferredRemoval() {
628 boolean stillDeferringRemoval = false;
629
630 for (int i = mChildren.size() - 1; i >= 0; --i) {
631 final WindowContainer wc = mChildren.get(i);
632 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
633 }
634
635 return stillDeferringRemoval;
636 }
637
638 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700639 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700640 for (int i = mChildren.size() - 1; i >= 0; --i) {
641 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700642 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700643 }
644 }
645
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700646 void onAppTransitionDone() {
647 for (int i = mChildren.size() - 1; i >= 0; --i) {
648 final WindowContainer wc = mChildren.get(i);
649 wc.onAppTransitionDone();
650 }
651 }
652
Wale Ogunwale51362492016-09-08 17:49:17 -0700653 void setOrientation(int orientation) {
654 mOrientation = orientation;
655 }
656
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700657 int getOrientation() {
658 return getOrientation(mOrientation);
659 }
660
Wale Ogunwale51362492016-09-08 17:49:17 -0700661 /**
662 * Returns the specified orientation for this window container or one of its children is there
663 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
664 * specification is set.
665 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
666 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700667 *
668 * @param candidate The current orientation candidate that will be returned if we don't find a
669 * better match.
670 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -0700671 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700672 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -0800673 if (!fillsParent()) {
674 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -0700675 return SCREEN_ORIENTATION_UNSET;
676 }
677
Bryce Leea163b762017-01-24 11:05:01 -0800678 // The container fills its parent so we can use it orientation if it has one
679 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -0700680 // specified and fall back on this container's unset or unspecified value as a candidate
681 // if none of the children have a better candidate for the orientation.
682 if (mOrientation != SCREEN_ORIENTATION_UNSET
683 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
684 return mOrientation;
685 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700686
687 for (int i = mChildren.size() - 1; i >= 0; --i) {
688 final WindowContainer wc = mChildren.get(i);
689
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700690 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
691 // SCREEN_ORIENTATION_UNSPECIFIED?
692 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
693 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -0700694 if (orientation == SCREEN_ORIENTATION_BEHIND) {
695 // container wants us to use the orientation of the container behind it. See if we
696 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
697 // look behind this container.
698 candidate = orientation;
699 continue;
700 }
701
702 if (orientation == SCREEN_ORIENTATION_UNSET) {
703 continue;
704 }
705
706 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
707 // Use the orientation if the container fills its parent or requested an explicit
708 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
709 return orientation;
710 }
711 }
712
713 return candidate;
714 }
715
716 /**
717 * Returns true if this container is opaque and fills all the space made available by its parent
718 * container.
719 *
720 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
721 * this is just a signal from the client to window manager stating its intent, but not what it
722 * actually does.
723 */
724 boolean fillsParent() {
725 return false;
726 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700727
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000728 // TODO: Users would have their own window containers under the display container?
729 void switchUser() {
730 for (int i = mChildren.size() - 1; i >= 0; --i) {
731 mChildren.get(i).switchUser();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700732 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700733 }
734
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800735 /**
736 * For all windows at or below this container call the callback.
737 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
738 * stops the search if {@link ToBooleanFunction#apply} returns true.
739 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
740 * z-order, else from bottom-to-top.
741 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800742 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800743 */
744 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700745 if (traverseTopToBottom) {
746 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800747 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
748 return true;
749 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700750 }
751 } else {
752 final int count = mChildren.size();
753 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800754 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
755 return true;
756 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700757 }
758 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800759 return false;
760 }
761
762 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800763 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
764 forAllWindows(wrapper, traverseTopToBottom);
765 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700766 }
767
Jorim Jaggi51304d72017-05-17 17:25:32 +0200768 /**
769 * For all tasks at or below this container call the callback.
770 *
771 * @param callback Callback to be called for every task.
772 */
773 void forAllTasks(Consumer<Task> callback) {
774 for (int i = mChildren.size() - 1; i >= 0; --i) {
775 mChildren.get(i).forAllTasks(callback);
776 }
777 }
778
Wale Ogunwaled1880962016-11-08 10:31:59 -0800779 WindowState getWindow(Predicate<WindowState> callback) {
780 for (int i = mChildren.size() - 1; i >= 0; --i) {
781 final WindowState w = mChildren.get(i).getWindow(callback);
782 if (w != null) {
783 return w;
784 }
785 }
786
787 return null;
788 }
789
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700790 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -0700791 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
792 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700793 */
794 @Override
795 public int compareTo(WindowContainer other) {
796 if (this == other) {
797 return 0;
798 }
799
800 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200801 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700802 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
803 }
804
805 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
806 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200807 try {
808 getParents(thisParentChain);
809 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700810
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200811 // Find the common ancestor of both containers.
812 WindowContainer commonAncestor = null;
813 WindowContainer thisTop = thisParentChain.peekLast();
814 WindowContainer otherTop = otherParentChain.peekLast();
815 while (thisTop != null && otherTop != null && thisTop == otherTop) {
816 commonAncestor = thisParentChain.removeLast();
817 otherParentChain.removeLast();
818 thisTop = thisParentChain.peekLast();
819 otherTop = otherParentChain.peekLast();
820 }
821
822 // Containers don't belong to the same hierarchy???
823 if (commonAncestor == null) {
824 throw new IllegalArgumentException("No in the same hierarchy this="
825 + thisParentChain + " other=" + otherParentChain);
826 }
827
828 // Children are always considered greater than their parents, so if one of the containers
829 // we are comparing it the parent of the other then whichever is the child is greater.
830 if (commonAncestor == this) {
831 return -1;
832 } else if (commonAncestor == other) {
833 return 1;
834 }
835
836 // The position of the first non-common ancestor in the common ancestor list determines
837 // which is greater the which.
838 final WindowList<WindowContainer> list = commonAncestor.mChildren;
839 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
840 ? 1 : -1;
841 } finally {
842 mTmpChain1.clear();
843 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700844 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700845 }
846
847 private void getParents(LinkedList<WindowContainer> parents) {
848 parents.clear();
849 WindowContainer current = this;
850 do {
851 parents.addLast(current);
852 current = current.mParent;
853 } while (current != null);
854 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700855
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800856 WindowContainerController getController() {
857 return mController;
858 }
859
860 void setController(WindowContainerController controller) {
861 if (mController != null && controller != null) {
862 throw new IllegalArgumentException("Can't set controller=" + mController
863 + " for container=" + this + " Already set to=" + mController);
864 }
865 if (controller != null) {
866 controller.setContainer(this);
867 } else if (mController != null) {
868 mController.setContainer(null);
869 }
870 mController = controller;
871 }
872
Robert Carrb1579c82017-09-05 14:54:47 -0700873 SurfaceControl.Builder makeSurface() {
874 final WindowContainer p = getParent();
875 return p.makeChildSurface(this);
876 }
877
Robert Carrf59b8dd2017-10-02 18:58:36 -0700878 /**
879 * @param child The WindowContainer this child surface is for, or null if the Surface
880 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
881 */
Robert Carrb1579c82017-09-05 14:54:47 -0700882 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
883 final WindowContainer p = getParent();
884 // Give the parent a chance to set properties. In hierarchy v1 we rely
885 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -0800886 return p.makeChildSurface(child)
887 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700888 }
889
Jorim Jaggia5e10572017-11-15 14:36:26 +0100890 @Override
891 public SurfaceControl getParentSurfaceControl() {
892 final WindowContainer parent = getParent();
893 if (parent == null) {
894 return null;
895 }
896 return parent.getSurfaceControl();
897 }
898
Robert Carrb1579c82017-09-05 14:54:47 -0700899 /**
900 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
901 */
902 boolean shouldMagnify() {
903 for (int i = 0; i < mChildren.size(); i++) {
904 if (!mChildren.get(i).shouldMagnify()) {
905 return false;
906 }
907 }
908 return true;
909 }
910
911 SurfaceSession getSession() {
912 if (getParent() != null) {
913 return getParent().getSession();
914 }
915 return null;
916 }
917
918 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100919 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
920 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100921 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100922 mLastLayer = layer;
923 mLastRelativeToLayer = null;
924 }
925 }
926
927 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
928 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
929 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100930 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100931 mLastLayer = layer;
932 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -0700933 }
934 }
935
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100936 protected void setLayer(Transaction t, int layer) {
937
938 // Route through surface animator to accommodate that our surface control might be
939 // attached to the leash, and leash is attached to parent container.
940 mSurfaceAnimator.setLayer(t, layer);
941 }
942
943 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
944
945 // Route through surface animator to accommodate that our surface control might be
946 // attached to the leash, and leash is attached to parent container.
947 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
948 }
949
950 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
951 mSurfaceAnimator.reparent(t, newParent);
952 }
953
Robert Carrb1579c82017-09-05 14:54:47 -0700954 void assignChildLayers(Transaction t) {
955 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -0700956
957 // We use two passes as a way to promote children which
958 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100959 for (int j = 0; j < mChildren.size(); ++j) {
960 final WindowContainer wc = mChildren.get(j);
961 wc.assignChildLayers(t);
962 if (!wc.needsZBoost()) {
963 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -0700964 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100965 }
966 for (int j = 0; j < mChildren.size(); ++j) {
967 final WindowContainer wc = mChildren.get(j);
968 if (wc.needsZBoost()) {
969 wc.assignLayer(t, layer++);
970 }
Robert Carrb1579c82017-09-05 14:54:47 -0700971 }
972 }
973
974 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -0700975 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100976 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700977 }
978
979 boolean needsZBoost() {
980 for (int i = 0; i < mChildren.size(); i++) {
981 if (mChildren.get(i).needsZBoost()) {
982 return true;
983 }
984 }
985 return false;
986 }
987
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700988 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700989 * Write to a protocol buffer output stream. Protocol buffer message definition is at
990 * {@link com.android.server.wm.proto.WindowContainerProto}.
991 *
Adrian Roos4921ccf2017-09-28 16:54:06 +0200992 * @param proto Stream to write the WindowContainer object to.
993 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
994 * @param trim If true, reduce the amount of data written.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700995 * @hide
996 */
997 @CallSuper
998 @Override
Adrian Roos4921ccf2017-09-28 16:54:06 +0200999 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
1000 final long token = proto.start(fieldId);
1001 super.writeToProto(proto, CONFIGURATION_CONTAINER, trim);
1002 proto.write(ORIENTATION, mOrientation);
Wale Ogunwaledf262f52017-12-07 18:17:12 -08001003 proto.write(VISIBLE, isVisible());
Vishnu Nair04ab4392018-01-10 11:00:06 -08001004 mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001005 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001006 }
1007
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001008 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1009 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1010 if (wrapper == null) {
1011 wrapper = new ForAllWindowsConsumerWrapper();
1012 }
1013 wrapper.setConsumer(consumer);
1014 return wrapper;
1015 }
1016
1017 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1018
1019 private Consumer<WindowState> mConsumer;
1020
1021 void setConsumer(Consumer<WindowState> consumer) {
1022 mConsumer = consumer;
1023 }
1024
1025 @Override
1026 public boolean apply(WindowState w) {
1027 mConsumer.accept(w);
1028 return false;
1029 }
1030
1031 void release() {
1032 mConsumer = null;
1033 mConsumerWrapperPool.release(this);
1034 }
1035 }
Robert Carrb1579c82017-09-05 14:54:47 -07001036
1037 // TODO(b/68336570): Should this really be on WindowContainer since it
1038 // can only be used on the top-level nodes that aren't animated?
1039 // (otherwise we would be fighting other callers of setMatrix).
1040 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1041 if (shouldMagnify()) {
1042 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1043 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
1044 } else {
1045 for (int i = 0; i < mChildren.size(); i++) {
1046 mChildren.get(i).applyMagnificationSpec(t, spec);
1047 }
1048 }
1049 }
1050
1051 /**
1052 * TODO: Once we totally eliminate global transaction we will pass transaction in here
1053 * rather than merging to global.
1054 */
1055 void prepareSurfaces() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001056 SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
chaviw7f1fa992018-01-10 13:52:12 -08001057
1058 // If a leash has been set when the transaction was committed, then the leash reparent has
1059 // been committed.
1060 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001061 for (int i = 0; i < mChildren.size(); i++) {
1062 mChildren.get(i).prepareSurfaces();
1063 }
1064 }
1065
1066 /**
chaviw7f1fa992018-01-10 13:52:12 -08001067 * @return true if the reparent to animation leash transaction has been committed, false
1068 * otherwise.
1069 */
1070 boolean hasCommittedReparentToAnimationLeash() {
1071 return mCommittedReparentToAnimationLeash;
1072 }
1073
1074 /**
Robert Carrb1579c82017-09-05 14:54:47 -07001075 * Trigger a call to prepareSurfaces from the animation thread, such that
1076 * mPendingTransaction will be applied.
1077 */
1078 void scheduleAnimation() {
1079 if (mParent != null) {
1080 mParent.scheduleAnimation();
1081 }
1082 }
1083
Jorim Jaggia5e10572017-11-15 14:36:26 +01001084 @Override
1085 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001086 return mSurfaceControl;
1087 }
1088
Jorim Jaggia5e10572017-11-15 14:36:26 +01001089 @Override
1090 public Transaction getPendingTransaction() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001091 return mPendingTransaction;
1092 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001093
1094 /**
1095 * Starts an animation on the container.
1096 *
1097 * @param anim The animation to run.
1098 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1099 * some point but the meaning is too weird to work for all containers.
1100 */
1101 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1102 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1103
1104 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1105 // the moment this doesn't work for all animatable window containers.
1106 mSurfaceAnimator.startAnimation(t, anim, hidden);
1107 }
1108
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001109 void transferAnimation(WindowContainer from) {
1110 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1111 }
1112
Jorim Jaggia5e10572017-11-15 14:36:26 +01001113 void cancelAnimation() {
1114 mSurfaceAnimator.cancelAnimation();
1115 }
1116
1117 @Override
1118 public Builder makeAnimationLeash() {
1119 return makeSurface();
1120 }
1121
Jorim Jaggi596a1992017-12-29 14:48:02 +01001122 @Override
1123 public SurfaceControl getAnimationLeashParent() {
1124 return getParentSurfaceControl();
1125 }
1126
chaviw23ee71c2017-12-18 11:29:41 -08001127 /**
1128 * @return The layer on which all app animations are happening.
1129 */
1130 SurfaceControl getAppAnimationLayer() {
1131 final WindowContainer parent = getParent();
1132 if (parent != null) {
1133 return parent.getAppAnimationLayer();
1134 }
1135 return null;
1136 }
1137
Jorim Jaggia5e10572017-11-15 14:36:26 +01001138 @Override
1139 public void commitPendingTransaction() {
1140 scheduleAnimation();
1141 }
1142
Robert Carr2f8aa392018-01-31 14:46:51 -08001143 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001144 final WindowContainer parent = getParent();
1145 if (parent != null) {
1146 parent.assignChildLayers(t);
1147 }
1148 }
1149
1150 @Override
1151 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001152 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001153 reassignLayer(t);
1154 }
1155
1156 @Override
1157 public void onAnimationLeashDestroyed(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001158 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001159 reassignLayer(t);
1160 }
1161
1162 /**
1163 * Called when an animation has finished running.
1164 */
1165 protected void onAnimationFinished() {
1166 }
1167
1168 /**
1169 * @return The currently running animation, if any, or {@code null} otherwise.
1170 */
1171 AnimationAdapter getAnimation() {
1172 return mSurfaceAnimator.getAnimation();
1173 }
1174
1175 /**
1176 * @see SurfaceAnimator#startDelayingAnimationStart
1177 */
1178 void startDelayingAnimationStart() {
1179 mSurfaceAnimator.startDelayingAnimationStart();
1180 }
1181
1182 /**
1183 * @see SurfaceAnimator#endDelayingAnimationStart
1184 */
1185 void endDelayingAnimationStart() {
1186 mSurfaceAnimator.endDelayingAnimationStart();
1187 }
1188
1189 @Override
1190 public int getSurfaceWidth() {
1191 return mSurfaceControl.getWidth();
1192 }
1193
1194 @Override
1195 public int getSurfaceHeight() {
1196 return mSurfaceControl.getHeight();
1197 }
1198
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001199 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01001200 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1201 if (mSurfaceAnimator.isAnimating()) {
1202 pw.print(prefix); pw.println("ContainerAnimator:");
1203 mSurfaceAnimator.dump(pw, prefix + " ");
1204 }
1205 }
chaviwe07246a2017-12-12 16:18:29 -08001206
chaviw2f0567b2018-01-29 16:22:02 -08001207 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08001208 if (mSurfaceControl == null) {
1209 return;
1210 }
1211
1212 getRelativePosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08001213 if (mTmpPos.equals(mLastSurfacePosition)) {
1214 return;
1215 }
1216
chaviw2f0567b2018-01-29 16:22:02 -08001217 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08001218 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08001219 }
1220
1221 void getRelativePosition(Point outPos) {
1222 final Rect bounds = getBounds();
1223 outPos.set(bounds.left, bounds.top);
1224 final WindowContainer parent = getParent();
1225 if (parent != null) {
1226 final Rect parentBounds = parent.getBounds();
1227 outPos.offset(-parentBounds.left, -parentBounds.top);
1228 }
1229 }
chaviw2fb06bc2018-01-19 17:09:15 -08001230
1231 Dimmer getDimmer() {
1232 if (mParent == null) {
1233 return null;
1234 }
1235 return mParent.getDimmer();
1236 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001237}