blob: 36e6418a39b52c35156b27809c2ef5374dd969b6 [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;
Jorim Jaggia5e10572017-11-15 14:36:26 +010022import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
23import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
24import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070025import static com.android.server.wm.proto.WindowContainerProto.CONFIGURATION_CONTAINER;
26import static com.android.server.wm.proto.WindowContainerProto.ORIENTATION;
Wale Ogunwaledf262f52017-12-07 18:17:12 -080027import static com.android.server.wm.proto.WindowContainerProto.VISIBLE;
Robert Carrb1579c82017-09-05 14:54:47 -070028import static android.view.SurfaceControl.Transaction;
Jorim Jaggi612bb882017-05-16 17:11:18 +020029
Wale Ogunwaled63594a2016-07-18 07:48:30 -070030import android.annotation.CallSuper;
Andrii Kulian441e4492016-09-29 15:25:00 -070031import android.content.res.Configuration;
chaviwe07246a2017-12-12 16:18:29 -080032import android.graphics.Point;
33import android.graphics.Rect;
Jorim Jaggia5e10572017-11-15 14:36:26 +010034import android.util.Slog;
Robert Carrb1579c82017-09-05 14:54:47 -070035import android.view.MagnificationSpec;
36import android.view.SurfaceControl;
Jorim Jaggia5e10572017-11-15 14:36:26 +010037import android.view.SurfaceControl.Builder;
Robert Carrb1579c82017-09-05 14:54:47 -070038import android.view.SurfaceSession;
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -080039import android.util.Pools;
40
Wale Ogunwale0d5609b2017-09-13 05:55:07 -070041import android.util.proto.ProtoOutputStream;
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();
Jorim Jaggi1e8c4c82018-01-09 15:14:15 +010098 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
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100103 WindowContainer(WindowManagerService service) {
104 mService = service;
105 mPendingTransaction = service.mTransactionFactory.make();
Jorim Jaggi4130a682018-01-09 14:28:44 +0100106 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished,
107 service.mAnimator::addAfterPrepareSurfacesRunnable, service);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100108 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800109
Wale Ogunwale98d62312017-07-12 09:24:56 -0700110 @Override
Wale Ogunwale51362492016-09-08 17:49:17 -0700111 final protected WindowContainer getParent() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700112 return mParent;
113 }
114
Wale Ogunwale98d62312017-07-12 09:24:56 -0700115 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700116 protected int getChildCount() {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700117 return mChildren.size();
118 }
119
120 @Override
Wale Ogunwale61911492017-10-11 08:50:50 -0700121 protected E getChildAt(int index) {
Wale Ogunwale98d62312017-07-12 09:24:56 -0700122 return mChildren.get(index);
123 }
124
chaviwe07246a2017-12-12 16:18:29 -0800125 @Override
126 public void onConfigurationChanged(Configuration newParentConfig) {
127 super.onConfigurationChanged(newParentConfig);
128 updateSurfacePosition(getPendingTransaction());
129 scheduleAnimation();
130 }
131
Jorim Jaggia5e10572017-11-15 14:36:26 +0100132 final protected void setParent(WindowContainer<WindowContainer> parent) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700133 mParent = parent;
Andrii Kulianb94292e2016-10-19 13:30:58 -0700134 // Removing parent usually means that we've detached this entity to destroy it or to attach
135 // to another parent. In both cases we don't need to update the configuration now.
136 if (mParent != null) {
137 // Update full configuration of this container and all its children.
Wale Ogunwale98d62312017-07-12 09:24:56 -0700138 onConfigurationChanged(mParent.getConfiguration());
Andrii Kulianb94292e2016-10-19 13:30:58 -0700139 // Update merged override configuration of this container and all its children.
140 onMergedOverrideConfigurationChanged();
141 }
Andrii Kuliand2765632016-12-12 22:26:34 -0800142
143 onParentSet();
144 }
145
146 /**
147 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
148 * Supposed to be overridden and contain actions that should be executed after parent was set.
149 */
150 void onParentSet() {
Robert Carrb1579c82017-09-05 14:54:47 -0700151 if (mParent == null) {
152 return;
153 }
Jorim Jaggia5e10572017-11-15 14:36:26 +0100154
Robert Carrb1579c82017-09-05 14:54:47 -0700155 if (mSurfaceControl == null) {
156 // If we don't yet have a surface, but we now have a parent, we should
157 // build a surface.
158 mSurfaceControl = makeSurface().build();
Robert Carrf59b8dd2017-10-02 18:58:36 -0700159 getPendingTransaction().show(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700160 } else {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100161 // If we have a surface but a new parent, we just need to perform a reparent. Go through
162 // surface animator such that hierarchy is preserved when animating, i.e.
163 // mSurfaceControl stays attached to the leash and we just reparent the leash to the
164 // new parent.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100165 reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700166 }
167
168 // Either way we need to ask the parent to assign us a Z-order.
169 mParent.assignChildLayers();
170 scheduleAnimation();
Andrii Kulian441e4492016-09-29 15:25:00 -0700171 }
172
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700173 // Temp. holders for a chain of containers we are currently processing.
Jorim Jaggia5e10572017-11-15 14:36:26 +0100174 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
175 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700176
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700177 /**
178 * Adds the input window container has a child of this container in order based on the input
179 * comparator.
180 * @param child The window container to add as a child of this window container.
181 * @param comparator Comparator to use in determining the position the child should be added to.
182 * If null, the child will be added to the top.
183 */
184 @CallSuper
Wale Ogunwaled90546a2016-09-09 23:28:03 -0700185 protected void addChild(E child, Comparator<E> comparator) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700186 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700187 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700188 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700189 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700190 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700191
Andrii Kulianb94292e2016-10-19 13:30:58 -0700192 int positionToAdd = -1;
193 if (comparator != null) {
194 final int count = mChildren.size();
195 for (int i = 0; i < count; i++) {
196 if (comparator.compare(child, mChildren.get(i)) < 0) {
197 positionToAdd = i;
198 break;
199 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700200 }
201 }
202
Andrii Kulianb94292e2016-10-19 13:30:58 -0700203 if (positionToAdd == -1) {
204 mChildren.add(child);
205 } else {
206 mChildren.add(positionToAdd, child);
207 }
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100208 onChildAdded(child);
209
Andrii Kulianb94292e2016-10-19 13:30:58 -0700210 // Set the parent after we've actually added a child in case a subclass depends on this.
211 child.setParent(this);
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700212 }
213
Wale Ogunwalef6192862016-09-10 13:42:30 -0700214 /** Adds the input window container has a child of this container at the input index. */
215 @CallSuper
Wale Ogunwale72919d22016-12-08 18:58:50 -0800216 void addChild(E child, int index) {
Andrii Kulian441e4492016-09-29 15:25:00 -0700217 if (child.getParent() != null) {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700218 throw new IllegalArgumentException("addChild: container=" + child.getName()
Andrii Kulian441e4492016-09-29 15:25:00 -0700219 + " is already a child of container=" + child.getParent().getName()
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700220 + " can't add to container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700221 }
Wale Ogunwalef6192862016-09-10 13:42:30 -0700222 mChildren.add(index, child);
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100223 onChildAdded(child);
224
Andrii Kulianb94292e2016-10-19 13:30:58 -0700225 // Set the parent after we've actually added a child in case a subclass depends on this.
226 child.setParent(this);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700227 }
228
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100229 private void onChildAdded(WindowContainer child) {
230 mTreeWeight += child.mTreeWeight;
231 WindowContainer parent = getParent();
232 while (parent != null) {
233 parent.mTreeWeight += child.mTreeWeight;
234 parent = parent.getParent();
235 }
236 }
237
Wale Ogunwalef6192862016-09-10 13:42:30 -0700238 /**
239 * Removes the input child container from this container which is its parent.
240 *
241 * @return True if the container did contain the input child and it was detached.
242 */
243 @CallSuper
244 void removeChild(E child) {
245 if (mChildren.remove(child)) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100246 onChildRemoved(child);
Andrii Kulian441e4492016-09-29 15:25:00 -0700247 child.setParent(null);
Wale Ogunwalef6192862016-09-10 13:42:30 -0700248 } else {
Wale Ogunwaleba51ca22016-09-23 06:06:54 -0700249 throw new IllegalArgumentException("removeChild: container=" + child.getName()
250 + " is not a child of container=" + getName());
Wale Ogunwalef6192862016-09-10 13:42:30 -0700251 }
252 }
253
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100254 private void onChildRemoved(WindowContainer child) {
255 mTreeWeight -= child.mTreeWeight;
256 WindowContainer parent = getParent();
257 while (parent != null) {
258 parent.mTreeWeight -= child.mTreeWeight;
259 parent = parent.getParent();
260 }
261 }
262
Wale Ogunwale571771c2016-08-26 13:18:50 -0700263 /**
264 * Removes this window container and its children with no regard for what else might be going on
265 * in the system. For example, the container will be removed during animation if this method is
266 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
267 * which allows the system to defer removal until a suitable time.
268 */
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700269 @CallSuper
Wale Ogunwale571771c2016-08-26 13:18:50 -0700270 void removeImmediately() {
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700271 while (!mChildren.isEmpty()) {
Jorim Jaggia5e10572017-11-15 14:36:26 +0100272 final E child = mChildren.peekLast();
Wale Ogunwale571771c2016-08-26 13:18:50 -0700273 child.removeImmediately();
274 // Need to do this after calling remove on the child because the child might try to
275 // remove/detach itself from its parent which will cause an exception if we remove
276 // it before calling remove on the child.
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100277 if (mChildren.remove(child)) {
278 onChildRemoved(child);
279 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700280 }
281
Robert Carrb1579c82017-09-05 14:54:47 -0700282 if (mSurfaceControl != null) {
283 destroyAfterPendingTransaction(mSurfaceControl);
284 mSurfaceControl = null;
285 }
286
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700287 if (mParent != null) {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700288 mParent.removeChild(this);
Wale Ogunwale571771c2016-08-26 13:18:50 -0700289 }
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800290
291 if (mController != null) {
292 setController(null);
293 }
Robert Carrb1579c82017-09-05 14:54:47 -0700294
Wale Ogunwale571771c2016-08-26 13:18:50 -0700295 }
296
297 /**
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100298 * @return The index of this element in the hierarchy tree in prefix order.
299 */
300 int getPrefixOrderIndex() {
301 if (mParent == null) {
302 return 0;
303 }
304 return mParent.getPrefixOrderIndex(this);
305 }
306
307 private int getPrefixOrderIndex(WindowContainer child) {
308 int order = 0;
309 for (int i = 0; i < mChildren.size(); i++) {
310 final WindowContainer childI = mChildren.get(i);
311 if (child == childI) {
312 break;
313 }
314 order += childI.mTreeWeight;
315 }
316 if (mParent != null) {
317 order += mParent.getPrefixOrderIndex(this);
318 }
319
320 // We also need to count ourselves.
321 order++;
322 return order;
323 }
324
325 /**
Wale Ogunwale571771c2016-08-26 13:18:50 -0700326 * Removes this window container and its children taking care not to remove them during a
327 * critical stage in the system. For example, some containers will not be removed during
328 * animation if this method is called.
329 */
330 // TODO: figure-out implementation that works best for this.
331 // E.g. when do we remove from parent list? maybe not...
332 void removeIfPossible() {
333 for (int i = mChildren.size() - 1; i >= 0; --i) {
334 final WindowContainer wc = mChildren.get(i);
335 wc.removeIfPossible();
336 }
337 }
338
Wale Ogunwaled63594a2016-07-18 07:48:30 -0700339 /** Returns true if this window container has the input child. */
340 boolean hasChild(WindowContainer child) {
341 for (int i = mChildren.size() - 1; i >= 0; --i) {
342 final WindowContainer current = mChildren.get(i);
343 if (current == child || current.hasChild(child)) {
344 return true;
345 }
346 }
347 return false;
348 }
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700349
Andrii Kulian441e4492016-09-29 15:25:00 -0700350 /**
Andrii Kuliand2765632016-12-12 22:26:34 -0800351 * Move a child from it's current place in siblings list to the specified position,
352 * with an option to move all its parents to top.
353 * @param position Target position to move the child to.
354 * @param child Child to move to selected position.
355 * @param includingParents Flag indicating whether we need to move the entire branch of the
356 * hierarchy when we're moving a child to {@link #POSITION_TOP} or
357 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions
358 * this flag will do nothing.
359 */
360 @CallSuper
361 void positionChildAt(int position, E child, boolean includingParents) {
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800362
363 if (child.getParent() != this) {
364 throw new IllegalArgumentException("removeChild: container=" + child.getName()
365 + " is not a child of container=" + getName()
366 + " current parent=" + child.getParent());
367 }
368
Andrii Kuliand2765632016-12-12 22:26:34 -0800369 if ((position < 0 && position != POSITION_BOTTOM)
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800370 || (position > mChildren.size() && position != POSITION_TOP)) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800371 throw new IllegalArgumentException("positionAt: invalid position=" + position
372 + ", children number=" + mChildren.size());
373 }
374
Wale Ogunwalec5cc3012017-01-13 13:26:16 -0800375 if (position >= mChildren.size() - 1) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800376 position = POSITION_TOP;
377 } else if (position == 0) {
378 position = POSITION_BOTTOM;
379 }
380
381 switch (position) {
382 case POSITION_TOP:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800383 if (mChildren.peekLast() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800384 mChildren.remove(child);
Jorim Jaggi612bb882017-05-16 17:11:18 +0200385 mChildren.add(child);
Andrii Kuliand2765632016-12-12 22:26:34 -0800386 }
387 if (includingParents && getParent() != null) {
388 getParent().positionChildAt(POSITION_TOP, this /* child */,
389 true /* includingParents */);
390 }
391 break;
392 case POSITION_BOTTOM:
Wale Ogunwalee1fe7fa22016-12-15 18:27:00 -0800393 if (mChildren.peekFirst() != child) {
Andrii Kuliand2765632016-12-12 22:26:34 -0800394 mChildren.remove(child);
395 mChildren.addFirst(child);
396 }
397 if (includingParents && getParent() != null) {
398 getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
399 true /* includingParents */);
400 }
401 break;
402 default:
403 mChildren.remove(child);
404 mChildren.add(position, child);
405 }
406 }
407
408 /**
Andrii Kulian441e4492016-09-29 15:25:00 -0700409 * Update override configuration and recalculate full config.
410 * @see #mOverrideConfiguration
411 * @see #mFullConfiguration
412 */
Wale Ogunwale98d62312017-07-12 09:24:56 -0700413 @Override
Bryce Leef3c6a472017-11-14 14:53:06 -0800414 public void onOverrideConfigurationChanged(Configuration overrideConfiguration) {
415 // We must diff before the configuration is applied so that we can capture the change
416 // against the existing bounds.
417 final int diff = diffOverrideBounds(overrideConfiguration.windowConfiguration.getBounds());
Wale Ogunwale98d62312017-07-12 09:24:56 -0700418 super.onOverrideConfigurationChanged(overrideConfiguration);
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700419 if (mParent != null) {
420 mParent.onDescendantOverrideConfigurationChanged();
421 }
Bryce Leef3c6a472017-11-14 14:53:06 -0800422
423 if (diff == BOUNDS_CHANGE_NONE) {
424 return;
425 }
426
427 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
428 onResize();
429 } else {
430 onMovedByResize();
431 }
Wale Ogunwale55ddf8f2017-03-20 08:56:38 -0700432 }
433
434 /**
435 * Notify that a descendant's overrideConfiguration has changed.
436 */
437 void onDescendantOverrideConfigurationChanged() {
438 if (mParent != null) {
439 mParent.onDescendantOverrideConfigurationChanged();
440 }
Andrii Kulian441e4492016-09-29 15:25:00 -0700441 }
442
443 /**
Wale Ogunwale02319a62016-09-26 15:21:22 -0700444 * Notify that the display this container is on has changed.
445 * @param dc The new display this container is on.
446 */
447 void onDisplayChanged(DisplayContent dc) {
448 for (int i = mChildren.size() - 1; i >= 0; --i) {
449 final WindowContainer child = mChildren.get(i);
450 child.onDisplayChanged(dc);
451 }
452 }
453
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700454 void setWaitingForDrawnIfResizingChanged() {
455 for (int i = mChildren.size() - 1; i >= 0; --i) {
456 final WindowContainer wc = mChildren.get(i);
457 wc.setWaitingForDrawnIfResizingChanged();
458 }
459 }
460
461 void onResize() {
462 for (int i = mChildren.size() - 1; i >= 0; --i) {
463 final WindowContainer wc = mChildren.get(i);
464 wc.onResize();
465 }
466 }
467
468 void onMovedByResize() {
469 for (int i = mChildren.size() - 1; i >= 0; --i) {
470 final WindowContainer wc = mChildren.get(i);
471 wc.onMovedByResize();
472 }
473 }
474
475 void resetDragResizingChangeReported() {
476 for (int i = mChildren.size() - 1; i >= 0; --i) {
477 final WindowContainer wc = mChildren.get(i);
478 wc.resetDragResizingChangeReported();
479 }
480 }
481
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700482 void forceWindowsScaleableInTransaction(boolean force) {
483 for (int i = mChildren.size() - 1; i >= 0; --i) {
484 final WindowContainer wc = mChildren.get(i);
485 wc.forceWindowsScaleableInTransaction(force);
486 }
487 }
488
Jorim Jaggia5e10572017-11-15 14:36:26 +0100489 /**
490 * @return Whether our own container is running an animation or any child, no matter how deep in
491 * the hierarchy, is animating.
492 */
493 boolean isSelfOrChildAnimating() {
494 if (isSelfAnimating()) {
495 return true;
496 }
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700497 for (int j = mChildren.size() - 1; j >= 0; j--) {
498 final WindowContainer wc = mChildren.get(j);
Jorim Jaggia5e10572017-11-15 14:36:26 +0100499 if (wc.isSelfOrChildAnimating()) {
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700500 return true;
501 }
502 }
503 return false;
504 }
505
Jorim Jaggia5e10572017-11-15 14:36:26 +0100506 /**
507 * @return Whether our own container is running an animation or our parent is animating. This
508 * doesn't consider whether children are animating.
509 */
510 boolean isAnimating() {
511
512 // We are animating if we ourselves are animating or if our parent is animating.
513 return isSelfAnimating() || mParent != null && mParent.isAnimating();
514 }
515
516 /**
Jorim Jaggif5f9e122017-10-24 18:21:09 +0200517 * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
518 * that is {@link #isSelfAnimating}; {@code false} otherwise.
519 */
520 boolean isAppAnimating() {
521 for (int j = mChildren.size() - 1; j >= 0; j--) {
522 final WindowContainer wc = mChildren.get(j);
523 if (wc.isAppAnimating()) {
524 return true;
525 }
526 }
527 return false;
528 }
529
530 /**
Jorim Jaggia5e10572017-11-15 14:36:26 +0100531 * @return Whether our own container running an animation at the moment.
532 */
533 boolean isSelfAnimating() {
534 return mSurfaceAnimator.isAnimating();
535 }
536
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700537 void sendAppVisibilityToClients() {
538 for (int i = mChildren.size() - 1; i >= 0; --i) {
539 final WindowContainer wc = mChildren.get(i);
540 wc.sendAppVisibilityToClients();
541 }
542 }
543
Wale Ogunwale44f21802016-09-02 12:49:48 -0700544 /**
545 * Returns true if the container or one of its children as some content it can display or wants
546 * to display (e.g. app views or saved surface).
547 *
548 * NOTE: While this method will return true if the there is some content to display, it doesn't
549 * mean the container is visible. Use {@link #isVisible()} to determine if the container is
550 * visible.
551 */
552 boolean hasContentToDisplay() {
553 for (int i = mChildren.size() - 1; i >= 0; --i) {
554 final WindowContainer wc = mChildren.get(i);
555 if (wc.hasContentToDisplay()) {
556 return true;
557 }
558 }
559 return false;
560 }
561
562 /**
563 * Returns true if the container or one of its children is considered visible from the
564 * WindowManager perspective which usually means valid surface and some other internal state
565 * are true.
566 *
567 * NOTE: While this method will return true if the surface is visible, it doesn't mean the
568 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
569 * the container has any content to display.
570 */
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700571 boolean isVisible() {
Wale Ogunwalef6192862016-09-10 13:42:30 -0700572 // TODO: Will this be more correct if it checks the visibility of its parents?
573 // It depends...For example, Tasks and Stacks are only visible if there children are visible
574 // but, WindowState are not visible if there parent are not visible. Maybe have the
Andrii Kuliancd5dcb8b2017-01-03 17:09:45 -0800575 // container specify which direction to traverse for visibility?
Wale Ogunwaled1c37912016-08-16 03:19:39 -0700576 for (int i = mChildren.size() - 1; i >= 0; --i) {
577 final WindowContainer wc = mChildren.get(i);
578 if (wc.isVisible()) {
579 return true;
580 }
581 }
582 return false;
583 }
584
Bryce Lee00d586d2017-07-28 20:48:43 -0700585 /**
Robert Carrb1579c82017-09-05 14:54:47 -0700586 * @return Whether this child is on top of the window hierarchy.
Bryce Lee00d586d2017-07-28 20:48:43 -0700587 */
588 boolean isOnTop() {
589 return getParent().getTopChild() == this && getParent().isOnTop();
590 }
591
Jorim Jaggi10abe2f2017-01-03 16:44:46 +0100592 /** Returns the top child container. */
593 E getTopChild() {
594 return mChildren.peekLast();
Wale Ogunwale9bc47732016-08-10 14:44:22 -0700595 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700596
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700597 /** Returns true if there is still a removal being deferred */
598 boolean checkCompleteDeferredRemoval() {
599 boolean stillDeferringRemoval = false;
600
601 for (int i = mChildren.size() - 1; i >= 0; --i) {
602 final WindowContainer wc = mChildren.get(i);
603 stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
604 }
605
606 return stillDeferringRemoval;
607 }
608
609 /** Checks if all windows in an app are all drawn and shows them if needed. */
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700610 void checkAppWindowsReadyToShow() {
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700611 for (int i = mChildren.size() - 1; i >= 0; --i) {
612 final WindowContainer wc = mChildren.get(i);
Wale Ogunwaleb0f3b832016-10-17 10:13:07 -0700613 wc.checkAppWindowsReadyToShow();
Wale Ogunwale3f4433d2016-08-18 20:42:42 -0700614 }
615 }
616
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700617 void onAppTransitionDone() {
618 for (int i = mChildren.size() - 1; i >= 0; --i) {
619 final WindowContainer wc = mChildren.get(i);
620 wc.onAppTransitionDone();
621 }
622 }
623
Wale Ogunwale51362492016-09-08 17:49:17 -0700624 void setOrientation(int orientation) {
625 mOrientation = orientation;
626 }
627
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700628 int getOrientation() {
629 return getOrientation(mOrientation);
630 }
631
Wale Ogunwale51362492016-09-08 17:49:17 -0700632 /**
633 * Returns the specified orientation for this window container or one of its children is there
634 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
635 * specification is set.
636 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
637 * specification...
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700638 *
639 * @param candidate The current orientation candidate that will be returned if we don't find a
640 * better match.
641 * @return The orientation as specified by this branch or the window hierarchy.
Wale Ogunwale51362492016-09-08 17:49:17 -0700642 */
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700643 int getOrientation(int candidate) {
Bryce Leea163b762017-01-24 11:05:01 -0800644 if (!fillsParent()) {
645 // Ignore containers that don't completely fill their parents.
Wale Ogunwale51362492016-09-08 17:49:17 -0700646 return SCREEN_ORIENTATION_UNSET;
647 }
648
Bryce Leea163b762017-01-24 11:05:01 -0800649 // The container fills its parent so we can use it orientation if it has one
650 // specified; otherwise we prefer to use the orientation of its topmost child that has one
Wale Ogunwale51362492016-09-08 17:49:17 -0700651 // specified and fall back on this container's unset or unspecified value as a candidate
652 // if none of the children have a better candidate for the orientation.
653 if (mOrientation != SCREEN_ORIENTATION_UNSET
654 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
655 return mOrientation;
656 }
Wale Ogunwale51362492016-09-08 17:49:17 -0700657
658 for (int i = mChildren.size() - 1; i >= 0; --i) {
659 final WindowContainer wc = mChildren.get(i);
660
Wale Ogunwale5e5a68d2017-03-24 17:36:38 -0700661 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
662 // SCREEN_ORIENTATION_UNSPECIFIED?
663 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
664 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
Wale Ogunwale51362492016-09-08 17:49:17 -0700665 if (orientation == SCREEN_ORIENTATION_BEHIND) {
666 // container wants us to use the orientation of the container behind it. See if we
667 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
668 // look behind this container.
669 candidate = orientation;
670 continue;
671 }
672
673 if (orientation == SCREEN_ORIENTATION_UNSET) {
674 continue;
675 }
676
677 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
678 // Use the orientation if the container fills its parent or requested an explicit
679 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
680 return orientation;
681 }
682 }
683
684 return candidate;
685 }
686
687 /**
688 * Returns true if this container is opaque and fills all the space made available by its parent
689 * container.
690 *
691 * NOTE: It is possible for this container to occupy more space than the parent has (or less),
692 * this is just a signal from the client to window manager stating its intent, but not what it
693 * actually does.
694 */
695 boolean fillsParent() {
696 return false;
697 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700698
Wale Ogunwale6213caa2016-12-02 16:47:15 +0000699 // TODO: Users would have their own window containers under the display container?
700 void switchUser() {
701 for (int i = mChildren.size() - 1; i >= 0; --i) {
702 mChildren.get(i).switchUser();
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700703 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700704 }
705
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800706 /**
707 * For all windows at or below this container call the callback.
708 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and
709 * stops the search if {@link ToBooleanFunction#apply} returns true.
710 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
711 * z-order, else from bottom-to-top.
712 * @return True if the search ended before we reached the end of the hierarchy due to
Wale Ogunwale1e129a42016-11-21 13:03:47 -0800713 * {@link ToBooleanFunction#apply} returning true.
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800714 */
715 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700716 if (traverseTopToBottom) {
717 for (int i = mChildren.size() - 1; i >= 0; --i) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800718 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
719 return true;
720 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700721 }
722 } else {
723 final int count = mChildren.size();
724 for (int i = 0; i < count; i++) {
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800725 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
726 return true;
727 }
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700728 }
729 }
Wale Ogunwalef4ebe2e2016-11-09 13:24:43 -0800730 return false;
731 }
732
733 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800734 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
735 forAllWindows(wrapper, traverseTopToBottom);
736 wrapper.release();
Wale Ogunwaleb783fd82016-11-04 09:51:54 -0700737 }
738
Jorim Jaggi51304d72017-05-17 17:25:32 +0200739 /**
740 * For all tasks at or below this container call the callback.
741 *
742 * @param callback Callback to be called for every task.
743 */
744 void forAllTasks(Consumer<Task> callback) {
745 for (int i = mChildren.size() - 1; i >= 0; --i) {
746 mChildren.get(i).forAllTasks(callback);
747 }
748 }
749
Wale Ogunwaled1880962016-11-08 10:31:59 -0800750 WindowState getWindow(Predicate<WindowState> callback) {
751 for (int i = mChildren.size() - 1; i >= 0; --i) {
752 final WindowState w = mChildren.get(i).getWindow(callback);
753 if (w != null) {
754 return w;
755 }
756 }
757
758 return null;
759 }
760
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700761 /**
Wale Ogunwalef6192862016-09-10 13:42:30 -0700762 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
763 * the input container in terms of z-order.
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700764 */
765 @Override
766 public int compareTo(WindowContainer other) {
767 if (this == other) {
768 return 0;
769 }
770
771 if (mParent != null && mParent == other.mParent) {
Jorim Jaggi612bb882017-05-16 17:11:18 +0200772 final WindowList<WindowContainer> list = mParent.mChildren;
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700773 return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
774 }
775
776 final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
777 final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200778 try {
779 getParents(thisParentChain);
780 other.getParents(otherParentChain);
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700781
Jorim Jaggi4448e1e2017-05-16 22:26:02 +0200782 // Find the common ancestor of both containers.
783 WindowContainer commonAncestor = null;
784 WindowContainer thisTop = thisParentChain.peekLast();
785 WindowContainer otherTop = otherParentChain.peekLast();
786 while (thisTop != null && otherTop != null && thisTop == otherTop) {
787 commonAncestor = thisParentChain.removeLast();
788 otherParentChain.removeLast();
789 thisTop = thisParentChain.peekLast();
790 otherTop = otherParentChain.peekLast();
791 }
792
793 // Containers don't belong to the same hierarchy???
794 if (commonAncestor == null) {
795 throw new IllegalArgumentException("No in the same hierarchy this="
796 + thisParentChain + " other=" + otherParentChain);
797 }
798
799 // Children are always considered greater than their parents, so if one of the containers
800 // we are comparing it the parent of the other then whichever is the child is greater.
801 if (commonAncestor == this) {
802 return -1;
803 } else if (commonAncestor == other) {
804 return 1;
805 }
806
807 // The position of the first non-common ancestor in the common ancestor list determines
808 // which is greater the which.
809 final WindowList<WindowContainer> list = commonAncestor.mChildren;
810 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
811 ? 1 : -1;
812 } finally {
813 mTmpChain1.clear();
814 mTmpChain2.clear();
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700815 }
Wale Ogunwale63d4ecc2016-09-08 18:48:26 -0700816 }
817
818 private void getParents(LinkedList<WindowContainer> parents) {
819 parents.clear();
820 WindowContainer current = this;
821 do {
822 parents.addLast(current);
823 current = current.mParent;
824 } while (current != null);
825 }
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700826
Wale Ogunwale26c0dfe2016-12-14 14:42:30 -0800827 WindowContainerController getController() {
828 return mController;
829 }
830
831 void setController(WindowContainerController controller) {
832 if (mController != null && controller != null) {
833 throw new IllegalArgumentException("Can't set controller=" + mController
834 + " for container=" + this + " Already set to=" + mController);
835 }
836 if (controller != null) {
837 controller.setContainer(this);
838 } else if (mController != null) {
839 mController.setContainer(null);
840 }
841 mController = controller;
842 }
843
Robert Carrb1579c82017-09-05 14:54:47 -0700844 SurfaceControl.Builder makeSurface() {
845 final WindowContainer p = getParent();
846 return p.makeChildSurface(this);
847 }
848
Robert Carrf59b8dd2017-10-02 18:58:36 -0700849 /**
850 * @param child The WindowContainer this child surface is for, or null if the Surface
851 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
852 */
Robert Carrb1579c82017-09-05 14:54:47 -0700853 SurfaceControl.Builder makeChildSurface(WindowContainer child) {
854 final WindowContainer p = getParent();
855 // Give the parent a chance to set properties. In hierarchy v1 we rely
856 // on this to set full-screen dimensions on all our Surface-less Layers.
Robert Carree4d4b92017-11-22 12:21:46 -0800857 return p.makeChildSurface(child)
858 .setParent(mSurfaceControl);
Robert Carrb1579c82017-09-05 14:54:47 -0700859 }
860
Jorim Jaggia5e10572017-11-15 14:36:26 +0100861 @Override
862 public SurfaceControl getParentSurfaceControl() {
863 final WindowContainer parent = getParent();
864 if (parent == null) {
865 return null;
866 }
867 return parent.getSurfaceControl();
868 }
869
Robert Carrb1579c82017-09-05 14:54:47 -0700870 /**
871 * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
872 */
873 boolean shouldMagnify() {
874 for (int i = 0; i < mChildren.size(); i++) {
875 if (!mChildren.get(i).shouldMagnify()) {
876 return false;
877 }
878 }
879 return true;
880 }
881
882 SurfaceSession getSession() {
883 if (getParent() != null) {
884 return getParent().getSession();
885 }
886 return null;
887 }
888
889 void assignLayer(Transaction t, int layer) {
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100890 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
891 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100892 setLayer(t, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100893 mLastLayer = layer;
894 mLastRelativeToLayer = null;
895 }
896 }
897
898 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
899 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
900 if (mSurfaceControl != null && changed) {
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100901 setRelativeLayer(t, relativeTo, layer);
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100902 mLastLayer = layer;
903 mLastRelativeToLayer = relativeTo;
Robert Carrb1579c82017-09-05 14:54:47 -0700904 }
905 }
906
Jorim Jaggi619c9f72017-12-19 18:04:29 +0100907 protected void setLayer(Transaction t, int layer) {
908
909 // Route through surface animator to accommodate that our surface control might be
910 // attached to the leash, and leash is attached to parent container.
911 mSurfaceAnimator.setLayer(t, layer);
912 }
913
914 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
915
916 // Route through surface animator to accommodate that our surface control might be
917 // attached to the leash, and leash is attached to parent container.
918 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
919 }
920
921 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
922 mSurfaceAnimator.reparent(t, newParent);
923 }
924
Robert Carrb1579c82017-09-05 14:54:47 -0700925 void assignChildLayers(Transaction t) {
926 int layer = 0;
Robert Carrb1579c82017-09-05 14:54:47 -0700927
928 // We use two passes as a way to promote children which
929 // need Z-boosting to the end of the list.
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100930 for (int j = 0; j < mChildren.size(); ++j) {
931 final WindowContainer wc = mChildren.get(j);
932 wc.assignChildLayers(t);
933 if (!wc.needsZBoost()) {
934 wc.assignLayer(t, layer++);
Robert Carrb1579c82017-09-05 14:54:47 -0700935 }
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100936 }
937 for (int j = 0; j < mChildren.size(); ++j) {
938 final WindowContainer wc = mChildren.get(j);
939 if (wc.needsZBoost()) {
940 wc.assignLayer(t, layer++);
941 }
Robert Carrb1579c82017-09-05 14:54:47 -0700942 }
943 }
944
945 void assignChildLayers() {
Robert Carrf59b8dd2017-10-02 18:58:36 -0700946 assignChildLayers(getPendingTransaction());
Jorim Jaggiffe128d2017-11-30 13:54:36 +0100947 scheduleAnimation();
Robert Carrb1579c82017-09-05 14:54:47 -0700948 }
949
950 boolean needsZBoost() {
951 for (int i = 0; i < mChildren.size(); i++) {
952 if (mChildren.get(i).needsZBoost()) {
953 return true;
954 }
955 }
956 return false;
957 }
958
Wale Ogunwale9adfe572016-09-08 20:43:58 -0700959 /**
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700960 * Write to a protocol buffer output stream. Protocol buffer message definition is at
961 * {@link com.android.server.wm.proto.WindowContainerProto}.
962 *
Adrian Roos4921ccf2017-09-28 16:54:06 +0200963 * @param proto Stream to write the WindowContainer object to.
964 * @param fieldId Field Id of the WindowContainer as defined in the parent message.
965 * @param trim If true, reduce the amount of data written.
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700966 * @hide
967 */
968 @CallSuper
969 @Override
Adrian Roos4921ccf2017-09-28 16:54:06 +0200970 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) {
971 final long token = proto.start(fieldId);
972 super.writeToProto(proto, CONFIGURATION_CONTAINER, trim);
973 proto.write(ORIENTATION, mOrientation);
Wale Ogunwaledf262f52017-12-07 18:17:12 -0800974 proto.write(VISIBLE, isVisible());
Adrian Roos4921ccf2017-09-28 16:54:06 +0200975 proto.end(token);
Wale Ogunwale0d5609b2017-09-13 05:55:07 -0700976 }
977
Wale Ogunwaleee41d4a2016-11-21 08:41:10 -0800978 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
979 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
980 if (wrapper == null) {
981 wrapper = new ForAllWindowsConsumerWrapper();
982 }
983 wrapper.setConsumer(consumer);
984 return wrapper;
985 }
986
987 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
988
989 private Consumer<WindowState> mConsumer;
990
991 void setConsumer(Consumer<WindowState> consumer) {
992 mConsumer = consumer;
993 }
994
995 @Override
996 public boolean apply(WindowState w) {
997 mConsumer.accept(w);
998 return false;
999 }
1000
1001 void release() {
1002 mConsumer = null;
1003 mConsumerWrapperPool.release(this);
1004 }
1005 }
Robert Carrb1579c82017-09-05 14:54:47 -07001006
1007 // TODO(b/68336570): Should this really be on WindowContainer since it
1008 // can only be used on the top-level nodes that aren't animated?
1009 // (otherwise we would be fighting other callers of setMatrix).
1010 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1011 if (shouldMagnify()) {
1012 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1013 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
1014 } else {
1015 for (int i = 0; i < mChildren.size(); i++) {
1016 mChildren.get(i).applyMagnificationSpec(t, spec);
1017 }
1018 }
1019 }
1020
1021 /**
1022 * TODO: Once we totally eliminate global transaction we will pass transaction in here
1023 * rather than merging to global.
1024 */
1025 void prepareSurfaces() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001026 SurfaceControl.mergeToGlobalTransaction(getPendingTransaction());
Robert Carrb1579c82017-09-05 14:54:47 -07001027 for (int i = 0; i < mChildren.size(); i++) {
1028 mChildren.get(i).prepareSurfaces();
1029 }
1030 }
1031
1032 /**
1033 * Trigger a call to prepareSurfaces from the animation thread, such that
1034 * mPendingTransaction will be applied.
1035 */
1036 void scheduleAnimation() {
1037 if (mParent != null) {
1038 mParent.scheduleAnimation();
1039 }
1040 }
1041
Jorim Jaggia5e10572017-11-15 14:36:26 +01001042 @Override
1043 public SurfaceControl getSurfaceControl() {
Robert Carrb1579c82017-09-05 14:54:47 -07001044 return mSurfaceControl;
1045 }
1046
1047 /**
1048 * Destroy a given surface after executing mPendingTransaction. This is
1049 * largely a workaround for destroy not being part of transactions
1050 * rather than an intentional design, so please take care when
1051 * expanding use.
1052 */
Jorim Jaggia5e10572017-11-15 14:36:26 +01001053 @Override
1054 public void destroyAfterPendingTransaction(SurfaceControl surface) {
Robert Carrb1579c82017-09-05 14:54:47 -07001055 if (mParent != null) {
1056 mParent.destroyAfterPendingTransaction(surface);
1057 }
1058 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001059
1060 @Override
1061 public Transaction getPendingTransaction() {
Robert Carrf59b8dd2017-10-02 18:58:36 -07001062 return mPendingTransaction;
1063 }
Jorim Jaggia5e10572017-11-15 14:36:26 +01001064
1065 /**
1066 * Starts an animation on the container.
1067 *
1068 * @param anim The animation to run.
1069 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1070 * some point but the meaning is too weird to work for all containers.
1071 */
1072 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1073 if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1074
1075 // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1076 // the moment this doesn't work for all animatable window containers.
1077 mSurfaceAnimator.startAnimation(t, anim, hidden);
1078 }
1079
Jorim Jaggi980c9de2017-11-17 01:41:37 +01001080 void transferAnimation(WindowContainer from) {
1081 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1082 }
1083
Jorim Jaggia5e10572017-11-15 14:36:26 +01001084 void cancelAnimation() {
1085 mSurfaceAnimator.cancelAnimation();
1086 }
1087
1088 @Override
1089 public Builder makeAnimationLeash() {
1090 return makeSurface();
1091 }
1092
Jorim Jaggi596a1992017-12-29 14:48:02 +01001093 @Override
1094 public SurfaceControl getAnimationLeashParent() {
1095 return getParentSurfaceControl();
1096 }
1097
chaviw23ee71c2017-12-18 11:29:41 -08001098 /**
1099 * @return The layer on which all app animations are happening.
1100 */
1101 SurfaceControl getAppAnimationLayer() {
1102 final WindowContainer parent = getParent();
1103 if (parent != null) {
1104 return parent.getAppAnimationLayer();
1105 }
1106 return null;
1107 }
1108
Jorim Jaggia5e10572017-11-15 14:36:26 +01001109 @Override
1110 public void commitPendingTransaction() {
1111 scheduleAnimation();
1112 }
1113
1114 private void reassignLayer(Transaction t) {
1115 final WindowContainer parent = getParent();
1116 if (parent != null) {
1117 parent.assignChildLayers(t);
1118 }
1119 }
1120
1121 @Override
1122 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
1123 reassignLayer(t);
1124 }
1125
1126 @Override
1127 public void onAnimationLeashDestroyed(Transaction t) {
1128 reassignLayer(t);
1129 }
1130
1131 /**
1132 * Called when an animation has finished running.
1133 */
1134 protected void onAnimationFinished() {
1135 }
1136
1137 /**
1138 * @return The currently running animation, if any, or {@code null} otherwise.
1139 */
1140 AnimationAdapter getAnimation() {
1141 return mSurfaceAnimator.getAnimation();
1142 }
1143
1144 /**
1145 * @see SurfaceAnimator#startDelayingAnimationStart
1146 */
1147 void startDelayingAnimationStart() {
1148 mSurfaceAnimator.startDelayingAnimationStart();
1149 }
1150
1151 /**
1152 * @see SurfaceAnimator#endDelayingAnimationStart
1153 */
1154 void endDelayingAnimationStart() {
1155 mSurfaceAnimator.endDelayingAnimationStart();
1156 }
1157
1158 @Override
1159 public int getSurfaceWidth() {
1160 return mSurfaceControl.getWidth();
1161 }
1162
1163 @Override
1164 public int getSurfaceHeight() {
1165 return mSurfaceControl.getHeight();
1166 }
1167
Jorim Jaggif5f9e122017-10-24 18:21:09 +02001168 @CallSuper
Jorim Jaggia5e10572017-11-15 14:36:26 +01001169 void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1170 if (mSurfaceAnimator.isAnimating()) {
1171 pw.print(prefix); pw.println("ContainerAnimator:");
1172 mSurfaceAnimator.dump(pw, prefix + " ");
1173 }
1174 }
chaviwe07246a2017-12-12 16:18:29 -08001175
1176 void updateSurfacePosition(SurfaceControl.Transaction transaction) {
1177 if (mSurfaceControl == null) {
1178 return;
1179 }
1180
1181 getRelativePosition(mTmpPos);
Jorim Jaggi1e8c4c82018-01-09 15:14:15 +01001182 if (mTmpPos.equals(mLastSurfacePosition)) {
1183 return;
1184 }
1185
chaviwe07246a2017-12-12 16:18:29 -08001186 transaction.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
Jorim Jaggi1e8c4c82018-01-09 15:14:15 +01001187 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
chaviwe07246a2017-12-12 16:18:29 -08001188
1189 for (int i = mChildren.size() - 1; i >= 0; i--) {
1190 mChildren.get(i).updateSurfacePosition(transaction);
1191 }
1192 }
1193
1194 void getRelativePosition(Point outPos) {
1195 final Rect bounds = getBounds();
1196 outPos.set(bounds.left, bounds.top);
1197 final WindowContainer parent = getParent();
1198 if (parent != null) {
1199 final Rect parentBounds = parent.getBounds();
1200 outPos.offset(-parentBounds.left, -parentBounds.top);
1201 }
1202 }
Wale Ogunwaled63594a2016-07-18 07:48:30 -07001203}