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