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