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 android.window; 18 19 import static android.app.ActivityOptions.ANIM_CLIP_REVEAL; 20 import static android.app.ActivityOptions.ANIM_CUSTOM; 21 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; 22 import static android.app.ActivityOptions.ANIM_SCALE_UP; 23 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; 24 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP; 25 import static android.app.WindowConfiguration.ROTATION_UNDEFINED; 26 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; 27 import static android.view.WindowManager.TRANSIT_CHANGE; 28 import static android.view.WindowManager.TRANSIT_CLOSE; 29 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; 30 import static android.view.WindowManager.TRANSIT_NONE; 31 import static android.view.WindowManager.TRANSIT_OPEN; 32 import static android.view.WindowManager.TRANSIT_TO_BACK; 33 import static android.view.WindowManager.TRANSIT_TO_FRONT; 34 import static android.view.WindowManager.TransitionFlags; 35 import static android.view.WindowManager.TransitionType; 36 import static android.view.WindowManager.transitTypeToString; 37 38 import android.annotation.IntDef; 39 import android.annotation.NonNull; 40 import android.annotation.Nullable; 41 import android.app.ActivityManager; 42 import android.graphics.Point; 43 import android.graphics.Rect; 44 import android.hardware.HardwareBuffer; 45 import android.os.Parcel; 46 import android.os.Parcelable; 47 import android.view.Surface; 48 import android.view.SurfaceControl; 49 50 import java.util.ArrayList; 51 import java.util.List; 52 53 /** 54 * Used to communicate information about what is changing during a transition to a TransitionPlayer. 55 * @hide 56 */ 57 public final class TransitionInfo implements Parcelable { 58 59 /** 60 * Modes are only a sub-set of all the transit-types since they are per-container 61 * @hide 62 */ 63 @IntDef(prefix = { "TRANSIT_" }, value = { 64 TRANSIT_NONE, 65 TRANSIT_OPEN, 66 TRANSIT_CLOSE, 67 // Note: to_front/to_back really mean show/hide respectively at the container level. 68 TRANSIT_TO_FRONT, 69 TRANSIT_TO_BACK, 70 TRANSIT_CHANGE 71 }) 72 public @interface TransitionMode {} 73 74 /** No flags */ 75 public static final int FLAG_NONE = 0; 76 77 /** The container shows the wallpaper behind it. */ 78 public static final int FLAG_SHOW_WALLPAPER = 1; 79 80 /** The container IS the wallpaper. */ 81 public static final int FLAG_IS_WALLPAPER = 1 << 1; 82 83 /** The container is translucent. */ 84 public static final int FLAG_TRANSLUCENT = 1 << 2; 85 86 // TODO: remove when starting-window is moved to Task 87 /** The container is the recipient of a transferred starting-window */ 88 public static final int FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT = 1 << 3; 89 90 /** The container has voice session. */ 91 public static final int FLAG_IS_VOICE_INTERACTION = 1 << 4; 92 93 /** The container is the display. */ 94 public static final int FLAG_IS_DISPLAY = 1 << 5; 95 96 /** The container can show on top of lock screen. */ 97 public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6; 98 99 /** 100 * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is 101 * used to prevent seamless rotation. 102 * TODO(b/194540864): Once we can include all windows in transition, then replace this with 103 * something like FLAG_IS_SYSTEM_ALERT instead. Then we can do mixed rotations. 104 */ 105 public static final int FLAG_DISPLAY_HAS_ALERT_WINDOWS = 1 << 7; 106 107 /** The first unused bit. This can be used by remotes to attach custom flags to this change. */ 108 public static final int FLAG_FIRST_CUSTOM = 1 << 8; 109 110 /** @hide */ 111 @IntDef(prefix = { "FLAG_" }, value = { 112 FLAG_NONE, 113 FLAG_SHOW_WALLPAPER, 114 FLAG_IS_WALLPAPER, 115 FLAG_TRANSLUCENT, 116 FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT, 117 FLAG_IS_VOICE_INTERACTION, 118 FLAG_IS_DISPLAY, 119 FLAG_OCCLUDES_KEYGUARD, 120 FLAG_DISPLAY_HAS_ALERT_WINDOWS, 121 FLAG_FIRST_CUSTOM 122 }) 123 public @interface ChangeFlags {} 124 125 private final @TransitionType int mType; 126 private final @TransitionFlags int mFlags; 127 private final ArrayList<Change> mChanges = new ArrayList<>(); 128 129 private SurfaceControl mRootLeash; 130 private final Point mRootOffset = new Point(); 131 132 private AnimationOptions mOptions; 133 134 /** @hide */ TransitionInfo(@ransitionType int type, @TransitionFlags int flags)135 public TransitionInfo(@TransitionType int type, @TransitionFlags int flags) { 136 mType = type; 137 mFlags = flags; 138 } 139 TransitionInfo(Parcel in)140 private TransitionInfo(Parcel in) { 141 mType = in.readInt(); 142 mFlags = in.readInt(); 143 in.readTypedList(mChanges, Change.CREATOR); 144 mRootLeash = new SurfaceControl(); 145 mRootLeash.readFromParcel(in); 146 mRootOffset.readFromParcel(in); 147 mOptions = in.readTypedObject(AnimationOptions.CREATOR); 148 } 149 150 @Override 151 /** @hide */ writeToParcel(@onNull Parcel dest, int flags)152 public void writeToParcel(@NonNull Parcel dest, int flags) { 153 dest.writeInt(mType); 154 dest.writeInt(mFlags); 155 dest.writeTypedList(mChanges); 156 mRootLeash.writeToParcel(dest, flags); 157 mRootOffset.writeToParcel(dest, flags); 158 dest.writeTypedObject(mOptions, flags); 159 } 160 161 @NonNull 162 public static final Creator<TransitionInfo> CREATOR = 163 new Creator<TransitionInfo>() { 164 @Override 165 public TransitionInfo createFromParcel(Parcel in) { 166 return new TransitionInfo(in); 167 } 168 169 @Override 170 public TransitionInfo[] newArray(int size) { 171 return new TransitionInfo[size]; 172 } 173 }; 174 175 @Override 176 /** @hide */ describeContents()177 public int describeContents() { 178 return 0; 179 } 180 181 /** @see #getRootLeash() */ setRootLeash(@onNull SurfaceControl leash, int offsetLeft, int offsetTop)182 public void setRootLeash(@NonNull SurfaceControl leash, int offsetLeft, int offsetTop) { 183 mRootLeash = leash; 184 mRootOffset.set(offsetLeft, offsetTop); 185 } 186 setAnimationOptions(AnimationOptions options)187 public void setAnimationOptions(AnimationOptions options) { 188 mOptions = options; 189 } 190 getType()191 public @TransitionType int getType() { 192 return mType; 193 } 194 getFlags()195 public int getFlags() { 196 return mFlags; 197 } 198 199 /** 200 * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing 201 * participants to animate within. This will generally be placed at the highest-z-order 202 * shared ancestor of all participants. While this is non-null, it's possible for the rootleash 203 * to be invalid if the transition is a no-op. 204 */ 205 @NonNull getRootLeash()206 public SurfaceControl getRootLeash() { 207 if (mRootLeash == null) { 208 throw new IllegalStateException("Trying to get a leash which wasn't set"); 209 } 210 return mRootLeash; 211 } 212 213 /** @return the offset (relative to the screen) of the root leash. */ 214 @NonNull getRootOffset()215 public Point getRootOffset() { 216 return mRootOffset; 217 } 218 getAnimationOptions()219 public AnimationOptions getAnimationOptions() { 220 return mOptions; 221 } 222 223 /** 224 * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom 225 * in Z (meaning index 0 is the top-most container). 226 */ 227 @NonNull getChanges()228 public List<Change> getChanges() { 229 return mChanges; 230 } 231 232 /** 233 * @return the Change that a window is undergoing or {@code null} if not directly 234 * represented. 235 */ 236 @Nullable getChange(@onNull WindowContainerToken token)237 public Change getChange(@NonNull WindowContainerToken token) { 238 for (int i = mChanges.size() - 1; i >= 0; --i) { 239 if (token.equals(mChanges.get(i).mContainer)) { 240 return mChanges.get(i); 241 } 242 } 243 return null; 244 } 245 246 /** 247 * Add a {@link Change} to this transition. 248 */ addChange(@onNull Change change)249 public void addChange(@NonNull Change change) { 250 mChanges.add(change); 251 } 252 253 /** 254 * Whether this transition includes keyguard going away. 255 */ isKeyguardGoingAway()256 public boolean isKeyguardGoingAway() { 257 return (mFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0; 258 } 259 260 @Override toString()261 public String toString() { 262 StringBuilder sb = new StringBuilder(); 263 sb.append("{t=" + transitTypeToString(mType) + " f=0x" + Integer.toHexString(mFlags) 264 + " ro=" + mRootOffset + " c=["); 265 for (int i = 0; i < mChanges.size(); ++i) { 266 if (i > 0) { 267 sb.append(','); 268 } 269 sb.append(mChanges.get(i)); 270 } 271 sb.append("]}"); 272 return sb.toString(); 273 } 274 275 /** Converts a transition mode/action to its string representation. */ 276 @NonNull modeToString(@ransitionMode int mode)277 public static String modeToString(@TransitionMode int mode) { 278 switch(mode) { 279 case TRANSIT_NONE: return "NONE"; 280 case TRANSIT_OPEN: return "OPEN"; 281 case TRANSIT_CLOSE: return "CLOSE"; 282 case TRANSIT_TO_FRONT: return "SHOW"; 283 case TRANSIT_TO_BACK: return "HIDE"; 284 case TRANSIT_CHANGE: return "CHANGE"; 285 default: return "<unknown:" + mode + ">"; 286 } 287 } 288 289 /** Converts change flags into a string representation. */ 290 @NonNull flagsToString(@hangeFlags int flags)291 public static String flagsToString(@ChangeFlags int flags) { 292 if (flags == 0) return "NONE"; 293 final StringBuilder sb = new StringBuilder(); 294 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 295 sb.append("SHOW_WALLPAPER"); 296 } 297 if ((flags & FLAG_IS_WALLPAPER) != 0) { 298 sb.append("IS_WALLPAPER"); 299 } 300 if ((flags & FLAG_TRANSLUCENT) != 0) { 301 sb.append((sb.length() == 0 ? "" : "|") + "TRANSLUCENT"); 302 } 303 if ((flags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) { 304 sb.append((sb.length() == 0 ? "" : "|") + "STARTING_WINDOW_TRANSFER"); 305 } 306 if ((flags & FLAG_IS_VOICE_INTERACTION) != 0) { 307 sb.append((sb.length() == 0 ? "" : "|") + "IS_VOICE_INTERACTION"); 308 } 309 if ((flags & FLAG_IS_DISPLAY) != 0) { 310 sb.append((sb.length() == 0 ? "" : "|") + "IS_DISPLAY"); 311 } 312 if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) { 313 sb.append((sb.length() == 0 ? "" : "|") + "OCCLUDES_KEYGUARD"); 314 } 315 if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) { 316 sb.append((sb.length() == 0 ? "" : "|") + "DISPLAY_HAS_ALERT_WINDOWS"); 317 } 318 if ((flags & FLAG_FIRST_CUSTOM) != 0) { 319 sb.append((sb.length() == 0 ? "" : "|") + "FIRST_CUSTOM"); 320 } 321 return sb.toString(); 322 } 323 324 /** 325 * Indication that `change` is independent of parents (ie. it has a different type of 326 * transition vs. "going along for the ride") 327 */ isIndependent(@onNull TransitionInfo.Change change, @NonNull TransitionInfo info)328 public static boolean isIndependent(@NonNull TransitionInfo.Change change, 329 @NonNull TransitionInfo info) { 330 // If the change has no parent (it is root), then it is independent 331 if (change.getParent() == null) return true; 332 333 // non-visibility changes will just be folded into the parent change, so they aren't 334 // independent either. 335 if (change.getMode() == TRANSIT_CHANGE) return false; 336 337 TransitionInfo.Change parentChg = info.getChange(change.getParent()); 338 while (parentChg != null) { 339 // If the parent is a visibility change, it will include the results of all child 340 // changes into itself, so none of its children can be independent. 341 if (parentChg.getMode() != TRANSIT_CHANGE) return false; 342 343 // If there are no more parents left, then all the parents, so far, have not been 344 // visibility changes which means this change is indpendent. 345 if (parentChg.getParent() == null) return true; 346 347 parentChg = info.getChange(parentChg.getParent()); 348 } 349 return false; 350 } 351 352 /** Represents the change a WindowContainer undergoes during a transition */ 353 public static final class Change implements Parcelable { 354 private final WindowContainerToken mContainer; 355 private WindowContainerToken mParent; 356 private final SurfaceControl mLeash; 357 private @TransitionMode int mMode = TRANSIT_NONE; 358 private @ChangeFlags int mFlags = FLAG_NONE; 359 private final Rect mStartAbsBounds = new Rect(); 360 private final Rect mEndAbsBounds = new Rect(); 361 private final Point mEndRelOffset = new Point(); 362 private ActivityManager.RunningTaskInfo mTaskInfo = null; 363 private boolean mAllowEnterPip; 364 private int mStartRotation = ROTATION_UNDEFINED; 365 private int mEndRotation = ROTATION_UNDEFINED; 366 private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; 367 Change(@ullable WindowContainerToken container, @NonNull SurfaceControl leash)368 public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) { 369 mContainer = container; 370 mLeash = leash; 371 } 372 Change(Parcel in)373 private Change(Parcel in) { 374 mContainer = in.readTypedObject(WindowContainerToken.CREATOR); 375 mParent = in.readTypedObject(WindowContainerToken.CREATOR); 376 mLeash = new SurfaceControl(); 377 mLeash.readFromParcel(in); 378 mMode = in.readInt(); 379 mFlags = in.readInt(); 380 mStartAbsBounds.readFromParcel(in); 381 mEndAbsBounds.readFromParcel(in); 382 mEndRelOffset.readFromParcel(in); 383 mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR); 384 mAllowEnterPip = in.readBoolean(); 385 mStartRotation = in.readInt(); 386 mEndRotation = in.readInt(); 387 mRotationAnimation = in.readInt(); 388 } 389 390 /** Sets the parent of this change's container. The parent must be a participant or null. */ setParent(@ullable WindowContainerToken parent)391 public void setParent(@Nullable WindowContainerToken parent) { 392 mParent = parent; 393 } 394 395 /** Sets the transition mode for this change */ setMode(@ransitionMode int mode)396 public void setMode(@TransitionMode int mode) { 397 mMode = mode; 398 } 399 400 /** Sets the flags for this change */ setFlags(@hangeFlags int flags)401 public void setFlags(@ChangeFlags int flags) { 402 mFlags = flags; 403 } 404 405 /** Sets the bounds this container occupied before the change in screen space */ setStartAbsBounds(@ullable Rect rect)406 public void setStartAbsBounds(@Nullable Rect rect) { 407 mStartAbsBounds.set(rect); 408 } 409 410 /** Sets the bounds this container will occupy after the change in screen space */ setEndAbsBounds(@ullable Rect rect)411 public void setEndAbsBounds(@Nullable Rect rect) { 412 mEndAbsBounds.set(rect); 413 } 414 415 /** Sets the offset of this container from its parent surface */ setEndRelOffset(int left, int top)416 public void setEndRelOffset(int left, int top) { 417 mEndRelOffset.set(left, top); 418 } 419 420 /** 421 * Sets the taskinfo of this container if this is a task. WARNING: this takes the 422 * reference, so don't modify it afterwards. 423 */ setTaskInfo(@ullable ActivityManager.RunningTaskInfo taskInfo)424 public void setTaskInfo(@Nullable ActivityManager.RunningTaskInfo taskInfo) { 425 mTaskInfo = taskInfo; 426 } 427 428 /** Sets the allowEnterPip flag which represents AppOpsManager check on PiP permission */ setAllowEnterPip(boolean allowEnterPip)429 public void setAllowEnterPip(boolean allowEnterPip) { 430 mAllowEnterPip = allowEnterPip; 431 } 432 433 /** Sets the start and end rotation of this container. */ setRotation(@urface.Rotation int start, @Surface.Rotation int end)434 public void setRotation(@Surface.Rotation int start, @Surface.Rotation int end) { 435 mStartRotation = start; 436 mEndRotation = end; 437 } 438 439 /** 440 * Sets the app-requested animation type for rotation. Will be one of the 441 * ROTATION_ANIMATION_ values in {@link android.view.WindowManager.LayoutParams}; 442 */ setRotationAnimation(int anim)443 public void setRotationAnimation(int anim) { 444 mRotationAnimation = anim; 445 } 446 447 /** @return the container that is changing. May be null if non-remotable (eg. activity) */ 448 @Nullable getContainer()449 public WindowContainerToken getContainer() { 450 return mContainer; 451 } 452 453 /** 454 * @return the parent of the changing container. This is the parent within the participants, 455 * not necessarily the actual parent. 456 */ 457 @Nullable getParent()458 public WindowContainerToken getParent() { 459 return mParent; 460 } 461 462 /** @return which action this change represents. */ getMode()463 public @TransitionMode int getMode() { 464 return mMode; 465 } 466 467 /** @return the flags for this change. */ getFlags()468 public @ChangeFlags int getFlags() { 469 return mFlags; 470 } 471 472 /** 473 * @return the bounds of the container before the change. It may be empty if the container 474 * is coming into existence. 475 */ 476 @NonNull getStartAbsBounds()477 public Rect getStartAbsBounds() { 478 return mStartAbsBounds; 479 } 480 481 /** 482 * @return the bounds of the container after the change. It may be empty if the container 483 * is disappearing. 484 */ 485 @NonNull getEndAbsBounds()486 public Rect getEndAbsBounds() { 487 return mEndAbsBounds; 488 } 489 490 /** 491 * @return the offset of the container's surface from its parent surface after the change. 492 */ 493 @NonNull getEndRelOffset()494 public Point getEndRelOffset() { 495 return mEndRelOffset; 496 } 497 498 /** @return the leash or surface to animate for this container */ 499 @NonNull getLeash()500 public SurfaceControl getLeash() { 501 return mLeash; 502 } 503 504 /** @return the task info or null if this isn't a task */ 505 @NonNull getTaskInfo()506 public ActivityManager.RunningTaskInfo getTaskInfo() { 507 return mTaskInfo; 508 } 509 getAllowEnterPip()510 public boolean getAllowEnterPip() { 511 return mAllowEnterPip; 512 } 513 getStartRotation()514 public int getStartRotation() { 515 return mStartRotation; 516 } 517 getEndRotation()518 public int getEndRotation() { 519 return mEndRotation; 520 } 521 522 /** @return the rotation animation. */ getRotationAnimation()523 public int getRotationAnimation() { 524 return mRotationAnimation; 525 } 526 527 /** @hide */ 528 @Override writeToParcel(@onNull Parcel dest, int flags)529 public void writeToParcel(@NonNull Parcel dest, int flags) { 530 dest.writeTypedObject(mContainer, flags); 531 dest.writeTypedObject(mParent, flags); 532 mLeash.writeToParcel(dest, flags); 533 dest.writeInt(mMode); 534 dest.writeInt(mFlags); 535 mStartAbsBounds.writeToParcel(dest, flags); 536 mEndAbsBounds.writeToParcel(dest, flags); 537 mEndRelOffset.writeToParcel(dest, flags); 538 dest.writeTypedObject(mTaskInfo, flags); 539 dest.writeBoolean(mAllowEnterPip); 540 dest.writeInt(mStartRotation); 541 dest.writeInt(mEndRotation); 542 dest.writeInt(mRotationAnimation); 543 } 544 545 @NonNull 546 public static final Creator<Change> CREATOR = 547 new Creator<Change>() { 548 @Override 549 public Change createFromParcel(Parcel in) { 550 return new Change(in); 551 } 552 553 @Override 554 public Change[] newArray(int size) { 555 return new Change[size]; 556 } 557 }; 558 559 /** @hide */ 560 @Override describeContents()561 public int describeContents() { 562 return 0; 563 } 564 565 @Override toString()566 public String toString() { 567 return "{" + mContainer + "(" + mParent + ") leash=" + mLeash 568 + " m=" + modeToString(mMode) + " f=" + flagsToString(mFlags) + " sb=" 569 + mStartAbsBounds + " eb=" + mEndAbsBounds + " eo=" + mEndRelOffset + " r=" 570 + mStartRotation + "->" + mEndRotation + ":" + mRotationAnimation + "}"; 571 } 572 } 573 574 /** Represents animation options during a transition */ 575 public static final class AnimationOptions implements Parcelable { 576 577 private int mType; 578 private int mEnterResId; 579 private int mExitResId; 580 private boolean mOverrideTaskTransition; 581 private String mPackageName; 582 private final Rect mTransitionBounds = new Rect(); 583 private HardwareBuffer mThumbnail; 584 AnimationOptions(int type)585 private AnimationOptions(int type) { 586 mType = type; 587 } 588 AnimationOptions(Parcel in)589 public AnimationOptions(Parcel in) { 590 mType = in.readInt(); 591 mEnterResId = in.readInt(); 592 mExitResId = in.readInt(); 593 mOverrideTaskTransition = in.readBoolean(); 594 mPackageName = in.readString(); 595 mTransitionBounds.readFromParcel(in); 596 mThumbnail = in.readTypedObject(HardwareBuffer.CREATOR); 597 } 598 makeCustomAnimOptions(String packageName, int enterResId, int exitResId, boolean overrideTaskTransition)599 public static AnimationOptions makeCustomAnimOptions(String packageName, int enterResId, 600 int exitResId, boolean overrideTaskTransition) { 601 AnimationOptions options = new AnimationOptions(ANIM_CUSTOM); 602 options.mPackageName = packageName; 603 options.mEnterResId = enterResId; 604 options.mExitResId = exitResId; 605 options.mOverrideTaskTransition = overrideTaskTransition; 606 return options; 607 } 608 makeClipRevealAnimOptions(int startX, int startY, int width, int height)609 public static AnimationOptions makeClipRevealAnimOptions(int startX, int startY, int width, 610 int height) { 611 AnimationOptions options = new AnimationOptions(ANIM_CLIP_REVEAL); 612 options.mTransitionBounds.set(startX, startY, startX + width, startY + height); 613 return options; 614 } 615 makeScaleUpAnimOptions(int startX, int startY, int width, int height)616 public static AnimationOptions makeScaleUpAnimOptions(int startX, int startY, int width, 617 int height) { 618 AnimationOptions options = new AnimationOptions(ANIM_SCALE_UP); 619 options.mTransitionBounds.set(startX, startY, startX + width, startY + height); 620 return options; 621 } 622 makeThumnbnailAnimOptions(HardwareBuffer srcThumb, int startX, int startY, boolean scaleUp)623 public static AnimationOptions makeThumnbnailAnimOptions(HardwareBuffer srcThumb, 624 int startX, int startY, boolean scaleUp) { 625 AnimationOptions options = new AnimationOptions( 626 scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN); 627 options.mTransitionBounds.set(startX, startY, startX, startY); 628 options.mThumbnail = srcThumb; 629 return options; 630 } 631 makeCrossProfileAnimOptions()632 public static AnimationOptions makeCrossProfileAnimOptions() { 633 AnimationOptions options = new AnimationOptions(ANIM_OPEN_CROSS_PROFILE_APPS); 634 return options; 635 } 636 getType()637 public int getType() { 638 return mType; 639 } 640 getEnterResId()641 public int getEnterResId() { 642 return mEnterResId; 643 } 644 getExitResId()645 public int getExitResId() { 646 return mExitResId; 647 } 648 getOverrideTaskTransition()649 public boolean getOverrideTaskTransition() { 650 return mOverrideTaskTransition; 651 } 652 getPackageName()653 public String getPackageName() { 654 return mPackageName; 655 } 656 getTransitionBounds()657 public Rect getTransitionBounds() { 658 return mTransitionBounds; 659 } 660 getThumbnail()661 public HardwareBuffer getThumbnail() { 662 return mThumbnail; 663 } 664 665 @Override writeToParcel(Parcel dest, int flags)666 public void writeToParcel(Parcel dest, int flags) { 667 dest.writeInt(mType); 668 dest.writeInt(mEnterResId); 669 dest.writeInt(mExitResId); 670 dest.writeBoolean(mOverrideTaskTransition); 671 dest.writeString(mPackageName); 672 mTransitionBounds.writeToParcel(dest, flags); 673 dest.writeTypedObject(mThumbnail, flags); 674 } 675 676 @NonNull 677 public static final Creator<AnimationOptions> CREATOR = 678 new Creator<AnimationOptions>() { 679 @Override 680 public AnimationOptions createFromParcel(Parcel in) { 681 return new AnimationOptions(in); 682 } 683 684 @Override 685 public AnimationOptions[] newArray(int size) { 686 return new AnimationOptions[size]; 687 } 688 }; 689 690 /** @hide */ 691 @Override describeContents()692 public int describeContents() { 693 return 0; 694 } 695 696 @NonNull typeToString(int mode)697 private static String typeToString(int mode) { 698 switch(mode) { 699 case ANIM_CUSTOM: return "ANIM_CUSTOM"; 700 case ANIM_CLIP_REVEAL: return "ANIM_CLIP_REVEAL"; 701 case ANIM_SCALE_UP: return "ANIM_SCALE_UP"; 702 case ANIM_THUMBNAIL_SCALE_UP: return "ANIM_THUMBNAIL_SCALE_UP"; 703 case ANIM_THUMBNAIL_SCALE_DOWN: return "ANIM_THUMBNAIL_SCALE_DOWN"; 704 case ANIM_OPEN_CROSS_PROFILE_APPS: return "ANIM_OPEN_CROSS_PROFILE_APPS"; 705 default: return "<unknown:" + mode + ">"; 706 } 707 } 708 709 @Override toString()710 public String toString() { 711 return "{ AnimationOtions type= " + typeToString(mType) + " package=" + mPackageName 712 + " override=" + mOverrideTaskTransition + " b=" + mTransitionBounds + "}"; 713 } 714 } 715 } 716