1 /* 2 * Copyright (C) 2013 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.app.ActivityManager.RESIZE_MODE_SYSTEM_SCREEN_ROTATION; 20 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY; 21 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY; 22 import static android.content.pm.ActivityInfo.RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; 23 import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET; 24 import static android.content.res.Configuration.EMPTY; 25 import static com.android.server.EventLogTags.WM_TASK_REMOVED; 26 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_STACK; 27 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; 28 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; 29 import static com.android.server.wm.TaskProto.APP_WINDOW_TOKENS; 30 import static com.android.server.wm.TaskProto.BOUNDS; 31 import static com.android.server.wm.TaskProto.DEFER_REMOVAL; 32 import static com.android.server.wm.TaskProto.FILLS_PARENT; 33 import static com.android.server.wm.TaskProto.ID; 34 import static com.android.server.wm.TaskProto.TEMP_INSET_BOUNDS; 35 import static com.android.server.wm.TaskProto.WINDOW_CONTAINER; 36 37 import android.annotation.CallSuper; 38 import android.app.ActivityManager.TaskDescription; 39 import android.content.pm.ActivityInfo; 40 import android.content.res.Configuration; 41 import android.graphics.Rect; 42 import android.util.EventLog; 43 import android.util.Slog; 44 import android.util.proto.ProtoOutputStream; 45 import android.view.Surface; 46 47 import android.view.SurfaceControl; 48 import com.android.internal.annotations.VisibleForTesting; 49 50 import java.io.PrintWriter; 51 import java.util.function.Consumer; 52 53 class Task extends WindowContainer<AppWindowToken> { 54 static final String TAG = TAG_WITH_CLASS_NAME ? "Task" : TAG_WM; 55 56 // TODO: Track parent marks like this in WindowContainer. 57 TaskStack mStack; 58 final int mTaskId; 59 final int mUserId; 60 private boolean mDeferRemoval = false; 61 62 final Rect mPreparedFrozenBounds = new Rect(); 63 final Configuration mPreparedFrozenMergedConfig = new Configuration(); 64 65 // Bounds used to calculate the insets. 66 private final Rect mTempInsetBounds = new Rect(); 67 68 // Device rotation as of the last time {@link #mBounds} was set. 69 private int mRotation; 70 71 // For comparison with DisplayContent bounds. 72 private Rect mTmpRect = new Rect(); 73 // For handling display rotations. 74 private Rect mTmpRect2 = new Rect(); 75 // For retrieving dim bounds 76 private Rect mTmpRect3 = new Rect(); 77 78 // Resize mode of the task. See {@link ActivityInfo#resizeMode} 79 private int mResizeMode; 80 81 // Whether the task supports picture-in-picture. 82 // See {@link ActivityInfo#FLAG_SUPPORTS_PICTURE_IN_PICTURE} 83 private boolean mSupportsPictureInPicture; 84 85 // Whether the task is currently being drag-resized 86 private boolean mDragResizing; 87 private int mDragResizeMode; 88 89 private TaskDescription mTaskDescription; 90 91 // If set to true, the task will report that it is not in the floating 92 // state regardless of it's stack affiliation. As the floating state drives 93 // production of content insets this can be used to preserve them across 94 // stack moves and we in fact do so when moving from full screen to pinned. 95 private boolean mPreserveNonFloatingState = false; 96 97 private Dimmer mDimmer = new Dimmer(this); 98 private final Rect mTmpDimBoundsRect = new Rect(); 99 100 /** @see #setCanAffectSystemUiFlags */ 101 private boolean mCanAffectSystemUiFlags = true; 102 103 Task(int taskId, TaskStack stack, int userId, WindowManagerService service, int resizeMode, 104 boolean supportsPictureInPicture, TaskDescription taskDescription, 105 TaskWindowContainerController controller) { 106 super(service); 107 mTaskId = taskId; 108 mStack = stack; 109 mUserId = userId; 110 mResizeMode = resizeMode; 111 mSupportsPictureInPicture = supportsPictureInPicture; 112 setController(controller); 113 setBounds(getOverrideBounds()); 114 mTaskDescription = taskDescription; 115 116 // Tasks have no set orientation value (including SCREEN_ORIENTATION_UNSPECIFIED). 117 setOrientation(SCREEN_ORIENTATION_UNSET); 118 } 119 120 DisplayContent getDisplayContent() { 121 return mStack != null ? mStack.getDisplayContent() : null; 122 } 123 124 private int getAdjustedAddPosition(int suggestedPosition) { 125 final int size = mChildren.size(); 126 if (suggestedPosition >= size) { 127 return Math.min(size, suggestedPosition); 128 } 129 130 for (int pos = 0; pos < size && pos < suggestedPosition; ++pos) { 131 // TODO: Confirm that this is the behavior we want long term. 132 if (mChildren.get(pos).removed) { 133 // suggestedPosition assumes removed tokens are actually gone. 134 ++suggestedPosition; 135 } 136 } 137 return Math.min(size, suggestedPosition); 138 } 139 140 @Override 141 void addChild(AppWindowToken wtoken, int position) { 142 position = getAdjustedAddPosition(position); 143 super.addChild(wtoken, position); 144 mDeferRemoval = false; 145 } 146 147 @Override 148 void positionChildAt(int position, AppWindowToken child, boolean includingParents) { 149 position = getAdjustedAddPosition(position); 150 super.positionChildAt(position, child, includingParents); 151 mDeferRemoval = false; 152 } 153 154 private boolean hasWindowsAlive() { 155 for (int i = mChildren.size() - 1; i >= 0; i--) { 156 if (mChildren.get(i).hasWindowsAlive()) { 157 return true; 158 } 159 } 160 return false; 161 } 162 163 @VisibleForTesting 164 boolean shouldDeferRemoval() { 165 // TODO: This should probably return false if mChildren.isEmpty() regardless if the stack 166 // is animating... 167 return hasWindowsAlive() && mStack.isSelfOrChildAnimating(); 168 } 169 170 @Override 171 void removeIfPossible() { 172 if (shouldDeferRemoval()) { 173 if (DEBUG_STACK) Slog.i(TAG, "removeTask: deferring removing taskId=" + mTaskId); 174 mDeferRemoval = true; 175 return; 176 } 177 removeImmediately(); 178 } 179 180 @Override 181 void removeImmediately() { 182 if (DEBUG_STACK) Slog.i(TAG, "removeTask: removing taskId=" + mTaskId); 183 EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeTask"); 184 mDeferRemoval = false; 185 186 super.removeImmediately(); 187 } 188 189 void reparent(TaskStack stack, int position, boolean moveParents) { 190 if (stack == mStack) { 191 throw new IllegalArgumentException( 192 "task=" + this + " already child of stack=" + mStack); 193 } 194 if (DEBUG_STACK) Slog.i(TAG, "reParentTask: removing taskId=" + mTaskId 195 + " from stack=" + mStack); 196 EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "reParentTask"); 197 final DisplayContent prevDisplayContent = getDisplayContent(); 198 199 // If we are moving from the fullscreen stack to the pinned stack 200 // then we want to preserve our insets so that there will not 201 // be a jump in the area covered by system decorations. We rely 202 // on the pinned animation to later unset this value. 203 if (stack.inPinnedWindowingMode()) { 204 mPreserveNonFloatingState = true; 205 } else { 206 mPreserveNonFloatingState = false; 207 } 208 209 getParent().removeChild(this); 210 stack.addTask(this, position, showForAllUsers(), moveParents); 211 212 // Relayout display(s). 213 final DisplayContent displayContent = stack.getDisplayContent(); 214 displayContent.setLayoutNeeded(); 215 if (prevDisplayContent != displayContent) { 216 onDisplayChanged(displayContent); 217 prevDisplayContent.setLayoutNeeded(); 218 } 219 } 220 221 /** @see com.android.server.am.ActivityManagerService#positionTaskInStack(int, int, int). */ 222 void positionAt(int position) { 223 mStack.positionChildAt(position, this, false /* includingParents */); 224 } 225 226 @Override 227 void onParentSet() { 228 super.onParentSet(); 229 230 // Update task bounds if needed. 231 updateDisplayInfo(getDisplayContent()); 232 233 if (getWindowConfiguration().windowsAreScaleable()) { 234 // We force windows out of SCALING_MODE_FREEZE so that we can continue to animate them 235 // while a resize is pending. 236 forceWindowsScaleable(true /* force */); 237 } else { 238 forceWindowsScaleable(false /* force */); 239 } 240 } 241 242 @Override 243 void removeChild(AppWindowToken token) { 244 if (!mChildren.contains(token)) { 245 Slog.e(TAG, "removeChild: token=" + this + " not found."); 246 return; 247 } 248 249 super.removeChild(token); 250 251 if (mChildren.isEmpty()) { 252 EventLog.writeEvent(WM_TASK_REMOVED, mTaskId, "removeAppToken: last token"); 253 if (mDeferRemoval) { 254 removeIfPossible(); 255 } 256 } 257 } 258 259 void setSendingToBottom(boolean toBottom) { 260 for (int appTokenNdx = 0; appTokenNdx < mChildren.size(); appTokenNdx++) { 261 mChildren.get(appTokenNdx).sendingToBottom = toBottom; 262 } 263 } 264 265 public int setBounds(Rect bounds, boolean forceResize) { 266 final int boundsChanged = setBounds(bounds); 267 268 if (forceResize && (boundsChanged & BOUNDS_CHANGE_SIZE) != BOUNDS_CHANGE_SIZE) { 269 onResize(); 270 return BOUNDS_CHANGE_SIZE | boundsChanged; 271 } 272 273 return boundsChanged; 274 } 275 276 /** Set the task bounds. Passing in null sets the bounds to fullscreen. */ 277 @Override 278 public int setBounds(Rect bounds) { 279 int rotation = Surface.ROTATION_0; 280 final DisplayContent displayContent = mStack.getDisplayContent(); 281 if (displayContent != null) { 282 rotation = displayContent.getDisplayInfo().rotation; 283 } else if (bounds == null) { 284 // Can't set to fullscreen if we don't have a display to get bounds from... 285 return BOUNDS_CHANGE_NONE; 286 } 287 288 if (equivalentOverrideBounds(bounds)) { 289 return BOUNDS_CHANGE_NONE; 290 } 291 292 final int boundsChange = super.setBounds(bounds); 293 294 mRotation = rotation; 295 296 return boundsChange; 297 } 298 299 /** 300 * Sets the bounds used to calculate the insets. See 301 * {@link android.app.IActivityManager#resizeDockedStack} why this is needed. 302 */ 303 void setTempInsetBounds(Rect tempInsetBounds) { 304 if (tempInsetBounds != null) { 305 mTempInsetBounds.set(tempInsetBounds); 306 } else { 307 mTempInsetBounds.setEmpty(); 308 } 309 } 310 311 /** 312 * Gets the bounds used to calculate the insets. See 313 * {@link android.app.IActivityManager#resizeDockedStack} why this is needed. 314 */ 315 void getTempInsetBounds(Rect out) { 316 out.set(mTempInsetBounds); 317 } 318 319 void setResizeable(int resizeMode) { 320 mResizeMode = resizeMode; 321 } 322 323 boolean isResizeable() { 324 return ActivityInfo.isResizeableMode(mResizeMode) || mSupportsPictureInPicture 325 || mService.mForceResizableTasks; 326 } 327 328 /** 329 * Tests if the orientation should be preserved upon user interactive resizig operations. 330 331 * @return true if orientation should not get changed upon resizing operation. 332 */ 333 boolean preserveOrientationOnResize() { 334 return mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PORTRAIT_ONLY 335 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_LANDSCAPE_ONLY 336 || mResizeMode == RESIZE_MODE_FORCE_RESIZABLE_PRESERVE_ORIENTATION; 337 } 338 339 boolean cropWindowsToStackBounds() { 340 return isResizeable(); 341 } 342 343 /** 344 * Prepares the task bounds to be frozen with the current size. See 345 * {@link AppWindowToken#freezeBounds}. 346 */ 347 void prepareFreezingBounds() { 348 mPreparedFrozenBounds.set(getBounds()); 349 mPreparedFrozenMergedConfig.setTo(getConfiguration()); 350 } 351 352 /** 353 * Align the task to the adjusted bounds. 354 * 355 * @param adjustedBounds Adjusted bounds to which the task should be aligned. 356 * @param tempInsetBounds Insets bounds for the task. 357 * @param alignBottom True if the task's bottom should be aligned to the adjusted 358 * bounds's bottom; false if the task's top should be aligned 359 * the adjusted bounds's top. 360 */ 361 void alignToAdjustedBounds(Rect adjustedBounds, Rect tempInsetBounds, boolean alignBottom) { 362 if (!isResizeable() || EMPTY.equals(getOverrideConfiguration())) { 363 return; 364 } 365 366 getBounds(mTmpRect2); 367 if (alignBottom) { 368 int offsetY = adjustedBounds.bottom - mTmpRect2.bottom; 369 mTmpRect2.offset(0, offsetY); 370 } else { 371 mTmpRect2.offsetTo(adjustedBounds.left, adjustedBounds.top); 372 } 373 setTempInsetBounds(tempInsetBounds); 374 setBounds(mTmpRect2, false /* forced */); 375 } 376 377 /** Return true if the current bound can get outputted to the rest of the system as-is. */ 378 private boolean useCurrentBounds() { 379 final DisplayContent displayContent = getDisplayContent(); 380 return matchParentBounds() 381 || !inSplitScreenSecondaryWindowingMode() 382 || displayContent == null 383 || displayContent.getSplitScreenPrimaryStackIgnoringVisibility() != null; 384 } 385 386 @Override 387 public void getBounds(Rect out) { 388 if (useCurrentBounds()) { 389 // No need to adjust the output bounds if fullscreen or the docked stack is visible 390 // since it is already what we want to represent to the rest of the system. 391 super.getBounds(out); 392 return; 393 } 394 395 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is 396 // not currently visible. Go ahead a represent it as fullscreen to the rest of the system. 397 mStack.getDisplayContent().getBounds(out); 398 } 399 400 /** 401 * Calculate the maximum visible area of this task. If the task has only one app, 402 * the result will be visible frame of that app. If the task has more than one apps, 403 * we search from top down if the next app got different visible area. 404 * 405 * This effort is to handle the case where some task (eg. GMail composer) might pop up 406 * a dialog that's different in size from the activity below, in which case we should 407 * be dimming the entire task area behind the dialog. 408 * 409 * @param out Rect containing the max visible bounds. 410 * @return true if the task has some visible app windows; false otherwise. 411 */ 412 boolean getMaxVisibleBounds(Rect out) { 413 boolean foundTop = false; 414 for (int i = mChildren.size() - 1; i >= 0; i--) { 415 final AppWindowToken token = mChildren.get(i); 416 // skip hidden (or about to hide) apps 417 if (token.mIsExiting || token.isClientHidden() || token.hiddenRequested) { 418 continue; 419 } 420 final WindowState win = token.findMainWindow(); 421 if (win == null) { 422 continue; 423 } 424 if (!foundTop) { 425 out.set(win.mVisibleFrame); 426 foundTop = true; 427 continue; 428 } 429 if (win.mVisibleFrame.left < out.left) { 430 out.left = win.mVisibleFrame.left; 431 } 432 if (win.mVisibleFrame.top < out.top) { 433 out.top = win.mVisibleFrame.top; 434 } 435 if (win.mVisibleFrame.right > out.right) { 436 out.right = win.mVisibleFrame.right; 437 } 438 if (win.mVisibleFrame.bottom > out.bottom) { 439 out.bottom = win.mVisibleFrame.bottom; 440 } 441 } 442 return foundTop; 443 } 444 445 /** Bounds of the task to be used for dimming, as well as touch related tests. */ 446 public void getDimBounds(Rect out) { 447 final DisplayContent displayContent = mStack.getDisplayContent(); 448 // It doesn't matter if we in particular are part of the resize, since we couldn't have 449 // a DimLayer anyway if we weren't visible. 450 final boolean dockedResizing = displayContent != null 451 && displayContent.mDividerControllerLocked.isResizing(); 452 if (useCurrentBounds()) { 453 if (inFreeformWindowingMode() && getMaxVisibleBounds(out)) { 454 return; 455 } 456 457 if (!matchParentBounds()) { 458 // When minimizing the docked stack when going home, we don't adjust the task bounds 459 // so we need to intersect the task bounds with the stack bounds here. 460 // 461 // If we are Docked Resizing with snap points, the task bounds could be smaller than the stack 462 // bounds and so we don't even want to use them. Even if the app should not be resized the Dim 463 // should keep up with the divider. 464 if (dockedResizing) { 465 mStack.getBounds(out); 466 } else { 467 mStack.getBounds(mTmpRect); 468 mTmpRect.intersect(getBounds()); 469 out.set(mTmpRect); 470 } 471 } else { 472 out.set(getBounds()); 473 } 474 return; 475 } 476 477 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack is 478 // not currently visible. Go ahead a represent it as fullscreen to the rest of the system. 479 if (displayContent != null) { 480 displayContent.getBounds(out); 481 } 482 } 483 484 void setDragResizing(boolean dragResizing, int dragResizeMode) { 485 if (mDragResizing != dragResizing) { 486 if (!DragResizeMode.isModeAllowedForStack(mStack, dragResizeMode)) { 487 throw new IllegalArgumentException("Drag resize mode not allow for stack stackId=" 488 + mStack.mStackId + " dragResizeMode=" + dragResizeMode); 489 } 490 mDragResizing = dragResizing; 491 mDragResizeMode = dragResizeMode; 492 resetDragResizingChangeReported(); 493 } 494 } 495 496 boolean isDragResizing() { 497 return mDragResizing; 498 } 499 500 int getDragResizeMode() { 501 return mDragResizeMode; 502 } 503 504 void updateDisplayInfo(final DisplayContent displayContent) { 505 if (displayContent == null) { 506 return; 507 } 508 if (matchParentBounds()) { 509 // TODO: Yeah...not sure if this works with WindowConfiguration, but shouldn't be a 510 // problem once we move mBounds into WindowConfiguration. 511 setBounds(null); 512 return; 513 } 514 final int newRotation = displayContent.getDisplayInfo().rotation; 515 if (mRotation == newRotation) { 516 return; 517 } 518 519 // Device rotation changed. 520 // - We don't want the task to move around on the screen when this happens, so update the 521 // task bounds so it stays in the same place. 522 // - Rotate the bounds and notify activity manager if the task can be resized independently 523 // from its stack. The stack will take care of task rotation for the other case. 524 mTmpRect2.set(getBounds()); 525 526 if (!getWindowConfiguration().canResizeTask()) { 527 setBounds(mTmpRect2); 528 return; 529 } 530 531 displayContent.rotateBounds(mRotation, newRotation, mTmpRect2); 532 if (setBounds(mTmpRect2) != BOUNDS_CHANGE_NONE) { 533 final TaskWindowContainerController controller = getController(); 534 if (controller != null) { 535 controller.requestResize(getBounds(), RESIZE_MODE_SYSTEM_SCREEN_ROTATION); 536 } 537 } 538 } 539 540 /** Cancels any running app transitions associated with the task. */ 541 void cancelTaskWindowTransition() { 542 for (int i = mChildren.size() - 1; i >= 0; --i) { 543 mChildren.get(i).cancelAnimation(); 544 } 545 } 546 547 boolean showForAllUsers() { 548 final int tokensCount = mChildren.size(); 549 return (tokensCount != 0) && mChildren.get(tokensCount - 1).mShowForAllUsers; 550 } 551 552 /** 553 * When we are in a floating stack (Freeform, Pinned, ...) we calculate 554 * insets differently. However if we are animating to the fullscreen stack 555 * we need to begin calculating insets as if we were fullscreen, otherwise 556 * we will have a jump at the end. 557 */ 558 boolean isFloating() { 559 return getWindowConfiguration().tasksAreFloating() 560 && !mStack.isAnimatingBoundsToFullscreen() && !mPreserveNonFloatingState; 561 } 562 563 @Override 564 public SurfaceControl getAnimationLeashParent() { 565 // Reparent to the animation layer so that we aren't clipped by the non-minimized 566 // stack bounds, currently we only animate the task for the recents animation 567 return getAppAnimationLayer(ANIMATION_LAYER_STANDARD); 568 } 569 570 boolean isTaskAnimating() { 571 final RecentsAnimationController recentsAnim = mService.getRecentsAnimationController(); 572 if (recentsAnim != null) { 573 if (recentsAnim.isAnimatingTask(this)) { 574 return true; 575 } 576 } 577 return false; 578 } 579 580 WindowState getTopVisibleAppMainWindow() { 581 final AppWindowToken token = getTopVisibleAppToken(); 582 return token != null ? token.findMainWindow() : null; 583 } 584 585 AppWindowToken getTopFullscreenAppToken() { 586 for (int i = mChildren.size() - 1; i >= 0; i--) { 587 final AppWindowToken token = mChildren.get(i); 588 final WindowState win = token.findMainWindow(); 589 if (win != null && win.mAttrs.isFullscreen()) { 590 return token; 591 } 592 } 593 return null; 594 } 595 596 AppWindowToken getTopVisibleAppToken() { 597 for (int i = mChildren.size() - 1; i >= 0; i--) { 598 final AppWindowToken token = mChildren.get(i); 599 // skip hidden (or about to hide) apps 600 if (!token.mIsExiting && !token.isClientHidden() && !token.hiddenRequested) { 601 return token; 602 } 603 } 604 return null; 605 } 606 607 boolean isFullscreen() { 608 if (useCurrentBounds()) { 609 return matchParentBounds(); 610 } 611 // The bounds has been adjusted to accommodate for a docked stack, but the docked stack 612 // is not currently visible. Go ahead a represent it as fullscreen to the rest of the 613 // system. 614 return true; 615 } 616 617 void forceWindowsScaleable(boolean force) { 618 mService.openSurfaceTransaction(); 619 try { 620 for (int i = mChildren.size() - 1; i >= 0; i--) { 621 mChildren.get(i).forceWindowsScaleableInTransaction(force); 622 } 623 } finally { 624 mService.closeSurfaceTransaction("forceWindowsScaleable"); 625 } 626 } 627 628 void setTaskDescription(TaskDescription taskDescription) { 629 mTaskDescription = taskDescription; 630 } 631 632 TaskDescription getTaskDescription() { 633 return mTaskDescription; 634 } 635 636 @Override 637 boolean fillsParent() { 638 return matchParentBounds() || !getWindowConfiguration().canResizeTask(); 639 } 640 641 @Override 642 TaskWindowContainerController getController() { 643 return (TaskWindowContainerController) super.getController(); 644 } 645 646 @Override 647 void forAllTasks(Consumer<Task> callback) { 648 callback.accept(this); 649 } 650 651 /** 652 * @param canAffectSystemUiFlags If false, all windows in this task can not affect SystemUI 653 * flags. See {@link WindowState#canAffectSystemUiFlags()}. 654 */ 655 void setCanAffectSystemUiFlags(boolean canAffectSystemUiFlags) { 656 mCanAffectSystemUiFlags = canAffectSystemUiFlags; 657 } 658 659 /** 660 * @see #setCanAffectSystemUiFlags 661 */ 662 boolean canAffectSystemUiFlags() { 663 return mCanAffectSystemUiFlags; 664 } 665 666 void dontAnimateDimExit() { 667 mDimmer.dontAnimateExit(); 668 } 669 670 @Override 671 public String toString() { 672 return "{taskId=" + mTaskId + " appTokens=" + mChildren + " mdr=" + mDeferRemoval + "}"; 673 } 674 675 String getName() { 676 return toShortString(); 677 } 678 679 void clearPreserveNonFloatingState() { 680 mPreserveNonFloatingState = false; 681 } 682 683 @Override 684 Dimmer getDimmer() { 685 return mDimmer; 686 } 687 688 @Override 689 void prepareSurfaces() { 690 mDimmer.resetDimStates(); 691 super.prepareSurfaces(); 692 getDimBounds(mTmpDimBoundsRect); 693 694 // Bounds need to be relative, as the dim layer is a child. 695 mTmpDimBoundsRect.offsetTo(0, 0); 696 if (mDimmer.updateDims(getPendingTransaction(), mTmpDimBoundsRect)) { 697 scheduleAnimation(); 698 } 699 } 700 701 @CallSuper 702 @Override 703 public void writeToProto(ProtoOutputStream proto, long fieldId, boolean trim) { 704 final long token = proto.start(fieldId); 705 super.writeToProto(proto, WINDOW_CONTAINER, trim); 706 proto.write(ID, mTaskId); 707 for (int i = mChildren.size() - 1; i >= 0; i--) { 708 final AppWindowToken appWindowToken = mChildren.get(i); 709 appWindowToken.writeToProto(proto, APP_WINDOW_TOKENS, trim); 710 } 711 proto.write(FILLS_PARENT, matchParentBounds()); 712 getBounds().writeToProto(proto, BOUNDS); 713 mTempInsetBounds.writeToProto(proto, TEMP_INSET_BOUNDS); 714 proto.write(DEFER_REMOVAL, mDeferRemoval); 715 proto.end(token); 716 } 717 718 @Override 719 public void dump(PrintWriter pw, String prefix, boolean dumpAll) { 720 super.dump(pw, prefix, dumpAll); 721 final String doublePrefix = prefix + " "; 722 723 pw.println(prefix + "taskId=" + mTaskId); 724 pw.println(doublePrefix + "mBounds=" + getBounds().toShortString()); 725 pw.println(doublePrefix + "mdr=" + mDeferRemoval); 726 pw.println(doublePrefix + "appTokens=" + mChildren); 727 pw.println(doublePrefix + "mTempInsetBounds=" + mTempInsetBounds.toShortString()); 728 729 final String triplePrefix = doublePrefix + " "; 730 final String quadruplePrefix = triplePrefix + " "; 731 732 for (int i = mChildren.size() - 1; i >= 0; i--) { 733 final AppWindowToken wtoken = mChildren.get(i); 734 pw.println(triplePrefix + "Activity #" + i + " " + wtoken); 735 wtoken.dump(pw, quadruplePrefix, dumpAll); 736 } 737 } 738 739 String toShortString() { 740 return "Task=" + mTaskId; 741 } 742 } 743