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.content.pm.ActivityInfo.isFixedOrientationLandscape; 23 import static android.content.pm.ActivityInfo.isFixedOrientationPortrait; 24 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE; 25 import static android.content.res.Configuration.ORIENTATION_PORTRAIT; 26 import static android.content.res.Configuration.ORIENTATION_UNDEFINED; 27 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER; 28 import static android.os.UserHandle.USER_NULL; 29 import static android.view.SurfaceControl.Transaction; 30 31 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER; 32 import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION; 33 import static com.android.server.wm.IdentifierProto.HASH_CODE; 34 import static com.android.server.wm.IdentifierProto.TITLE; 35 import static com.android.server.wm.IdentifierProto.USER_ID; 36 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS; 37 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM; 38 import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; 39 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_ALL; 40 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION; 41 import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN; 42 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS; 43 import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION; 44 import static com.android.server.wm.WindowContainerChildProto.WINDOW_CONTAINER; 45 import static com.android.server.wm.WindowContainerProto.CONFIGURATION_CONTAINER; 46 import static com.android.server.wm.WindowContainerProto.ORIENTATION; 47 import static com.android.server.wm.WindowContainerProto.SURFACE_ANIMATOR; 48 import static com.android.server.wm.WindowContainerProto.VISIBLE; 49 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; 50 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 51 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 52 import static com.android.server.wm.WindowManagerService.logWithStack; 53 import static com.android.server.wm.WindowManagerService.sHierarchicalAnimations; 54 import static com.android.server.wm.WindowStateAnimator.STACK_CLIP_AFTER_ANIM; 55 56 import android.annotation.CallSuper; 57 import android.annotation.IntDef; 58 import android.annotation.Nullable; 59 import android.app.WindowConfiguration; 60 import android.content.pm.ActivityInfo; 61 import android.content.res.Configuration; 62 import android.graphics.Point; 63 import android.graphics.Rect; 64 import android.os.Debug; 65 import android.os.IBinder; 66 import android.os.Trace; 67 import android.util.ArraySet; 68 import android.util.Pair; 69 import android.util.Pools; 70 import android.util.Slog; 71 import android.util.proto.ProtoOutputStream; 72 import android.view.DisplayInfo; 73 import android.view.MagnificationSpec; 74 import android.view.RemoteAnimationDefinition; 75 import android.view.RemoteAnimationTarget; 76 import android.view.SurfaceControl; 77 import android.view.SurfaceControl.Builder; 78 import android.view.SurfaceSession; 79 import android.view.WindowManager; 80 import android.view.animation.Animation; 81 import android.window.IWindowContainerToken; 82 import android.window.WindowContainerToken; 83 84 import com.android.internal.annotations.VisibleForTesting; 85 import com.android.internal.util.ToBooleanFunction; 86 import com.android.server.protolog.common.ProtoLog; 87 import com.android.server.wm.SurfaceAnimator.Animatable; 88 import com.android.server.wm.SurfaceAnimator.AnimationType; 89 import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback; 90 91 import java.io.PrintWriter; 92 import java.lang.ref.WeakReference; 93 import java.util.ArrayList; 94 import java.util.Comparator; 95 import java.util.LinkedList; 96 import java.util.Set; 97 import java.util.function.Consumer; 98 import java.util.function.Function; 99 import java.util.function.Predicate; 100 101 /** 102 * Defines common functionality for classes that can hold windows directly or through their 103 * children in a hierarchy form. 104 * The test class is {@link WindowContainerTests} which must be kept up-to-date and ran anytime 105 * changes are made to this class. 106 */ 107 class WindowContainer<E extends WindowContainer> extends ConfigurationContainer<E> 108 implements Comparable<WindowContainer>, Animatable, SurfaceFreezer.Freezable, 109 BLASTSyncEngine.TransactionReadyListener { 110 111 private static final String TAG = TAG_WITH_CLASS_NAME ? "WindowContainer" : TAG_WM; 112 113 /** Animation layer that happens above all animating {@link ActivityStack}s. */ 114 static final int ANIMATION_LAYER_STANDARD = 0; 115 116 /** Animation layer that happens above all {@link ActivityStack}s. */ 117 static final int ANIMATION_LAYER_BOOSTED = 1; 118 119 /** 120 * Animation layer that is reserved for {@link WindowConfiguration#ACTIVITY_TYPE_HOME} 121 * activities and all activities that are being controlled by the recents animation. This 122 * layer is generally below all {@link ActivityStack}s. 123 */ 124 static final int ANIMATION_LAYER_HOME = 2; 125 126 @IntDef(prefix = { "ANIMATION_LAYER_" }, value = { 127 ANIMATION_LAYER_STANDARD, 128 ANIMATION_LAYER_BOOSTED, 129 ANIMATION_LAYER_HOME, 130 }) 131 @interface AnimationLayer {} 132 133 static final int POSITION_TOP = Integer.MAX_VALUE; 134 static final int POSITION_BOTTOM = Integer.MIN_VALUE; 135 136 /** 137 * The parent of this window container. 138 * For removing or setting new parent {@link #setParent} should be used, because it also 139 * performs configuration updates based on new parent's settings. 140 */ 141 private WindowContainer<WindowContainer> mParent = null; 142 143 // Set to true when we are performing a reparenting operation so we only send one 144 // onParentChanged() notification. 145 boolean mReparenting; 146 147 // List of children for this window container. List is in z-order as the children appear on 148 // screen with the top-most window container at the tail of the list. 149 protected final WindowList<E> mChildren = new WindowList<E>(); 150 151 // The specified orientation for this window container. 152 @ActivityInfo.ScreenOrientation 153 protected int mOrientation = SCREEN_ORIENTATION_UNSPECIFIED; 154 155 /** 156 * The window container which decides its orientation since the last time 157 * {@link #getOrientation(int) was called. 158 */ 159 protected WindowContainer mLastOrientationSource; 160 161 private final Pools.SynchronizedPool<ForAllWindowsConsumerWrapper> mConsumerWrapperPool = 162 new Pools.SynchronizedPool<>(3); 163 164 // The display this window container is on. 165 protected DisplayContent mDisplayContent; 166 167 protected SurfaceControl mSurfaceControl; 168 private int mLastLayer = 0; 169 private SurfaceControl mLastRelativeToLayer = null; 170 171 // TODO(b/132320879): Remove this from WindowContainers except DisplayContent. 172 private final Transaction mPendingTransaction; 173 174 /** 175 * Windows that clients are waiting to have drawn. 176 */ 177 final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>(); 178 179 /** 180 * Applied as part of the animation pass in "prepareSurfaces". 181 */ 182 protected final SurfaceAnimator mSurfaceAnimator; 183 private boolean mAnyParentAnimating; 184 185 final SurfaceFreezer mSurfaceFreezer; 186 protected final WindowManagerService mWmService; 187 188 /** 189 * Sources which triggered a surface animation on this container. An animation target can be 190 * promoted to higher level, for example, from a set of {@link ActivityRecord}s to 191 * {@link ActivityStack}. In this case, {@link ActivityRecord}s are set on this variable while 192 * the animation is running, and reset after finishing it. 193 */ 194 private final ArraySet<WindowContainer> mSurfaceAnimationSources = new ArraySet<>(); 195 196 private final Point mTmpPos = new Point(); 197 protected final Point mLastSurfacePosition = new Point(); 198 199 /** Total number of elements in this subtree, including our own hierarchy element. */ 200 private int mTreeWeight = 1; 201 202 /** 203 * Indicates whether we are animating and have committed the transaction to reparent our 204 * surface to the animation leash 205 */ 206 private boolean mCommittedReparentToAnimationLeash; 207 208 /** Interface for {@link #isAnimating} to check which cases for the container is animating. */ 209 public interface AnimationFlags { 210 /** 211 * A bit flag indicates that {@link #isAnimating} should also return {@code true} 212 * even though the container is not yet animating, but the window container or its 213 * relatives as specified by PARENTS or CHILDREN are part of an {@link AppTransition} 214 * that is pending so an animation starts soon. 215 */ 216 int TRANSITION = 1; 217 218 /** 219 * A bit flag indicates that {@link #isAnimating} should also check if one of the 220 * ancestors of the container are animating in addition to the container itself. 221 */ 222 int PARENTS = 2; 223 224 /** 225 * A bit flag indicates that {@link #isAnimating} should also check if one of the 226 * descendants of the container are animating in addition to the container itself. 227 */ 228 int CHILDREN = 4; 229 } 230 231 /** 232 * Callback which is triggered while changing the parent, after setting up the surface but 233 * before asking the parent to assign child layers. 234 */ 235 interface PreAssignChildLayersCallback { onPreAssignChildLayers()236 void onPreAssignChildLayers(); 237 } 238 239 /** 240 * True if this an AppWindowToken and the activity which created this was launched with 241 * ActivityOptions.setLaunchTaskBehind. 242 * 243 * TODO(b/142617871): We run a special animation when the activity was launched with that 244 * flag, but it's not necessary anymore. Keep the window invisible until the task is explicitly 245 * selected to suppress an animation, and remove this flag. 246 */ 247 boolean mLaunchTaskBehind; 248 249 /** 250 * If we are running an animation, this determines the transition type. Must be one of 251 * {@link AppTransition#TransitionFlags}. 252 */ 253 int mTransit; 254 255 /** 256 * If we are running an animation, this determines the flags during this animation. Must be a 257 * bitwise combination of AppTransition.TRANSIT_FLAG_* constants. 258 */ 259 int mTransitFlags; 260 261 /** Whether this container should be boosted at the top of all its siblings. */ 262 @VisibleForTesting boolean mNeedsZBoost; 263 264 /** Layer used to constrain the animation to a container's stack bounds. */ 265 SurfaceControl mAnimationBoundsLayer; 266 267 /** Whether this container needs to create mAnimationBoundsLayer for cropping animations. */ 268 boolean mNeedsAnimationBoundsLayer; 269 270 /** 271 * This gets used during some open/close transitions as well as during a change transition 272 * where it represents the starting-state snapshot. 273 */ 274 WindowContainerThumbnail mThumbnail; 275 final Point mTmpPoint = new Point(); 276 protected final Rect mTmpRect = new Rect(); 277 final Rect mTmpPrevBounds = new Rect(); 278 279 private MagnificationSpec mLastMagnificationSpec; 280 281 private boolean mIsFocusable = true; 282 283 /** 284 * Used as a unique, cross-process identifier for this Container. It also serves a minimal 285 * interface to other processes. 286 */ 287 RemoteToken mRemoteToken = null; 288 289 BLASTSyncEngine mBLASTSyncEngine = new BLASTSyncEngine(); 290 SurfaceControl.Transaction mBLASTSyncTransaction; 291 boolean mUsingBLASTSyncTransaction = false; 292 BLASTSyncEngine.TransactionReadyListener mWaitingListener; 293 int mWaitingSyncId; 294 WindowContainer(WindowManagerService wms)295 WindowContainer(WindowManagerService wms) { 296 mWmService = wms; 297 mPendingTransaction = wms.mTransactionFactory.get(); 298 mBLASTSyncTransaction = wms.mTransactionFactory.get(); 299 mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms); 300 mSurfaceFreezer = new SurfaceFreezer(this, wms); 301 } 302 303 @Override getParent()304 final protected WindowContainer getParent() { 305 return mParent; 306 } 307 308 @Override getChildCount()309 protected int getChildCount() { 310 return mChildren.size(); 311 } 312 313 @Override getChildAt(int index)314 protected E getChildAt(int index) { 315 return mChildren.get(index); 316 } 317 318 @Override onConfigurationChanged(Configuration newParentConfig)319 public void onConfigurationChanged(Configuration newParentConfig) { 320 super.onConfigurationChanged(newParentConfig); 321 updateSurfacePosition(); 322 scheduleAnimation(); 323 } 324 reparent(WindowContainer newParent, int position)325 void reparent(WindowContainer newParent, int position) { 326 if (newParent == null) { 327 throw new IllegalArgumentException("reparent: can't reparent to null " + this); 328 } 329 330 final WindowContainer oldParent = mParent; 331 if (mParent == newParent) { 332 throw new IllegalArgumentException("WC=" + this + " already child of " + mParent); 333 } 334 335 // The display object before reparenting as that might lead to old parent getting removed 336 // from the display if it no longer has any child. 337 final DisplayContent prevDc = oldParent.getDisplayContent(); 338 final DisplayContent dc = newParent.getDisplayContent(); 339 340 mReparenting = true; 341 oldParent.removeChild(this); 342 newParent.addChild(this, position); 343 mReparenting = false; 344 345 // Relayout display(s) 346 dc.setLayoutNeeded(); 347 if (prevDc != dc) { 348 onDisplayChanged(dc); 349 prevDc.setLayoutNeeded(); 350 } 351 getDisplayContent().layoutAndAssignWindowLayersIfNeeded(); 352 353 // Send onParentChanged notification here is we disabled sending it in setParent for 354 // reparenting case. 355 onParentChanged(newParent, oldParent); 356 } 357 setParent(WindowContainer<WindowContainer> parent)358 final protected void setParent(WindowContainer<WindowContainer> parent) { 359 final WindowContainer oldParent = mParent; 360 mParent = parent; 361 362 if (mParent != null) { 363 mParent.onChildAdded(this); 364 } 365 if (!mReparenting) { 366 if (mParent != null && mParent.mDisplayContent != null 367 && mDisplayContent != mParent.mDisplayContent) { 368 onDisplayChanged(mParent.mDisplayContent); 369 } 370 onParentChanged(mParent, oldParent); 371 } 372 } 373 374 /** 375 * Callback that is triggered when @link WindowContainer#setParent(WindowContainer)} was called. 376 * Supposed to be overridden and contain actions that should be executed after parent was set. 377 */ 378 @Override onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent)379 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent) { 380 onParentChanged(newParent, oldParent, null); 381 } 382 onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent, PreAssignChildLayersCallback callback)383 void onParentChanged(ConfigurationContainer newParent, ConfigurationContainer oldParent, 384 PreAssignChildLayersCallback callback) { 385 super.onParentChanged(newParent, oldParent); 386 if (mParent == null) { 387 return; 388 } 389 390 if (mSurfaceControl == null) { 391 // If we don't yet have a surface, but we now have a parent, we should 392 // build a surface. 393 createSurfaceControl(false /*force*/); 394 } else { 395 // If we have a surface but a new parent, we just need to perform a reparent. Go through 396 // surface animator such that hierarchy is preserved when animating, i.e. 397 // mSurfaceControl stays attached to the leash and we just reparent the leash to the 398 // new parent. 399 reparentSurfaceControl(getSyncTransaction(), mParent.mSurfaceControl); 400 } 401 402 if (callback != null) { 403 callback.onPreAssignChildLayers(); 404 } 405 406 // Either way we need to ask the parent to assign us a Z-order. 407 mParent.assignChildLayers(); 408 scheduleAnimation(); 409 } 410 createSurfaceControl(boolean force)411 void createSurfaceControl(boolean force) { 412 setInitialSurfaceControlProperties(makeSurface()); 413 } 414 setInitialSurfaceControlProperties(SurfaceControl.Builder b)415 void setInitialSurfaceControlProperties(SurfaceControl.Builder b) { 416 setSurfaceControl(b.setCallsite("WindowContainer.setInitialSurfaceControlProperties").build()); 417 getSyncTransaction().show(mSurfaceControl); 418 onSurfaceShown(getSyncTransaction()); 419 updateSurfacePosition(); 420 } 421 422 /** 423 * Create a new SurfaceControl for this WindowContainer and migrate all properties to the new 424 * SurfaceControl. Properties include: 425 * 1. Children 426 * 2. Position 427 * 3. Z order 428 * 429 * Remove the old SurfaceControl since it's no longer needed. 430 * 431 * This is used to revoke control of the SurfaceControl from a client process that was 432 * previously organizing this WindowContainer. 433 */ migrateToNewSurfaceControl()434 void migrateToNewSurfaceControl() { 435 SurfaceControl.Transaction t = getPendingTransaction(); 436 t.remove(mSurfaceControl); 437 // Clear the last position so the new SurfaceControl will get correct position 438 mLastSurfacePosition.set(0, 0); 439 440 final SurfaceControl.Builder b = mWmService.makeSurfaceBuilder(null) 441 .setContainerLayer() 442 .setName(getName()); 443 444 setInitialSurfaceControlProperties(b); 445 446 // If parent is null, the layer should be placed offscreen so reparent to null. Otherwise, 447 // set to the available parent. 448 t.reparent(mSurfaceControl, mParent == null ? null : mParent.getSurfaceControl()); 449 450 if (mLastRelativeToLayer != null) { 451 t.setRelativeLayer(mSurfaceControl, mLastRelativeToLayer, mLastLayer); 452 } else { 453 t.setLayer(mSurfaceControl, mLastLayer); 454 } 455 456 for (int i = 0; i < mChildren.size(); i++) { 457 SurfaceControl sc = mChildren.get(i).getSurfaceControl(); 458 if (sc != null) { 459 t.reparent(sc, mSurfaceControl); 460 } 461 } 462 scheduleAnimation(); 463 } 464 465 /** 466 * Called when the surface is shown for the first time. 467 */ onSurfaceShown(Transaction t)468 void onSurfaceShown(Transaction t) { 469 // do nothing 470 } 471 472 // Temp. holders for a chain of containers we are currently processing. 473 private final LinkedList<WindowContainer> mTmpChain1 = new LinkedList<>(); 474 private final LinkedList<WindowContainer> mTmpChain2 = new LinkedList<>(); 475 476 /** 477 * Adds the input window container has a child of this container in order based on the input 478 * comparator. 479 * @param child The window container to add as a child of this window container. 480 * @param comparator Comparator to use in determining the position the child should be added to. 481 * If null, the child will be added to the top. 482 */ 483 @CallSuper addChild(E child, Comparator<E> comparator)484 protected void addChild(E child, Comparator<E> comparator) { 485 if (!child.mReparenting && child.getParent() != null) { 486 throw new IllegalArgumentException("addChild: container=" + child.getName() 487 + " is already a child of container=" + child.getParent().getName() 488 + " can't add to container=" + getName()); 489 } 490 491 int positionToAdd = -1; 492 if (comparator != null) { 493 final int count = mChildren.size(); 494 for (int i = 0; i < count; i++) { 495 if (comparator.compare(child, mChildren.get(i)) < 0) { 496 positionToAdd = i; 497 break; 498 } 499 } 500 } 501 502 if (positionToAdd == -1) { 503 mChildren.add(child); 504 } else { 505 mChildren.add(positionToAdd, child); 506 } 507 508 // Set the parent after we've actually added a child in case a subclass depends on this. 509 child.setParent(this); 510 } 511 512 /** Adds the input window container has a child of this container at the input index. */ 513 @CallSuper addChild(E child, int index)514 void addChild(E child, int index) { 515 if (!child.mReparenting && child.getParent() != null) { 516 throw new IllegalArgumentException("addChild: container=" + child.getName() 517 + " is already a child of container=" + child.getParent().getName() 518 + " can't add to container=" + getName() 519 + "\n callers=" + Debug.getCallers(15, "\n")); 520 } 521 522 if ((index < 0 && index != POSITION_BOTTOM) 523 || (index > mChildren.size() && index != POSITION_TOP)) { 524 throw new IllegalArgumentException("addChild: invalid position=" + index 525 + ", children number=" + mChildren.size()); 526 } 527 528 if (index == POSITION_TOP) { 529 index = mChildren.size(); 530 } else if (index == POSITION_BOTTOM) { 531 index = 0; 532 } 533 534 mChildren.add(index, child); 535 536 // Set the parent after we've actually added a child in case a subclass depends on this. 537 child.setParent(this); 538 } 539 onChildAdded(WindowContainer child)540 private void onChildAdded(WindowContainer child) { 541 mTreeWeight += child.mTreeWeight; 542 WindowContainer parent = getParent(); 543 while (parent != null) { 544 parent.mTreeWeight += child.mTreeWeight; 545 parent = parent.getParent(); 546 } 547 onChildPositionChanged(child); 548 } 549 550 /** 551 * Removes the input child container from this container which is its parent. 552 * 553 * @return True if the container did contain the input child and it was detached. 554 */ 555 @CallSuper removeChild(E child)556 void removeChild(E child) { 557 if (mChildren.remove(child)) { 558 onChildRemoved(child); 559 if (!child.mReparenting) { 560 child.setParent(null); 561 } 562 } else { 563 throw new IllegalArgumentException("removeChild: container=" + child.getName() 564 + " is not a child of container=" + getName()); 565 } 566 } 567 onChildRemoved(WindowContainer child)568 private void onChildRemoved(WindowContainer child) { 569 mTreeWeight -= child.mTreeWeight; 570 WindowContainer parent = getParent(); 571 while (parent != null) { 572 parent.mTreeWeight -= child.mTreeWeight; 573 parent = parent.getParent(); 574 } 575 onChildPositionChanged(child); 576 } 577 578 /** 579 * Removes this window container and its children with no regard for what else might be going on 580 * in the system. For example, the container will be removed during animation if this method is 581 * called which isn't desirable. For most cases you want to call {@link #removeIfPossible()} 582 * which allows the system to defer removal until a suitable time. 583 */ 584 @CallSuper removeImmediately()585 void removeImmediately() { 586 final DisplayContent dc = getDisplayContent(); 587 if (dc != null) { 588 mSurfaceFreezer.unfreeze(getSyncTransaction()); 589 dc.mChangingContainers.remove(this); 590 } 591 while (!mChildren.isEmpty()) { 592 final E child = mChildren.peekLast(); 593 child.removeImmediately(); 594 // Need to do this after calling remove on the child because the child might try to 595 // remove/detach itself from its parent which will cause an exception if we remove 596 // it before calling remove on the child. 597 if (mChildren.remove(child)) { 598 onChildRemoved(child); 599 } 600 } 601 602 if (mSurfaceControl != null) { 603 getSyncTransaction().remove(mSurfaceControl); 604 setSurfaceControl(null); 605 mLastSurfacePosition.set(0, 0); 606 scheduleAnimation(); 607 } 608 609 if (mParent != null) { 610 mParent.removeChild(this); 611 } 612 } 613 614 /** 615 * @return The index of this element in the hierarchy tree in prefix order. 616 */ getPrefixOrderIndex()617 int getPrefixOrderIndex() { 618 if (mParent == null) { 619 return 0; 620 } 621 return mParent.getPrefixOrderIndex(this); 622 } 623 getPrefixOrderIndex(WindowContainer child)624 private int getPrefixOrderIndex(WindowContainer child) { 625 int order = 0; 626 for (int i = 0; i < mChildren.size(); i++) { 627 final WindowContainer childI = mChildren.get(i); 628 if (child == childI) { 629 break; 630 } 631 order += childI.mTreeWeight; 632 } 633 if (mParent != null) { 634 order += mParent.getPrefixOrderIndex(this); 635 } 636 637 // We also need to count ourselves. 638 order++; 639 return order; 640 } 641 642 /** 643 * Removes this window container and its children taking care not to remove them during a 644 * critical stage in the system. For example, some containers will not be removed during 645 * animation if this method is called. 646 */ 647 // TODO: figure-out implementation that works best for this. 648 // E.g. when do we remove from parent list? maybe not... removeIfPossible()649 void removeIfPossible() { 650 for (int i = mChildren.size() - 1; i >= 0; --i) { 651 final WindowContainer wc = mChildren.get(i); 652 wc.removeIfPossible(); 653 } 654 } 655 656 /** Returns true if this window container has the input child. */ hasChild(E child)657 boolean hasChild(E child) { 658 for (int i = mChildren.size() - 1; i >= 0; --i) { 659 final E current = mChildren.get(i); 660 if (current == child || current.hasChild(child)) { 661 return true; 662 } 663 } 664 return false; 665 } 666 667 /** @return true if this window container is a descendant of the input container. */ isDescendantOf(WindowContainer ancestor)668 boolean isDescendantOf(WindowContainer ancestor) { 669 final WindowContainer parent = getParent(); 670 if (parent == ancestor) return true; 671 return (parent != null) && parent.isDescendantOf(ancestor); 672 } 673 674 /** 675 * Move a child from it's current place in siblings list to the specified position, 676 * with an option to move all its parents to top. 677 * @param position Target position to move the child to. 678 * @param child Child to move to selected position. 679 * @param includingParents Flag indicating whether we need to move the entire branch of the 680 * hierarchy when we're moving a child to {@link #POSITION_TOP} or 681 * {@link #POSITION_BOTTOM}. When moving to other intermediate positions 682 * this flag will do nothing. 683 */ 684 @CallSuper positionChildAt(int position, E child, boolean includingParents)685 void positionChildAt(int position, E child, boolean includingParents) { 686 687 if (child.getParent() != this) { 688 throw new IllegalArgumentException("positionChildAt: container=" + child.getName() 689 + " is not a child of container=" + getName() 690 + " current parent=" + child.getParent()); 691 } 692 693 if (position >= mChildren.size() - 1) { 694 position = POSITION_TOP; 695 } else if (position <= 0) { 696 position = POSITION_BOTTOM; 697 } 698 699 switch (position) { 700 case POSITION_TOP: 701 if (mChildren.peekLast() != child) { 702 mChildren.remove(child); 703 mChildren.add(child); 704 onChildPositionChanged(child); 705 } 706 if (includingParents && getParent() != null) { 707 getParent().positionChildAt(POSITION_TOP, this /* child */, 708 true /* includingParents */); 709 } 710 break; 711 case POSITION_BOTTOM: 712 if (mChildren.peekFirst() != child) { 713 mChildren.remove(child); 714 mChildren.addFirst(child); 715 onChildPositionChanged(child); 716 } 717 if (includingParents && getParent() != null) { 718 getParent().positionChildAt(POSITION_BOTTOM, this /* child */, 719 true /* includingParents */); 720 } 721 break; 722 default: 723 // TODO: Removing the child before reinserting requires the caller to provide a 724 // position that takes into account the removed child (if the index of the 725 // child < position, then the position should be adjusted). We should consider 726 // doing this adjustment here and remove any adjustments in the callers. 727 if (mChildren.indexOf(child) != position) { 728 mChildren.remove(child); 729 mChildren.add(position, child); 730 onChildPositionChanged(child); 731 } 732 } 733 } 734 735 /** 736 * Notify that a child's position has changed. Possible changes are adding or removing a child. 737 */ onChildPositionChanged(WindowContainer child)738 void onChildPositionChanged(WindowContainer child) { } 739 740 /** 741 * Update override configuration and recalculate full config. 742 * @see #mRequestedOverrideConfiguration 743 * @see #mFullConfiguration 744 */ 745 @Override onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration)746 public void onRequestedOverrideConfigurationChanged(Configuration overrideConfiguration) { 747 // We must diff before the configuration is applied so that we can capture the change 748 // against the existing bounds. 749 final int diff = diffRequestedOverrideBounds( 750 overrideConfiguration.windowConfiguration.getBounds()); 751 super.onRequestedOverrideConfigurationChanged(overrideConfiguration); 752 if (mParent != null) { 753 mParent.onDescendantOverrideConfigurationChanged(); 754 } 755 756 if (diff == BOUNDS_CHANGE_NONE) { 757 return; 758 } 759 760 if ((diff & BOUNDS_CHANGE_SIZE) == BOUNDS_CHANGE_SIZE) { 761 onResize(); 762 } else { 763 onMovedByResize(); 764 } 765 } 766 767 /** 768 * Notify that a descendant's overrideConfiguration has changed. 769 */ onDescendantOverrideConfigurationChanged()770 void onDescendantOverrideConfigurationChanged() { 771 if (mParent != null) { 772 mParent.onDescendantOverrideConfigurationChanged(); 773 } 774 } 775 776 /** 777 * Notify that the display this container is on has changed. This could be either this container 778 * is moved to a new display, or some configurations on the display it is on changes. 779 * 780 * @param dc The display this container is on after changes. 781 */ onDisplayChanged(DisplayContent dc)782 void onDisplayChanged(DisplayContent dc) { 783 if (mDisplayContent != null && mDisplayContent.mChangingContainers.remove(this)) { 784 // Cancel any change transition queued-up for this container on the old display. 785 mSurfaceFreezer.unfreeze(getPendingTransaction()); 786 } 787 mDisplayContent = dc; 788 if (dc != null && dc != this) { 789 dc.getPendingTransaction().merge(mPendingTransaction); 790 } 791 for (int i = mChildren.size() - 1; i >= 0; --i) { 792 final WindowContainer child = mChildren.get(i); 793 child.onDisplayChanged(dc); 794 } 795 } 796 getDisplayContent()797 DisplayContent getDisplayContent() { 798 return mDisplayContent; 799 } 800 801 /** Get the first node of type {@link DisplayArea} above or at this node. */ 802 @Nullable getDisplayArea()803 DisplayArea getDisplayArea() { 804 WindowContainer parent = getParent(); 805 return parent != null ? parent.getDisplayArea() : null; 806 } 807 isAttached()808 boolean isAttached() { 809 return getDisplayArea() != null; 810 } 811 setWaitingForDrawnIfResizingChanged()812 void setWaitingForDrawnIfResizingChanged() { 813 for (int i = mChildren.size() - 1; i >= 0; --i) { 814 final WindowContainer wc = mChildren.get(i); 815 wc.setWaitingForDrawnIfResizingChanged(); 816 } 817 } 818 onResize()819 void onResize() { 820 for (int i = mChildren.size() - 1; i >= 0; --i) { 821 final WindowContainer wc = mChildren.get(i); 822 wc.onParentResize(); 823 } 824 } 825 onParentResize()826 void onParentResize() { 827 // In the case this container has specified its own bounds, a parent resize will not 828 // affect its bounds. Any relevant changes will be propagated through changes to the 829 // Configuration override. 830 if (hasOverrideBounds()) { 831 return; 832 } 833 834 // Default implementation is to treat as resize on self. 835 onResize(); 836 } 837 onMovedByResize()838 void onMovedByResize() { 839 for (int i = mChildren.size() - 1; i >= 0; --i) { 840 final WindowContainer wc = mChildren.get(i); 841 wc.onMovedByResize(); 842 } 843 } 844 resetDragResizingChangeReported()845 void resetDragResizingChangeReported() { 846 for (int i = mChildren.size() - 1; i >= 0; --i) { 847 final WindowContainer wc = mChildren.get(i); 848 wc.resetDragResizingChangeReported(); 849 } 850 } 851 forceWindowsScaleableInTransaction(boolean force)852 void forceWindowsScaleableInTransaction(boolean force) { 853 for (int i = mChildren.size() - 1; i >= 0; --i) { 854 final WindowContainer wc = mChildren.get(i); 855 wc.forceWindowsScaleableInTransaction(force); 856 } 857 } 858 859 /** 860 * @return {@code true} when this container or its related containers are running an 861 * animation, {@code false} otherwise. 862 * 863 * By default this predicate only checks if this container itself is actually running an 864 * animation, but you can extend the check target over its relatives, or relax the condition 865 * so that this can return {@code true} if an animation starts soon by giving a combination 866 * of {@link AnimationFlags}. 867 * 868 * Note that you can give a combination of bitmask flags to specify targets and condition for 869 * checking animating status. 870 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this 871 * container itself or one of its parents is running an animation or waiting for an app 872 * transition. 873 * 874 * Note that TRANSITION propagates to parents and children as well. 875 * 876 * @param flags The combination of bitmask flags to specify targets and condition for 877 * checking animating status. 878 * @param typesToCheck The combination of bitmask {@link AnimationType} to compare when 879 * determining if animating. 880 * 881 * @see AnimationFlags#TRANSITION 882 * @see AnimationFlags#PARENTS 883 * @see AnimationFlags#CHILDREN 884 */ isAnimating(int flags, int typesToCheck)885 final boolean isAnimating(int flags, int typesToCheck) { 886 return getAnimatingContainer(flags, typesToCheck) != null; 887 } 888 889 /** 890 * Similar to {@link #isAnimating(int, int)} except provide a bitmask of 891 * {@link AnimationType} to exclude, rather than include 892 * @param flags The combination of bitmask flags to specify targets and condition for 893 * checking animating status. 894 * @param typesToExclude The combination of bitmask {@link AnimationType} to exclude when 895 * checking if animating. 896 * 897 * @deprecated Use {@link #isAnimating(int, int)} 898 */ 899 @Deprecated isAnimatingExcluding(int flags, int typesToExclude)900 final boolean isAnimatingExcluding(int flags, int typesToExclude) { 901 return isAnimating(flags, ANIMATION_TYPE_ALL & ~typesToExclude); 902 } 903 904 /** 905 * @deprecated Use {@link #isAnimating(int, int)} 906 * TODO (b/152333373): Migrate calls to use isAnimating with specified animation type 907 */ 908 @Deprecated isAnimating(int flags)909 final boolean isAnimating(int flags) { 910 return isAnimating(flags, ANIMATION_TYPE_ALL); 911 } 912 913 /** 914 * @return {@code true} when the container is waiting the app transition start, {@code false} 915 * otherwise. 916 */ isWaitingForTransitionStart()917 boolean isWaitingForTransitionStart() { 918 return false; 919 } 920 921 /** 922 * @return {@code true} if in this subtree of the hierarchy we have an 923 * {@code ActivityRecord#isAnimating(TRANSITION)}, {@code false} otherwise. 924 */ isAppTransitioning()925 boolean isAppTransitioning() { 926 return getActivity(app -> app.isAnimating(PARENTS | TRANSITION)) != null; 927 } 928 929 /** 930 * @return Whether our own container running an animation at the moment. 931 */ isAnimating()932 final boolean isAnimating() { 933 return isAnimating(0 /* self only */); 934 } 935 936 /** 937 * @return {@code true} if the container is in changing app transition. 938 */ isChangingAppTransition()939 boolean isChangingAppTransition() { 940 return mDisplayContent != null && mDisplayContent.mChangingContainers.contains(this); 941 } 942 sendAppVisibilityToClients()943 void sendAppVisibilityToClients() { 944 for (int i = mChildren.size() - 1; i >= 0; --i) { 945 final WindowContainer wc = mChildren.get(i); 946 wc.sendAppVisibilityToClients(); 947 } 948 } 949 950 /** 951 * Returns true if the container or one of its children as some content it can display or wants 952 * to display (e.g. app views or saved surface). 953 * 954 * NOTE: While this method will return true if the there is some content to display, it doesn't 955 * mean the container is visible. Use {@link #isVisible()} to determine if the container is 956 * visible. 957 */ hasContentToDisplay()958 boolean hasContentToDisplay() { 959 for (int i = mChildren.size() - 1; i >= 0; --i) { 960 final WindowContainer wc = mChildren.get(i); 961 if (wc.hasContentToDisplay()) { 962 return true; 963 } 964 } 965 return false; 966 } 967 968 /** 969 * Returns true if the container or one of its children is considered visible from the 970 * WindowManager perspective which usually means valid surface and some other internal state 971 * are true. 972 * 973 * NOTE: While this method will return true if the surface is visible, it doesn't mean the 974 * client has actually displayed any content. Use {@link #hasContentToDisplay()} to determine if 975 * the container has any content to display. 976 */ isVisible()977 boolean isVisible() { 978 // TODO: Will this be more correct if it checks the visibility of its parents? 979 // It depends...For example, Tasks and Stacks are only visible if there children are visible 980 // but, WindowState are not visible if there parent are not visible. Maybe have the 981 // container specify which direction to traverse for visibility? 982 for (int i = mChildren.size() - 1; i >= 0; --i) { 983 final WindowContainer wc = mChildren.get(i); 984 if (wc.isVisible()) { 985 return true; 986 } 987 } 988 return false; 989 } 990 991 /** 992 * Called when the visibility of a child is asked to change. This is before visibility actually 993 * changes (eg. a transition animation might play out first). 994 */ onChildVisibilityRequested(boolean visible)995 void onChildVisibilityRequested(boolean visible) { 996 // If we are changing visibility, then a snapshot isn't necessary and we are no-longer 997 // part of a change transition. 998 mSurfaceFreezer.unfreeze(getSyncTransaction()); 999 if (mDisplayContent != null) { 1000 mDisplayContent.mChangingContainers.remove(this); 1001 } 1002 WindowContainer parent = getParent(); 1003 if (parent != null) { 1004 parent.onChildVisibilityRequested(visible); 1005 } 1006 } 1007 writeIdentifierToProto(ProtoOutputStream proto, long fieldId)1008 void writeIdentifierToProto(ProtoOutputStream proto, long fieldId) { 1009 final long token = proto.start(fieldId); 1010 proto.write(HASH_CODE, System.identityHashCode(this)); 1011 proto.write(USER_ID, USER_NULL); 1012 proto.write(TITLE, "WindowContainer"); 1013 proto.end(token); 1014 } 1015 1016 /** 1017 * Returns {@code true} if this container is focusable. Generally, if a parent is not focusable, 1018 * this will not be focusable either. 1019 */ isFocusable()1020 boolean isFocusable() { 1021 final WindowContainer parent = getParent(); 1022 return (parent == null || parent.isFocusable()) && mIsFocusable; 1023 } 1024 1025 /** Set whether this container or its children can be focusable */ setFocusable(boolean focusable)1026 boolean setFocusable(boolean focusable) { 1027 if (mIsFocusable == focusable) { 1028 return false; 1029 } 1030 mIsFocusable = focusable; 1031 return true; 1032 } 1033 1034 /** 1035 * @return Whether this child is on top of the window hierarchy. 1036 */ isOnTop()1037 boolean isOnTop() { 1038 final WindowContainer parent = getParent(); 1039 return parent != null && parent.getTopChild() == this && parent.isOnTop(); 1040 } 1041 1042 /** Returns the top child container. */ getTopChild()1043 E getTopChild() { 1044 return mChildren.peekLast(); 1045 } 1046 1047 /** 1048 * Removes the containers which were deferred. 1049 * 1050 * @return {@code true} if there is still a removal being deferred. 1051 */ handleCompleteDeferredRemoval()1052 boolean handleCompleteDeferredRemoval() { 1053 boolean stillDeferringRemoval = false; 1054 1055 for (int i = mChildren.size() - 1; i >= 0; --i) { 1056 final WindowContainer wc = mChildren.get(i); 1057 stillDeferringRemoval |= wc.handleCompleteDeferredRemoval(); 1058 if (!hasChild()) { 1059 // All child containers of current level could be removed from a removal of 1060 // descendant. E.g. if a display is pending to be removed because it contains an 1061 // activity with {@link ActivityRecord#mIsExiting} is true, the display may be 1062 // removed when completing the removal of the last activity from 1063 // {@link ActivityRecord#checkCompleteDeferredRemoval}. 1064 return false; 1065 } 1066 } 1067 1068 return stillDeferringRemoval; 1069 } 1070 1071 /** Checks if all windows in an app are all drawn and shows them if needed. */ checkAppWindowsReadyToShow()1072 void checkAppWindowsReadyToShow() { 1073 for (int i = mChildren.size() - 1; i >= 0; --i) { 1074 final WindowContainer wc = mChildren.get(i); 1075 wc.checkAppWindowsReadyToShow(); 1076 } 1077 } 1078 onAppTransitionDone()1079 void onAppTransitionDone() { 1080 for (int i = mChildren.size() - 1; i >= 0; --i) { 1081 final WindowContainer wc = mChildren.get(i); 1082 wc.onAppTransitionDone(); 1083 } 1084 } 1085 1086 /** 1087 * Called when this container or one of its descendants changed its requested orientation, and 1088 * wants this container to handle it or pass it to its parent. 1089 * 1090 * @param freezeDisplayToken freeze this app window token if display needs to freeze 1091 * @param requestingContainer the container which orientation request has changed 1092 * @return {@code true} if handled; {@code false} otherwise. 1093 */ onDescendantOrientationChanged(@ullable IBinder freezeDisplayToken, @Nullable ConfigurationContainer requestingContainer)1094 boolean onDescendantOrientationChanged(@Nullable IBinder freezeDisplayToken, 1095 @Nullable ConfigurationContainer requestingContainer) { 1096 final WindowContainer parent = getParent(); 1097 if (parent == null) { 1098 return false; 1099 } 1100 return parent.onDescendantOrientationChanged(freezeDisplayToken, 1101 requestingContainer); 1102 } 1103 1104 /** 1105 * Check if this container or its parent will handle orientation changes from descendants. It's 1106 * different from the return value of {@link #onDescendantOrientationChanged(IBinder, 1107 * ConfigurationContainer)} in the sense that the return value of this method tells if this 1108 * container or its parent will handle the request eventually, while the return value of the 1109 * other method is if it handled the request synchronously. 1110 * 1111 * @return {@code true} if it handles or will handle orientation change in the future; {@code 1112 * false} if it won't handle the change at anytime. 1113 */ handlesOrientationChangeFromDescendant()1114 boolean handlesOrientationChangeFromDescendant() { 1115 final WindowContainer parent = getParent(); 1116 return parent != null && parent.handlesOrientationChangeFromDescendant(); 1117 } 1118 1119 /** 1120 * Get the configuration orientation by the requested screen orientation 1121 * ({@link ActivityInfo.ScreenOrientation}) of this activity. 1122 * 1123 * @return orientation in ({@link Configuration#ORIENTATION_LANDSCAPE}, 1124 * {@link Configuration#ORIENTATION_PORTRAIT}, 1125 * {@link Configuration#ORIENTATION_UNDEFINED}). 1126 */ getRequestedConfigurationOrientation()1127 int getRequestedConfigurationOrientation() { 1128 if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_NOSENSOR) { 1129 // NOSENSOR means the display's "natural" orientation, so return that. 1130 if (mDisplayContent != null) { 1131 return mDisplayContent.getNaturalOrientation(); 1132 } 1133 } else if (mOrientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) { 1134 // LOCKED means the activity's orientation remains unchanged, so return existing value. 1135 return getConfiguration().orientation; 1136 } else if (isFixedOrientationLandscape(mOrientation)) { 1137 return ORIENTATION_LANDSCAPE; 1138 } else if (isFixedOrientationPortrait(mOrientation)) { 1139 return ORIENTATION_PORTRAIT; 1140 } 1141 return ORIENTATION_UNDEFINED; 1142 } 1143 1144 /** 1145 * Calls {@link #setOrientation(int, IBinder, ActivityRecord)} with {@code null} to the last 2 1146 * parameters. 1147 * 1148 * @param orientation the specified orientation. 1149 */ setOrientation(int orientation)1150 void setOrientation(int orientation) { 1151 setOrientation(orientation, null /* freezeDisplayToken */, 1152 null /* ActivityRecord */); 1153 } 1154 1155 /** 1156 * Sets the specified orientation of this container. It percolates this change upward along the 1157 * hierarchy to let each level of the hierarchy a chance to respond to it. 1158 * 1159 * @param orientation the specified orientation. Needs to be one of {@link 1160 * android.content.pm.ActivityInfo.ScreenOrientation}. 1161 * @param freezeDisplayToken uses this token to freeze display if orientation change is not 1162 * done. Display will not be frozen if this is {@code null}, which 1163 * should only happen in tests. 1164 * @param requestingContainer the container which orientation request has changed. Mostly used 1165 * to ensure it gets correct configuration. 1166 */ setOrientation(int orientation, @Nullable IBinder freezeDisplayToken, @Nullable ConfigurationContainer requestingContainer)1167 void setOrientation(int orientation, @Nullable IBinder freezeDisplayToken, 1168 @Nullable ConfigurationContainer requestingContainer) { 1169 if (mOrientation == orientation) { 1170 return; 1171 } 1172 1173 mOrientation = orientation; 1174 final WindowContainer parent = getParent(); 1175 if (parent != null) { 1176 if (getConfiguration().orientation != getRequestedConfigurationOrientation()) { 1177 // Resolve the requested orientation. 1178 onConfigurationChanged(parent.getConfiguration()); 1179 } 1180 onDescendantOrientationChanged(freezeDisplayToken, requestingContainer); 1181 } 1182 } 1183 1184 @ActivityInfo.ScreenOrientation getOrientation()1185 int getOrientation() { 1186 return getOrientation(mOrientation); 1187 } 1188 1189 /** 1190 * Returns the specified orientation for this window container or one of its children is there 1191 * is one set, or {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSET} if no 1192 * specification is set. 1193 * NOTE: {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} is a 1194 * specification... 1195 * 1196 * @param candidate The current orientation candidate that will be returned if we don't find a 1197 * better match. 1198 * @return The orientation as specified by this branch or the window hierarchy. 1199 */ getOrientation(int candidate)1200 int getOrientation(int candidate) { 1201 mLastOrientationSource = null; 1202 if (!fillsParent()) { 1203 // Ignore containers that don't completely fill their parents. 1204 return SCREEN_ORIENTATION_UNSET; 1205 } 1206 1207 // The container fills its parent so we can use it orientation if it has one 1208 // specified; otherwise we prefer to use the orientation of its topmost child that has one 1209 // specified and fall back on this container's unset or unspecified value as a candidate 1210 // if none of the children have a better candidate for the orientation. 1211 if (mOrientation != SCREEN_ORIENTATION_UNSET 1212 && mOrientation != SCREEN_ORIENTATION_UNSPECIFIED) { 1213 mLastOrientationSource = this; 1214 return mOrientation; 1215 } 1216 1217 for (int i = mChildren.size() - 1; i >= 0; --i) { 1218 final WindowContainer wc = mChildren.get(i); 1219 1220 // TODO: Maybe mOrientation should default to SCREEN_ORIENTATION_UNSET vs. 1221 // SCREEN_ORIENTATION_UNSPECIFIED? 1222 final int orientation = wc.getOrientation(candidate == SCREEN_ORIENTATION_BEHIND 1223 ? SCREEN_ORIENTATION_BEHIND : SCREEN_ORIENTATION_UNSET); 1224 if (orientation == SCREEN_ORIENTATION_BEHIND) { 1225 // container wants us to use the orientation of the container behind it. See if we 1226 // can find one. Else return SCREEN_ORIENTATION_BEHIND so the caller can choose to 1227 // look behind this container. 1228 candidate = orientation; 1229 mLastOrientationSource = wc; 1230 continue; 1231 } 1232 1233 if (orientation == SCREEN_ORIENTATION_UNSET) { 1234 continue; 1235 } 1236 1237 if (wc.fillsParent() || orientation != SCREEN_ORIENTATION_UNSPECIFIED) { 1238 // Use the orientation if the container fills its parent or requested an explicit 1239 // orientation that isn't SCREEN_ORIENTATION_UNSPECIFIED. 1240 ProtoLog.v(WM_DEBUG_ORIENTATION, "%s is requesting orientation %d (%s)", 1241 wc.toString(), orientation, 1242 ActivityInfo.screenOrientationToString(orientation)); 1243 mLastOrientationSource = wc; 1244 return orientation; 1245 } 1246 } 1247 1248 return candidate; 1249 } 1250 1251 /** 1252 * @return The deepest source which decides the orientation of this window container since the 1253 * last time {@link #getOrientation(int) was called. 1254 */ 1255 @Nullable getLastOrientationSource()1256 WindowContainer getLastOrientationSource() { 1257 final WindowContainer source = mLastOrientationSource; 1258 if (source != null && source != this) { 1259 final WindowContainer nextSource = source.getLastOrientationSource(); 1260 if (nextSource != null) { 1261 return nextSource; 1262 } 1263 } 1264 return source; 1265 } 1266 1267 /** 1268 * Returns true if this container is opaque and fills all the space made available by its parent 1269 * container. 1270 * 1271 * NOTE: It is possible for this container to occupy more space than the parent has (or less), 1272 * this is just a signal from the client to window manager stating its intent, but not what it 1273 * actually does. 1274 */ fillsParent()1275 boolean fillsParent() { 1276 return false; 1277 } 1278 1279 // TODO: Users would have their own window containers under the display container? switchUser(int userId)1280 void switchUser(int userId) { 1281 for (int i = mChildren.size() - 1; i >= 0; --i) { 1282 mChildren.get(i).switchUser(userId); 1283 } 1284 } 1285 showToCurrentUser()1286 boolean showToCurrentUser() { 1287 return true; 1288 } 1289 1290 /** 1291 * For all windows at or below this container call the callback. 1292 * @param callback Calls the {@link ToBooleanFunction#apply} method for each window found and 1293 * stops the search if {@link ToBooleanFunction#apply} returns true. 1294 * @param traverseTopToBottom If true traverses the hierarchy from top-to-bottom in terms of 1295 * z-order, else from bottom-to-top. 1296 * @return True if the search ended before we reached the end of the hierarchy due to 1297 * {@link ToBooleanFunction#apply} returning true. 1298 */ forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom)1299 boolean forAllWindows(ToBooleanFunction<WindowState> callback, boolean traverseTopToBottom) { 1300 if (traverseTopToBottom) { 1301 for (int i = mChildren.size() - 1; i >= 0; --i) { 1302 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) { 1303 return true; 1304 } 1305 } 1306 } else { 1307 final int count = mChildren.size(); 1308 for (int i = 0; i < count; i++) { 1309 if (mChildren.get(i).forAllWindows(callback, traverseTopToBottom)) { 1310 return true; 1311 } 1312 } 1313 } 1314 return false; 1315 } 1316 forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom)1317 void forAllWindows(Consumer<WindowState> callback, boolean traverseTopToBottom) { 1318 ForAllWindowsConsumerWrapper wrapper = obtainConsumerWrapper(callback); 1319 forAllWindows(wrapper, traverseTopToBottom); 1320 wrapper.release(); 1321 } 1322 forAllActivities(Function<ActivityRecord, Boolean> callback)1323 boolean forAllActivities(Function<ActivityRecord, Boolean> callback) { 1324 return forAllActivities(callback, true /*traverseTopToBottom*/); 1325 } 1326 forAllActivities( Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom)1327 boolean forAllActivities( 1328 Function<ActivityRecord, Boolean> callback, boolean traverseTopToBottom) { 1329 if (traverseTopToBottom) { 1330 for (int i = mChildren.size() - 1; i >= 0; --i) { 1331 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true; 1332 } 1333 } else { 1334 final int count = mChildren.size(); 1335 for (int i = 0; i < count; i++) { 1336 if (mChildren.get(i).forAllActivities(callback, traverseTopToBottom)) return true; 1337 } 1338 } 1339 1340 return false; 1341 } 1342 forAllActivities(Consumer<ActivityRecord> callback)1343 void forAllActivities(Consumer<ActivityRecord> callback) { 1344 forAllActivities(callback, true /*traverseTopToBottom*/); 1345 } 1346 forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom)1347 void forAllActivities(Consumer<ActivityRecord> callback, boolean traverseTopToBottom) { 1348 if (traverseTopToBottom) { 1349 for (int i = mChildren.size() - 1; i >= 0; --i) { 1350 mChildren.get(i).forAllActivities(callback, traverseTopToBottom); 1351 } 1352 } else { 1353 final int count = mChildren.size(); 1354 for (int i = 0; i < count; i++) { 1355 mChildren.get(i).forAllActivities(callback, traverseTopToBottom); 1356 } 1357 } 1358 } 1359 1360 /** 1361 * Process all activities in this branch of the tree. 1362 * 1363 * @param callback Called for each activity found. 1364 * @param boundary We don't return activities via {@param callback} until we get to this node in 1365 * the tree. 1366 * @param includeBoundary If the boundary from be processed to return activities. 1367 * @param traverseTopToBottom direction to traverse the tree. 1368 * @return {@code true} if we ended the search before reaching the end of the tree. 1369 */ forAllActivities(Function<ActivityRecord, Boolean> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom)1370 final boolean forAllActivities(Function<ActivityRecord, Boolean> callback, 1371 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) { 1372 return forAllActivities( 1373 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]); 1374 } 1375 forAllActivities(Function<ActivityRecord, Boolean> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound)1376 private boolean forAllActivities(Function<ActivityRecord, Boolean> callback, 1377 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, 1378 boolean[] boundaryFound) { 1379 if (traverseTopToBottom) { 1380 for (int i = mChildren.size() - 1; i >= 0; --i) { 1381 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary, 1382 traverseTopToBottom, boundaryFound, mChildren.get(i))) { 1383 return true; 1384 } 1385 } 1386 } else { 1387 final int count = mChildren.size(); 1388 for (int i = 0; i < count; i++) { 1389 if (processForAllActivitiesWithBoundary(callback, boundary, includeBoundary, 1390 traverseTopToBottom, boundaryFound, mChildren.get(i))) { 1391 return true; 1392 } 1393 } 1394 } 1395 1396 return false; 1397 } 1398 processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound, WindowContainer wc)1399 private boolean processForAllActivitiesWithBoundary(Function<ActivityRecord, Boolean> callback, 1400 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, 1401 boolean[] boundaryFound, WindowContainer wc) { 1402 if (wc == boundary) { 1403 boundaryFound[0] = true; 1404 if (!includeBoundary) return false; 1405 } 1406 1407 if (boundaryFound[0]) { 1408 return wc.forAllActivities(callback, traverseTopToBottom); 1409 } 1410 1411 return wc.forAllActivities( 1412 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound); 1413 } 1414 1415 /** @return {@code true} if this node or any of its children contains an activity. */ hasActivity()1416 boolean hasActivity() { 1417 for (int i = mChildren.size() - 1; i >= 0; --i) { 1418 if (mChildren.get(i).hasActivity()) { 1419 return true; 1420 } 1421 } 1422 return false; 1423 } 1424 getActivity(Predicate<ActivityRecord> callback)1425 ActivityRecord getActivity(Predicate<ActivityRecord> callback) { 1426 return getActivity(callback, true /*traverseTopToBottom*/); 1427 } 1428 getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom)1429 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom) { 1430 return getActivity(callback, traverseTopToBottom, null /*boundary*/); 1431 } 1432 getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom, ActivityRecord boundary)1433 ActivityRecord getActivity(Predicate<ActivityRecord> callback, boolean traverseTopToBottom, 1434 ActivityRecord boundary) { 1435 if (traverseTopToBottom) { 1436 for (int i = mChildren.size() - 1; i >= 0; --i) { 1437 final WindowContainer wc = mChildren.get(i); 1438 // TODO(b/156986561): Improve the correctness of the boundary check. 1439 if (wc == boundary) return boundary; 1440 1441 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary); 1442 if (r != null) { 1443 return r; 1444 } 1445 } 1446 } else { 1447 final int count = mChildren.size(); 1448 for (int i = 0; i < count; i++) { 1449 final WindowContainer wc = mChildren.get(i); 1450 // TODO(b/156986561): Improve the correctness of the boundary check. 1451 if (wc == boundary) return boundary; 1452 1453 final ActivityRecord r = wc.getActivity(callback, traverseTopToBottom, boundary); 1454 if (r != null) { 1455 return r; 1456 } 1457 } 1458 } 1459 1460 return null; 1461 } 1462 1463 /** 1464 * Gets an activity in a branch of the tree. 1465 * 1466 * @param callback called to test if this is the activity that should be returned. 1467 * @param boundary We don't return activities via {@param callback} until we get to this node in 1468 * the tree. 1469 * @param includeBoundary If the boundary from be processed to return activities. 1470 * @param traverseTopToBottom direction to traverse the tree. 1471 * @return The activity if found or null. 1472 */ getActivity(Predicate<ActivityRecord> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom)1473 final ActivityRecord getActivity(Predicate<ActivityRecord> callback, 1474 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom) { 1475 return getActivity( 1476 callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]); 1477 } 1478 getActivity(Predicate<ActivityRecord> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound)1479 private ActivityRecord getActivity(Predicate<ActivityRecord> callback, 1480 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, 1481 boolean[] boundaryFound) { 1482 if (traverseTopToBottom) { 1483 for (int i = mChildren.size() - 1; i >= 0; --i) { 1484 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary, 1485 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i)); 1486 if (r != null) { 1487 return r; 1488 } 1489 } 1490 } else { 1491 final int count = mChildren.size(); 1492 for (int i = 0; i < count; i++) { 1493 final ActivityRecord r = processGetActivityWithBoundary(callback, boundary, 1494 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i)); 1495 if (r != null) { 1496 return r; 1497 } 1498 } 1499 } 1500 1501 return null; 1502 } 1503 processGetActivityWithBoundary(Predicate<ActivityRecord> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound, WindowContainer wc)1504 private ActivityRecord processGetActivityWithBoundary(Predicate<ActivityRecord> callback, 1505 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, 1506 boolean[] boundaryFound, WindowContainer wc) { 1507 if (wc == boundary || boundary == null) { 1508 boundaryFound[0] = true; 1509 if (!includeBoundary) return null; 1510 } 1511 1512 if (boundaryFound[0]) { 1513 return wc.getActivity(callback, traverseTopToBottom); 1514 } 1515 1516 return wc.getActivity( 1517 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound); 1518 } 1519 getActivityAbove(ActivityRecord r)1520 ActivityRecord getActivityAbove(ActivityRecord r) { 1521 return getActivity((above) -> true, r, 1522 false /*includeBoundary*/, false /*traverseTopToBottom*/); 1523 } 1524 getActivityBelow(ActivityRecord r)1525 ActivityRecord getActivityBelow(ActivityRecord r) { 1526 return getActivity((below) -> true, r, 1527 false /*includeBoundary*/, true /*traverseTopToBottom*/); 1528 } 1529 getBottomMostActivity()1530 ActivityRecord getBottomMostActivity() { 1531 return getActivity((r) -> true, false /*traverseTopToBottom*/); 1532 } 1533 getTopMostActivity()1534 ActivityRecord getTopMostActivity() { 1535 return getActivity((r) -> true, true /*traverseTopToBottom*/); 1536 } 1537 getTopActivity(boolean includeFinishing, boolean includeOverlays)1538 ActivityRecord getTopActivity(boolean includeFinishing, boolean includeOverlays) { 1539 // Break down into 4 calls to avoid object creation due to capturing input params. 1540 if (includeFinishing) { 1541 if (includeOverlays) { 1542 return getActivity((r) -> true); 1543 } 1544 return getActivity((r) -> !r.isTaskOverlay()); 1545 } else if (includeOverlays) { 1546 return getActivity((r) -> !r.finishing); 1547 } 1548 1549 return getActivity((r) -> !r.finishing && !r.isTaskOverlay()); 1550 } 1551 forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback)1552 void forAllWallpaperWindows(Consumer<WallpaperWindowToken> callback) { 1553 for (int i = mChildren.size() - 1; i >= 0; --i) { 1554 mChildren.get(i).forAllWallpaperWindows(callback); 1555 } 1556 } 1557 1558 /** 1559 * For all tasks at or below this container call the callback. 1560 * 1561 * @param callback Calls the {@link ToBooleanFunction#apply} method for each task found and 1562 * stops the search if {@link ToBooleanFunction#apply} returns {@code true}. 1563 */ forAllTasks(Function<Task, Boolean> callback)1564 boolean forAllTasks(Function<Task, Boolean> callback) { 1565 for (int i = mChildren.size() - 1; i >= 0; --i) { 1566 if (mChildren.get(i).forAllTasks(callback)) { 1567 return true; 1568 } 1569 } 1570 return false; 1571 } 1572 forAllLeafTasks(Function<Task, Boolean> callback)1573 boolean forAllLeafTasks(Function<Task, Boolean> callback) { 1574 for (int i = mChildren.size() - 1; i >= 0; --i) { 1575 if (mChildren.get(i).forAllLeafTasks(callback)) { 1576 return true; 1577 } 1578 } 1579 return false; 1580 } 1581 1582 /** 1583 * For all tasks at or below this container call the callback. 1584 * 1585 * @param callback Callback to be called for every task. 1586 */ forAllTasks(Consumer<Task> callback)1587 void forAllTasks(Consumer<Task> callback) { 1588 forAllTasks(callback, true /*traverseTopToBottom*/); 1589 } 1590 forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom)1591 void forAllTasks(Consumer<Task> callback, boolean traverseTopToBottom) { 1592 final int count = mChildren.size(); 1593 if (traverseTopToBottom) { 1594 for (int i = count - 1; i >= 0; --i) { 1595 mChildren.get(i).forAllTasks(callback, traverseTopToBottom); 1596 } 1597 } else { 1598 for (int i = 0; i < count; i++) { 1599 mChildren.get(i).forAllTasks(callback, traverseTopToBottom); 1600 } 1601 } 1602 } 1603 forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom)1604 void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) { 1605 final int count = mChildren.size(); 1606 if (traverseTopToBottom) { 1607 for (int i = count - 1; i >= 0; --i) { 1608 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom); 1609 } 1610 } else { 1611 for (int i = 0; i < count; i++) { 1612 mChildren.get(i).forAllLeafTasks(callback, traverseTopToBottom); 1613 } 1614 } 1615 } 1616 getTaskAbove(Task t)1617 Task getTaskAbove(Task t) { 1618 return getTask( 1619 (above) -> true, t, false /*includeBoundary*/, false /*traverseTopToBottom*/); 1620 } 1621 getTaskBelow(Task t)1622 Task getTaskBelow(Task t) { 1623 return getTask((below) -> true, t, false /*includeBoundary*/, true /*traverseTopToBottom*/); 1624 } 1625 getBottomMostTask()1626 Task getBottomMostTask() { 1627 return getTask((t) -> true, false /*traverseTopToBottom*/); 1628 } 1629 getTopMostTask()1630 Task getTopMostTask() { 1631 return getTask((t) -> true, true /*traverseTopToBottom*/); 1632 } 1633 getTask(Predicate<Task> callback)1634 Task getTask(Predicate<Task> callback) { 1635 return getTask(callback, true /*traverseTopToBottom*/); 1636 } 1637 getTask(Predicate<Task> callback, boolean traverseTopToBottom)1638 Task getTask(Predicate<Task> callback, boolean traverseTopToBottom) { 1639 if (traverseTopToBottom) { 1640 for (int i = mChildren.size() - 1; i >= 0; --i) { 1641 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom); 1642 if (t != null) { 1643 return t; 1644 } 1645 } 1646 } else { 1647 final int count = mChildren.size(); 1648 for (int i = 0; i < count; i++) { 1649 final Task t = mChildren.get(i).getTask(callback, traverseTopToBottom); 1650 if (t != null) { 1651 return t; 1652 } 1653 } 1654 } 1655 1656 return null; 1657 } 1658 1659 /** 1660 * Gets an task in a branch of the tree. 1661 * 1662 * @param callback called to test if this is the task that should be returned. 1663 * @param boundary We don't return tasks via {@param callback} until we get to this node in 1664 * the tree. 1665 * @param includeBoundary If the boundary from be processed to return tasks. 1666 * @param traverseTopToBottom direction to traverse the tree. 1667 * @return The task if found or null. 1668 */ getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom)1669 final Task getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary, 1670 boolean traverseTopToBottom) { 1671 return getTask(callback, boundary, includeBoundary, traverseTopToBottom, new boolean[1]); 1672 } 1673 getTask(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound)1674 private Task getTask(Predicate<Task> callback, 1675 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, 1676 boolean[] boundaryFound) { 1677 if (traverseTopToBottom) { 1678 for (int i = mChildren.size() - 1; i >= 0; --i) { 1679 final Task t = processGetTaskWithBoundary(callback, boundary, 1680 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i)); 1681 if (t != null) { 1682 return t; 1683 } 1684 } 1685 } else { 1686 final int count = mChildren.size(); 1687 for (int i = 0; i < count; i++) { 1688 final Task t = processGetTaskWithBoundary(callback, boundary, 1689 includeBoundary, traverseTopToBottom, boundaryFound, mChildren.get(i)); 1690 if (t != null) { 1691 return t; 1692 } 1693 } 1694 } 1695 1696 return null; 1697 } 1698 processGetTaskWithBoundary(Predicate<Task> callback, WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, boolean[] boundaryFound, WindowContainer wc)1699 private Task processGetTaskWithBoundary(Predicate<Task> callback, 1700 WindowContainer boundary, boolean includeBoundary, boolean traverseTopToBottom, 1701 boolean[] boundaryFound, WindowContainer wc) { 1702 if (wc == boundary || boundary == null) { 1703 boundaryFound[0] = true; 1704 if (!includeBoundary) return null; 1705 } 1706 1707 if (boundaryFound[0]) { 1708 return wc.getTask(callback, traverseTopToBottom); 1709 } 1710 1711 return wc.getTask( 1712 callback, boundary, includeBoundary, traverseTopToBottom, boundaryFound); 1713 } 1714 getWindow(Predicate<WindowState> callback)1715 WindowState getWindow(Predicate<WindowState> callback) { 1716 for (int i = mChildren.size() - 1; i >= 0; --i) { 1717 final WindowState w = mChildren.get(i).getWindow(callback); 1718 if (w != null) { 1719 return w; 1720 } 1721 } 1722 1723 return null; 1724 } 1725 forAllDisplayAreas(Consumer<DisplayArea> callback)1726 void forAllDisplayAreas(Consumer<DisplayArea> callback) { 1727 for (int i = mChildren.size() - 1; i >= 0; --i) { 1728 mChildren.get(i).forAllDisplayAreas(callback); 1729 } 1730 } 1731 1732 /** 1733 * Returns 1, 0, or -1 depending on if this container is greater than, equal to, or lesser than 1734 * the input container in terms of z-order. 1735 */ 1736 @Override compareTo(WindowContainer other)1737 public int compareTo(WindowContainer other) { 1738 if (this == other) { 1739 return 0; 1740 } 1741 1742 if (mParent != null && mParent == other.mParent) { 1743 final WindowList<WindowContainer> list = mParent.mChildren; 1744 return list.indexOf(this) > list.indexOf(other) ? 1 : -1; 1745 } 1746 1747 final LinkedList<WindowContainer> thisParentChain = mTmpChain1; 1748 final LinkedList<WindowContainer> otherParentChain = mTmpChain2; 1749 try { 1750 getParents(thisParentChain); 1751 other.getParents(otherParentChain); 1752 1753 // Find the common ancestor of both containers. 1754 WindowContainer commonAncestor = null; 1755 WindowContainer thisTop = thisParentChain.peekLast(); 1756 WindowContainer otherTop = otherParentChain.peekLast(); 1757 while (thisTop != null && otherTop != null && thisTop == otherTop) { 1758 commonAncestor = thisParentChain.removeLast(); 1759 otherParentChain.removeLast(); 1760 thisTop = thisParentChain.peekLast(); 1761 otherTop = otherParentChain.peekLast(); 1762 } 1763 1764 // Containers don't belong to the same hierarchy??? 1765 if (commonAncestor == null) { 1766 throw new IllegalArgumentException("No in the same hierarchy this=" 1767 + thisParentChain + " other=" + otherParentChain); 1768 } 1769 1770 // Children are always considered greater than their parents, so if one of the containers 1771 // we are comparing it the parent of the other then whichever is the child is greater. 1772 if (commonAncestor == this) { 1773 return -1; 1774 } else if (commonAncestor == other) { 1775 return 1; 1776 } 1777 1778 // The position of the first non-common ancestor in the common ancestor list determines 1779 // which is greater the which. 1780 final WindowList<WindowContainer> list = commonAncestor.mChildren; 1781 return list.indexOf(thisParentChain.peekLast()) > list.indexOf(otherParentChain.peekLast()) 1782 ? 1 : -1; 1783 } finally { 1784 mTmpChain1.clear(); 1785 mTmpChain2.clear(); 1786 } 1787 } 1788 getParents(LinkedList<WindowContainer> parents)1789 private void getParents(LinkedList<WindowContainer> parents) { 1790 parents.clear(); 1791 WindowContainer current = this; 1792 do { 1793 parents.addLast(current); 1794 current = current.mParent; 1795 } while (current != null); 1796 } 1797 makeSurface()1798 SurfaceControl.Builder makeSurface() { 1799 final WindowContainer p = getParent(); 1800 return p.makeChildSurface(this); 1801 } 1802 1803 /** 1804 * @param child The WindowContainer this child surface is for, or null if the Surface 1805 * is not assosciated with a WindowContainer (e.g. a surface used for Dimming). 1806 */ makeChildSurface(WindowContainer child)1807 SurfaceControl.Builder makeChildSurface(WindowContainer child) { 1808 final WindowContainer p = getParent(); 1809 // Give the parent a chance to set properties. In hierarchy v1 we rely 1810 // on this to set full-screen dimensions on all our Surface-less Layers. 1811 return p.makeChildSurface(child) 1812 .setParent(mSurfaceControl); 1813 } 1814 /* 1815 * @return The SurfaceControl parent for this containers SurfaceControl. 1816 * The SurfaceControl must be valid if non-null. 1817 */ 1818 @Override getParentSurfaceControl()1819 public SurfaceControl getParentSurfaceControl() { 1820 final WindowContainer parent = getParent(); 1821 if (parent == null) { 1822 return null; 1823 } 1824 return parent.getSurfaceControl(); 1825 } 1826 1827 /** 1828 * @return Whether this WindowContainer should be magnified by the accessibility magnifier. 1829 */ shouldMagnify()1830 boolean shouldMagnify() { 1831 if (mSurfaceControl == null) { 1832 return false; 1833 } 1834 1835 for (int i = 0; i < mChildren.size(); i++) { 1836 if (!mChildren.get(i).shouldMagnify()) { 1837 return false; 1838 } 1839 } 1840 return true; 1841 } 1842 getSession()1843 SurfaceSession getSession() { 1844 if (getParent() != null) { 1845 return getParent().getSession(); 1846 } 1847 return null; 1848 } 1849 assignLayer(Transaction t, int layer)1850 void assignLayer(Transaction t, int layer) { 1851 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != null; 1852 if (mSurfaceControl != null && changed) { 1853 setLayer(t, layer); 1854 mLastLayer = layer; 1855 mLastRelativeToLayer = null; 1856 } 1857 } 1858 assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer)1859 void assignRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { 1860 final boolean changed = layer != mLastLayer || mLastRelativeToLayer != relativeTo; 1861 if (mSurfaceControl != null && changed) { 1862 setRelativeLayer(t, relativeTo, layer); 1863 mLastLayer = layer; 1864 mLastRelativeToLayer = relativeTo; 1865 } 1866 } 1867 setLayer(Transaction t, int layer)1868 protected void setLayer(Transaction t, int layer) { 1869 1870 // Route through surface animator to accommodate that our surface control might be 1871 // attached to the leash, and leash is attached to parent container. 1872 mSurfaceAnimator.setLayer(t, layer); 1873 } 1874 setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer)1875 protected void setRelativeLayer(Transaction t, SurfaceControl relativeTo, int layer) { 1876 1877 // Route through surface animator to accommodate that our surface control might be 1878 // attached to the leash, and leash is attached to parent container. 1879 mSurfaceAnimator.setRelativeLayer(t, relativeTo, layer); 1880 } 1881 reparentSurfaceControl(Transaction t, SurfaceControl newParent)1882 protected void reparentSurfaceControl(Transaction t, SurfaceControl newParent) { 1883 mSurfaceAnimator.reparent(t, newParent); 1884 } 1885 assignChildLayers(Transaction t)1886 void assignChildLayers(Transaction t) { 1887 int layer = 0; 1888 1889 // We use two passes as a way to promote children which 1890 // need Z-boosting to the end of the list. 1891 for (int j = 0; j < mChildren.size(); ++j) { 1892 final WindowContainer wc = mChildren.get(j); 1893 wc.assignChildLayers(t); 1894 if (!wc.needsZBoost()) { 1895 wc.assignLayer(t, layer++); 1896 } 1897 } 1898 for (int j = 0; j < mChildren.size(); ++j) { 1899 final WindowContainer wc = mChildren.get(j); 1900 if (wc.needsZBoost()) { 1901 wc.assignLayer(t, layer++); 1902 } 1903 } 1904 } 1905 assignChildLayers()1906 void assignChildLayers() { 1907 assignChildLayers(getSyncTransaction()); 1908 scheduleAnimation(); 1909 } 1910 needsZBoost()1911 boolean needsZBoost() { 1912 if (mNeedsZBoost) return true; 1913 for (int i = 0; i < mChildren.size(); i++) { 1914 if (mChildren.get(i).needsZBoost()) { 1915 return true; 1916 } 1917 } 1918 return false; 1919 } 1920 1921 /** 1922 * Write to a protocol buffer output stream. Protocol buffer message definition is at 1923 * {@link com.android.server.wm.WindowContainerProto}. 1924 * 1925 * @param proto Stream to write the WindowContainer object to. 1926 * @param fieldId Field Id of the WindowContainer as defined in the parent message. 1927 * @param logLevel Determines the amount of data to be written to the Protobuf. 1928 * @hide 1929 */ 1930 @CallSuper 1931 @Override dumpDebug(ProtoOutputStream proto, long fieldId, @WindowTraceLogLevel int logLevel)1932 public void dumpDebug(ProtoOutputStream proto, long fieldId, 1933 @WindowTraceLogLevel int logLevel) { 1934 boolean isVisible = isVisible(); 1935 if (logLevel == WindowTraceLogLevel.CRITICAL && !isVisible) { 1936 return; 1937 } 1938 1939 final long token = proto.start(fieldId); 1940 super.dumpDebug(proto, CONFIGURATION_CONTAINER, logLevel); 1941 proto.write(ORIENTATION, mOrientation); 1942 proto.write(VISIBLE, isVisible); 1943 if (mSurfaceAnimator.isAnimating()) { 1944 mSurfaceAnimator.dumpDebug(proto, SURFACE_ANIMATOR); 1945 } 1946 1947 // add children to proto 1948 for (int i = 0; i < getChildCount(); i++) { 1949 final long childToken = proto.start(WindowContainerProto.CHILDREN); 1950 final E child = getChildAt(i); 1951 child.dumpDebug(proto, child.getProtoFieldId(), logLevel); 1952 proto.end(childToken); 1953 } 1954 proto.end(token); 1955 } 1956 1957 /** 1958 * @return a proto field id to identify where to add the derived class to the generic window 1959 * container proto. 1960 */ getProtoFieldId()1961 long getProtoFieldId() { 1962 return WINDOW_CONTAINER; 1963 } 1964 obtainConsumerWrapper(Consumer<WindowState> consumer)1965 private ForAllWindowsConsumerWrapper obtainConsumerWrapper(Consumer<WindowState> consumer) { 1966 ForAllWindowsConsumerWrapper wrapper = mConsumerWrapperPool.acquire(); 1967 if (wrapper == null) { 1968 wrapper = new ForAllWindowsConsumerWrapper(); 1969 } 1970 wrapper.setConsumer(consumer); 1971 return wrapper; 1972 } 1973 1974 private final class ForAllWindowsConsumerWrapper implements ToBooleanFunction<WindowState> { 1975 1976 private Consumer<WindowState> mConsumer; 1977 setConsumer(Consumer<WindowState> consumer)1978 void setConsumer(Consumer<WindowState> consumer) { 1979 mConsumer = consumer; 1980 } 1981 1982 @Override apply(WindowState w)1983 public boolean apply(WindowState w) { 1984 mConsumer.accept(w); 1985 return false; 1986 } 1987 release()1988 void release() { 1989 mConsumer = null; 1990 mConsumerWrapperPool.release(this); 1991 } 1992 } 1993 1994 // TODO(b/68336570): Should this really be on WindowContainer since it 1995 // can only be used on the top-level nodes that aren't animated? 1996 // (otherwise we would be fighting other callers of setMatrix). applyMagnificationSpec(Transaction t, MagnificationSpec spec)1997 void applyMagnificationSpec(Transaction t, MagnificationSpec spec) { 1998 if (shouldMagnify()) { 1999 t.setMatrix(mSurfaceControl, spec.scale, 0, 0, spec.scale) 2000 .setPosition(mSurfaceControl, spec.offsetX, spec.offsetY); 2001 mLastMagnificationSpec = spec; 2002 } else { 2003 clearMagnificationSpec(t); 2004 for (int i = 0; i < mChildren.size(); i++) { 2005 mChildren.get(i).applyMagnificationSpec(t, spec); 2006 } 2007 } 2008 } 2009 clearMagnificationSpec(Transaction t)2010 void clearMagnificationSpec(Transaction t) { 2011 if (mLastMagnificationSpec != null) { 2012 t.setMatrix(mSurfaceControl, 1, 0, 0, 1) 2013 .setPosition(mSurfaceControl, 0, 0); 2014 } 2015 mLastMagnificationSpec = null; 2016 for (int i = 0; i < mChildren.size(); i++) { 2017 mChildren.get(i).clearMagnificationSpec(t); 2018 } 2019 } 2020 prepareSurfaces()2021 void prepareSurfaces() { 2022 // If a leash has been set when the transaction was committed, then the leash reparent has 2023 // been committed. 2024 mCommittedReparentToAnimationLeash = mSurfaceAnimator.hasLeash(); 2025 for (int i = 0; i < mChildren.size(); i++) { 2026 mChildren.get(i).prepareSurfaces(); 2027 } 2028 } 2029 2030 /** 2031 * @return true if the reparent to animation leash transaction has been committed, false 2032 * otherwise. 2033 */ hasCommittedReparentToAnimationLeash()2034 boolean hasCommittedReparentToAnimationLeash() { 2035 return mCommittedReparentToAnimationLeash; 2036 } 2037 2038 /** 2039 * Trigger a call to prepareSurfaces from the animation thread, such that pending transactions 2040 * will be applied. 2041 */ scheduleAnimation()2042 void scheduleAnimation() { 2043 if (mParent != null) { 2044 mParent.scheduleAnimation(); 2045 } 2046 } 2047 2048 /** 2049 * @return The SurfaceControl for this container. 2050 * The SurfaceControl must be valid if non-null. 2051 */ 2052 @Override getSurfaceControl()2053 public SurfaceControl getSurfaceControl() { 2054 return mSurfaceControl; 2055 } 2056 2057 /** 2058 * Use this method instead of {@link #getPendingTransaction()} if the Transaction should be 2059 * synchronized with the client. 2060 * 2061 * @return {@link #mBLASTSyncTransaction} if available. Otherwise, returns 2062 * {@link #getPendingTransaction()} 2063 */ getSyncTransaction()2064 public Transaction getSyncTransaction() { 2065 if (mUsingBLASTSyncTransaction) { 2066 return mBLASTSyncTransaction; 2067 } 2068 2069 return getPendingTransaction(); 2070 } 2071 2072 @Override getPendingTransaction()2073 public Transaction getPendingTransaction() { 2074 final DisplayContent displayContent = getDisplayContent(); 2075 if (displayContent != null && displayContent != this) { 2076 return displayContent.getPendingTransaction(); 2077 } 2078 // This WindowContainer has not attached to a display yet or this is a DisplayContent, so we 2079 // let the caller to save the surface operations within the local mPendingTransaction. 2080 // If this is not a DisplayContent, we will merge it to the pending transaction of its 2081 // display once it attaches to it. 2082 return mPendingTransaction; 2083 } 2084 2085 /** 2086 * Starts an animation on the container. 2087 * 2088 * @param anim The animation to run. 2089 * @param hidden Whether our container is currently hidden. TODO This should use isVisible at 2090 * some point but the meaning is too weird to work for all containers. 2091 * @param type The type of animation defined as {@link AnimationType}. 2092 * @param animationFinishedCallback The callback being triggered when the animation finishes. 2093 */ startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type, @Nullable OnAnimationFinishedCallback animationFinishedCallback)2094 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, 2095 @AnimationType int type, 2096 @Nullable OnAnimationFinishedCallback animationFinishedCallback) { 2097 if (DEBUG_ANIM) { 2098 Slog.v(TAG, "Starting animation on " + this + ": type=" + type + ", anim=" + anim); 2099 } 2100 2101 // TODO: This should use isVisible() but because isVisible has a really weird meaning at 2102 // the moment this doesn't work for all animatable window containers. 2103 mSurfaceAnimator.startAnimation(t, anim, hidden, type, animationFinishedCallback, 2104 mSurfaceFreezer); 2105 } 2106 startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, @AnimationType int type)2107 void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden, 2108 @AnimationType int type) { 2109 startAnimation(t, anim, hidden, type, null /* animationFinishedCallback */); 2110 } 2111 transferAnimation(WindowContainer from)2112 void transferAnimation(WindowContainer from) { 2113 mSurfaceAnimator.transferAnimation(from.mSurfaceAnimator); 2114 } 2115 cancelAnimation()2116 void cancelAnimation() { 2117 doAnimationFinished(mSurfaceAnimator.getAnimationType(), mSurfaceAnimator.getAnimation()); 2118 mSurfaceAnimator.cancelAnimation(); 2119 mSurfaceFreezer.unfreeze(getPendingTransaction()); 2120 } 2121 getAnimationSources()2122 ArraySet<WindowContainer> getAnimationSources() { 2123 return mSurfaceAnimationSources; 2124 } 2125 2126 @Override getFreezeSnapshotTarget()2127 public SurfaceControl getFreezeSnapshotTarget() { 2128 return null; 2129 } 2130 2131 @Override makeAnimationLeash()2132 public Builder makeAnimationLeash() { 2133 return makeSurface().setContainerLayer(); 2134 } 2135 2136 @Override getAnimationLeashParent()2137 public SurfaceControl getAnimationLeashParent() { 2138 return getParentSurfaceControl(); 2139 } 2140 2141 /** 2142 * @return The layer on which all app animations are happening. 2143 */ getAppAnimationLayer(@nimationLayer int animationLayer)2144 SurfaceControl getAppAnimationLayer(@AnimationLayer int animationLayer) { 2145 final WindowContainer parent = getParent(); 2146 if (parent != null) { 2147 return parent.getAppAnimationLayer(animationLayer); 2148 } 2149 return null; 2150 } 2151 2152 // TODO: Remove this and use #getBounds() instead once we set an app transition animation 2153 // on TaskStack. getAnimationBounds(int appStackClipMode)2154 Rect getAnimationBounds(int appStackClipMode) { 2155 return getBounds(); 2156 } 2157 2158 /** Gets the position relative to parent for animation. */ getAnimationPosition(Point outPosition)2159 void getAnimationPosition(Point outPosition) { 2160 getRelativePosition(outPosition); 2161 } 2162 2163 /** 2164 * Applies the app transition animation according the given the layout properties in the 2165 * window hierarchy. 2166 * 2167 * @param lp The layout parameters of the window. 2168 * @param transit The app transition type indicates what kind of transition to be applied. 2169 * @param enter Whether the app transition is entering transition or not. 2170 * @param isVoiceInteraction Whether the container is participating in voice interaction or not. 2171 * @param sources {@link ActivityRecord}s which causes this app transition animation. 2172 * 2173 * @return {@code true} when the container applied the app transition, {@code false} if the 2174 * app transition is disabled or skipped. 2175 * 2176 * @see #getAnimationAdapter 2177 */ applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources)2178 boolean applyAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, 2179 boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources) { 2180 if (mWmService.mDisableTransitionAnimation) { 2181 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, 2182 "applyAnimation: transition animation is disabled or skipped. " 2183 + "container=%s", this); 2184 cancelAnimation(); 2185 return false; 2186 } 2187 2188 // Only apply an animation if the display isn't frozen. If it is frozen, there is no reason 2189 // to animate and it can cause strange artifacts when we unfreeze the display if some 2190 // different animation is running. 2191 try { 2192 Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "WC#applyAnimation"); 2193 if (okToAnimate()) { 2194 applyAnimationUnchecked(lp, enter, transit, isVoiceInteraction, sources); 2195 } else { 2196 cancelAnimation(); 2197 } 2198 } finally { 2199 Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER); 2200 } 2201 2202 return isAnimating(); 2203 } 2204 2205 /** 2206 * Gets the {@link AnimationAdapter} according the given window layout properties in the window 2207 * hierarchy. 2208 * 2209 * @return The return value will always contain two elements, one for normal animations and the 2210 * other for thumbnail animation, both can be {@code null}. 2211 * 2212 * @See com.android.server.wm.RemoteAnimationController.RemoteAnimationRecord 2213 * @See LocalAnimationAdapter 2214 */ getAnimationAdapter(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction)2215 Pair<AnimationAdapter, AnimationAdapter> getAnimationAdapter(WindowManager.LayoutParams lp, 2216 int transit, boolean enter, boolean isVoiceInteraction) { 2217 final Pair<AnimationAdapter, AnimationAdapter> resultAdapters; 2218 final int appStackClipMode = getDisplayContent().mAppTransition.getAppStackClipMode(); 2219 2220 // Separate position and size for use in animators. 2221 final Rect screenBounds = getAnimationBounds(appStackClipMode); 2222 mTmpRect.set(screenBounds); 2223 getAnimationPosition(mTmpPoint); 2224 if (!sHierarchicalAnimations) { 2225 // Non-hierarchical animation uses position in global coordinates. 2226 mTmpPoint.set(mTmpRect.left, mTmpRect.top); 2227 } 2228 mTmpRect.offsetTo(0, 0); 2229 2230 final RemoteAnimationController controller = 2231 getDisplayContent().mAppTransition.getRemoteAnimationController(); 2232 final boolean isChanging = AppTransition.isChangeTransit(transit) && enter 2233 && isChangingAppTransition(); 2234 2235 // Delaying animation start isn't compatible with remote animations at all. 2236 if (controller != null && !mSurfaceAnimator.isAnimationStartDelayed()) { 2237 final Rect localBounds = new Rect(mTmpRect); 2238 localBounds.offsetTo(mTmpPoint.x, mTmpPoint.y); 2239 final RemoteAnimationController.RemoteAnimationRecord adapters = 2240 controller.createRemoteAnimationRecord(this, mTmpPoint, localBounds, 2241 screenBounds, (isChanging ? mSurfaceFreezer.mFreezeBounds : null)); 2242 resultAdapters = new Pair<>(adapters.mAdapter, adapters.mThumbnailAdapter); 2243 } else if (isChanging) { 2244 final float durationScale = mWmService.getTransitionAnimationScaleLocked(); 2245 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo(); 2246 mTmpRect.offsetTo(mTmpPoint.x, mTmpPoint.y); 2247 2248 final AnimationAdapter adapter = new LocalAnimationAdapter( 2249 new WindowChangeAnimationSpec(mSurfaceFreezer.mFreezeBounds, mTmpRect, 2250 displayInfo, durationScale, true /* isAppAnimation */, 2251 false /* isThumbnail */), 2252 getSurfaceAnimationRunner()); 2253 2254 final AnimationAdapter thumbnailAdapter = mSurfaceFreezer.mSnapshot != null 2255 ? new LocalAnimationAdapter(new WindowChangeAnimationSpec( 2256 mSurfaceFreezer.mFreezeBounds, mTmpRect, displayInfo, durationScale, 2257 true /* isAppAnimation */, true /* isThumbnail */), getSurfaceAnimationRunner()) 2258 : null; 2259 resultAdapters = new Pair<>(adapter, thumbnailAdapter); 2260 mTransit = transit; 2261 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags(); 2262 } else { 2263 mNeedsAnimationBoundsLayer = (appStackClipMode == STACK_CLIP_AFTER_ANIM); 2264 final Animation a = loadAnimation(lp, transit, enter, isVoiceInteraction); 2265 2266 if (a != null) { 2267 // Only apply corner radius to animation if we're not in multi window mode. 2268 // We don't want rounded corners when in pip or split screen. 2269 final float windowCornerRadius = !inMultiWindowMode() 2270 ? getDisplayContent().getWindowCornerRadius() 2271 : 0; 2272 AnimationAdapter adapter = new LocalAnimationAdapter( 2273 new WindowAnimationSpec(a, mTmpPoint, mTmpRect, 2274 getDisplayContent().mAppTransition.canSkipFirstFrame(), 2275 appStackClipMode, true /* isAppAnimation */, windowCornerRadius), 2276 getSurfaceAnimationRunner()); 2277 2278 resultAdapters = new Pair<>(adapter, null); 2279 mNeedsZBoost = a.getZAdjustment() == Animation.ZORDER_TOP 2280 || AppTransition.isClosingTransit(transit); 2281 mTransit = transit; 2282 mTransitFlags = getDisplayContent().mAppTransition.getTransitFlags(); 2283 } else { 2284 resultAdapters = new Pair<>(null, null); 2285 } 2286 } 2287 return resultAdapters; 2288 } 2289 applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter, int transit, boolean isVoiceInteraction, @Nullable ArrayList<WindowContainer> sources)2290 protected void applyAnimationUnchecked(WindowManager.LayoutParams lp, boolean enter, 2291 int transit, boolean isVoiceInteraction, 2292 @Nullable ArrayList<WindowContainer> sources) { 2293 final Pair<AnimationAdapter, AnimationAdapter> adapters = getAnimationAdapter(lp, 2294 transit, enter, isVoiceInteraction); 2295 AnimationAdapter adapter = adapters.first; 2296 AnimationAdapter thumbnailAdapter = adapters.second; 2297 if (adapter != null) { 2298 if (sources != null) { 2299 mSurfaceAnimationSources.addAll(sources); 2300 } 2301 startAnimation(getPendingTransaction(), adapter, !isVisible(), 2302 ANIMATION_TYPE_APP_TRANSITION); 2303 if (adapter.getShowWallpaper()) { 2304 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER; 2305 } 2306 if (thumbnailAdapter != null) { 2307 mSurfaceFreezer.mSnapshot.startAnimation(getPendingTransaction(), 2308 thumbnailAdapter, ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> { }); 2309 } 2310 } 2311 } 2312 getSurfaceAnimationRunner()2313 final SurfaceAnimationRunner getSurfaceAnimationRunner() { 2314 return mWmService.mSurfaceAnimationRunner; 2315 } 2316 loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, boolean isVoiceInteraction)2317 private Animation loadAnimation(WindowManager.LayoutParams lp, int transit, boolean enter, 2318 boolean isVoiceInteraction) { 2319 if (isOrganized()) { 2320 // Defer to the task organizer to run animations 2321 return null; 2322 } 2323 2324 final DisplayContent displayContent = getDisplayContent(); 2325 final DisplayInfo displayInfo = displayContent.getDisplayInfo(); 2326 final int width = displayInfo.appWidth; 2327 final int height = displayInfo.appHeight; 2328 ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM, "applyAnimation: container=%s", this); 2329 2330 // Determine the visible rect to calculate the thumbnail clip with 2331 // getAnimationFrames. 2332 final Rect frame = new Rect(0, 0, width, height); 2333 final Rect displayFrame = new Rect(0, 0, 2334 displayInfo.logicalWidth, displayInfo.logicalHeight); 2335 final Rect insets = new Rect(); 2336 final Rect stableInsets = new Rect(); 2337 final Rect surfaceInsets = new Rect(); 2338 getAnimationFrames(frame, insets, stableInsets, surfaceInsets); 2339 2340 if (mLaunchTaskBehind) { 2341 // Differentiate the two animations. This one which is briefly on the screen 2342 // gets the !enter animation, and the other one which remains on the 2343 // screen gets the enter animation. Both appear in the mOpeningApps set. 2344 enter = false; 2345 } 2346 ProtoLog.d(WM_DEBUG_APP_TRANSITIONS, 2347 "Loading animation for app transition. transit=%s enter=%b frame=%s insets=%s " 2348 + "surfaceInsets=%s", 2349 AppTransition.appTransitionToString(transit), enter, frame, insets, surfaceInsets); 2350 final Configuration displayConfig = displayContent.getConfiguration(); 2351 final Animation a = getDisplayContent().mAppTransition.loadAnimation(lp, transit, enter, 2352 displayConfig.uiMode, displayConfig.orientation, frame, displayFrame, insets, 2353 surfaceInsets, stableInsets, isVoiceInteraction, inFreeformWindowingMode(), this); 2354 if (a != null) { 2355 if (a != null) { 2356 // Setup the maximum app transition duration to prevent malicious app may set a long 2357 // animation duration or infinite repeat counts for the app transition through 2358 // ActivityOption#makeCustomAnimation or WindowManager#overridePendingTransition. 2359 a.restrictDuration(MAX_APP_TRANSITION_DURATION); 2360 } 2361 if (DEBUG_ANIM) { 2362 logWithStack(TAG, "Loaded animation " + a + " for " + this 2363 + ", duration: " + ((a != null) ? a.getDuration() : 0)); 2364 } 2365 final int containingWidth = frame.width(); 2366 final int containingHeight = frame.height(); 2367 a.initialize(containingWidth, containingHeight, width, height); 2368 a.scaleCurrentDuration(mWmService.getTransitionAnimationScaleLocked()); 2369 } 2370 return a; 2371 } 2372 createRemoteAnimationTarget( RemoteAnimationController.RemoteAnimationRecord record)2373 RemoteAnimationTarget createRemoteAnimationTarget( 2374 RemoteAnimationController.RemoteAnimationRecord record) { 2375 return null; 2376 } 2377 canCreateRemoteAnimationTarget()2378 boolean canCreateRemoteAnimationTarget() { 2379 return false; 2380 } 2381 okToDisplay()2382 boolean okToDisplay() { 2383 final DisplayContent dc = getDisplayContent(); 2384 return dc != null && dc.okToDisplay(); 2385 } 2386 okToAnimate()2387 boolean okToAnimate() { 2388 return okToAnimate(false /* ignoreFrozen */); 2389 } 2390 okToAnimate(boolean ignoreFrozen)2391 boolean okToAnimate(boolean ignoreFrozen) { 2392 final DisplayContent dc = getDisplayContent(); 2393 return dc != null && dc.okToAnimate(ignoreFrozen); 2394 } 2395 2396 @Override commitPendingTransaction()2397 public void commitPendingTransaction() { 2398 scheduleAnimation(); 2399 } 2400 reassignLayer(Transaction t)2401 void reassignLayer(Transaction t) { 2402 final WindowContainer parent = getParent(); 2403 if (parent != null) { 2404 parent.assignChildLayers(t); 2405 } 2406 } 2407 resetSurfacePositionForAnimationLeash(Transaction t)2408 void resetSurfacePositionForAnimationLeash(Transaction t) { 2409 t.setPosition(mSurfaceControl, 0, 0); 2410 mLastSurfacePosition.set(0, 0); 2411 } 2412 2413 @Override onAnimationLeashCreated(Transaction t, SurfaceControl leash)2414 public void onAnimationLeashCreated(Transaction t, SurfaceControl leash) { 2415 mLastLayer = -1; 2416 reassignLayer(t); 2417 2418 // Leash is now responsible for position, so set our position to 0. 2419 resetSurfacePositionForAnimationLeash(t); 2420 } 2421 2422 @Override onAnimationLeashLost(Transaction t)2423 public void onAnimationLeashLost(Transaction t) { 2424 mLastLayer = -1; 2425 mSurfaceFreezer.unfreeze(t); 2426 reassignLayer(t); 2427 updateSurfacePosition(t); 2428 } 2429 doAnimationFinished(@nimationType int type, AnimationAdapter anim)2430 private void doAnimationFinished(@AnimationType int type, AnimationAdapter anim) { 2431 for (int i = 0; i < mSurfaceAnimationSources.size(); ++i) { 2432 mSurfaceAnimationSources.valueAt(i).onAnimationFinished(type, anim); 2433 } 2434 mSurfaceAnimationSources.clear(); 2435 } 2436 2437 /** 2438 * Called when an animation has finished running. 2439 */ onAnimationFinished(@nimationType int type, AnimationAdapter anim)2440 protected void onAnimationFinished(@AnimationType int type, AnimationAdapter anim) { 2441 doAnimationFinished(type, anim); 2442 mWmService.onAnimationFinished(); 2443 mNeedsZBoost = false; 2444 } 2445 2446 /** 2447 * @return The currently running animation, if any, or {@code null} otherwise. 2448 */ getAnimation()2449 AnimationAdapter getAnimation() { 2450 return mSurfaceAnimator.getAnimation(); 2451 } 2452 2453 /** 2454 * @return The {@link WindowContainer} which is running an animation. 2455 * 2456 * By default this only checks if this container itself is actually running an animation, but 2457 * you can extend the check target over its relatives, or relax the condition so that this can 2458 * return {@code WindowContainer} if an animation starts soon by giving a combination 2459 * of {@link AnimationFlags}. 2460 * 2461 * Note that you can give a combination of bitmask flags to specify targets and condition for 2462 * checking animating status. 2463 * e.g. {@code isAnimating(TRANSITION | PARENT)} returns {@code true} if either this 2464 * container itself or one of its parents is running an animation or waiting for an app 2465 * transition. 2466 * 2467 * Note that TRANSITION propagates to parents and children as well. 2468 * 2469 * @param flags The combination of bitmask flags to specify targets and condition for 2470 * checking animating status. 2471 * @param typesToCheck The combination of bitmask {@link AnimationType} to compare when 2472 * determining if animating. 2473 * 2474 * @see AnimationFlags#TRANSITION 2475 * @see AnimationFlags#PARENTS 2476 * @see AnimationFlags#CHILDREN 2477 */ 2478 @Nullable getAnimatingContainer(int flags, int typesToCheck)2479 WindowContainer getAnimatingContainer(int flags, int typesToCheck) { 2480 if (isSelfAnimating(flags, typesToCheck)) { 2481 return this; 2482 } 2483 if ((flags & PARENTS) != 0) { 2484 WindowContainer parent = getParent(); 2485 while (parent != null) { 2486 if (parent.isSelfAnimating(flags, typesToCheck)) { 2487 return parent; 2488 } 2489 parent = parent.getParent(); 2490 } 2491 } 2492 if ((flags & CHILDREN) != 0) { 2493 for (int i = 0; i < mChildren.size(); ++i) { 2494 final WindowContainer wc = mChildren.get(i).getAnimatingContainer( 2495 flags & ~PARENTS, typesToCheck); 2496 if (wc != null) { 2497 return wc; 2498 } 2499 } 2500 } 2501 return null; 2502 } 2503 2504 /** 2505 * Internal method only to be used during {@link #getAnimatingContainer(int, int)}.DO NOT CALL 2506 * FROM OUTSIDE. 2507 */ isSelfAnimating(int flags, int typesToCheck)2508 protected boolean isSelfAnimating(int flags, int typesToCheck) { 2509 if (mSurfaceAnimator.isAnimating() 2510 && (mSurfaceAnimator.getAnimationType() & typesToCheck) > 0) { 2511 return true; 2512 } 2513 if ((flags & TRANSITION) != 0 && isWaitingForTransitionStart()) { 2514 return true; 2515 } 2516 return false; 2517 } 2518 2519 /** 2520 * @deprecated Use {@link #getAnimatingContainer(int, int)} instead. 2521 */ 2522 @Nullable 2523 @Deprecated getAnimatingContainer()2524 final WindowContainer getAnimatingContainer() { 2525 return getAnimatingContainer(PARENTS, ANIMATION_TYPE_ALL); 2526 } 2527 2528 /** 2529 * @see SurfaceAnimator#startDelayingAnimationStart 2530 */ startDelayingAnimationStart()2531 void startDelayingAnimationStart() { 2532 mSurfaceAnimator.startDelayingAnimationStart(); 2533 } 2534 2535 /** 2536 * @see SurfaceAnimator#endDelayingAnimationStart 2537 */ endDelayingAnimationStart()2538 void endDelayingAnimationStart() { 2539 mSurfaceAnimator.endDelayingAnimationStart(); 2540 } 2541 2542 @Override getSurfaceWidth()2543 public int getSurfaceWidth() { 2544 return mSurfaceControl.getWidth(); 2545 } 2546 2547 @Override getSurfaceHeight()2548 public int getSurfaceHeight() { 2549 return mSurfaceControl.getHeight(); 2550 } 2551 2552 @CallSuper dump(PrintWriter pw, String prefix, boolean dumpAll)2553 void dump(PrintWriter pw, String prefix, boolean dumpAll) { 2554 if (mSurfaceAnimator.isAnimating()) { 2555 pw.print(prefix); pw.println("ContainerAnimator:"); 2556 mSurfaceAnimator.dump(pw, prefix + " "); 2557 } 2558 if (mLastOrientationSource != null) { 2559 pw.println(prefix + "mLastOrientationSource=" + mLastOrientationSource); 2560 } 2561 } 2562 updateSurfacePosition()2563 final void updateSurfacePosition() { 2564 updateSurfacePosition(getSyncTransaction()); 2565 } 2566 updateSurfacePosition(Transaction t)2567 void updateSurfacePosition(Transaction t) { 2568 // Avoid fighting with the organizer over Surface position. 2569 if (isOrganized()) return; 2570 2571 if (mSurfaceControl == null || mSurfaceAnimator.hasLeash()) { 2572 return; 2573 } 2574 2575 getRelativePosition(mTmpPos); 2576 if (mTmpPos.equals(mLastSurfacePosition)) { 2577 return; 2578 } 2579 2580 t.setPosition(mSurfaceControl, mTmpPos.x, mTmpPos.y); 2581 mLastSurfacePosition.set(mTmpPos.x, mTmpPos.y); 2582 } 2583 2584 @VisibleForTesting getLastSurfacePosition()2585 Point getLastSurfacePosition() { 2586 return mLastSurfacePosition; 2587 } 2588 2589 /** 2590 * The {@code outFrame} retrieved by this method specifies where the animation will finish 2591 * the entrance animation, as the next frame will display the window at these coordinates. In 2592 * case of exit animation, this is where the animation will start, as the frame before the 2593 * animation is displaying the window at these bounds. 2594 * 2595 * @param outFrame The bounds where entrance animation finishes or exit animation starts. 2596 * @param outInsets Insets that are covered by system windows. 2597 * @param outStableInsets Insets that determine the area covered by the stable system windows. 2598 * @param outSurfaceInsets Positive insets between the drawing surface and window content. 2599 */ getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, Rect outSurfaceInsets)2600 void getAnimationFrames(Rect outFrame, Rect outInsets, Rect outStableInsets, 2601 Rect outSurfaceInsets) { 2602 final DisplayInfo displayInfo = getDisplayContent().getDisplayInfo(); 2603 outFrame.set(0, 0, displayInfo.appWidth, displayInfo.appHeight); 2604 outInsets.setEmpty(); 2605 outStableInsets.setEmpty(); 2606 outSurfaceInsets.setEmpty(); 2607 } 2608 getRelativePosition(Point outPos)2609 void getRelativePosition(Point outPos) { 2610 // In addition to updateSurfacePosition, we keep other code that sets 2611 // position from fighting with the organizer 2612 if (isOrganized()) { 2613 outPos.set(0, 0); 2614 return; 2615 } 2616 2617 final Rect dispBounds = getBounds(); 2618 outPos.set(dispBounds.left, dispBounds.top); 2619 final WindowContainer parent = getParent(); 2620 if (parent != null) { 2621 final Rect parentBounds = parent.getBounds(); 2622 outPos.offset(-parentBounds.left, -parentBounds.top); 2623 } 2624 } 2625 waitForAllWindowsDrawn()2626 void waitForAllWindowsDrawn() { 2627 forAllWindows(w -> { 2628 w.requestDrawIfNeeded(mWaitingForDrawn); 2629 }, true /* traverseTopToBottom */); 2630 } 2631 getDimmer()2632 Dimmer getDimmer() { 2633 if (mParent == null) { 2634 return null; 2635 } 2636 return mParent.getDimmer(); 2637 } 2638 setSurfaceControl(SurfaceControl sc)2639 void setSurfaceControl(SurfaceControl sc) { 2640 mSurfaceControl = sc; 2641 } 2642 getRemoteAnimationDefinition()2643 RemoteAnimationDefinition getRemoteAnimationDefinition() { 2644 return null; 2645 } 2646 2647 /** Cheap way of doing cast and instanceof. */ asTask()2648 Task asTask() { 2649 return null; 2650 } 2651 2652 /** Cheap way of doing cast and instanceof. */ asActivityRecord()2653 ActivityRecord asActivityRecord() { 2654 return null; 2655 } 2656 2657 /** 2658 * @return {@code true} if window container is manage by a 2659 * {@link android.window.WindowOrganizer} 2660 */ isOrganized()2661 boolean isOrganized() { 2662 return false; 2663 } 2664 fromBinder(IBinder binder)2665 static WindowContainer fromBinder(IBinder binder) { 2666 return RemoteToken.fromBinder(binder).getContainer(); 2667 } 2668 2669 static class RemoteToken extends IWindowContainerToken.Stub { 2670 2671 final WeakReference<WindowContainer> mWeakRef; 2672 private WindowContainerToken mWindowContainerToken; 2673 RemoteToken(WindowContainer container)2674 RemoteToken(WindowContainer container) { 2675 mWeakRef = new WeakReference<>(container); 2676 } 2677 getContainer()2678 WindowContainer getContainer() { 2679 return mWeakRef.get(); 2680 } 2681 fromBinder(IBinder binder)2682 static RemoteToken fromBinder(IBinder binder) { 2683 return (RemoteToken) binder; 2684 } 2685 toWindowContainerToken()2686 WindowContainerToken toWindowContainerToken() { 2687 if (mWindowContainerToken == null) { 2688 mWindowContainerToken = new WindowContainerToken(this); 2689 } 2690 return mWindowContainerToken; 2691 } 2692 2693 @Override toString()2694 public String toString() { 2695 StringBuilder sb = new StringBuilder(128); 2696 sb.append("RemoteToken{"); 2697 sb.append(Integer.toHexString(System.identityHashCode(this))); 2698 sb.append(' '); 2699 sb.append(mWeakRef.get()); 2700 sb.append('}'); 2701 return sb.toString(); 2702 } 2703 } 2704 2705 @Override onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady)2706 public void onTransactionReady(int mSyncId, Set<WindowContainer> windowContainersReady) { 2707 if (mWaitingListener == null) { 2708 return; 2709 } 2710 2711 windowContainersReady.add(this); 2712 mWaitingListener.onTransactionReady(mWaitingSyncId, windowContainersReady); 2713 2714 mWaitingListener = null; 2715 mWaitingSyncId = -1; 2716 } 2717 2718 /** 2719 * Returns true if any of the children elected to participate in the Sync 2720 */ addChildrenToSyncSet(int localId)2721 boolean addChildrenToSyncSet(int localId) { 2722 boolean willSync = false; 2723 2724 for (int i = 0; i < mChildren.size(); i++) { 2725 final WindowContainer child = mChildren.get(i); 2726 willSync |= mBLASTSyncEngine.addToSyncSet(localId, child); 2727 } 2728 return willSync; 2729 } 2730 setPendingListener(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId)2731 boolean setPendingListener(BLASTSyncEngine.TransactionReadyListener waitingListener, 2732 int waitingId) { 2733 // If we are invisible, no need to sync, likewise if we are already engaged in a sync, 2734 // we can't support overlapping syncs on a single container yet. 2735 if (!isVisible() || mWaitingListener != null) { 2736 return false; 2737 } 2738 mUsingBLASTSyncTransaction = true; 2739 2740 // Make sure to set these before we call setReady in case the sync was a no-op 2741 mWaitingSyncId = waitingId; 2742 mWaitingListener = waitingListener; 2743 return true; 2744 } 2745 prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, int waitingId)2746 boolean prepareForSync(BLASTSyncEngine.TransactionReadyListener waitingListener, 2747 int waitingId) { 2748 boolean willSync = setPendingListener(waitingListener, waitingId); 2749 if (!willSync) { 2750 return false; 2751 } 2752 2753 int localId = mBLASTSyncEngine.startSyncSet(this); 2754 willSync |= addChildrenToSyncSet(localId); 2755 mBLASTSyncEngine.setReady(localId); 2756 2757 return willSync; 2758 } 2759 useBLASTSync()2760 boolean useBLASTSync() { 2761 return mUsingBLASTSyncTransaction; 2762 } 2763 mergeBlastSyncTransaction(Transaction t)2764 void mergeBlastSyncTransaction(Transaction t) { 2765 t.merge(mBLASTSyncTransaction); 2766 mUsingBLASTSyncTransaction = false; 2767 } 2768 } 2769