1 /* 2 * Copyright (C) 2020 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.wm.shell.pip; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.app.ActivityTaskManager; 23 import android.app.PictureInPictureParams; 24 import android.app.PictureInPictureUiState; 25 import android.content.ComponentName; 26 import android.content.Context; 27 import android.content.pm.ActivityInfo; 28 import android.graphics.Point; 29 import android.graphics.Rect; 30 import android.os.RemoteException; 31 import android.util.ArraySet; 32 import android.util.Size; 33 import android.view.Display; 34 35 import com.android.internal.annotations.VisibleForTesting; 36 import com.android.internal.protolog.common.ProtoLog; 37 import com.android.internal.util.function.TriConsumer; 38 import com.android.wm.shell.R; 39 import com.android.wm.shell.common.DisplayLayout; 40 import com.android.wm.shell.pip.phone.PipSizeSpecHandler; 41 import com.android.wm.shell.protolog.ShellProtoLogGroup; 42 43 import java.io.PrintWriter; 44 import java.lang.annotation.Retention; 45 import java.lang.annotation.RetentionPolicy; 46 import java.util.ArrayList; 47 import java.util.HashMap; 48 import java.util.List; 49 import java.util.Map; 50 import java.util.Objects; 51 import java.util.Set; 52 import java.util.function.Consumer; 53 54 /** 55 * Singleton source of truth for the current state of PIP bounds. 56 */ 57 public class PipBoundsState { 58 public static final int STASH_TYPE_NONE = 0; 59 public static final int STASH_TYPE_LEFT = 1; 60 public static final int STASH_TYPE_RIGHT = 2; 61 public static final int STASH_TYPE_BOTTOM = 3; 62 public static final int STASH_TYPE_TOP = 4; 63 64 @IntDef(prefix = { "STASH_TYPE_" }, value = { 65 STASH_TYPE_NONE, 66 STASH_TYPE_LEFT, 67 STASH_TYPE_RIGHT, 68 STASH_TYPE_BOTTOM, 69 STASH_TYPE_TOP 70 }) 71 @Retention(RetentionPolicy.SOURCE) 72 public @interface StashType {} 73 74 private static final String TAG = PipBoundsState.class.getSimpleName(); 75 76 private final @NonNull Rect mBounds = new Rect(); 77 private final @NonNull Rect mMovementBounds = new Rect(); 78 private final @NonNull Rect mNormalBounds = new Rect(); 79 private final @NonNull Rect mExpandedBounds = new Rect(); 80 private final @NonNull Rect mNormalMovementBounds = new Rect(); 81 private final @NonNull Rect mExpandedMovementBounds = new Rect(); 82 private final Point mMaxSize = new Point(); 83 private final Point mMinSize = new Point(); 84 private final @NonNull Context mContext; 85 private float mAspectRatio; 86 private int mStashedState = STASH_TYPE_NONE; 87 private int mStashOffset; 88 private @Nullable PipReentryState mPipReentryState; 89 private final LauncherState mLauncherState = new LauncherState(); 90 private final @Nullable PipSizeSpecHandler mPipSizeSpecHandler; 91 private @Nullable ComponentName mLastPipComponentName; 92 private int mDisplayId = Display.DEFAULT_DISPLAY; 93 private final @NonNull DisplayLayout mDisplayLayout = new DisplayLayout(); 94 private final @NonNull MotionBoundsState mMotionBoundsState = new MotionBoundsState(); 95 private boolean mIsImeShowing; 96 private int mImeHeight; 97 private boolean mIsShelfShowing; 98 private int mShelfHeight; 99 /** Whether the user has resized the PIP manually. */ 100 private boolean mHasUserResizedPip; 101 /** Whether the user has moved the PIP manually. */ 102 private boolean mHasUserMovedPip; 103 /** 104 * Areas defined by currently visible apps that they prefer to keep clear from overlays such as 105 * the PiP. Restricted areas may only move the PiP a limited amount from its anchor position. 106 * The system will try to respect these areas, but when not possible will ignore them. 107 * 108 * @see android.view.View#setPreferKeepClearRects 109 */ 110 private final Set<Rect> mRestrictedKeepClearAreas = new ArraySet<>(); 111 /** 112 * Areas defined by currently visible apps holding 113 * {@link android.Manifest.permission#SET_UNRESTRICTED_KEEP_CLEAR_AREAS} that they prefer to 114 * keep clear from overlays such as the PiP. 115 * Unrestricted areas can move the PiP farther than restricted areas, and the system will try 116 * harder to respect these areas. 117 * 118 * @see android.view.View#setPreferKeepClearRects 119 */ 120 private final Set<Rect> mUnrestrictedKeepClearAreas = new ArraySet<>(); 121 /** 122 * Additional to {@link #mUnrestrictedKeepClearAreas}, allow the caller to append named bounds 123 * as unrestricted keep clear area. Values in this map would be appended to 124 * {@link #getUnrestrictedKeepClearAreas()} and this is meant for internal usage only. 125 */ 126 private final Map<String, Rect> mNamedUnrestrictedKeepClearAreas = new HashMap<>(); 127 128 private @Nullable Runnable mOnMinimalSizeChangeCallback; 129 private @Nullable TriConsumer<Boolean, Integer, Boolean> mOnShelfVisibilityChangeCallback; 130 private List<Consumer<Rect>> mOnPipExclusionBoundsChangeCallbacks = new ArrayList<>(); 131 PipBoundsState(@onNull Context context, PipSizeSpecHandler pipSizeSpecHandler)132 public PipBoundsState(@NonNull Context context, PipSizeSpecHandler pipSizeSpecHandler) { 133 mContext = context; 134 reloadResources(); 135 mPipSizeSpecHandler = pipSizeSpecHandler; 136 } 137 138 /** Reloads the resources. */ onConfigurationChanged()139 public void onConfigurationChanged() { 140 reloadResources(); 141 } 142 reloadResources()143 private void reloadResources() { 144 mStashOffset = mContext.getResources().getDimensionPixelSize(R.dimen.pip_stash_offset); 145 } 146 147 /** Set the current PIP bounds. */ setBounds(@onNull Rect bounds)148 public void setBounds(@NonNull Rect bounds) { 149 mBounds.set(bounds); 150 for (Consumer<Rect> callback : mOnPipExclusionBoundsChangeCallbacks) { 151 callback.accept(bounds); 152 } 153 } 154 155 /** Get the current PIP bounds. */ 156 @NonNull getBounds()157 public Rect getBounds() { 158 return new Rect(mBounds); 159 } 160 161 /** Returns the current movement bounds. */ 162 @NonNull getMovementBounds()163 public Rect getMovementBounds() { 164 return mMovementBounds; 165 } 166 167 /** Set the current normal PIP bounds. */ setNormalBounds(@onNull Rect bounds)168 public void setNormalBounds(@NonNull Rect bounds) { 169 mNormalBounds.set(bounds); 170 } 171 172 /** Get the current normal PIP bounds. */ 173 @NonNull getNormalBounds()174 public Rect getNormalBounds() { 175 return mNormalBounds; 176 } 177 178 /** Set the expanded bounds of PIP. */ setExpandedBounds(@onNull Rect bounds)179 public void setExpandedBounds(@NonNull Rect bounds) { 180 mExpandedBounds.set(bounds); 181 } 182 183 /** Get the PIP expanded bounds. */ 184 @NonNull getExpandedBounds()185 public Rect getExpandedBounds() { 186 return mExpandedBounds; 187 } 188 189 /** Set the normal movement bounds. */ setNormalMovementBounds(@onNull Rect bounds)190 public void setNormalMovementBounds(@NonNull Rect bounds) { 191 mNormalMovementBounds.set(bounds); 192 } 193 194 /** Returns the normal movement bounds. */ 195 @NonNull getNormalMovementBounds()196 public Rect getNormalMovementBounds() { 197 return mNormalMovementBounds; 198 } 199 200 /** Set the expanded movement bounds. */ setExpandedMovementBounds(@onNull Rect bounds)201 public void setExpandedMovementBounds(@NonNull Rect bounds) { 202 mExpandedMovementBounds.set(bounds); 203 } 204 205 /** Sets the max possible size for resize. */ setMaxSize(int width, int height)206 public void setMaxSize(int width, int height) { 207 mMaxSize.set(width, height); 208 } 209 210 /** Sets the min possible size for resize. */ setMinSize(int width, int height)211 public void setMinSize(int width, int height) { 212 mMinSize.set(width, height); 213 } 214 getMaxSize()215 public Point getMaxSize() { 216 return mMaxSize; 217 } 218 getMinSize()219 public Point getMinSize() { 220 return mMinSize; 221 } 222 223 /** Returns the expanded movement bounds. */ 224 @NonNull getExpandedMovementBounds()225 public Rect getExpandedMovementBounds() { 226 return mExpandedMovementBounds; 227 } 228 229 /** Dictate where PiP currently should be stashed, if at all. */ setStashed(@tashType int stashedState)230 public void setStashed(@StashType int stashedState) { 231 if (mStashedState == stashedState) { 232 return; 233 } 234 235 mStashedState = stashedState; 236 try { 237 ActivityTaskManager.getService().onPictureInPictureStateChanged( 238 new PictureInPictureUiState(stashedState != STASH_TYPE_NONE /* isStashed */) 239 ); 240 } catch (RemoteException e) { 241 ProtoLog.e(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE, 242 "%s: Unable to set alert PiP state change.", TAG); 243 } 244 } 245 246 /** 247 * Return where the PiP is stashed, if at all. 248 * @return {@code STASH_NONE}, {@code STASH_LEFT} or {@code STASH_RIGHT}. 249 */ getStashedState()250 public @StashType int getStashedState() { 251 return mStashedState; 252 } 253 254 /** Whether PiP is stashed or not. */ isStashed()255 public boolean isStashed() { 256 return mStashedState != STASH_TYPE_NONE; 257 } 258 259 /** Returns the offset from the edge of the screen for PiP stash. */ getStashOffset()260 public int getStashOffset() { 261 return mStashOffset; 262 } 263 264 /** Set the PIP aspect ratio. */ setAspectRatio(float aspectRatio)265 public void setAspectRatio(float aspectRatio) { 266 mAspectRatio = aspectRatio; 267 } 268 269 /** Get the PIP aspect ratio. */ getAspectRatio()270 public float getAspectRatio() { 271 return mAspectRatio; 272 } 273 274 /** Save the reentry state to restore to when re-entering PIP mode. */ saveReentryState(Size size, float fraction)275 public void saveReentryState(Size size, float fraction) { 276 mPipReentryState = new PipReentryState(size, fraction); 277 } 278 279 /** Returns the saved reentry state. */ 280 @Nullable getReentryState()281 public PipReentryState getReentryState() { 282 return mPipReentryState; 283 } 284 285 /** Set the last {@link ComponentName} to enter PIP mode. */ setLastPipComponentName(@ullable ComponentName lastPipComponentName)286 public void setLastPipComponentName(@Nullable ComponentName lastPipComponentName) { 287 final boolean changed = !Objects.equals(mLastPipComponentName, lastPipComponentName); 288 mLastPipComponentName = lastPipComponentName; 289 if (changed) { 290 clearReentryState(); 291 setHasUserResizedPip(false); 292 setHasUserMovedPip(false); 293 } 294 } 295 296 /** Get the last PIP component name, if any. */ 297 @Nullable getLastPipComponentName()298 public ComponentName getLastPipComponentName() { 299 return mLastPipComponentName; 300 } 301 302 /** Get the current display id. */ getDisplayId()303 public int getDisplayId() { 304 return mDisplayId; 305 } 306 307 /** Set the current display id for the associated display layout. */ setDisplayId(int displayId)308 public void setDisplayId(int displayId) { 309 mDisplayId = displayId; 310 } 311 312 /** Returns the display's bounds. */ 313 @NonNull getDisplayBounds()314 public Rect getDisplayBounds() { 315 return new Rect(0, 0, mDisplayLayout.width(), mDisplayLayout.height()); 316 } 317 318 /** Update the display layout. */ setDisplayLayout(@onNull DisplayLayout displayLayout)319 public void setDisplayLayout(@NonNull DisplayLayout displayLayout) { 320 mDisplayLayout.set(displayLayout); 321 } 322 323 /** Get a copy of the display layout. */ 324 @NonNull getDisplayLayout()325 public DisplayLayout getDisplayLayout() { 326 return new DisplayLayout(mDisplayLayout); 327 } 328 329 @VisibleForTesting clearReentryState()330 void clearReentryState() { 331 mPipReentryState = null; 332 } 333 334 /** Sets the preferred size of PIP as specified by the activity in PIP mode. */ setOverrideMinSize(@ullable Size overrideMinSize)335 public void setOverrideMinSize(@Nullable Size overrideMinSize) { 336 final boolean changed = !Objects.equals(overrideMinSize, getOverrideMinSize()); 337 mPipSizeSpecHandler.setOverrideMinSize(overrideMinSize); 338 if (changed && mOnMinimalSizeChangeCallback != null) { 339 mOnMinimalSizeChangeCallback.run(); 340 } 341 } 342 343 /** Returns the preferred minimal size specified by the activity in PIP. */ 344 @Nullable getOverrideMinSize()345 public Size getOverrideMinSize() { 346 return mPipSizeSpecHandler.getOverrideMinSize(); 347 } 348 349 /** Returns the minimum edge size of the override minimum size, or 0 if not set. */ getOverrideMinEdgeSize()350 public int getOverrideMinEdgeSize() { 351 return mPipSizeSpecHandler.getOverrideMinEdgeSize(); 352 } 353 354 /** Get the state of the bounds in motion. */ 355 @NonNull getMotionBoundsState()356 public MotionBoundsState getMotionBoundsState() { 357 return mMotionBoundsState; 358 } 359 360 /** Set whether the IME is currently showing and its height. */ setImeVisibility(boolean imeShowing, int imeHeight)361 public void setImeVisibility(boolean imeShowing, int imeHeight) { 362 mIsImeShowing = imeShowing; 363 mImeHeight = imeHeight; 364 } 365 366 /** Returns whether the IME is currently showing. */ isImeShowing()367 public boolean isImeShowing() { 368 return mIsImeShowing; 369 } 370 371 /** Returns the IME height. */ getImeHeight()372 public int getImeHeight() { 373 return mImeHeight; 374 } 375 376 /** Set whether the shelf is showing and its height. */ setShelfVisibility(boolean showing, int height)377 public void setShelfVisibility(boolean showing, int height) { 378 setShelfVisibility(showing, height, true); 379 } 380 381 /** Set whether the shelf is showing and its height. */ setShelfVisibility(boolean showing, int height, boolean updateMovementBounds)382 public void setShelfVisibility(boolean showing, int height, boolean updateMovementBounds) { 383 final boolean shelfShowing = showing && height > 0; 384 if (shelfShowing == mIsShelfShowing && height == mShelfHeight) { 385 return; 386 } 387 388 mIsShelfShowing = showing; 389 mShelfHeight = height; 390 if (mOnShelfVisibilityChangeCallback != null) { 391 mOnShelfVisibilityChangeCallback.accept(mIsShelfShowing, mShelfHeight, 392 updateMovementBounds); 393 } 394 } 395 396 /** Set the keep clear areas onscreen. The PiP should ideally not cover them. */ setKeepClearAreas(@onNull Set<Rect> restrictedAreas, @NonNull Set<Rect> unrestrictedAreas)397 public void setKeepClearAreas(@NonNull Set<Rect> restrictedAreas, 398 @NonNull Set<Rect> unrestrictedAreas) { 399 mRestrictedKeepClearAreas.clear(); 400 mRestrictedKeepClearAreas.addAll(restrictedAreas); 401 mUnrestrictedKeepClearAreas.clear(); 402 mUnrestrictedKeepClearAreas.addAll(unrestrictedAreas); 403 } 404 405 /** Add a named unrestricted keep clear area. */ addNamedUnrestrictedKeepClearArea(@onNull String name, Rect unrestrictedArea)406 public void addNamedUnrestrictedKeepClearArea(@NonNull String name, Rect unrestrictedArea) { 407 mNamedUnrestrictedKeepClearAreas.put(name, unrestrictedArea); 408 } 409 410 /** Remove a named unrestricted keep clear area. */ removeNamedUnrestrictedKeepClearArea(@onNull String name)411 public void removeNamedUnrestrictedKeepClearArea(@NonNull String name) { 412 mNamedUnrestrictedKeepClearAreas.remove(name); 413 } 414 415 @NonNull getRestrictedKeepClearAreas()416 public Set<Rect> getRestrictedKeepClearAreas() { 417 return mRestrictedKeepClearAreas; 418 } 419 420 @NonNull getUnrestrictedKeepClearAreas()421 public Set<Rect> getUnrestrictedKeepClearAreas() { 422 if (mNamedUnrestrictedKeepClearAreas.isEmpty()) return mUnrestrictedKeepClearAreas; 423 final Set<Rect> unrestrictedAreas = new ArraySet<>(mUnrestrictedKeepClearAreas); 424 unrestrictedAreas.addAll(mNamedUnrestrictedKeepClearAreas.values()); 425 return unrestrictedAreas; 426 } 427 428 /** 429 * Initialize states when first entering PiP. 430 */ setBoundsStateForEntry(ComponentName componentName, ActivityInfo activityInfo, PictureInPictureParams params, PipBoundsAlgorithm pipBoundsAlgorithm)431 public void setBoundsStateForEntry(ComponentName componentName, ActivityInfo activityInfo, 432 PictureInPictureParams params, PipBoundsAlgorithm pipBoundsAlgorithm) { 433 setLastPipComponentName(componentName); 434 setAspectRatio(pipBoundsAlgorithm.getAspectRatioOrDefault(params)); 435 setOverrideMinSize(pipBoundsAlgorithm.getMinimalSize(activityInfo)); 436 } 437 438 /** Returns whether the shelf is currently showing. */ isShelfShowing()439 public boolean isShelfShowing() { 440 return mIsShelfShowing; 441 } 442 443 /** Returns the shelf height. */ getShelfHeight()444 public int getShelfHeight() { 445 return mShelfHeight; 446 } 447 448 /** Returns whether the user has resized the PIP. */ hasUserResizedPip()449 public boolean hasUserResizedPip() { 450 return mHasUserResizedPip; 451 } 452 453 /** Set whether the user has resized the PIP. */ setHasUserResizedPip(boolean hasUserResizedPip)454 public void setHasUserResizedPip(boolean hasUserResizedPip) { 455 mHasUserResizedPip = hasUserResizedPip; 456 } 457 458 /** Returns whether the user has moved the PIP. */ hasUserMovedPip()459 public boolean hasUserMovedPip() { 460 return mHasUserMovedPip; 461 } 462 463 /** Set whether the user has moved the PIP. */ setHasUserMovedPip(boolean hasUserMovedPip)464 public void setHasUserMovedPip(boolean hasUserMovedPip) { 465 mHasUserMovedPip = hasUserMovedPip; 466 } 467 468 /** 469 * Registers a callback when the minimal size of PIP that is set by the app changes. 470 */ setOnMinimalSizeChangeCallback(@ullable Runnable onMinimalSizeChangeCallback)471 public void setOnMinimalSizeChangeCallback(@Nullable Runnable onMinimalSizeChangeCallback) { 472 mOnMinimalSizeChangeCallback = onMinimalSizeChangeCallback; 473 } 474 475 /** Set a callback to be notified when the shelf visibility changes. */ setOnShelfVisibilityChangeCallback( @ullable TriConsumer<Boolean, Integer, Boolean> onShelfVisibilityChangeCallback)476 public void setOnShelfVisibilityChangeCallback( 477 @Nullable TriConsumer<Boolean, Integer, Boolean> onShelfVisibilityChangeCallback) { 478 mOnShelfVisibilityChangeCallback = onShelfVisibilityChangeCallback; 479 } 480 481 /** 482 * Add a callback to watch out for PiP bounds. This is mostly used by SystemUI's 483 * Back-gesture handler, to avoid conflicting with PiP when it's stashed. 484 */ addPipExclusionBoundsChangeCallback( @ullable Consumer<Rect> onPipExclusionBoundsChangeCallback)485 public void addPipExclusionBoundsChangeCallback( 486 @Nullable Consumer<Rect> onPipExclusionBoundsChangeCallback) { 487 mOnPipExclusionBoundsChangeCallbacks.add(onPipExclusionBoundsChangeCallback); 488 for (Consumer<Rect> callback : mOnPipExclusionBoundsChangeCallbacks) { 489 callback.accept(getBounds()); 490 } 491 } 492 493 /** 494 * Remove a callback that was previously added. 495 */ removePipExclusionBoundsChangeCallback( @ullable Consumer<Rect> onPipExclusionBoundsChangeCallback)496 public void removePipExclusionBoundsChangeCallback( 497 @Nullable Consumer<Rect> onPipExclusionBoundsChangeCallback) { 498 mOnPipExclusionBoundsChangeCallbacks.remove(onPipExclusionBoundsChangeCallback); 499 } 500 getLauncherState()501 public LauncherState getLauncherState() { 502 return mLauncherState; 503 } 504 505 /** Source of truth for the current bounds of PIP that may be in motion. */ 506 public static class MotionBoundsState { 507 /** The bounds used when PIP is in motion (e.g. during a drag or animation) */ 508 private final @NonNull Rect mBoundsInMotion = new Rect(); 509 /** The destination bounds to which PIP is animating. */ 510 private final @NonNull Rect mAnimatingToBounds = new Rect(); 511 512 /** Whether PIP is being dragged or animated (e.g. resizing, in fling, etc). */ isInMotion()513 public boolean isInMotion() { 514 return !mBoundsInMotion.isEmpty(); 515 } 516 517 /** Set the temporary bounds used to represent the drag or animation bounds of PIP. */ setBoundsInMotion(@onNull Rect bounds)518 public void setBoundsInMotion(@NonNull Rect bounds) { 519 mBoundsInMotion.set(bounds); 520 } 521 522 /** Set the bounds to which PIP is animating. */ setAnimatingToBounds(@onNull Rect bounds)523 public void setAnimatingToBounds(@NonNull Rect bounds) { 524 mAnimatingToBounds.set(bounds); 525 } 526 527 /** Called when all ongoing motion operations have ended. */ onAllAnimationsEnded()528 public void onAllAnimationsEnded() { 529 mBoundsInMotion.setEmpty(); 530 } 531 532 /** Called when an ongoing physics animation has ended. */ onPhysicsAnimationEnded()533 public void onPhysicsAnimationEnded() { 534 mAnimatingToBounds.setEmpty(); 535 } 536 537 /** Returns the motion bounds. */ 538 @NonNull getBoundsInMotion()539 public Rect getBoundsInMotion() { 540 return mBoundsInMotion; 541 } 542 543 /** Returns the destination bounds to which PIP is currently animating. */ 544 @NonNull getAnimatingToBounds()545 public Rect getAnimatingToBounds() { 546 return mAnimatingToBounds; 547 } 548 dump(PrintWriter pw, String prefix)549 void dump(PrintWriter pw, String prefix) { 550 final String innerPrefix = prefix + " "; 551 pw.println(prefix + MotionBoundsState.class.getSimpleName()); 552 pw.println(innerPrefix + "mBoundsInMotion=" + mBoundsInMotion); 553 pw.println(innerPrefix + "mAnimatingToBounds=" + mAnimatingToBounds); 554 } 555 } 556 557 /** Data class for Launcher state. */ 558 public static final class LauncherState { 559 private int mAppIconSizePx; 560 setAppIconSizePx(int appIconSizePx)561 public void setAppIconSizePx(int appIconSizePx) { 562 mAppIconSizePx = appIconSizePx; 563 } 564 getAppIconSizePx()565 public int getAppIconSizePx() { 566 return mAppIconSizePx; 567 } 568 dump(PrintWriter pw, String prefix)569 void dump(PrintWriter pw, String prefix) { 570 final String innerPrefix = prefix + " "; 571 pw.println(prefix + LauncherState.class.getSimpleName()); 572 pw.println(innerPrefix + "getAppIconSizePx=" + getAppIconSizePx()); 573 } 574 } 575 576 static final class PipReentryState { 577 private static final String TAG = PipReentryState.class.getSimpleName(); 578 579 private final @Nullable Size mSize; 580 private final float mSnapFraction; 581 PipReentryState(@ullable Size size, float snapFraction)582 PipReentryState(@Nullable Size size, float snapFraction) { 583 mSize = size; 584 mSnapFraction = snapFraction; 585 } 586 587 @Nullable getSize()588 Size getSize() { 589 return mSize; 590 } 591 getSnapFraction()592 float getSnapFraction() { 593 return mSnapFraction; 594 } 595 dump(PrintWriter pw, String prefix)596 void dump(PrintWriter pw, String prefix) { 597 final String innerPrefix = prefix + " "; 598 pw.println(prefix + TAG); 599 pw.println(innerPrefix + "mSize=" + mSize); 600 pw.println(innerPrefix + "mSnapFraction=" + mSnapFraction); 601 } 602 } 603 604 /** Dumps internal state. */ dump(PrintWriter pw, String prefix)605 public void dump(PrintWriter pw, String prefix) { 606 final String innerPrefix = prefix + " "; 607 pw.println(prefix + TAG); 608 pw.println(innerPrefix + "mBounds=" + mBounds); 609 pw.println(innerPrefix + "mNormalBounds=" + mNormalBounds); 610 pw.println(innerPrefix + "mExpandedBounds=" + mExpandedBounds); 611 pw.println(innerPrefix + "mMovementBounds=" + mMovementBounds); 612 pw.println(innerPrefix + "mNormalMovementBounds=" + mNormalMovementBounds); 613 pw.println(innerPrefix + "mExpandedMovementBounds=" + mExpandedMovementBounds); 614 pw.println(innerPrefix + "mLastPipComponentName=" + mLastPipComponentName); 615 pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio); 616 pw.println(innerPrefix + "mDisplayId=" + mDisplayId); 617 pw.println(innerPrefix + "mStashedState=" + mStashedState); 618 pw.println(innerPrefix + "mStashOffset=" + mStashOffset); 619 pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing); 620 pw.println(innerPrefix + "mImeHeight=" + mImeHeight); 621 pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing); 622 pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight); 623 pw.println(innerPrefix + "mHasUserMovedPip=" + mHasUserMovedPip); 624 pw.println(innerPrefix + "mHasUserResizedPip=" + mHasUserResizedPip); 625 if (mPipReentryState == null) { 626 pw.println(innerPrefix + "mPipReentryState=null"); 627 } else { 628 mPipReentryState.dump(pw, innerPrefix); 629 } 630 mLauncherState.dump(pw, innerPrefix); 631 mMotionBoundsState.dump(pw, innerPrefix); 632 } 633 } 634