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