1 /*
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 
17 package com.android.server.wm;
18 
19 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_BEHIND;
20 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
21 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
22 import static android.view.SurfaceControl.Transaction;
23 
24 import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER;
25 import static com.android.server.wm.WindowContainerProto.ORIENTATION;
26 import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR;
27 import static com.android.server.wm.WindowContainerProto.VISIBLE;
28 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM;
29 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
30 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
31 
32 import android.annotation.CallSuper;
33 import android.annotation.IntDef;
34 import android.annotation.Nullable;
35 import android.app.WindowConfiguration;
36 import android.content.res.Configuration;
37 import android.graphics.Point;
38 import android.graphics.Rect;
39 import android.os.IBinder;
40 import android.util.Pools;
41 import android.util.Slog;
42 import android.util.proto.ProtoOutputStream;
43 import android.view.MagnificationSpec;
44 import android.view.SurfaceControl;
45 import android.view.SurfaceControl.Builder;
46 import android.view.SurfaceSession;
47 
48 import com.android.internal.annotations.VisibleForTesting;
49 import com.android.internal.util.ToBooleanFunction;
50 import com.android.server.wm.SurfaceAnimator.Animatable;
51 
52 import java.io.PrintWriter;
53 import java.util.Comparator;
54 import java.util.LinkedList;
55 import java.util.function.Consumer;
56 import java.util.function.Predicate;
57 
58 /**
59  * Defines common functionality for classes that can hold windows directly or through their
60  * children in a hierarchy form.
61  * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime
62  * changes are made to this class.
63  */
64 class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E>
65         implements Comparable<WindowContainer>, Animatable {
66 
67     private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM;
68 
69     /** Animation layer that happens above all animating {@link TaskStack}s. */
70     static final int ANIMATION_LAYER_STANDARD = 0;
71 
72     /** Animation layer that happens above all {@link TaskStack}s. */
73     static final int ANIMATION_LAYER_BOOSTED = 1;
74 
75     /**
76      * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME}
77      * activities and all activities that are being controlled by the recents animation. This
78      * layer is generally below all {@link TaskStack}s.
79      */
80     static final int ANIMATION_LAYER_HOME = 2;
81 
82     @IntDef(prefix = { "ANIMATION_LAYER_" }, value = {
83             ANIMATION_LAYER_STANDARD,
84             ANIMATION_LAYER_BOOSTED,
85             ANIMATION_LAYER_HOME,
86     })
87     @interface AnimationLayer {}
88 
89     static final int POSITION_TOP = Integer.MAX_VALUE;
90     static final int POSITION_BOTTOM = Integer.MIN_VALUE;
91 
92     /**
93      * The parent of this window container.
94      * For removing or setting new parent {@link #setParent} should be used, because it also
95      * performs configuration updates based on new parent's settings.
96      */
97     private WindowContainer<WindowContainer> mParent = null;
98 
99     // List of children for this window container. List is in z-order as the children appear on
100     // screen with the top-most window container at the tail of the list.
101     protected final WindowList<E> mChildren = new WindowList<E>();
102 
103     // The specified orientation for this window container.
104     protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED;
105 
106     private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool =
107             new Pools.SynchronizedPool<>(3);
108 
109     // The owner/creator for this container. No controller if null.
110     WindowContainerController mController;
111 
112     // The display this window container is on.
113     protected DisplayContent mDisplayContent;
114 
115     protected SurfaceControl mSurfaceControl;
116     private int mLastLayer = 0;
117     private SurfaceControl mLastRelativeToLayer = null;
118 
119     // TODO(b/132320879): Remove this from WindowContainers except DisplayContent.
120     private final Transaction mPendingTransaction;
121 
122     /**
123      * Applied as part of the animation pass in "prepareSurfaces".
124      */
125     protected final SurfaceAnimator mSurfaceAnimator;
126     protected final WindowManagerService mWmService;
127 
128     private final Point mTmpPos = new Point();
129     protected final Point mLastSurfacePosition = new Point();
130 
131     /** Total number of elements in this subtree, including our own hierarchy element. */
132     private int mTreeWeight = 1;
133 
134     /**
135      * Indicates whether we are animating and have committed the transaction to reparent our
136      * surface to the animation leash
137      */
138     private boolean mCommittedReparentToAnimationLeash;
139 
140     private MagnificationSpec mLastMagnificationSpec;
141 
WindowContainer(WindowManagerService wms)142     WindowContainer(WindowManagerService wms) {
143         mWmService = wms;
144         mPendingTransaction = wms.mTransactionFactory.make();
145         mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
146     }
147 
148     @Override
getParent()149     final protected WindowContainer getParent() {
150         return mParent;
151     }
152 
153     @Override
getChildCount()154     protected int getChildCount() {
155         return mChildren.size();
156     }
157 
158     @Override
getChildAt(int index)159     protected E getChildAt(int index) {
160         return mChildren.get(index);
161     }
162 
163     @Override
onConfigurationChanged(Configuration newParentConfig)164     public void onConfigurationChanged(Configuration newParentConfig) {
165         super.onConfigurationChanged(newParentConfig);
166         updateSurfacePosition();
167         scheduleAnimation();
168     }
169 
setParent(WindowContainer<WindowContainer> parent)170     final protected void setParent(WindowContainer<WindowContainer> parent) {
171         mParent = parent;
172         onParentChanged();
173     }
174 
175     /**
176      * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called.
177      * Supposed to be overridden and contain actions that should be executed after parent was set.
178      */
179     @Override
onParentChanged()180     void onParentChanged() {
181         super.onParentChanged();
182         if (mParent == null) {
183             return;
184         }
185 
186         if (mSurfaceControl == null) {
187             // If we don't yet have a surface, but we now have a parent, we should
188             // build a surface.
189             mSurfaceControl = makeSurface().build();
190             getPendingTransaction().show(mSurfaceControl);
191             updateSurfacePosition();
192         } else {
193             // If we have a surface but a new parent, we just need to perform a reparent. Go through
194             // surface animator such that hierarchy is preserved when animating, i.e.
195             // mSurfaceControl stays attached to the leash and we just reparent the leash to the
196             // new parent.
197             reparentSurfaceControl(getPendingTransaction(), mParent.mSurfaceControl);
198         }
199 
200         // Either way we need to ask the parent to assign us a Z-order.
201         mParent.assignChildLayers();
202         scheduleAnimation();
203     }
204 
205     // Temp. holders for a chain of containers we are currently processing.
206     private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>();
207     private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>();
208 
209     /**
210      * Adds the input window container has a child of this container in order based on the input
211      * comparator.
212      * @param child The window container to add as a child of this window container.
213      * @param comparator Comparator to use in determining the position the child should be added to.
214      *                   If null, the child will be added to the top.
215      */
216     @CallSuper
addChild(E child, Comparator<E> comparator)217     protected void addChild(E child, Comparator<E> comparator) {
218         if (child.getParent() != null) {
219             throw new IllegalArgumentException("addChild: container=" + child.getName()
220                     + " is already a child of container=" + child.getParent().getName()
221                     + " can't add to container=" + getName());
222         }
223 
224         int positionToAdd = -1;
225         if (comparator != null) {
226             final int count = mChildren.size();
227             for (int i = 0; i < count; i++) {
228                 if (comparator.compare(child, mChildren.get(i)) < 0) {
229                     positionToAdd = i;
230                     break;
231                 }
232             }
233         }
234 
235         if (positionToAdd == -1) {
236             mChildren.add(child);
237         } else {
238             mChildren.add(positionToAdd, child);
239         }
240         onChildAdded(child);
241 
242         // Set the parent after we've actually added a child in case a subclass depends on this.
243         child.setParent(this);
244     }
245 
246     /** Adds the input window container has a child of this container at the input index. */
247     @CallSuper
addChild(E child, int index)248     void addChild(E child, int index) {
249         if (child.getParent() != null) {
250             throw new IllegalArgumentException("addChild: container=" + child.getName()
251                     + " is already a child of container=" + child.getParent().getName()
252                     + " can't add to container=" + getName());
253         }
254 
255         if ((index < 0 && index != POSITION_BOTTOM)
256                 || (index > mChildren.size() && index != POSITION_TOP)) {
257             throw new IllegalArgumentException("addChild: invalid position=" + index
258                     + ", children number=" + mChildren.size());
259         }
260 
261         if (index == POSITION_TOP) {
262             index = mChildren.size();
263         } else if (index == POSITION_BOTTOM) {
264             index = 0;
265         }
266 
267         mChildren.add(index, child);
268         onChildAdded(child);
269 
270         // Set the parent after we've actually added a child in case a subclass depends on this.
271         child.setParent(this);
272     }
273 
onChildAdded(WindowContainer child)274     private void onChildAdded(WindowContainer child) {
275         mTreeWeight += child.mTreeWeight;
276         WindowContainer parent = getParent();
277         while (parent != null) {
278             parent.mTreeWeight += child.mTreeWeight;
279             parent = parent.getParent();
280         }
281         onChildPositionChanged();
282     }
283 
284     /**
285      * Removes the input child container from this container which is its parent.
286      *
287      * @return True if the container did contain the input child and it was detached.
288      */
289     @CallSuper
removeChild(E child)290     void removeChild(E child) {
291         if (mChildren.remove(child)) {
292             onChildRemoved(child);
293             child.setParent(null);
294         } else {
295             throw new IllegalArgumentException("removeChild: container=" + child.getName()
296                     + " is not a child of container=" + getName());
297         }
298     }
299 
onChildRemoved(WindowContainer child)300     private void onChildRemoved(WindowContainer child) {
301         mTreeWeight -= child.mTreeWeight;
302         WindowContainer parent = getParent();
303         while (parent != null) {
304             parent.mTreeWeight -= child.mTreeWeight;
305             parent = parent.getParent();
306         }
307         onChildPositionChanged();
308     }
309 
310     /**
311      * Removes this window container and its children with no regard for what else might be going on
312      * in the system. For example, the container will be removed during animation if this method is
313      * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()}
314      * which allows the system to defer removal until a suitable time.
315      */
316     @CallSuper
removeImmediately()317     void removeImmediately() {
318         while (!mChildren.isEmpty()) {
319             final E child = mChildren.peekLast();
320             child.removeImmediately();
321             // Need to do this after calling remove on the child because the child might try to
322             // remove/detach itself from its parent which will cause an exception if we remove
323             // it before calling remove on the child.
324             if (mChildren.remove(child)) {
325                 onChildRemoved(child);
326             }
327         }
328 
329         if (mSurfaceControl != null) {
330             getPendingTransaction().remove(mSurfaceControl);
331 
332             // Merge to parent transaction to ensure the transactions on this WindowContainer are
333             // applied in native even if WindowContainer is removed.
334             if (mParent != null) {
335                 mParent.getPendingTransaction().merge(getPendingTransaction());
336             }
337 
338             mSurfaceControl = null;
339             scheduleAnimation();
340         }
341 
342         if (mParent != null) {
343             mParent.removeChild(this);
344         }
345 
346         if (mController != null) {
347             setController(null);
348         }
349 
350     }
351 
352     /**
353      * @return The index of this element in the hierarchy tree in prefix order.
354      */
getPrefixOrderIndex()355     int getPrefixOrderIndex() {
356         if (mParent == null) {
357             return 0;
358         }
359         return mParent.getPrefixOrderIndex(this);
360     }
361 
getPrefixOrderIndex(WindowContainer child)362     private int getPrefixOrderIndex(WindowContainer child) {
363         int order = 0;
364         for (int i = 0; i < mChildren.size(); i++) {
365             final WindowContainer childI = mChildren.get(i);
366             if (child == childI) {
367                 break;
368             }
369             order += childI.mTreeWeight;
370         }
371         if (mParent != null) {
372             order += mParent.getPrefixOrderIndex(this);
373         }
374 
375         // We also need to count ourselves.
376         order++;
377         return order;
378     }
379 
380     /**
381      * Removes this window container and its children taking care not to remove them during a
382      * critical stage in the system. For example, some containers will not be removed during
383      * animation if this method is called.
384      */
385     // TODO: figure-out implementation that works best for this.
386     // E.g. when do we remove from parent list? maybe not...
removeIfPossible()387     void removeIfPossible() {
388         for (int i = mChildren.size() - 1; i >= 0; --i) {
389             final WindowContainer wc = mChildren.get(i);
390             wc.removeIfPossible();
391         }
392     }
393 
394     /** Returns true if this window container has the input child. */
hasChild(E child)395     boolean hasChild(E child) {
396         for (int i = mChildren.size() - 1; i >= 0; --i) {
397             final E current = mChildren.get(i);
398             if (current == child || current.hasChild(child)) {
399                 return true;
400             }
401         }
402         return false;
403     }
404 
405     /**
406      * Move a child from it's current place in siblings list to the specified position,
407      * with an option to move all its parents to top.
408      * @param position Target position to move the child to.
409      * @param child Child to move to selected position.
410      * @param includingParents Flag indicating whether we need to move the entire branch of the
411      *                         hierarchy when we're moving a child to {@link #POSITION_TOP} or
412      *                         {@link #POSITION_BOTTOM}. When moving to other intermediate positions
413      *                         this flag will do nothing.
414      */
415     @CallSuper
positionChildAt(int position, E child, boolean includingParents)416     void positionChildAt(int position, E child, boolean includingParents) {
417 
418         if (child.getParent() != this) {
419             throw new IllegalArgumentException("removeChild: container=" + child.getName()
420                     + " is not a child of container=" + getName()
421                     + " current parent=" + child.getParent());
422         }
423 
424         if ((position < 0 && position != POSITION_BOTTOM)
425                 || (position > mChildren.size() && position != POSITION_TOP)) {
426             throw new IllegalArgumentException("positionAt: invalid position=" + position
427                     + ", children number=" + mChildren.size());
428         }
429 
430         if (position >= mChildren.size() - 1) {
431             position = POSITION_TOP;
432         } else if (position == 0) {
433             position = POSITION_BOTTOM;
434         }
435 
436         switch (position) {
437             case POSITION_TOP:
438                 if (mChildren.peekLast() != child) {
439                     mChildren.remove(child);
440                     mChildren.add(child);
441                     onChildPositionChanged();
442                 }
443                 if (includingParents && getParent() != null) {
444                     getParent().positionChildAt(POSITION_TOP, this /* child */,
445                             true /* includingParents */);
446                 }
447                 break;
448             case POSITION_BOTTOM:
449                 if (mChildren.peekFirst() != child) {
450                     mChildren.remove(child);
451                     mChildren.addFirst(child);
452                     onChildPositionChanged();
453                 }
454                 if (includingParents && getParent() != null) {
455                     getParent().positionChildAt(POSITION_BOTTOM, this /* child */,
456                             true /* includingParents */);
457                 }
458                 break;
459             default:
460                 // TODO: Removing the child before reinserting requires the caller to provide a
461                 //       position that takes into account the removed child (if the index of the
462                 //       child < position, then the position should be adjusted). We should consider
463                 //       doing this adjustment here and remove any adjustments in the callers.
464                 mChildren.remove(child);
465                 mChildren.add(position, child);
466                 onChildPositionChanged();
467         }
468     }
469 
470     /**
471      * Notify that a child's position has changed. Possible changes are adding or removing a child.
472      */
onChildPositionChanged()473     void onChildPositionChanged() { }
474 
475     /**
476      * Update override configuration and recalculate full config.
477      * @see #mRequestedOverrideConfiguration
478      * @see #mFullConfiguration
479      */
480     @Override
onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)481     public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) {
482         // We must diff before the configuration is applied so that we can capture the change
483         // against the existing bounds.
484         final int diff = diffRequestedOverrideBounds(
485                 overrideConfiguration.windowConfiguration.getBounds());
486         super.onRequestedOverrideConfigurationChanged(overrideConfiguration);
487         if (mParent != null) {
488             mParent.onDescendantOverrideConfigurationChanged();
489         }
490 
491         if (diff == BOUNDS_CHANGE_NONE) {
492             return;
493         }
494 
495         if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) {
496             onResize();
497         } else {
498             onMovedByResize();
499         }
500     }
501 
502     /**
503      * Notify that a descendant's overrideConfiguration has changed.
504      */
onDescendantOverrideConfigurationChanged()505     void onDescendantOverrideConfigurationChanged() {
506         if (mParent != null) {
507             mParent.onDescendantOverrideConfigurationChanged();
508         }
509     }
510 
511     /**
512      * Notify that the display this container is on has changed. This could be either this container
513      * is moved to a new display, or some configurations on the display it is on changes.
514      *
515      * @param dc The display this container is on after changes.
516      */
onDisplayChanged(DisplayContent dc)517     void onDisplayChanged(DisplayContent dc) {
518         mDisplayContent = dc;
519         if (dc != null && dc != this) {
520             dc.getPendingTransaction().merge(mPendingTransaction);
521         }
522         for (int i = mChildren.size() - 1; i >= 0; --i) {
523             final WindowContainer child = mChildren.get(i);
524             child.onDisplayChanged(dc);
525         }
526     }
527 
getDisplayContent()528     DisplayContent getDisplayContent() {
529         return mDisplayContent;
530     }
531 
setWaitingForDrawnIfResizingChanged()532     void setWaitingForDrawnIfResizingChanged() {
533         for (int i = mChildren.size() - 1; i >= 0; --i) {
534             final WindowContainer wc = mChildren.get(i);
535             wc.setWaitingForDrawnIfResizingChanged();
536         }
537     }
538 
onResize()539     void onResize() {
540         for (int i = mChildren.size() - 1; i >= 0; --i) {
541             final WindowContainer wc = mChildren.get(i);
542             wc.onParentResize();
543         }
544     }
545 
onParentResize()546     void onParentResize() {
547         // In the case this container has specified its own bounds, a parent resize will not
548         // affect its bounds. Any relevant changes will be propagated through changes to the
549         // Configuration override.
550         if (hasOverrideBounds()) {
551             return;
552         }
553 
554         // Default implementation is to treat as resize on self.
555         onResize();
556     }
557 
onMovedByResize()558     void onMovedByResize() {
559         for (int i = mChildren.size() - 1; i >= 0; --i) {
560             final WindowContainer wc = mChildren.get(i);
561             wc.onMovedByResize();
562         }
563     }
564 
resetDragResizingChangeReported()565     void resetDragResizingChangeReported() {
566         for (int i = mChildren.size() - 1; i >= 0; --i) {
567             final WindowContainer wc = mChildren.get(i);
568             wc.resetDragResizingChangeReported();
569         }
570     }
571 
forceWindowsScaleableInTransaction(boolean force)572     void forceWindowsScaleableInTransaction(boolean force) {
573         for (int i = mChildren.size() - 1; i >= 0; --i) {
574             final WindowContainer wc = mChildren.get(i);
575             wc.forceWindowsScaleableInTransaction(force);
576         }
577     }
578 
579     /**
580      * @return Whether our own container is running an animation or any child, no matter how deep in
581      *         the hierarchy, is animating.
582      */
isSelfOrChildAnimating()583     boolean isSelfOrChildAnimating() {
584         if (isSelfAnimating()) {
585             return true;
586         }
587         for (int j = mChildren.size() - 1; j >= 0; j--) {
588             final WindowContainer wc = mChildren.get(j);
589             if (wc.isSelfOrChildAnimating()) {
590                 return true;
591             }
592         }
593         return false;
594     }
595 
596     /**
597      * @return Whether our own container is running an animation or our parent is animating. This
598      *         doesn't consider whether children are animating.
599      */
isAnimating()600     boolean isAnimating() {
601 
602         // We are animating if we ourselves are animating or if our parent is animating.
603         return isSelfAnimating() || mParent != null && mParent.isAnimating();
604     }
605 
606     /**
607      * @return {@code true} if in this subtree of the hierarchy we have an {@link AppWindowToken}
608      *         that is {@link #isSelfAnimating}; {@code false} otherwise.
609      */
isAppAnimating()610     boolean isAppAnimating() {
611         for (int j = mChildren.size() - 1; j >= 0; j--) {
612             final WindowContainer wc = mChildren.get(j);
613             if (wc.isAppAnimating()) {
614                 return true;
615             }
616         }
617         return false;
618     }
619 
620     /**
621      * @return Whether our own container running an animation at the moment.
622      */
isSelfAnimating()623     boolean isSelfAnimating() {
624         return mSurfaceAnimator.isAnimating();
625     }
626 
sendAppVisibilityToClients()627     void sendAppVisibilityToClients() {
628         for (int i = mChildren.size() - 1; i >= 0; --i) {
629             final WindowContainer wc = mChildren.get(i);
630             wc.sendAppVisibilityToClients();
631         }
632     }
633 
634     /**
635      * Returns true if the container or one of its children as some content it can display or wants
636      * to display (e.g. app views or saved surface).
637      *
638      * NOTE: While this method will return true if the there is some content to display, it doesn't
639      * mean the container is visible. Use {@link #isVisible()} to determine if the container is
640      * visible.
641      */
hasContentToDisplay()642     boolean hasContentToDisplay() {
643         for (int i = mChildren.size() - 1; i >= 0; --i) {
644             final WindowContainer wc = mChildren.get(i);
645             if (wc.hasContentToDisplay()) {
646                 return true;
647             }
648         }
649         return false;
650     }
651 
652     /**
653      * Returns true if the container or one of its children is considered visible from the
654      * WindowManager perspective which usually means valid surface and some other internal state
655      * are true.
656      *
657      * NOTE: While this method will return true if the surface is visible, it doesn't mean the
658      * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if
659      * the container has any content to display.
660      */
isVisible()661     boolean isVisible() {
662         // TODO: Will this be more correct if it checks the visibility of its parents?
663         // It depends...For example, Tasks and Stacks are only visible if there children are visible
664         // but, WindowState are not visible if there parent are not visible. Maybe have the
665         // container specify which direction to traverse for visibility?
666         for (int i = mChildren.size() - 1; i >= 0; --i) {
667             final WindowContainer wc = mChildren.get(i);
668             if (wc.isVisible()) {
669                 return true;
670             }
671         }
672         return false;
673     }
674 
675     /**
676      * @return Whether this child is on top of the window hierarchy.
677      */
isOnTop()678     boolean isOnTop() {
679         return getParent().getTopChild() == this && getParent().isOnTop();
680     }
681 
682     /** Returns the top child container. */
getTopChild()683     E getTopChild() {
684         return mChildren.peekLast();
685     }
686 
687     /** Returns true if there is still a removal being deferred */
checkCompleteDeferredRemoval()688     boolean checkCompleteDeferredRemoval() {
689         boolean stillDeferringRemoval = false;
690 
691         for (int i = mChildren.size() - 1; i >= 0; --i) {
692             final WindowContainer wc = mChildren.get(i);
693             stillDeferringRemoval |= wc.checkCompleteDeferredRemoval();
694         }
695 
696         return stillDeferringRemoval;
697     }
698 
699     /** Checks if all windows in an app are all drawn and shows them if needed. */
checkAppWindowsReadyToShow()700     void checkAppWindowsReadyToShow() {
701         for (int i = mChildren.size() - 1; i >= 0; --i) {
702             final WindowContainer wc = mChildren.get(i);
703             wc.checkAppWindowsReadyToShow();
704         }
705     }
706 
onAppTransitionDone()707     void onAppTransitionDone() {
708         for (int i = mChildren.size() - 1; i >= 0; --i) {
709             final WindowContainer wc = mChildren.get(i);
710             wc.onAppTransitionDone();
711         }
712     }
713 
714     /**
715      * Called when this container or one of its descendants changed its requested orientation, and
716      * wants this container to handle it or pass it to its parent.
717      *
718      * @param freezeDisplayToken freeze this app window token if display needs to freeze
719      * @param requestingContainer the container which orientation request has changed
720      * @return {@code true} if handled; {@code false} otherwise.
721      */
onDescendantOrientationChanged(@ullable IBinder freezeDisplayToken, @Nullable ConfigurationContainer requestingContainer)722     boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken,
723             @Nullable ConfigurationContainer requestingContainer) {
724         final WindowContainer parent = getParent();
725         if (parent == null) {
726             return false;
727         }
728         return parent.onDescendantOrientationChanged(freezeDisplayToken,
729                 requestingContainer);
730     }
731 
732     /**
733      * Check if this container or its parent will handle orientation changes from descendants. It's
734      * different from the return value of {@link #onDescendantOrientationChanged(IBinder,
735      * ConfigurationContainer)} in the sense that the return value of this method tells if this
736      * container or its parent will handle the request eventually, while the return value of the
737      * other method is if it handled the request synchronously.
738      *
739      * @return {@code true} if it handles or will handle orientation change in the future; {@code
740      *         false} if it won't handle the change at anytime.
741      */
handlesOrientationChangeFromDescendant()742     boolean handlesOrientationChangeFromDescendant() {
743         final WindowContainer parent = getParent();
744         return parent != null && parent.handlesOrientationChangeFromDescendant();
745     }
746 
747     /**
748      * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2
749      * parameters.
750      *
751      * @param orientation the specified orientation.
752      */
setOrientation(int orientation)753     void setOrientation(int orientation) {
754         setOrientation(orientation, null /* freezeDisplayToken */,
755                 null /* ActivityRecord */);
756     }
757 
758     /**
759      * Sets the specified orientation of this container. It percolates this change upward along the
760      * hierarchy to let each level of the hierarchy a chance to respond to it.
761      *
762      * @param orientation the specified orientation. Needs to be one of {@link
763      *      android.content.pm.ActivityInfo.ScreenOrientation}.
764      * @param freezeDisplayToken uses this token to freeze display if orientation change is not
765      *                           done. Display will not be frozen if this is {@code null}, which
766      *                           should only happen in tests.
767      * @param requestingContainer the container which orientation request has changed. Mostly used
768      *                            to ensure it gets correct configuration.
769      */
setOrientation(int orientation, @Nullable IBinder freezeDisplayToken, @Nullable ConfigurationContainer requestingContainer)770     void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken,
771             @Nullable ConfigurationContainer requestingContainer) {
772         final boolean changed = mOrientation != orientation;
773         mOrientation = orientation;
774         if (!changed) {
775             return;
776         }
777         final WindowContainer parent = getParent();
778         if (parent != null) {
779             onDescendantOrientationChanged(freezeDisplayToken, requestingContainer);
780         }
781     }
782 
getOrientation()783     int getOrientation() {
784         return getOrientation(mOrientation);
785     }
786 
787     /**
788      * Returns the specified orientation for this window container or one of its children is there
789      * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no
790      * specification is set.
791      * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a
792      * specification...
793      *
794      * @param candidate The current orientation candidate that will be returned if we don't find a
795      *                  better match.
796      * @return The orientation as specified by this branch or the window hierarchy.
797      */
getOrientation(int candidate)798     int getOrientation(int candidate) {
799         if (!fillsParent()) {
800             // Ignore containers that don't completely fill their parents.
801             return SCREEN_ORIENTATION_UNSET;
802         }
803 
804         // The container fills its parent so we can use it orientation if it has one
805         // specified; otherwise we prefer to use the orientation of its topmost child that has one
806         // specified and fall back on this container's unset or unspecified value as a candidate
807         // if none of the children have a better candidate for the orientation.
808         if (mOrientation != SCREEN_ORIENTATION_UNSET
809                 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) {
810             return mOrientation;
811         }
812 
813         for (int i = mChildren.size() - 1; i >= 0; --i) {
814             final WindowContainer wc = mChildren.get(i);
815 
816             // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs.
817             // SCREEN_ORIENTATION_UNSPECIFIED?
818             final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND
819                     ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET);
820             if (orientation == SCREEN_ORIENTATION_BEHIND) {
821                 // container wants us to use the orientation of the container behind it. See if we
822                 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to
823                 // look behind this container.
824                 candidate = orientation;
825                 continue;
826             }
827 
828             if (orientation == SCREEN_ORIENTATION_UNSET) {
829                 continue;
830             }
831 
832             if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) {
833                 // Use the orientation if the container fills its parent or requested an explicit
834                 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED.
835                 return orientation;
836             }
837         }
838 
839         return candidate;
840     }
841 
842     /**
843      * Returns true if this container is opaque and fills all the space made available by its parent
844      * container.
845      *
846      * NOTE: It is possible for this container to occupy more space than the parent has (or less),
847      * this is just a signal from the client to window manager stating its intent, but not what it
848      * actually does.
849      */
fillsParent()850     boolean fillsParent() {
851         return false;
852     }
853 
854     // TODO: Users would have their own window containers under the display container?
switchUser()855     void switchUser() {
856         for (int i = mChildren.size() - 1; i >= 0; --i) {
857             mChildren.get(i).switchUser();
858         }
859     }
860 
861     /**
862      * For all windows at or below this container call the callback.
863      * @param   callback Calls the {@link ToBooleanFunction#apply} method for each window found and
864      *                   stops the search if {@link ToBooleanFunction#apply} returns true.
865      * @param   traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of
866      *                              z-order, else from bottom-to-top.
867      * @return  True if the search ended before we reached the end of the hierarchy due to
868      *          {@link ToBooleanFunction#apply} returning true.
869      */
forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)870     boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) {
871         if (traverseTopToBottom) {
872             for (int i = mChildren.size() - 1; i >= 0; --i) {
873                 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
874                     return true;
875                 }
876             }
877         } else {
878             final int count = mChildren.size();
879             for (int i = 0; i < count; i++) {
880                 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) {
881                     return true;
882                 }
883             }
884         }
885         return false;
886     }
887 
forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom)888     void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) {
889         ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback);
890         forAllWindows(wrapper, traverseTopToBottom);
891         wrapper.release();
892     }
893 
forAllAppWindows(Consumer<AppWindowToken> callback)894     void forAllAppWindows(Consumer<AppWindowToken> callback) {
895         for (int i = mChildren.size() - 1; i >= 0; --i) {
896             mChildren.get(i).forAllAppWindows(callback);
897         }
898     }
899 
900     /**
901      * For all tasks at or below this container call the callback.
902      *
903      * @param callback Callback to be called for every task.
904      */
forAllTasks(Consumer<Task> callback)905     void forAllTasks(Consumer<Task> callback) {
906         for (int i = mChildren.size() - 1; i >= 0; --i) {
907             mChildren.get(i).forAllTasks(callback);
908         }
909     }
910 
getWindow(Predicate<WindowState> callback)911     WindowState getWindow(Predicate<WindowState> callback) {
912         for (int i = mChildren.size() - 1; i >= 0; --i) {
913             final WindowState w = mChildren.get(i).getWindow(callback);
914             if (w != null) {
915                 return w;
916             }
917         }
918 
919         return null;
920     }
921 
922     /**
923      * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than
924      * the input container in terms of z-order.
925      */
926     @Override
compareTo(WindowContainer other)927     public int compareTo(WindowContainer other) {
928         if (this == other) {
929             return 0;
930         }
931 
932         if (mParent != null && mParent == other.mParent) {
933             final WindowList<WindowContainer> list = mParent.mChildren;
934             return list.indexOf(this) > list.indexOf(other) ? 1 : -1;
935         }
936 
937         final LinkedList<WindowContainer> thisParentChain = mTmpChain1;
938         final LinkedList<WindowContainer> otherParentChain = mTmpChain2;
939         try {
940             getParents(thisParentChain);
941             other.getParents(otherParentChain);
942 
943             // Find the common ancestor of both containers.
944             WindowContainer commonAncestor = null;
945             WindowContainer thisTop = thisParentChain.peekLast();
946             WindowContainer otherTop = otherParentChain.peekLast();
947             while (thisTop != null && otherTop != null && thisTop == otherTop) {
948                 commonAncestor = thisParentChain.removeLast();
949                 otherParentChain.removeLast();
950                 thisTop = thisParentChain.peekLast();
951                 otherTop = otherParentChain.peekLast();
952             }
953 
954             // Containers don't belong to the same hierarchy???
955             if (commonAncestor == null) {
956                 throw new IllegalArgumentException("No in the same hierarchy this="
957                         + thisParentChain + " other=" + otherParentChain);
958             }
959 
960             // Children are always considered greater than their parents, so if one of the containers
961             // we are comparing it the parent of the other then whichever is the child is greater.
962             if (commonAncestor == this) {
963                 return -1;
964             } else if (commonAncestor == other) {
965                 return 1;
966             }
967 
968             // The position of the first non-common ancestor in the common ancestor list determines
969             // which is greater the which.
970             final WindowList<WindowContainer> list = commonAncestor.mChildren;
971             return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast())
972                     ? 1 : -1;
973         } finally {
974             mTmpChain1.clear();
975             mTmpChain2.clear();
976         }
977     }
978 
getParents(LinkedList<WindowContainer> parents)979     private void getParents(LinkedList<WindowContainer> parents) {
980         parents.clear();
981         WindowContainer current = this;
982         do {
983             parents.addLast(current);
984             current = current.mParent;
985         } while (current != null);
986     }
987 
getController()988     WindowContainerController getController() {
989         return mController;
990     }
991 
setController(WindowContainerController controller)992     void setController(WindowContainerController controller) {
993         if (mController != null && controller != null) {
994             throw new IllegalArgumentException("Can't set controller=" + mController
995                     + " for container=" + this + " Already set to=" + mController);
996         }
997         if (controller != null) {
998             controller.setContainer(this);
999         } else if (mController != null) {
1000             mController.setContainer(null);
1001         }
1002         mController = controller;
1003     }
1004 
makeSurface()1005     SurfaceControl.Builder makeSurface() {
1006         final WindowContainer p = getParent();
1007         return p.makeChildSurface(this);
1008     }
1009 
1010     /**
1011      * @param child The WindowContainer this child surface is for, or null if the Surface
1012      *              is not assosciated with a WindowContainer (e.g. a surface used for Dimming).
1013      */
makeChildSurface(WindowContainer child)1014     SurfaceControl.Builder makeChildSurface(WindowContainer child) {
1015         final WindowContainer p = getParent();
1016         // Give the parent a chance to set properties. In hierarchy v1 we rely
1017         // on this to set full-screen dimensions on all our Surface-less Layers.
1018         return p.makeChildSurface(child)
1019                 .setParent(mSurfaceControl);
1020     }
1021     /*
1022      * @return The SurfaceControl parent for this containers SurfaceControl.
1023      *         The SurfaceControl must be valid if non-null.
1024      */
1025     @Override
getParentSurfaceControl()1026     public SurfaceControl getParentSurfaceControl() {
1027         final WindowContainer parent = getParent();
1028         if (parent == null) {
1029             return null;
1030         }
1031         return parent.getSurfaceControl();
1032     }
1033 
1034     /**
1035      * @return Whether this WindowContainer should be magnified by the accessibility magnifier.
1036      */
shouldMagnify()1037     boolean shouldMagnify() {
1038         if (mSurfaceControl == null) {
1039             return false;
1040         }
1041 
1042         for (int i = 0; i < mChildren.size(); i++) {
1043             if (!mChildren.get(i).shouldMagnify()) {
1044                 return false;
1045             }
1046         }
1047         return true;
1048     }
1049 
getSession()1050     SurfaceSession getSession() {
1051         if (getParent() != null) {
1052             return getParent().getSession();
1053         }
1054         return null;
1055     }
1056 
assignLayer(Transaction t, int layer)1057     void assignLayer(Transaction t, int layer) {
1058         final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null;
1059         if (mSurfaceControl != null && changed) {
1060             setLayer(t, layer);
1061             mLastLayer = layer;
1062             mLastRelativeToLayer = null;
1063         }
1064     }
1065 
assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer)1066     void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1067         final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo;
1068         if (mSurfaceControl != null && changed) {
1069             setRelativeLayer(t, relativeTo, layer);
1070             mLastLayer = layer;
1071             mLastRelativeToLayer = relativeTo;
1072         }
1073     }
1074 
setLayer(Transaction t, int layer)1075     protected void setLayer(Transaction t, int layer) {
1076 
1077         // Route through surface animator to accommodate that our surface control might be
1078         // attached to the leash, and leash is attached to parent container.
1079         mSurfaceAnimator.setLayer(t, layer);
1080     }
1081 
setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer)1082     protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) {
1083 
1084         // Route through surface animator to accommodate that our surface control might be
1085         // attached to the leash, and leash is attached to parent container.
1086         mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer);
1087     }
1088 
reparentSurfaceControl(Transaction t, SurfaceControl newParent)1089     protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) {
1090         mSurfaceAnimator.reparent(t, newParent);
1091     }
1092 
assignChildLayers(Transaction t)1093     void assignChildLayers(Transaction t) {
1094         int layer = 0;
1095 
1096         // We use two passes as a way to promote children which
1097         // need Z-boosting to the end of the list.
1098         for (int j = 0; j < mChildren.size(); ++j) {
1099             final WindowContainer wc = mChildren.get(j);
1100             wc.assignChildLayers(t);
1101             if (!wc.needsZBoost()) {
1102                 wc.assignLayer(t, layer++);
1103             }
1104         }
1105         for (int j = 0; j < mChildren.size(); ++j) {
1106             final WindowContainer wc = mChildren.get(j);
1107             if (wc.needsZBoost()) {
1108                 wc.assignLayer(t, layer++);
1109             }
1110         }
1111     }
1112 
assignChildLayers()1113     void assignChildLayers() {
1114         assignChildLayers(getPendingTransaction());
1115         scheduleAnimation();
1116     }
1117 
needsZBoost()1118     boolean needsZBoost() {
1119         for (int i = 0; i < mChildren.size(); i++) {
1120             if (mChildren.get(i).needsZBoost()) {
1121                 return true;
1122             }
1123         }
1124         return false;
1125     }
1126 
1127     /**
1128      * Write to a protocol buffer output stream. Protocol buffer message definition is at
1129      * {@link com.android.server.wm.WindowContainerProto}.
1130      *
1131      * @param proto     Stream to write the WindowContainer object to.
1132      * @param fieldId   Field Id of the WindowContainer as defined in the parent message.
1133      * @param logLevel  Determines the amount of data to be written to the Protobuf.
1134      * @hide
1135      */
1136     @CallSuper
1137     @Override
writeToProto(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)1138     public void writeToProto(ProtoOutputStream proto, long fieldId,
1139             @WindowTraceLogLevel int logLevel) {
1140         boolean isVisible = isVisible();
1141         if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) {
1142             return;
1143         }
1144 
1145         final long token = proto.start(fieldId);
1146         super.writeToProto(proto, CONFIGURATION_CONTAINER, logLevel);
1147         proto.write(ORIENTATION, mOrientation);
1148         proto.write(VISIBLE, isVisible);
1149         if (mSurfaceAnimator.isAnimating()) {
1150             mSurfaceAnimator.writeToProto(proto, SURFACE_ANIMATOR);
1151         }
1152         proto.end(token);
1153     }
1154 
obtainConsumerWrapper(Consumer<WindowState> consumer)1155     private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) {
1156         ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire();
1157         if (wrapper == null) {
1158             wrapper = new ForAllWindowsConsumerWrapper();
1159         }
1160         wrapper.setConsumer(consumer);
1161         return wrapper;
1162     }
1163 
1164     private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> {
1165 
1166         private Consumer<WindowState> mConsumer;
1167 
setConsumer(Consumer<WindowState> consumer)1168         void setConsumer(Consumer<WindowState> consumer) {
1169             mConsumer = consumer;
1170         }
1171 
1172         @Override
apply(WindowState w)1173         public boolean apply(WindowState w) {
1174             mConsumer.accept(w);
1175             return false;
1176         }
1177 
release()1178         void release() {
1179             mConsumer = null;
1180             mConsumerWrapperPool.release(this);
1181         }
1182     }
1183 
1184     // TODO(b/68336570): Should this really be on WindowContainer since it
1185     // can only be used on the top-level nodes that aren't animated?
1186     // (otherwise we would be fighting other callers of setMatrix).
applyMagnificationSpec(Transaction t, MagnificationSpec spec)1187     void applyMagnificationSpec(Transaction t, MagnificationSpec spec) {
1188         if (shouldMagnify()) {
1189             t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale)
1190                     .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY);
1191             mLastMagnificationSpec = spec;
1192         } else {
1193             clearMagnificationSpec(t);
1194             for (int i = 0; i < mChildren.size(); i++) {
1195                 mChildren.get(i).applyMagnificationSpec(t, spec);
1196             }
1197         }
1198     }
1199 
clearMagnificationSpec(Transaction t)1200     void clearMagnificationSpec(Transaction t) {
1201         if (mLastMagnificationSpec != null) {
1202             t.setMatrix(mSurfaceControl, 1, 0, 0, 1)
1203                 .setPosition(mSurfaceControl, 0, 0);
1204         }
1205         mLastMagnificationSpec = null;
1206         for (int i = 0; i < mChildren.size(); i++) {
1207             mChildren.get(i).clearMagnificationSpec(t);
1208         }
1209     }
1210 
prepareSurfaces()1211     void prepareSurfaces() {
1212         // If a leash has been set when the transaction was committed, then the leash reparent has
1213         // been committed.
1214         mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash();
1215         for (int i = 0; i < mChildren.size(); i++) {
1216             mChildren.get(i).prepareSurfaces();
1217         }
1218     }
1219 
1220     /**
1221      * @return true if the reparent to animation leash transaction has been committed, false
1222      * otherwise.
1223      */
hasCommittedReparentToAnimationLeash()1224     boolean hasCommittedReparentToAnimationLeash() {
1225         return mCommittedReparentToAnimationLeash;
1226     }
1227 
1228     /**
1229      * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions
1230      * will be applied.
1231      */
scheduleAnimation()1232     void scheduleAnimation() {
1233         if (mParent != null) {
1234             mParent.scheduleAnimation();
1235         }
1236     }
1237 
1238     /**
1239      * @return The SurfaceControl for this container.
1240      *         The SurfaceControl must be valid if non-null.
1241      */
1242     @Override
getSurfaceControl()1243     public SurfaceControl getSurfaceControl() {
1244         return mSurfaceControl;
1245     }
1246 
1247     @Override
getPendingTransaction()1248     public Transaction getPendingTransaction() {
1249         final DisplayContent displayContent = getDisplayContent();
1250         if (displayContent != null && displayContent != this) {
1251             return displayContent.getPendingTransaction();
1252         }
1253         // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we
1254         // let the caller to save the surface operations within the local mPendingTransaction.
1255         // If this is not a DisplayContent, we will merge it to the pending transaction of its
1256         // display once it attaches to it.
1257         return mPendingTransaction;
1258     }
1259 
1260     /**
1261      * Starts an animation on the container.
1262      *
1263      * @param anim The animation to run.
1264      * @param hidden Whether our container is currently hidden. TODO This should use isVisible at
1265      *               some point but the meaning is too weird to work for all containers.
1266      */
startAnimation(Transaction t, AnimationAdapter anim, boolean hidden)1267     void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden) {
1268         if (DEBUG_ANIM) Slog.v(TAG, "Starting animation on " + this + ": " + anim);
1269 
1270         // TODO: This should use isVisible() but because isVisible has a really weird meaning at
1271         // the moment this doesn't work for all animatable window containers.
1272         mSurfaceAnimator.startAnimation(t, anim, hidden);
1273     }
1274 
transferAnimation(WindowContainer from)1275     void transferAnimation(WindowContainer from) {
1276         mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator);
1277     }
1278 
cancelAnimation()1279     void cancelAnimation() {
1280         mSurfaceAnimator.cancelAnimation();
1281     }
1282 
1283     @Override
makeAnimationLeash()1284     public Builder makeAnimationLeash() {
1285         return makeSurface();
1286     }
1287 
1288     @Override
getAnimationLeashParent()1289     public SurfaceControl getAnimationLeashParent() {
1290         return getParentSurfaceControl();
1291     }
1292 
1293     /**
1294      * @return The layer on which all app animations are happening.
1295      */
getAppAnimationLayer(@nimationLayer int animationLayer)1296     SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) {
1297         final WindowContainer parent = getParent();
1298         if (parent != null) {
1299             return parent.getAppAnimationLayer(animationLayer);
1300         }
1301         return null;
1302     }
1303 
1304     @Override
commitPendingTransaction()1305     public void commitPendingTransaction() {
1306         scheduleAnimation();
1307     }
1308 
reassignLayer(Transaction t)1309     void reassignLayer(Transaction t) {
1310         final WindowContainer parent = getParent();
1311         if (parent != null) {
1312             parent.assignChildLayers(t);
1313         }
1314     }
1315 
1316     @Override
onAnimationLeashCreated(Transaction t, SurfaceControl leash)1317     public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) {
1318         mLastLayer = -1;
1319         reassignLayer(t);
1320     }
1321 
1322     @Override
onAnimationLeashLost(Transaction t)1323     public void onAnimationLeashLost(Transaction t) {
1324         mLastLayer = -1;
1325         reassignLayer(t);
1326     }
1327 
1328     /**
1329      * Called when an animation has finished running.
1330      */
onAnimationFinished()1331     protected void onAnimationFinished() {
1332         mWmService.onAnimationFinished();
1333     }
1334 
1335     /**
1336      * @return The currently running animation, if any, or {@code null} otherwise.
1337      */
getAnimation()1338     AnimationAdapter getAnimation() {
1339         return mSurfaceAnimator.getAnimation();
1340     }
1341 
1342     /**
1343      * @see SurfaceAnimator#startDelayingAnimationStart
1344      */
startDelayingAnimationStart()1345     void startDelayingAnimationStart() {
1346         mSurfaceAnimator.startDelayingAnimationStart();
1347     }
1348 
1349     /**
1350      * @see SurfaceAnimator#endDelayingAnimationStart
1351      */
endDelayingAnimationStart()1352     void endDelayingAnimationStart() {
1353         mSurfaceAnimator.endDelayingAnimationStart();
1354     }
1355 
1356     @Override
getSurfaceWidth()1357     public int getSurfaceWidth() {
1358         return mSurfaceControl.getWidth();
1359     }
1360 
1361     @Override
getSurfaceHeight()1362     public int getSurfaceHeight() {
1363         return mSurfaceControl.getHeight();
1364     }
1365 
1366     @CallSuper
dump(PrintWriter pw, String prefix, boolean dumpAll)1367     void dump(PrintWriter pw, String prefix, boolean dumpAll) {
1368         if (mSurfaceAnimator.isAnimating()) {
1369             pw.print(prefix); pw.println("ContainerAnimator:");
1370             mSurfaceAnimator.dump(pw, prefix + "  ");
1371         }
1372     }
1373 
updateSurfacePosition()1374     void updateSurfacePosition() {
1375         if (mSurfaceControl == null) {
1376             return;
1377         }
1378 
1379         getRelativeDisplayedPosition(mTmpPos);
1380         if (mTmpPos.equals(mLastSurfacePosition)) {
1381             return;
1382         }
1383 
1384         getPendingTransaction().setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y);
1385         mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y);
1386     }
1387 
1388     @VisibleForTesting
getLastSurfacePosition()1389     Point getLastSurfacePosition() {
1390         return mLastSurfacePosition;
1391     }
1392 
1393     /**
1394      * Displayed bounds specify where to display this container at. It differs from bounds during
1395      * certain operations (like animation or interactive dragging).
1396      *
1397      * @return the bounds to display this container at.
1398      */
getDisplayedBounds()1399     Rect getDisplayedBounds() {
1400         return getBounds();
1401     }
1402 
getRelativeDisplayedPosition(Point outPos)1403     void getRelativeDisplayedPosition(Point outPos) {
1404         final Rect dispBounds = getDisplayedBounds();
1405         outPos.set(dispBounds.left, dispBounds.top);
1406         final WindowContainer parent = getParent();
1407         if (parent != null) {
1408             final Rect parentBounds = parent.getDisplayedBounds();
1409             outPos.offset(-parentBounds.left, -parentBounds.top);
1410         }
1411     }
1412 
getDimmer()1413     Dimmer getDimmer() {
1414         if (mParent == null) {
1415             return null;
1416         }
1417         return mParent.getDimmer();
1418     }
1419 }
1420