blob: 8fe7063c815b5d2bf70aacf1e03f84f9821c26d5 [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;
Yi Jin6c6e9ca2018-03-20 16:53:35 -070026import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
27import static com.android.server.wm.WindowContainerProto.ORIENTATION;
28import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
29import static com.android.server.wm.WindowContainerProto.VISIBLE;
Jorim Jaggi612bb882017-05-16 17:11:18 +020030
Wale Ogunwaled63594a2016-07-18 07:48:30 -070031import android.annotation.CallSuper;
Jorim Jaggi391790622018-04-18 15:30:44 +020032import android.annotation.IntDef;
33import android.app.WindowConfiguration;
Andrii Kulian441e4492016-09-29 15:25:00 -070034import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080035import android.graphics.Point;
36import android.graphics.Rect;
Vishnu Nair04ab4392018-01-10 11:00:06 -080037import android.util.Pools;
Jorim Jaggia5e10572017-11-15 14:36:26 +010038import android.util.Slog;
Vishnu Nair04ab4392018-01-10 11:00:06 -080039import android.util.proto.ProtoOutputStream;
Robert Carrb1579c82017-09-05 14:54:47 -070040import android.view.MagnificationSpec;
41import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010042import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070043import android.view.SurfaceSession;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070044
Jorim Jaggia5e10572017-11-15 14:36:26 +010045import com.android.internal.util.ToBooleanFunction;
46import com.android.server.wm.SurfaceAnimator.Animatable;
47
48import java.io.PrintWriter;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070049import java.util.Comparator;
50import java.util.LinkedList;
Wale Ogunwaleb783fd82016-11-04 09:51:54 -070051import java.util.function.Consumer;
Wale Ogunwaled1880962016-11-08 10:31:59 -080052import java.util.function.Predicate;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070053
54/**
55 * Defines common functionality for classes that can hold windows directly or through their
Wale Ogunwale51362492016-09-08 17:49:17 -070056 * children in a hierarchy form.
Wale Ogunwaled63594a2016-07-18 07:48:30 -070057 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
58 * changes are made to this class.
59 */
Wale Ogunwale98d62312017-07-12 09:24:56 -070060class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
Jorim Jaggia5e10572017-11-15 14:36:26 +010061 implements Comparable<WindowContainer>, Animatable {
62
63 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070064
Jorim Jaggi391790622018-04-18 15:30:44 +020065 /** Animation layer that happens above all animating {@link TaskStack}s. */
66 static final int ANIMATION_LAYER_STANDARD = 0;
67
68 /** Animation layer that happens above all {@link TaskStack}s. */
69 static final int ANIMATION_LAYER_BOOSTED = 1;
70
71 /**
72 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
73 * activities that happens below all {@link TaskStack}s.
74 */
75 static final int ANIMATION_LAYER_HOME = 2;
76
77 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
78 ANIMATION_LAYER_STANDARD,
79 ANIMATION_LAYER_BOOSTED,
80 ANIMATION_LAYER_HOME,
81 })
82 @interface AnimationLayer {}
83
Andrii Kuliand2765632016-12-12 22:26:34 -080084 static final int POSITION_TOP = Integer.MAX_VALUE;
85 static final int POSITION_BOTTOM = Integer.MIN_VALUE;
86
Andrii Kulian441e4492016-09-29 15:25:00 -070087 /**
88 * The parent of this window container.
89 * For removing or setting new parent {@link #setParent} should be used, because it also
90 * performs configuration updates based on new parent's settings.
91 */
Jorim Jaggia5e10572017-11-15 14:36:26 +010092 private WindowContainer<WindowContainer> mParent = null;
Wale Ogunwaled63594a2016-07-18 07:48:30 -070093
94 // List of children for this window container. List is in z-order as the children appear on
95 // screen with the top-most window container at the tail of the list.
Jorim Jaggi612bb882017-05-16 17:11:18 +020096 protected final WindowList<E> mChildren = new WindowList<E>();
Wale Ogunwaled63594a2016-07-18 07:48:30 -070097
Wale Ogunwale51362492016-09-08 17:49:17 -070098 // The specified orientation for this window container.
99 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
100
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800101 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
102 new Pools.SynchronizedPool<>(3);
103
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800104 // The owner/creator for this container. No controller if null.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100105 WindowContainerController mController;
Robert Carrb1579c82017-09-05 14:54:47 -0700106
107 protected SurfaceControl mSurfaceControl;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100108 private int mLastLayer = 0;
109 private SurfaceControl mLastRelativeToLayer = null;
Robert Carrb1579c82017-09-05 14:54:47 -0700110
111 /**
112 * Applied as part of the animation pass in "prepareSurfaces".
113 */
Jorim Jaggia5e10572017-11-15 14:36:26 +0100114 protected final Transaction mPendingTransaction;
115 protected final SurfaceAnimator mSurfaceAnimator;
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100116 protected final WindowManagerService mService;
117
chaviwe07246a2017-12-12 16:18:29 -0800118 private final Point mTmpPos = new Point();
chaviw3e751af2018-01-11 11:22:39 -0800119 protected final Point mLastSurfacePosition = new Point();
chaviwe07246a2017-12-12 16:18:29 -0800120
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100121 /** Total number of elements in this subtree, including our own hierarchy element. */
122 private int mTreeWeight = 1;
123
chaviw7f1fa992018-01-10 13:52:12 -0800124 /**
125 * Indicates whether we are animating and have committed the transaction to reparent our
126 * surface to the animation leash
127 */
128 private boolean mCommittedReparentToAnimationLeash;
129
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100130 WindowContainer(WindowManagerService service) {
131 mService = service;
132 mPendingTransaction = service.mTransactionFactory.make();
Chavi Weingartenb736e322018-02-23 00:27:54 +0000133 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, service);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100134 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800135
Wale Ogunwale98d62312017-07-12 09:24:56 -0700136 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700137 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700138 return mParent;
139 }
140
Wale Ogunwale98d62312017-07-12 09:24:56 -0700141 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700142 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700143 return mChildren.size();
144 }
145
146 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700147 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700148 return mChildren.get(index);
149 }
150
chaviwe07246a2017-12-12 16:18:29 -0800151 @Override
152 public void onConfigurationChanged(Configuration newParentConfig) {
153 super.onConfigurationChanged(newParentConfig);
chaviw2f0567b2018-01-29 16:22:02 -0800154 updateSurfacePosition();
chaviwe07246a2017-12-12 16:18:29 -0800155 scheduleAnimation();
156 }
157
Jorim Jaggia5e10572017-11-15 14:36:26 +0100158 final protected void setParent(WindowContainer<WindowContainer> parent) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700159 mParent = parent;
Andrii Kulianb94292e2016-10-19 13:30:58 -0700160 // Removing parent usually means that we've detached this entity to destroy it or to attach
161 // to another parent. In both cases we don't need to update the configuration now.
162 if (mParent != null) {
163 // Update full configuration of this container and all its children.
Wale Ogunwale98d62312017-07-12 09:24:56 -0700164 onConfigurationChanged(mParent.getConfiguration());
Andrii Kulianb94292e2016-10-19 13:30:58 -0700165 // Update merged override configuration of this container and all its children.
166 onMergedOverrideConfigurationChanged();
167 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800168
169 onParentSet();
170 }
171
172 /**
173 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
174 * Supposed to be overridden and contain actions that should be executed after parent was set.
175 */
176 void onParentSet() {
Robert Carrb1579c82017-09-05 14:54:47 -0700177 if (mParent == null) {
178 return;
179 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100180
Robert Carrb1579c82017-09-05 14:54:47 -0700181 if (mSurfaceControl == null) {
182 // If we don't yet have a surface, but we now have a parent, we should
183 // build a surface.
184 mSurfaceControl = makeSurface().build();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700185 getPendingTransaction().show(mSurfaceControl);
Evan Roskyb1ea7ca2018-04-05 17:17:35 -0700186 updateSurfacePosition();
Robert Carrb1579c82017-09-05 14:54:47 -0700187 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100188 // If we have a surface but a new parent, we just need to perform a reparent. Go through
189 // surface animator such that hierarchy is preserved when animating, i.e.
190 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
191 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100192 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700193 }
194
195 // Either way we need to ask the parent to assign us a Z-order.
196 mParent.assignChildLayers();
197 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700198 }
199
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700200 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100201 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
202 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700203
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700204 /**
205 * Adds the input window container has a child of this container in order based on the input
206 * comparator.
207 * @param child The window container to add as a child of this window container.
208 * @param comparator Comparator to use in determining the position the child should be added to.
209 * If null, the child will be added to the top.
210 */
211 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700212 protected void addChild(E child, Comparator<E> comparator) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700213 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700214 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700215 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700216 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700217 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700218
Andrii Kulianb94292e2016-10-19 13:30:58 -0700219 int positionToAdd = -1;
220 if (comparator != null) {
221 final int count = mChildren.size();
222 for (int i = 0; i < count; i++) {
223 if (comparator.compare(child, mChildren.get(i)) < 0) {
224 positionToAdd = i;
225 break;
226 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700227 }
228 }
229
Andrii Kulianb94292e2016-10-19 13:30:58 -0700230 if (positionToAdd == -1) {
231 mChildren.add(child);
232 } else {
233 mChildren.add(positionToAdd, child);
234 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100235 onChildAdded(child);
236
Andrii Kulianb94292e2016-10-19 13:30:58 -0700237 // Set the parent after we've actually added a child in case a subclass depends on this.
238 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700239 }
240
Wale Ogunwalef6192862016-09-10 13:42:30 -0700241 /** Adds the input window container has a child of this container at the input index. */
242 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800243 void addChild(E child, int index) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700244 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700245 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700246 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700247 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700248 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700249 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100250 onChildAdded(child);
251
Andrii Kulianb94292e2016-10-19 13:30:58 -0700252 // Set the parent after we've actually added a child in case a subclass depends on this.
253 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700254 }
255
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100256 private void onChildAdded(WindowContainer child) {
257 mTreeWeight += child.mTreeWeight;
258 WindowContainer parent = getParent();
259 while (parent != null) {
260 parent.mTreeWeight += child.mTreeWeight;
261 parent = parent.getParent();
262 }
263 }
264
Wale Ogunwalef6192862016-09-10 13:42:30 -0700265 /**
266 * Removes the input child container from this container which is its parent.
267 *
268 * @return True if the container did contain the input child and it was detached.
269 */
270 @CallSuper
271 void removeChild(E child) {
272 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100273 onChildRemoved(child);
Andrii Kulian441e4492016-09-29 15:25:00 -0700274 child.setParent(null);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700275 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700276 throw new IllegalArgumentException("removeChild: container=" + child.getName()
277 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700278 }
279 }
280
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100281 private void onChildRemoved(WindowContainer child) {
282 mTreeWeight -= child.mTreeWeight;
283 WindowContainer parent = getParent();
284 while (parent != null) {
285 parent.mTreeWeight -= child.mTreeWeight;
286 parent = parent.getParent();
287 }
288 }
289
Wale Ogunwale571771c2016-08-26 13:18:50 -0700290 /**
291 * Removes this window container and its children with no regard for what else might be going on
292 * in the system. For example, the container will be removed during animation if this method is
293 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
294 * which allows the system to defer removal until a suitable time.
295 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700296 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700297 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700298 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100299 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700300 child.removeImmediately();
301 // Need to do this after calling remove on the child because the child might try to
302 // remove/detach itself from its parent which will cause an exception if we remove
303 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100304 if (mChildren.remove(child)) {
305 onChildRemoved(child);
306 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700307 }
308
Robert Carrb1579c82017-09-05 14:54:47 -0700309 if (mSurfaceControl != null) {
chaviw6728e2f2018-03-19 15:58:04 -0700310 mPendingTransaction.destroy(mSurfaceControl);
311
312 // Merge to parent transaction to ensure the transactions on this WindowContainer are
313 // applied in native even if WindowContainer is removed.
314 if (mParent != null) {
315 mParent.getPendingTransaction().merge(mPendingTransaction);
316 }
317
Robert Carrb1579c82017-09-05 14:54:47 -0700318 mSurfaceControl = null;
Chavi Weingartenb736e322018-02-23 00:27:54 +0000319 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700320 }
321
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700322 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700323 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700324 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800325
326 if (mController != null) {
327 setController(null);
328 }
Robert Carrb1579c82017-09-05 14:54:47 -0700329
Wale Ogunwale571771c2016-08-26 13:18:50 -0700330 }
331
332 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100333 * @return The index of this element in the hierarchy tree in prefix order.
334 */
335 int getPrefixOrderIndex() {
336 if (mParent == null) {
337 return 0;
338 }
339 return mParent.getPrefixOrderIndex(this);
340 }
341
342 private int getPrefixOrderIndex(WindowContainer child) {
343 int order = 0;
344 for (int i = 0; i < mChildren.size(); i++) {
345 final WindowContainer childI = mChildren.get(i);
346 if (child == childI) {
347 break;
348 }
349 order += childI.mTreeWeight;
350 }
351 if (mParent != null) {
352 order += mParent.getPrefixOrderIndex(this);
353 }
354
355 // We also need to count ourselves.
356 order++;
357 return order;
358 }
359
360 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700361 * Removes this window container and its children taking care not to remove them during a
362 * critical stage in the system. For example, some containers will not be removed during
363 * animation if this method is called.
364 */
365 // TODO: figure-out implementation that works best for this.
366 // E.g. when do we remove from parent list? maybe not...
367 void removeIfPossible() {
368 for (int i = mChildren.size() - 1; i >= 0; --i) {
369 final WindowContainer wc = mChildren.get(i);
370 wc.removeIfPossible();
371 }
372 }
373
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700374 /** Returns true if this window container has the input child. */
Winson Chunge2d72172018-01-25 17:46:20 +0000375 boolean hasChild(E child) {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700376 for (int i = mChildren.size() - 1; i >= 0; --i) {
Winson Chunge2d72172018-01-25 17:46:20 +0000377 final E current = mChildren.get(i);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700378 if (current == child || current.hasChild(child)) {
379 return true;
380 }
381 }
382 return false;
383 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700384
Andrii Kulian441e4492016-09-29 15:25:00 -0700385 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800386 * Move a child from it's current place in siblings list to the specified position,
387 * with an option to move all its parents to top.
388 * @param position Target position to move the child to.
389 * @param child Child to move to selected position.
390 * @param includingParents Flag indicating whether we need to move the entire branch of the
391 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
392 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
393 * this flag will do nothing.
394 */
395 @CallSuper
396 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800397
398 if (child.getParent() != this) {
399 throw new IllegalArgumentException("removeChild: container=" + child.getName()
400 + " is not a child of container=" + getName()
401 + " current parent=" + child.getParent());
402 }
403
Andrii Kuliand2765632016-12-12 22:26:34 -0800404 if ((position < 0 && position != POSITION_BOTTOM)
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800405 || (position > mChildren.size() && position != POSITION_TOP)) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800406 throw new IllegalArgumentException("positionAt: invalid position=" + position
407 + ", children number=" + mChildren.size());
408 }
409
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800410 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800411 position = POSITION_TOP;
412 } else if (position == 0) {
413 position = POSITION_BOTTOM;
414 }
415
416 switch (position) {
417 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800418 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800419 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200420 mChildren.add(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800421 }
422 if (includingParents && getParent() != null) {
423 getParent().positionChildAt(POSITION_TOP, this /* child */,
424 true /* includingParents */);
425 }
426 break;
427 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800428 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800429 mChildren.remove(child);
430 mChildren.addFirst(child);
431 }
432 if (includingParents && getParent() != null) {
433 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
434 true /* includingParents */);
435 }
436 break;
437 default:
Winson Chung123e07a2018-02-27 11:47:16 -0800438 // TODO: Removing the child before reinserting requires the caller to provide a
439 // position that takes into account the removed child (if the index of the
440 // child < position, then the position should be adjusted). We should consider
441 // doing this adjustment here and remove any adjustments in the callers.
Andrii Kuliand2765632016-12-12 22:26:34 -0800442 mChildren.remove(child);
443 mChildren.add(position, child);
444 }
445 }
446
447 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700448 * Update override configuration and recalculate full config.
449 * @see #mOverrideConfiguration
450 * @see #mFullConfiguration
451 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700452 @Override
Bryce Leef3c6a472017-11-14 14:53:06 -0800453 public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
454 // We must diff before the configuration is applied so that we can capture the change
455 // against the existing bounds.
456 final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds());
Wale Ogunwale98d62312017-07-12 09:24:56 -0700457 super.onOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700458 if (mParent != null) {
459 mParent.onDescendantOverrideConfigurationChanged();
460 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800461
462 if (diff == BOUNDS_CHANGE_NONE) {
463 return;
464 }
465
466 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
467 onResize();
468 } else {
469 onMovedByResize();
470 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700471 }
472
473 /**
474 * Notify that a descendant's overrideConfiguration has changed.
475 */
476 void onDescendantOverrideConfigurationChanged() {
477 if (mParent != null) {
478 mParent.onDescendantOverrideConfigurationChanged();
479 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700480 }
481
482 /**
Wale Ogunwale02319a62016-09-26 15:21:22 -0700483 * Notify that the display this container is on has changed.
484 * @param dc The new display this container is on.
485 */
486 void onDisplayChanged(DisplayContent dc) {
487 for (int i = mChildren.size() - 1; i >= 0; --i) {
488 final WindowContainer child = mChildren.get(i);
489 child.onDisplayChanged(dc);
490 }
491 }
492
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700493 void setWaitingForDrawnIfResizingChanged() {
494 for (int i = mChildren.size() - 1; i >= 0; --i) {
495 final WindowContainer wc = mChildren.get(i);
496 wc.setWaitingForDrawnIfResizingChanged();
497 }
498 }
499
500 void onResize() {
501 for (int i = mChildren.size() - 1; i >= 0; --i) {
502 final WindowContainer wc = mChildren.get(i);
Bryce Leed92ae482018-01-22 13:56:23 -0800503 wc.onParentResize();
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700504 }
505 }
506
Bryce Leed92ae482018-01-22 13:56:23 -0800507 void onParentResize() {
508 // In the case this container has specified its own bounds, a parent resize will not
509 // affect its bounds. Any relevant changes will be propagated through changes to the
510 // Configuration override.
511 if (hasOverrideBounds()) {
512 return;
513 }
514
515 // Default implementation is to treat as resize on self.
516 onResize();
517 }
518
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700519 void onMovedByResize() {
520 for (int i = mChildren.size() - 1; i >= 0; --i) {
521 final WindowContainer wc = mChildren.get(i);
522 wc.onMovedByResize();
523 }
524 }
525
526 void resetDragResizingChangeReported() {
527 for (int i = mChildren.size() - 1; i >= 0; --i) {
528 final WindowContainer wc = mChildren.get(i);
529 wc.resetDragResizingChangeReported();
530 }
531 }
532
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700533 void forceWindowsScaleableInTransaction(boolean force) {
534 for (int i = mChildren.size() - 1; i >= 0; --i) {
535 final WindowContainer wc = mChildren.get(i);
536 wc.forceWindowsScaleableInTransaction(force);
537 }
538 }
539
Jorim Jaggia5e10572017-11-15 14:36:26 +0100540 /**
541 * @return Whether our own container is running an animation or any child, no matter how deep in
542 * the hierarchy, is animating.
543 */
544 boolean isSelfOrChildAnimating() {
545 if (isSelfAnimating()) {
546 return true;
547 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700548 for (int j = mChildren.size() - 1; j >= 0; j--) {
549 final WindowContainer wc = mChildren.get(j);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100550 if (wc.isSelfOrChildAnimating()) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700551 return true;
552 }
553 }
554 return false;
555 }
556
Jorim Jaggia5e10572017-11-15 14:36:26 +0100557 /**
558 * @return Whether our own container is running an animation or our parent is animating. This
559 * doesn't consider whether children are animating.
560 */
561 boolean isAnimating() {
562
563 // We are animating if we ourselves are animating or if our parent is animating.
564 return isSelfAnimating() || mParent != null && mParent.isAnimating();
565 }
566
567 /**
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200568 * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
569 * that is {@link #isSelfAnimating}; {@code false} otherwise.
570 */
571 boolean isAppAnimating() {
572 for (int j = mChildren.size() - 1; j >= 0; j--) {
573 final WindowContainer wc = mChildren.get(j);
574 if (wc.isAppAnimating()) {
575 return true;
576 }
577 }
578 return false;
579 }
580
581 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100582 * @return Whether our own container running an animation at the moment.
583 */
584 boolean isSelfAnimating() {
585 return mSurfaceAnimator.isAnimating();
586 }
587
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700588 void sendAppVisibilityToClients() {
589 for (int i = mChildren.size() - 1; i >= 0; --i) {
590 final WindowContainer wc = mChildren.get(i);
591 wc.sendAppVisibilityToClients();
592 }
593 }
594
Wale Ogunwale44f21802016-09-02 12:49:48 -0700595 /**
596 * Returns true if the container or one of its children as some content it can display or wants
597 * to display (e.g. app views or saved surface).
598 *
599 * NOTE: While this method will return true if the there is some content to display, it doesn't
600 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
601 * visible.
602 */
603 boolean hasContentToDisplay() {
604 for (int i = mChildren.size() - 1; i >= 0; --i) {
605 final WindowContainer wc = mChildren.get(i);
606 if (wc.hasContentToDisplay()) {
607 return true;
608 }
609 }
610 return false;
611 }
612
613 /**
614 * Returns true if the container or one of its children is considered visible from the
615 * WindowManager perspective which usually means valid surface and some other internal state
616 * are true.
617 *
618 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
619 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
620 * the container has any content to display.
621 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700622 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700623 // TODO: Will this be more correct if it checks the visibility of its parents?
624 // It depends...For example, Tasks and Stacks are only visible if there children are visible
625 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800626 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700627 for (int i = mChildren.size() - 1; i >= 0; --i) {
628 final WindowContainer wc = mChildren.get(i);
629 if (wc.isVisible()) {
630 return true;
631 }
632 }
633 return false;
634 }
635
Bryce Lee00d586d2017-07-28 20:48:43 -0700636 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700637 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700638 */
639 boolean isOnTop() {
640 return getParent().getTopChild() == this && getParent().isOnTop();
641 }
642
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100643 /** Returns the top child container. */
644 E getTopChild() {
645 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700646 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700647
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700648 /** Returns true if there is still a removal being deferred */
649 boolean checkCompleteDeferredRemoval() {
650 boolean stillDeferringRemoval = false;
651
652 for (int i = mChildren.size() - 1; i >= 0; --i) {
653 final WindowContainer wc = mChildren.get(i);
654 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
655 }
656
657 return stillDeferringRemoval;
658 }
659
660 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700661 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700662 for (int i = mChildren.size() - 1; i >= 0; --i) {
663 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700664 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700665 }
666 }
667
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700668 void onAppTransitionDone() {
669 for (int i = mChildren.size() - 1; i >= 0; --i) {
670 final WindowContainer wc = mChildren.get(i);
671 wc.onAppTransitionDone();
672 }
673 }
674
Wale Ogunwale51362492016-09-08 17:49:17 -0700675 void setOrientation(int orientation) {
676 mOrientation = orientation;
677 }
678
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700679 int getOrientation() {
680 return getOrientation(mOrientation);
681 }
682
Wale Ogunwale51362492016-09-08 17:49:17 -0700683 /**
684 * Returns the specified orientation for this window container or one of its children is there
685 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
686 * specification is set.
687 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
688 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700689 *
690 * @param candidate The current orientation candidate that will be returned if we don't find a
691 * better match.
692 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -0700693 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700694 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -0800695 if (!fillsParent()) {
696 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -0700697 return SCREEN_ORIENTATION_UNSET;
698 }
699
Bryce Leea163b762017-01-24 11:05:01 -0800700 // The container fills its parent so we can use it orientation if it has one
701 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -0700702 // specified and fall back on this container's unset or unspecified value as a candidate
703 // if none of the children have a better candidate for the orientation.
704 if (mOrientation != SCREEN_ORIENTATION_UNSET
705 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
706 return mOrientation;
707 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700708
709 for (int i = mChildren.size() - 1; i >= 0; --i) {
710 final WindowContainer wc = mChildren.get(i);
711
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700712 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
713 // SCREEN_ORIENTATION_UNSPECIFIED?
714 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
715 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -0700716 if (orientation == SCREEN_ORIENTATION_BEHIND) {
717 // container wants us to use the orientation of the container behind it. See if we
718 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
719 // look behind this container.
720 candidate = orientation;
721 continue;
722 }
723
724 if (orientation == SCREEN_ORIENTATION_UNSET) {
725 continue;
726 }
727
728 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
729 // Use the orientation if the container fills its parent or requested an explicit
730 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
731 return orientation;
732 }
733 }
734
735 return candidate;
736 }
737
738 /**
Adrian Roos41f7e9d2018-06-07 15:29:34 +0200739 * Seamlessly rotates the container, by recomputing the location in the new
740 * rotation, and rotating buffers until they are updated for the new rotation.
741 *
742 * @param t the transaction to perform the seamless rotation in
743 * @param oldRotation the rotation we are rotating from
744 * @param newRotation the rotation we are rotating to
745 */
746 void seamlesslyRotate(Transaction t, int oldRotation, int newRotation) {
747 for (int i = mChildren.size() - 1; i >= 0; --i) {
748 mChildren.get(i).seamlesslyRotate(t, oldRotation, newRotation);
749 }
750 }
751
752 /**
Wale Ogunwale51362492016-09-08 17:49:17 -0700753 * Returns true if this container is opaque and fills all the space made available by its parent
754 * container.
755 *
756 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
757 * this is just a signal from the client to window manager stating its intent, but not what it
758 * actually does.
759 */
760 boolean fillsParent() {
761 return false;
762 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700763
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000764 // TODO: Users would have their own window containers under the display container?
765 void switchUser() {
766 for (int i = mChildren.size() - 1; i >= 0; --i) {
767 mChildren.get(i).switchUser();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700768 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700769 }
770
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800771 /**
772 * For all windows at or below this container call the callback.
773 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
774 * stops the search if {@link ToBooleanFunction#apply} returns true.
775 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
776 * z-order, else from bottom-to-top.
777 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800778 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800779 */
780 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700781 if (traverseTopToBottom) {
782 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800783 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
784 return true;
785 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700786 }
787 } else {
788 final int count = mChildren.size();
789 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800790 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
791 return true;
792 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700793 }
794 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800795 return false;
796 }
797
798 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800799 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
800 forAllWindows(wrapper, traverseTopToBottom);
801 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700802 }
803
Jorim Jaggi51304d72017-05-17 17:25:32 +0200804 /**
805 * For all tasks at or below this container call the callback.
806 *
807 * @param callback Callback to be called for every task.
808 */
809 void forAllTasks(Consumer<Task> callback) {
810 for (int i = mChildren.size() - 1; i >= 0; --i) {
811 mChildren.get(i).forAllTasks(callback);
812 }
813 }
814
Wale Ogunwaled1880962016-11-08 10:31:59 -0800815 WindowState getWindow(Predicate<WindowState> callback) {
816 for (int i = mChildren.size() - 1; i >= 0; --i) {
817 final WindowState w = mChildren.get(i).getWindow(callback);
818 if (w != null) {
819 return w;
820 }
821 }
822
823 return null;
824 }
825
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700826 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -0700827 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
828 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700829 */
830 @Override
831 public int compareTo(WindowContainer other) {
832 if (this == other) {
833 return 0;
834 }
835
836 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200837 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700838 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
839 }
840
841 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
842 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200843 try {
844 getParents(thisParentChain);
845 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700846
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200847 // Find the common ancestor of both containers.
848 WindowContainer commonAncestor = null;
849 WindowContainer thisTop = thisParentChain.peekLast();
850 WindowContainer otherTop = otherParentChain.peekLast();
851 while (thisTop != null && otherTop != null && thisTop == otherTop) {
852 commonAncestor = thisParentChain.removeLast();
853 otherParentChain.removeLast();
854 thisTop = thisParentChain.peekLast();
855 otherTop = otherParentChain.peekLast();
856 }
857
858 // Containers don't belong to the same hierarchy???
859 if (commonAncestor == null) {
860 throw new IllegalArgumentException("No in the same hierarchy this="
861 + thisParentChain + " other=" + otherParentChain);
862 }
863
864 // Children are always considered greater than their parents, so if one of the containers
865 // we are comparing it the parent of the other then whichever is the child is greater.
866 if (commonAncestor == this) {
867 return -1;
868 } else if (commonAncestor == other) {
869 return 1;
870 }
871
872 // The position of the first non-common ancestor in the common ancestor list determines
873 // which is greater the which.
874 final WindowList<WindowContainer> list = commonAncestor.mChildren;
875 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
876 ? 1 : -1;
877 } finally {
878 mTmpChain1.clear();
879 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700880 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700881 }
882
883 private void getParents(LinkedList<WindowContainer> parents) {
884 parents.clear();
885 WindowContainer current = this;
886 do {
887 parents.addLast(current);
888 current = current.mParent;
889 } while (current != null);
890 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700891
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800892 WindowContainerController getController() {
893 return mController;
894 }
895
896 void setController(WindowContainerController controller) {
897 if (mController != null && controller != null) {
898 throw new IllegalArgumentException("Can't set controller=" + mController
899 + " for container=" + this + " Already set to=" + mController);
900 }
901 if (controller != null) {
902 controller.setContainer(this);
903 } else if (mController != null) {
904 mController.setContainer(null);
905 }
906 mController = controller;
907 }
908
Robert Carrb1579c82017-09-05 14:54:47 -0700909 SurfaceControl.Builder makeSurface() {
910 final WindowContainer p = getParent();
911 return p.makeChildSurface(this);
912 }
913
Robert Carrf59b8dd2017-10-02 18:58:36 -0700914 /**
915 * @param child The WindowContainer this child surface is for, or null if the Surface
916 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
917 */
Robert Carrb1579c82017-09-05 14:54:47 -0700918 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
919 final WindowContainer p = getParent();
920 // Give the parent a chance to set properties. In hierarchy v1 we rely
921 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -0800922 return p.makeChildSurface(child)
923 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700924 }
925
Jorim Jaggia5e10572017-11-15 14:36:26 +0100926 @Override
927 public SurfaceControl getParentSurfaceControl() {
928 final WindowContainer parent = getParent();
929 if (parent == null) {
930 return null;
931 }
932 return parent.getSurfaceControl();
933 }
934
Robert Carrb1579c82017-09-05 14:54:47 -0700935 /**
936 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
937 */
938 boolean shouldMagnify() {
Yuki Awano4c36b552018-04-24 17:27:50 +0900939 if (mSurfaceControl == null) {
940 return false;
941 }
942
Robert Carrb1579c82017-09-05 14:54:47 -0700943 for (int i = 0; i < mChildren.size(); i++) {
944 if (!mChildren.get(i).shouldMagnify()) {
945 return false;
946 }
947 }
948 return true;
949 }
950
951 SurfaceSession getSession() {
952 if (getParent() != null) {
953 return getParent().getSession();
954 }
955 return null;
956 }
957
958 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100959 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
960 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100961 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100962 mLastLayer = layer;
963 mLastRelativeToLayer = null;
964 }
965 }
966
967 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
968 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
969 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100970 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100971 mLastLayer = layer;
972 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -0700973 }
974 }
975
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100976 protected void setLayer(Transaction t, int layer) {
977
978 // Route through surface animator to accommodate that our surface control might be
979 // attached to the leash, and leash is attached to parent container.
980 mSurfaceAnimator.setLayer(t, layer);
981 }
982
983 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
984
985 // Route through surface animator to accommodate that our surface control might be
986 // attached to the leash, and leash is attached to parent container.
987 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
988 }
989
990 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
991 mSurfaceAnimator.reparent(t, newParent);
992 }
993
Robert Carrb1579c82017-09-05 14:54:47 -0700994 void assignChildLayers(Transaction t) {
995 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -0700996
997 // We use two passes as a way to promote children which
998 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100999 for (int j = 0; j < mChildren.size(); ++j) {
1000 final WindowContainer wc = mChildren.get(j);
1001 wc.assignChildLayers(t);
1002 if (!wc.needsZBoost()) {
1003 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -07001004 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001005 }
1006 for (int j = 0; j < mChildren.size(); ++j) {
1007 final WindowContainer wc = mChildren.get(j);
1008 if (wc.needsZBoost()) {
1009 wc.assignLayer(t, layer++);
1010 }
Robert Carrb1579c82017-09-05 14:54:47 -07001011 }
1012 }
1013
1014 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001015 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +01001016 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -07001017 }
1018
1019 boolean needsZBoost() {
1020 for (int i = 0; i < mChildren.size(); i++) {
1021 if (mChildren.get(i).needsZBoost()) {
1022 return true;
1023 }
1024 }
1025 return false;
1026 }
1027
Wale Ogunwale9adfe572016-09-08 20:43:58 -07001028 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001029 * Write to a protocol buffer output stream. Protocol buffer message definition is at
Yi Jin6c6e9ca2018-03-20 16:53:35 -07001030 * {@link com.android.server.wm.WindowContainerProto}.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001031 *
Adrian Roos4921ccf2017-09-28 16:54:06 +02001032 * @param proto Stream to write the WindowContainer object to.
1033 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
1034 * @param trim If true, reduce the amount of data written.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001035 * @hide
1036 */
1037 @CallSuper
1038 @Override
Adrian Roos4921ccf2017-09-28 16:54:06 +02001039 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
1040 final long token = proto.start(fieldId);
1041 super.writeToProto(proto, CONFIGURATION_CONTAINER, trim);
1042 proto.write(ORIENTATION, mOrientation);
Wale Ogunwaledf262f52017-12-07 18:17:12 -08001043 proto.write(VISIBLE, isVisible());
Vishnu Nair04ab4392018-01-10 11:00:06 -08001044 mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
Adrian Roos4921ccf2017-09-28 16:54:06 +02001045 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -07001046 }
1047
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -08001048 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1049 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1050 if (wrapper == null) {
1051 wrapper = new ForAllWindowsConsumerWrapper();
1052 }
1053 wrapper.setConsumer(consumer);
1054 return wrapper;
1055 }
1056
1057 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1058
1059 private Consumer<WindowState> mConsumer;
1060
1061 void setConsumer(Consumer<WindowState> consumer) {
1062 mConsumer = consumer;
1063 }
1064
1065 @Override
1066 public boolean apply(WindowState w) {
1067 mConsumer.accept(w);
1068 return false;
1069 }
1070
1071 void release() {
1072 mConsumer = null;
1073 mConsumerWrapperPool.release(this);
1074 }
1075 }
Robert Carrb1579c82017-09-05 14:54:47 -07001076
1077 // TODO(b/68336570): Should this really be on WindowContainer since it
1078 // can only be used on the top-level nodes that aren't animated?
1079 // (otherwise we would be fighting other callers of setMatrix).
1080 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1081 if (shouldMagnify()) {
1082 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1083 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
1084 } else {
1085 for (int i = 0; i < mChildren.size(); i++) {
1086 mChildren.get(i).applyMagnificationSpec(t, spec);
1087 }
1088 }
1089 }
1090
1091 /**
1092 * TODO: Once we totally eliminate global transaction we will pass transaction in here
1093 * rather than merging to global.
1094 */
1095 void prepareSurfaces() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001096 SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
chaviw7f1fa992018-01-10 13:52:12 -08001097
1098 // If a leash has been set when the transaction was committed, then the leash reparent has
1099 // been committed.
1100 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
Robert Carrb1579c82017-09-05 14:54:47 -07001101 for (int i = 0; i < mChildren.size(); i++) {
1102 mChildren.get(i).prepareSurfaces();
1103 }
1104 }
1105
1106 /**
chaviw7f1fa992018-01-10 13:52:12 -08001107 * @return true if the reparent to animation leash transaction has been committed, false
1108 * otherwise.
1109 */
1110 boolean hasCommittedReparentToAnimationLeash() {
1111 return mCommittedReparentToAnimationLeash;
1112 }
1113
1114 /**
Robert Carrb1579c82017-09-05 14:54:47 -07001115 * Trigger a call to prepareSurfaces from the animation thread, such that
1116 * mPendingTransaction will be applied.
1117 */
1118 void scheduleAnimation() {
1119 if (mParent != null) {
1120 mParent.scheduleAnimation();
1121 }
1122 }
1123
Jorim Jaggia5e10572017-11-15 14:36:26 +01001124 @Override
1125 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001126 return mSurfaceControl;
1127 }
1128
Jorim Jaggia5e10572017-11-15 14:36:26 +01001129 @Override
1130 public Transaction getPendingTransaction() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001131 return mPendingTransaction;
1132 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001133
1134 /**
1135 * Starts an animation on the container.
1136 *
1137 * @param anim The animation to run.
1138 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1139 * some point but the meaning is too weird to work for all containers.
1140 */
1141 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1142 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1143
1144 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1145 // the moment this doesn't work for all animatable window containers.
1146 mSurfaceAnimator.startAnimation(t, anim, hidden);
1147 }
1148
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001149 void transferAnimation(WindowContainer from) {
1150 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1151 }
1152
Jorim Jaggia5e10572017-11-15 14:36:26 +01001153 void cancelAnimation() {
1154 mSurfaceAnimator.cancelAnimation();
1155 }
1156
1157 @Override
1158 public Builder makeAnimationLeash() {
1159 return makeSurface();
1160 }
1161
Jorim Jaggi596a1992017-12-29 14:48:02 +01001162 @Override
1163 public SurfaceControl getAnimationLeashParent() {
1164 return getParentSurfaceControl();
1165 }
1166
chaviw23ee71c2017-12-18 11:29:41 -08001167 /**
1168 * @return The layer on which all app animations are happening.
1169 */
Jorim Jaggi391790622018-04-18 15:30:44 +02001170 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
chaviw23ee71c2017-12-18 11:29:41 -08001171 final WindowContainer parent = getParent();
1172 if (parent != null) {
Jorim Jaggi391790622018-04-18 15:30:44 +02001173 return parent.getAppAnimationLayer(animationLayer);
chaviw23ee71c2017-12-18 11:29:41 -08001174 }
1175 return null;
1176 }
1177
Jorim Jaggia5e10572017-11-15 14:36:26 +01001178 @Override
1179 public void commitPendingTransaction() {
1180 scheduleAnimation();
1181 }
1182
Robert Carr2f8aa392018-01-31 14:46:51 -08001183 void reassignLayer(Transaction t) {
Jorim Jaggia5e10572017-11-15 14:36:26 +01001184 final WindowContainer parent = getParent();
1185 if (parent != null) {
1186 parent.assignChildLayers(t);
1187 }
1188 }
1189
1190 @Override
1191 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001192 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001193 reassignLayer(t);
1194 }
1195
1196 @Override
1197 public void onAnimationLeashDestroyed(Transaction t) {
Robert Carrf12f9d32018-03-01 15:24:36 -08001198 mLastLayer = -1;
Jorim Jaggia5e10572017-11-15 14:36:26 +01001199 reassignLayer(t);
1200 }
1201
1202 /**
1203 * Called when an animation has finished running.
1204 */
1205 protected void onAnimationFinished() {
1206 }
1207
1208 /**
1209 * @return The currently running animation, if any, or {@code null} otherwise.
1210 */
1211 AnimationAdapter getAnimation() {
1212 return mSurfaceAnimator.getAnimation();
1213 }
1214
1215 /**
1216 * @see SurfaceAnimator#startDelayingAnimationStart
1217 */
1218 void startDelayingAnimationStart() {
1219 mSurfaceAnimator.startDelayingAnimationStart();
1220 }
1221
1222 /**
1223 * @see SurfaceAnimator#endDelayingAnimationStart
1224 */
1225 void endDelayingAnimationStart() {
1226 mSurfaceAnimator.endDelayingAnimationStart();
1227 }
1228
1229 @Override
1230 public int getSurfaceWidth() {
1231 return mSurfaceControl.getWidth();
1232 }
1233
1234 @Override
1235 public int getSurfaceHeight() {
1236 return mSurfaceControl.getHeight();
1237 }
1238
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001239 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01001240 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1241 if (mSurfaceAnimator.isAnimating()) {
1242 pw.print(prefix); pw.println("ContainerAnimator:");
1243 mSurfaceAnimator.dump(pw, prefix + " ");
1244 }
1245 }
chaviwe07246a2017-12-12 16:18:29 -08001246
chaviw2f0567b2018-01-29 16:22:02 -08001247 void updateSurfacePosition() {
chaviwe07246a2017-12-12 16:18:29 -08001248 if (mSurfaceControl == null) {
1249 return;
1250 }
1251
1252 getRelativePosition(mTmpPos);
chaviw3e751af2018-01-11 11:22:39 -08001253 if (mTmpPos.equals(mLastSurfacePosition)) {
1254 return;
1255 }
1256
chaviw2f0567b2018-01-29 16:22:02 -08001257 getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
chaviw3e751af2018-01-11 11:22:39 -08001258 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08001259 }
1260
1261 void getRelativePosition(Point outPos) {
1262 final Rect bounds = getBounds();
1263 outPos.set(bounds.left, bounds.top);
1264 final WindowContainer parent = getParent();
1265 if (parent != null) {
1266 final Rect parentBounds = parent.getBounds();
1267 outPos.offset(-parentBounds.left, -parentBounds.top);
1268 }
1269 }
chaviw2fb06bc2018-01-19 17:09:15 -08001270
1271 Dimmer getDimmer() {
1272 if (mParent == null) {
1273 return null;
1274 }
1275 return mParent.getDimmer();
1276 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001277}