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_FROM_STYLE; 22 import static android.app.ActivityOptions.ANIM_OPEN_CROSS_PROFILE_APPS; 23 import static android.app.ActivityOptions.ANIM_SCALE_UP; 24 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_DOWN; 25 import static android.app.ActivityOptions.ANIM_THUMBNAIL_SCALE_UP; 26 import static android.app.WindowConfiguration.ROTATION_UNDEFINED; 27 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED; 28 import static android.view.WindowManager.TRANSIT_CHANGE; 29 import static android.view.WindowManager.TRANSIT_CLOSE; 30 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY; 31 import static android.view.WindowManager.TRANSIT_NONE; 32 import static android.view.WindowManager.TRANSIT_OPEN; 33 import static android.view.WindowManager.TRANSIT_TO_BACK; 34 import static android.view.WindowManager.TRANSIT_TO_FRONT; 35 import static android.view.WindowManager.TransitionFlags; 36 import static android.view.WindowManager.TransitionType; 37 import static android.view.WindowManager.transitTypeToString; 38 39 import android.annotation.ColorInt; 40 import android.annotation.IntDef; 41 import android.annotation.NonNull; 42 import android.annotation.Nullable; 43 import android.app.ActivityManager; 44 import android.graphics.Point; 45 import android.graphics.Rect; 46 import android.hardware.HardwareBuffer; 47 import android.os.Parcel; 48 import android.os.Parcelable; 49 import android.view.Surface; 50 import android.view.SurfaceControl; 51 import android.view.WindowManager; 52 53 import java.util.ArrayList; 54 import java.util.List; 55 56 /** 57 * Used to communicate information about what is changing during a transition to a TransitionPlayer. 58 * @hide 59 */ 60 public final class TransitionInfo implements Parcelable { 61 62 /** 63 * Modes are only a sub-set of all the transit-types since they are per-container 64 * @hide 65 */ 66 @IntDef(prefix = { "TRANSIT_" }, value = { 67 TRANSIT_NONE, 68 TRANSIT_OPEN, 69 TRANSIT_CLOSE, 70 // Note: to_front/to_back really mean show/hide respectively at the container level. 71 TRANSIT_TO_FRONT, 72 TRANSIT_TO_BACK, 73 TRANSIT_CHANGE 74 }) 75 public @interface TransitionMode {} 76 77 /** No flags */ 78 public static final int FLAG_NONE = 0; 79 80 /** The container shows the wallpaper behind it. */ 81 public static final int FLAG_SHOW_WALLPAPER = 1; 82 83 /** The container IS the wallpaper. */ 84 public static final int FLAG_IS_WALLPAPER = 1 << 1; 85 86 /** The container is translucent. */ 87 public static final int FLAG_TRANSLUCENT = 1 << 2; 88 89 // TODO: remove when starting-window is moved to Task 90 /** The container is the recipient of a transferred starting-window */ 91 public static final int FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT = 1 << 3; 92 93 /** The container has voice session. */ 94 public static final int FLAG_IS_VOICE_INTERACTION = 1 << 4; 95 96 /** The container is the display. */ 97 public static final int FLAG_IS_DISPLAY = 1 << 5; 98 99 /** The container can show on top of lock screen. */ 100 public static final int FLAG_OCCLUDES_KEYGUARD = 1 << 6; 101 102 /** 103 * Only for IS_DISPLAY containers. Is set if the display has system alert windows. This is 104 * used to prevent seamless rotation. 105 * TODO(b/194540864): Once we can include all windows in transition, then replace this with 106 * something like FLAG_IS_SYSTEM_ALERT instead. Then we can do mixed rotations. 107 */ 108 public static final int FLAG_DISPLAY_HAS_ALERT_WINDOWS = 1 << 7; 109 110 /** The container is an input-method window. */ 111 public static final int FLAG_IS_INPUT_METHOD = 1 << 8; 112 113 /** The container is in a Task with embedded activity. */ 114 public static final int FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY = 1 << 9; 115 116 /** The container fills its parent Task before and after the transition. */ 117 public static final int FLAG_FILLS_TASK = 1 << 10; 118 119 /** The container is going to show IME on its task after the transition. */ 120 public static final int FLAG_WILL_IME_SHOWN = 1 << 11; 121 122 /** The container attaches owner profile thumbnail for cross profile animation. */ 123 public static final int FLAG_CROSS_PROFILE_OWNER_THUMBNAIL = 1 << 12; 124 125 /** The container attaches work profile thumbnail for cross profile animation. */ 126 public static final int FLAG_CROSS_PROFILE_WORK_THUMBNAIL = 1 << 13; 127 128 /** 129 * Whether the window is covered by an app starting window. This is different from 130 * {@link #FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT} which is only set on the Activity window 131 * that contains the starting window. 132 */ 133 public static final int FLAG_IS_BEHIND_STARTING_WINDOW = 1 << 14; 134 135 /** This change happened underneath something else. */ 136 public static final int FLAG_IS_OCCLUDED = 1 << 15; 137 138 /** The container is a system window, excluding wallpaper and input-method. */ 139 public static final int FLAG_IS_SYSTEM_WINDOW = 1 << 16; 140 141 /** The first unused bit. This can be used by remotes to attach custom flags to this change. */ 142 public static final int FLAG_FIRST_CUSTOM = 1 << 17; 143 144 /** The change belongs to a window that won't contain activities. */ 145 public static final int FLAGS_IS_NON_APP_WINDOW = 146 FLAG_IS_WALLPAPER | FLAG_IS_INPUT_METHOD | FLAG_IS_SYSTEM_WINDOW; 147 148 /** @hide */ 149 @IntDef(prefix = { "FLAG_" }, value = { 150 FLAG_NONE, 151 FLAG_SHOW_WALLPAPER, 152 FLAG_IS_WALLPAPER, 153 FLAG_TRANSLUCENT, 154 FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT, 155 FLAG_IS_VOICE_INTERACTION, 156 FLAG_IS_DISPLAY, 157 FLAG_OCCLUDES_KEYGUARD, 158 FLAG_DISPLAY_HAS_ALERT_WINDOWS, 159 FLAG_IS_INPUT_METHOD, 160 FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY, 161 FLAG_FILLS_TASK, 162 FLAG_WILL_IME_SHOWN, 163 FLAG_CROSS_PROFILE_OWNER_THUMBNAIL, 164 FLAG_CROSS_PROFILE_WORK_THUMBNAIL, 165 FLAG_IS_BEHIND_STARTING_WINDOW, 166 FLAG_IS_OCCLUDED, 167 FLAG_IS_SYSTEM_WINDOW, 168 FLAG_FIRST_CUSTOM 169 }) 170 public @interface ChangeFlags {} 171 172 private final @TransitionType int mType; 173 private final @TransitionFlags int mFlags; 174 private final ArrayList<Change> mChanges = new ArrayList<>(); 175 176 private SurfaceControl mRootLeash; 177 private final Point mRootOffset = new Point(); 178 179 private AnimationOptions mOptions; 180 181 /** @hide */ TransitionInfo(@ransitionType int type, @TransitionFlags int flags)182 public TransitionInfo(@TransitionType int type, @TransitionFlags int flags) { 183 mType = type; 184 mFlags = flags; 185 } 186 TransitionInfo(Parcel in)187 private TransitionInfo(Parcel in) { 188 mType = in.readInt(); 189 mFlags = in.readInt(); 190 in.readTypedList(mChanges, Change.CREATOR); 191 mRootLeash = new SurfaceControl(); 192 mRootLeash.readFromParcel(in); 193 mRootOffset.readFromParcel(in); 194 mOptions = in.readTypedObject(AnimationOptions.CREATOR); 195 } 196 197 @Override 198 /** @hide */ writeToParcel(@onNull Parcel dest, int flags)199 public void writeToParcel(@NonNull Parcel dest, int flags) { 200 dest.writeInt(mType); 201 dest.writeInt(mFlags); 202 dest.writeTypedList(mChanges); 203 mRootLeash.writeToParcel(dest, flags); 204 mRootOffset.writeToParcel(dest, flags); 205 dest.writeTypedObject(mOptions, flags); 206 } 207 208 @NonNull 209 public static final Creator<TransitionInfo> CREATOR = 210 new Creator<TransitionInfo>() { 211 @Override 212 public TransitionInfo createFromParcel(Parcel in) { 213 return new TransitionInfo(in); 214 } 215 216 @Override 217 public TransitionInfo[] newArray(int size) { 218 return new TransitionInfo[size]; 219 } 220 }; 221 222 @Override 223 /** @hide */ describeContents()224 public int describeContents() { 225 return 0; 226 } 227 228 /** @see #getRootLeash() */ setRootLeash(@onNull SurfaceControl leash, int offsetLeft, int offsetTop)229 public void setRootLeash(@NonNull SurfaceControl leash, int offsetLeft, int offsetTop) { 230 mRootLeash = leash; 231 mRootOffset.set(offsetLeft, offsetTop); 232 } 233 setAnimationOptions(AnimationOptions options)234 public void setAnimationOptions(AnimationOptions options) { 235 mOptions = options; 236 } 237 getType()238 public @TransitionType int getType() { 239 return mType; 240 } 241 getFlags()242 public int getFlags() { 243 return mFlags; 244 } 245 246 /** 247 * @return a surfacecontrol that can serve as a parent surfacecontrol for all the changing 248 * participants to animate within. This will generally be placed at the highest-z-order 249 * shared ancestor of all participants. While this is non-null, it's possible for the rootleash 250 * to be invalid if the transition is a no-op. 251 */ 252 @NonNull getRootLeash()253 public SurfaceControl getRootLeash() { 254 if (mRootLeash == null) { 255 throw new IllegalStateException("Trying to get a leash which wasn't set"); 256 } 257 return mRootLeash; 258 } 259 260 /** @return the offset (relative to the screen) of the root leash. */ 261 @NonNull getRootOffset()262 public Point getRootOffset() { 263 return mRootOffset; 264 } 265 getAnimationOptions()266 public AnimationOptions getAnimationOptions() { 267 return mOptions; 268 } 269 270 /** 271 * @return the list of {@link Change}s in this transition. The list is sorted top-to-bottom 272 * in Z (meaning index 0 is the top-most container). 273 */ 274 @NonNull getChanges()275 public List<Change> getChanges() { 276 return mChanges; 277 } 278 279 /** 280 * @return the Change that a window is undergoing or {@code null} if not directly 281 * represented. 282 */ 283 @Nullable getChange(@onNull WindowContainerToken token)284 public Change getChange(@NonNull WindowContainerToken token) { 285 for (int i = mChanges.size() - 1; i >= 0; --i) { 286 if (token.equals(mChanges.get(i).mContainer)) { 287 return mChanges.get(i); 288 } 289 } 290 return null; 291 } 292 293 /** 294 * Add a {@link Change} to this transition. 295 */ addChange(@onNull Change change)296 public void addChange(@NonNull Change change) { 297 mChanges.add(change); 298 } 299 300 /** 301 * Whether this transition includes keyguard going away. 302 */ isKeyguardGoingAway()303 public boolean isKeyguardGoingAway() { 304 return (mFlags & TRANSIT_FLAG_KEYGUARD_GOING_AWAY) != 0; 305 } 306 307 @Override toString()308 public String toString() { 309 StringBuilder sb = new StringBuilder(); 310 sb.append("{t=" + transitTypeToString(mType) + " f=0x" + Integer.toHexString(mFlags) 311 + " ro=" + mRootOffset + " c=["); 312 for (int i = 0; i < mChanges.size(); ++i) { 313 if (i > 0) { 314 sb.append(','); 315 } 316 sb.append(mChanges.get(i)); 317 } 318 sb.append("]}"); 319 return sb.toString(); 320 } 321 322 /** Converts a transition mode/action to its string representation. */ 323 @NonNull modeToString(@ransitionMode int mode)324 public static String modeToString(@TransitionMode int mode) { 325 switch(mode) { 326 case TRANSIT_NONE: return "NONE"; 327 case TRANSIT_OPEN: return "OPEN"; 328 case TRANSIT_CLOSE: return "CLOSE"; 329 case TRANSIT_TO_FRONT: return "SHOW"; 330 case TRANSIT_TO_BACK: return "HIDE"; 331 case TRANSIT_CHANGE: return "CHANGE"; 332 default: return "<unknown:" + mode + ">"; 333 } 334 } 335 336 /** Converts change flags into a string representation. */ 337 @NonNull flagsToString(@hangeFlags int flags)338 public static String flagsToString(@ChangeFlags int flags) { 339 if (flags == 0) return "NONE"; 340 final StringBuilder sb = new StringBuilder(); 341 if ((flags & FLAG_SHOW_WALLPAPER) != 0) { 342 sb.append("SHOW_WALLPAPER"); 343 } 344 if ((flags & FLAG_IS_WALLPAPER) != 0) { 345 sb.append("IS_WALLPAPER"); 346 } 347 if ((flags & FLAG_IS_INPUT_METHOD) != 0) { 348 sb.append("IS_INPUT_METHOD"); 349 } 350 if ((flags & FLAG_TRANSLUCENT) != 0) { 351 sb.append(sb.length() == 0 ? "" : "|").append("TRANSLUCENT"); 352 } 353 if ((flags & FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT) != 0) { 354 sb.append(sb.length() == 0 ? "" : "|").append("STARTING_WINDOW_TRANSFER"); 355 } 356 if ((flags & FLAG_IS_VOICE_INTERACTION) != 0) { 357 sb.append(sb.length() == 0 ? "" : "|").append("IS_VOICE_INTERACTION"); 358 } 359 if ((flags & FLAG_IS_DISPLAY) != 0) { 360 sb.append(sb.length() == 0 ? "" : "|").append("IS_DISPLAY"); 361 } 362 if ((flags & FLAG_OCCLUDES_KEYGUARD) != 0) { 363 sb.append(sb.length() == 0 ? "" : "|").append("OCCLUDES_KEYGUARD"); 364 } 365 if ((flags & FLAG_DISPLAY_HAS_ALERT_WINDOWS) != 0) { 366 sb.append(sb.length() == 0 ? "" : "|").append("DISPLAY_HAS_ALERT_WINDOWS"); 367 } 368 if ((flags & FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY) != 0) { 369 sb.append(sb.length() == 0 ? "" : "|").append("IN_TASK_WITH_EMBEDDED_ACTIVITY"); 370 } 371 if ((flags & FLAG_FILLS_TASK) != 0) { 372 sb.append(sb.length() == 0 ? "" : "|").append("FILLS_TASK"); 373 } 374 if ((flags & FLAG_IS_BEHIND_STARTING_WINDOW) != 0) { 375 sb.append(sb.length() == 0 ? "" : "|").append("IS_BEHIND_STARTING_WINDOW"); 376 } 377 if ((flags & FLAG_IS_OCCLUDED) != 0) { 378 sb.append(sb.length() == 0 ? "" : "|").append("IS_OCCLUDED"); 379 } 380 if ((flags & FLAG_IS_SYSTEM_WINDOW) != 0) { 381 sb.append(sb.length() == 0 ? "" : "|").append("FLAG_IS_SYSTEM_WINDOW"); 382 } 383 if ((flags & FLAG_FIRST_CUSTOM) != 0) { 384 sb.append(sb.length() == 0 ? "" : "|").append("FIRST_CUSTOM"); 385 } 386 return sb.toString(); 387 } 388 389 /** 390 * Indication that `change` is independent of parents (ie. it has a different type of 391 * transition vs. "going along for the ride") 392 */ isIndependent(@onNull TransitionInfo.Change change, @NonNull TransitionInfo info)393 public static boolean isIndependent(@NonNull TransitionInfo.Change change, 394 @NonNull TransitionInfo info) { 395 // If the change has no parent (it is root), then it is independent 396 if (change.getParent() == null) return true; 397 398 // non-visibility changes will just be folded into the parent change, so they aren't 399 // independent either. 400 if (change.getMode() == TRANSIT_CHANGE) return false; 401 402 TransitionInfo.Change parentChg = info.getChange(change.getParent()); 403 while (parentChg != null) { 404 // If the parent is a visibility change, it will include the results of all child 405 // changes into itself, so none of its children can be independent. 406 if (parentChg.getMode() != TRANSIT_CHANGE) return false; 407 408 // If there are no more parents left, then all the parents, so far, have not been 409 // visibility changes which means this change is independent. 410 if (parentChg.getParent() == null) return true; 411 412 parentChg = info.getChange(parentChg.getParent()); 413 } 414 return false; 415 } 416 417 /** 418 * Releases temporary-for-animation surfaces referenced by this to potentially free up memory. 419 * This includes root-leash and snapshots. 420 */ releaseAnimSurfaces()421 public void releaseAnimSurfaces() { 422 for (int i = mChanges.size() - 1; i >= 0; --i) { 423 final Change c = mChanges.get(i); 424 if (c.mSnapshot != null) { 425 c.mSnapshot.release(); 426 c.mSnapshot = null; 427 } 428 } 429 if (mRootLeash != null) { 430 mRootLeash.release(); 431 } 432 } 433 434 /** 435 * Releases ALL the surfaces referenced by this to potentially free up memory. Do NOT use this 436 * if the surface-controls get stored and used elsewhere in the process. To just release 437 * temporary-for-animation surfaces, use {@link #releaseAnimSurfaces}. 438 */ releaseAllSurfaces()439 public void releaseAllSurfaces() { 440 releaseAnimSurfaces(); 441 for (int i = mChanges.size() - 1; i >= 0; --i) { 442 mChanges.get(i).getLeash().release(); 443 } 444 } 445 446 /** 447 * Makes a copy of this as if it were parcel'd and unparcel'd. This implies that surfacecontrol 448 * refcounts are incremented which allows the "remote" receiver to release them without breaking 449 * the caller's references. Use this only if you need to "send" this to a local function which 450 * assumes it is being called from a remote caller. 451 */ localRemoteCopy()452 public TransitionInfo localRemoteCopy() { 453 final TransitionInfo out = new TransitionInfo(mType, mFlags); 454 for (int i = 0; i < mChanges.size(); ++i) { 455 out.mChanges.add(mChanges.get(i).localRemoteCopy()); 456 } 457 out.mRootLeash = mRootLeash != null ? new SurfaceControl(mRootLeash, "localRemote") : null; 458 // Doesn't have any native stuff, so no need for actual copy 459 out.mOptions = mOptions; 460 out.mRootOffset.set(mRootOffset); 461 return out; 462 } 463 464 /** Represents the change a WindowContainer undergoes during a transition */ 465 public static final class Change implements Parcelable { 466 private final WindowContainerToken mContainer; 467 private WindowContainerToken mParent; 468 private WindowContainerToken mLastParent; 469 private final SurfaceControl mLeash; 470 private @TransitionMode int mMode = TRANSIT_NONE; 471 private @ChangeFlags int mFlags = FLAG_NONE; 472 private final Rect mStartAbsBounds = new Rect(); 473 private final Rect mEndAbsBounds = new Rect(); 474 private final Point mEndRelOffset = new Point(); 475 private ActivityManager.RunningTaskInfo mTaskInfo = null; 476 private boolean mAllowEnterPip; 477 private @Surface.Rotation int mStartRotation = ROTATION_UNDEFINED; 478 private @Surface.Rotation int mEndRotation = ROTATION_UNDEFINED; 479 /** 480 * The end rotation of the top activity after fixed rotation is finished. If the top 481 * activity is not in fixed rotation, it will be {@link ROTATION_UNDEFINED}. 482 */ 483 private @Surface.Rotation int mEndFixedRotation = ROTATION_UNDEFINED; 484 private int mRotationAnimation = ROTATION_ANIMATION_UNSPECIFIED; 485 private @ColorInt int mBackgroundColor; 486 private SurfaceControl mSnapshot = null; 487 private float mSnapshotLuma; 488 Change(@ullable WindowContainerToken container, @NonNull SurfaceControl leash)489 public Change(@Nullable WindowContainerToken container, @NonNull SurfaceControl leash) { 490 mContainer = container; 491 mLeash = leash; 492 } 493 Change(Parcel in)494 private Change(Parcel in) { 495 mContainer = in.readTypedObject(WindowContainerToken.CREATOR); 496 mParent = in.readTypedObject(WindowContainerToken.CREATOR); 497 mLastParent = in.readTypedObject(WindowContainerToken.CREATOR); 498 mLeash = new SurfaceControl(); 499 mLeash.readFromParcel(in); 500 mMode = in.readInt(); 501 mFlags = in.readInt(); 502 mStartAbsBounds.readFromParcel(in); 503 mEndAbsBounds.readFromParcel(in); 504 mEndRelOffset.readFromParcel(in); 505 mTaskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR); 506 mAllowEnterPip = in.readBoolean(); 507 mStartRotation = in.readInt(); 508 mEndRotation = in.readInt(); 509 mEndFixedRotation = in.readInt(); 510 mRotationAnimation = in.readInt(); 511 mBackgroundColor = in.readInt(); 512 mSnapshot = in.readTypedObject(SurfaceControl.CREATOR); 513 mSnapshotLuma = in.readFloat(); 514 } 515 localRemoteCopy()516 private Change localRemoteCopy() { 517 final Change out = new Change(mContainer, new SurfaceControl(mLeash, "localRemote")); 518 out.mParent = mParent; 519 out.mLastParent = mLastParent; 520 out.mMode = mMode; 521 out.mFlags = mFlags; 522 out.mStartAbsBounds.set(mStartAbsBounds); 523 out.mEndAbsBounds.set(mEndAbsBounds); 524 out.mEndRelOffset.set(mEndRelOffset); 525 out.mTaskInfo = mTaskInfo; 526 out.mAllowEnterPip = mAllowEnterPip; 527 out.mStartRotation = mStartRotation; 528 out.mEndRotation = mEndRotation; 529 out.mEndFixedRotation = mEndFixedRotation; 530 out.mRotationAnimation = mRotationAnimation; 531 out.mBackgroundColor = mBackgroundColor; 532 out.mSnapshot = mSnapshot != null ? new SurfaceControl(mSnapshot, "localRemote") : null; 533 out.mSnapshotLuma = mSnapshotLuma; 534 return out; 535 } 536 537 /** Sets the parent of this change's container. The parent must be a participant or null. */ setParent(@ullable WindowContainerToken parent)538 public void setParent(@Nullable WindowContainerToken parent) { 539 mParent = parent; 540 } 541 542 /** 543 * Sets the parent of this change's container before the transition if this change's 544 * container is reparented in the transition. 545 */ setLastParent(@ullable WindowContainerToken lastParent)546 public void setLastParent(@Nullable WindowContainerToken lastParent) { 547 mLastParent = lastParent; 548 } 549 550 /** Sets the transition mode for this change */ setMode(@ransitionMode int mode)551 public void setMode(@TransitionMode int mode) { 552 mMode = mode; 553 } 554 555 /** Sets the flags for this change */ setFlags(@hangeFlags int flags)556 public void setFlags(@ChangeFlags int flags) { 557 mFlags = flags; 558 } 559 560 /** Sets the bounds this container occupied before the change in screen space */ setStartAbsBounds(@ullable Rect rect)561 public void setStartAbsBounds(@Nullable Rect rect) { 562 mStartAbsBounds.set(rect); 563 } 564 565 /** Sets the bounds this container will occupy after the change in screen space */ setEndAbsBounds(@ullable Rect rect)566 public void setEndAbsBounds(@Nullable Rect rect) { 567 mEndAbsBounds.set(rect); 568 } 569 570 /** Sets the offset of this container from its parent surface */ setEndRelOffset(int left, int top)571 public void setEndRelOffset(int left, int top) { 572 mEndRelOffset.set(left, top); 573 } 574 575 /** 576 * Sets the taskinfo of this container if this is a task. WARNING: this takes the 577 * reference, so don't modify it afterwards. 578 */ setTaskInfo(@ullable ActivityManager.RunningTaskInfo taskInfo)579 public void setTaskInfo(@Nullable ActivityManager.RunningTaskInfo taskInfo) { 580 mTaskInfo = taskInfo; 581 } 582 583 /** Sets the allowEnterPip flag which represents AppOpsManager check on PiP permission */ setAllowEnterPip(boolean allowEnterPip)584 public void setAllowEnterPip(boolean allowEnterPip) { 585 mAllowEnterPip = allowEnterPip; 586 } 587 588 /** Sets the start and end rotation of this container. */ setRotation(@urface.Rotation int start, @Surface.Rotation int end)589 public void setRotation(@Surface.Rotation int start, @Surface.Rotation int end) { 590 mStartRotation = start; 591 mEndRotation = end; 592 } 593 594 /** Sets end rotation that top activity will be launched to after fixed rotation. */ setEndFixedRotation(@urface.Rotation int endFixedRotation)595 public void setEndFixedRotation(@Surface.Rotation int endFixedRotation) { 596 mEndFixedRotation = endFixedRotation; 597 } 598 599 /** 600 * Sets the app-requested animation type for rotation. Will be one of the 601 * ROTATION_ANIMATION_ values in {@link android.view.WindowManager.LayoutParams}; 602 */ setRotationAnimation(int anim)603 public void setRotationAnimation(int anim) { 604 mRotationAnimation = anim; 605 } 606 607 /** Sets the background color of this change's container. */ setBackgroundColor(@olorInt int backgroundColor)608 public void setBackgroundColor(@ColorInt int backgroundColor) { 609 mBackgroundColor = backgroundColor; 610 } 611 612 /** Sets a snapshot surface for the "start" state of the container. */ setSnapshot(@ullable SurfaceControl snapshot, float luma)613 public void setSnapshot(@Nullable SurfaceControl snapshot, float luma) { 614 mSnapshot = snapshot; 615 mSnapshotLuma = luma; 616 } 617 618 /** @return the container that is changing. May be null if non-remotable (eg. activity) */ 619 @Nullable getContainer()620 public WindowContainerToken getContainer() { 621 return mContainer; 622 } 623 624 /** 625 * @return the parent of the changing container. This is the parent within the participants, 626 * not necessarily the actual parent. 627 */ 628 @Nullable getParent()629 public WindowContainerToken getParent() { 630 return mParent; 631 } 632 633 /** 634 * @return the parent of the changing container before the transition if it is reparented 635 * in the transition. The parent window may not be collected in the transition as a 636 * participant, and it may have been detached from the display. {@code null} if the changing 637 * container has not been reparented in the transition, or if the parent is not organizable. 638 */ 639 @Nullable getLastParent()640 public WindowContainerToken getLastParent() { 641 return mLastParent; 642 } 643 644 /** @return which action this change represents. */ getMode()645 public @TransitionMode int getMode() { 646 return mMode; 647 } 648 649 /** @return the flags for this change. */ getFlags()650 public @ChangeFlags int getFlags() { 651 return mFlags; 652 } 653 654 /** Whether this change contains any of the given change flags. */ hasFlags(@hangeFlags int flags)655 public boolean hasFlags(@ChangeFlags int flags) { 656 return (mFlags & flags) != 0; 657 } 658 659 /** Whether this change contains all of the given change flags. */ hasAllFlags(@hangeFlags int flags)660 public boolean hasAllFlags(@ChangeFlags int flags) { 661 return (mFlags & flags) == flags; 662 } 663 664 /** 665 * @return the bounds of the container before the change. It may be empty if the container 666 * is coming into existence. 667 */ 668 @NonNull getStartAbsBounds()669 public Rect getStartAbsBounds() { 670 return mStartAbsBounds; 671 } 672 673 /** 674 * @return the bounds of the container after the change. It may be empty if the container 675 * is disappearing. 676 */ 677 @NonNull getEndAbsBounds()678 public Rect getEndAbsBounds() { 679 return mEndAbsBounds; 680 } 681 682 /** 683 * @return the offset of the container's surface from its parent surface after the change. 684 */ 685 @NonNull getEndRelOffset()686 public Point getEndRelOffset() { 687 return mEndRelOffset; 688 } 689 690 /** @return the leash or surface to animate for this container */ 691 @NonNull getLeash()692 public SurfaceControl getLeash() { 693 return mLeash; 694 } 695 696 /** @return the task info or null if this isn't a task */ 697 @Nullable getTaskInfo()698 public ActivityManager.RunningTaskInfo getTaskInfo() { 699 return mTaskInfo; 700 } 701 getAllowEnterPip()702 public boolean getAllowEnterPip() { 703 return mAllowEnterPip; 704 } 705 706 @Surface.Rotation getStartRotation()707 public int getStartRotation() { 708 return mStartRotation; 709 } 710 711 @Surface.Rotation getEndRotation()712 public int getEndRotation() { 713 return mEndRotation; 714 } 715 716 @Surface.Rotation getEndFixedRotation()717 public int getEndFixedRotation() { 718 return mEndFixedRotation; 719 } 720 721 /** @return the rotation animation. */ getRotationAnimation()722 public int getRotationAnimation() { 723 return mRotationAnimation; 724 } 725 726 /** @return get the background color of this change's container. */ 727 @ColorInt getBackgroundColor()728 public int getBackgroundColor() { 729 return mBackgroundColor; 730 } 731 732 /** @return a snapshot surface (if applicable). */ 733 @Nullable getSnapshot()734 public SurfaceControl getSnapshot() { 735 return mSnapshot; 736 } 737 738 /** @return the luma calculated for the snapshot surface (if applicable). */ getSnapshotLuma()739 public float getSnapshotLuma() { 740 return mSnapshotLuma; 741 } 742 743 /** @hide */ 744 @Override writeToParcel(@onNull Parcel dest, int flags)745 public void writeToParcel(@NonNull Parcel dest, int flags) { 746 dest.writeTypedObject(mContainer, flags); 747 dest.writeTypedObject(mParent, flags); 748 dest.writeTypedObject(mLastParent, flags); 749 mLeash.writeToParcel(dest, flags); 750 dest.writeInt(mMode); 751 dest.writeInt(mFlags); 752 mStartAbsBounds.writeToParcel(dest, flags); 753 mEndAbsBounds.writeToParcel(dest, flags); 754 mEndRelOffset.writeToParcel(dest, flags); 755 dest.writeTypedObject(mTaskInfo, flags); 756 dest.writeBoolean(mAllowEnterPip); 757 dest.writeInt(mStartRotation); 758 dest.writeInt(mEndRotation); 759 dest.writeInt(mEndFixedRotation); 760 dest.writeInt(mRotationAnimation); 761 dest.writeInt(mBackgroundColor); 762 dest.writeTypedObject(mSnapshot, flags); 763 dest.writeFloat(mSnapshotLuma); 764 } 765 766 @NonNull 767 public static final Creator<Change> CREATOR = 768 new Creator<Change>() { 769 @Override 770 public Change createFromParcel(Parcel in) { 771 return new Change(in); 772 } 773 774 @Override 775 public Change[] newArray(int size) { 776 return new Change[size]; 777 } 778 }; 779 780 /** @hide */ 781 @Override describeContents()782 public int describeContents() { 783 return 0; 784 } 785 786 @Override toString()787 public String toString() { 788 final StringBuilder sb = new StringBuilder(); 789 sb.append('{'); sb.append(mContainer); 790 sb.append(" m="); sb.append(modeToString(mMode)); 791 sb.append(" f="); sb.append(flagsToString(mFlags)); 792 if (mParent != null) { 793 sb.append(" p="); sb.append(mParent); 794 } 795 if (mLeash != null) { 796 sb.append(" leash="); sb.append(mLeash); 797 } 798 sb.append(" sb="); sb.append(mStartAbsBounds); 799 sb.append(" eb="); sb.append(mEndAbsBounds); 800 if (mEndRelOffset.x != 0 || mEndRelOffset.y != 0) { 801 sb.append(" eo="); sb.append(mEndRelOffset); 802 } 803 if (mStartRotation != mEndRotation) { 804 sb.append(" r="); sb.append(mStartRotation); 805 sb.append("->"); sb.append(mEndRotation); 806 sb.append(':'); sb.append(mRotationAnimation); 807 } 808 if (mEndFixedRotation != ROTATION_UNDEFINED) { 809 sb.append(" endFixedRotation="); sb.append(mEndFixedRotation); 810 } 811 if (mSnapshot != null) { 812 sb.append(" snapshot="); sb.append(mSnapshot); 813 } 814 if (mLastParent != null) { 815 sb.append(" lastParent="); sb.append(mLastParent); 816 } 817 sb.append('}'); 818 return sb.toString(); 819 } 820 } 821 822 /** Represents animation options during a transition */ 823 public static final class AnimationOptions implements Parcelable { 824 825 private int mType; 826 private int mEnterResId; 827 private int mExitResId; 828 private boolean mOverrideTaskTransition; 829 private String mPackageName; 830 private final Rect mTransitionBounds = new Rect(); 831 private HardwareBuffer mThumbnail; 832 private int mAnimations; 833 private @ColorInt int mBackgroundColor; 834 AnimationOptions(int type)835 private AnimationOptions(int type) { 836 mType = type; 837 } 838 AnimationOptions(Parcel in)839 public AnimationOptions(Parcel in) { 840 mType = in.readInt(); 841 mEnterResId = in.readInt(); 842 mExitResId = in.readInt(); 843 mBackgroundColor = in.readInt(); 844 mOverrideTaskTransition = in.readBoolean(); 845 mPackageName = in.readString(); 846 mTransitionBounds.readFromParcel(in); 847 mThumbnail = in.readTypedObject(HardwareBuffer.CREATOR); 848 mAnimations = in.readInt(); 849 } 850 makeAnimOptionsFromLayoutParameters( WindowManager.LayoutParams lp)851 public static AnimationOptions makeAnimOptionsFromLayoutParameters( 852 WindowManager.LayoutParams lp) { 853 AnimationOptions options = new AnimationOptions(ANIM_FROM_STYLE); 854 options.mPackageName = lp.packageName; 855 options.mAnimations = lp.windowAnimations; 856 return options; 857 } 858 makeCustomAnimOptions(String packageName, int enterResId, int exitResId, @ColorInt int backgroundColor, boolean overrideTaskTransition)859 public static AnimationOptions makeCustomAnimOptions(String packageName, int enterResId, 860 int exitResId, @ColorInt int backgroundColor, boolean overrideTaskTransition) { 861 AnimationOptions options = new AnimationOptions(ANIM_CUSTOM); 862 options.mPackageName = packageName; 863 options.mEnterResId = enterResId; 864 options.mExitResId = exitResId; 865 options.mBackgroundColor = backgroundColor; 866 options.mOverrideTaskTransition = overrideTaskTransition; 867 return options; 868 } 869 makeClipRevealAnimOptions(int startX, int startY, int width, int height)870 public static AnimationOptions makeClipRevealAnimOptions(int startX, int startY, int width, 871 int height) { 872 AnimationOptions options = new AnimationOptions(ANIM_CLIP_REVEAL); 873 options.mTransitionBounds.set(startX, startY, startX + width, startY + height); 874 return options; 875 } 876 makeScaleUpAnimOptions(int startX, int startY, int width, int height)877 public static AnimationOptions makeScaleUpAnimOptions(int startX, int startY, int width, 878 int height) { 879 AnimationOptions options = new AnimationOptions(ANIM_SCALE_UP); 880 options.mTransitionBounds.set(startX, startY, startX + width, startY + height); 881 return options; 882 } 883 makeThumbnailAnimOptions(HardwareBuffer srcThumb, int startX, int startY, boolean scaleUp)884 public static AnimationOptions makeThumbnailAnimOptions(HardwareBuffer srcThumb, 885 int startX, int startY, boolean scaleUp) { 886 AnimationOptions options = new AnimationOptions( 887 scaleUp ? ANIM_THUMBNAIL_SCALE_UP : ANIM_THUMBNAIL_SCALE_DOWN); 888 options.mTransitionBounds.set(startX, startY, startX, startY); 889 options.mThumbnail = srcThumb; 890 return options; 891 } 892 makeCrossProfileAnimOptions()893 public static AnimationOptions makeCrossProfileAnimOptions() { 894 AnimationOptions options = new AnimationOptions(ANIM_OPEN_CROSS_PROFILE_APPS); 895 return options; 896 } 897 getType()898 public int getType() { 899 return mType; 900 } 901 getEnterResId()902 public int getEnterResId() { 903 return mEnterResId; 904 } 905 getExitResId()906 public int getExitResId() { 907 return mExitResId; 908 } 909 getBackgroundColor()910 public @ColorInt int getBackgroundColor() { 911 return mBackgroundColor; 912 } 913 getOverrideTaskTransition()914 public boolean getOverrideTaskTransition() { 915 return mOverrideTaskTransition; 916 } 917 getPackageName()918 public String getPackageName() { 919 return mPackageName; 920 } 921 getTransitionBounds()922 public Rect getTransitionBounds() { 923 return mTransitionBounds; 924 } 925 getThumbnail()926 public HardwareBuffer getThumbnail() { 927 return mThumbnail; 928 } 929 getAnimations()930 public int getAnimations() { 931 return mAnimations; 932 } 933 934 @Override writeToParcel(Parcel dest, int flags)935 public void writeToParcel(Parcel dest, int flags) { 936 dest.writeInt(mType); 937 dest.writeInt(mEnterResId); 938 dest.writeInt(mExitResId); 939 dest.writeInt(mBackgroundColor); 940 dest.writeBoolean(mOverrideTaskTransition); 941 dest.writeString(mPackageName); 942 mTransitionBounds.writeToParcel(dest, flags); 943 dest.writeTypedObject(mThumbnail, flags); 944 dest.writeInt(mAnimations); 945 } 946 947 @NonNull 948 public static final Creator<AnimationOptions> CREATOR = 949 new Creator<AnimationOptions>() { 950 @Override 951 public AnimationOptions createFromParcel(Parcel in) { 952 return new AnimationOptions(in); 953 } 954 955 @Override 956 public AnimationOptions[] newArray(int size) { 957 return new AnimationOptions[size]; 958 } 959 }; 960 961 /** @hide */ 962 @Override describeContents()963 public int describeContents() { 964 return 0; 965 } 966 967 @NonNull typeToString(int mode)968 private static String typeToString(int mode) { 969 switch(mode) { 970 case ANIM_CUSTOM: return "ANIM_CUSTOM"; 971 case ANIM_CLIP_REVEAL: return "ANIM_CLIP_REVEAL"; 972 case ANIM_SCALE_UP: return "ANIM_SCALE_UP"; 973 case ANIM_THUMBNAIL_SCALE_UP: return "ANIM_THUMBNAIL_SCALE_UP"; 974 case ANIM_THUMBNAIL_SCALE_DOWN: return "ANIM_THUMBNAIL_SCALE_DOWN"; 975 case ANIM_OPEN_CROSS_PROFILE_APPS: return "ANIM_OPEN_CROSS_PROFILE_APPS"; 976 default: return "<unknown:" + mode + ">"; 977 } 978 } 979 980 @Override toString()981 public String toString() { 982 return "{ AnimationOptions type= " + typeToString(mType) + " package=" + mPackageName 983 + " override=" + mOverrideTaskTransition + " b=" + mTransitionBounds + "}"; 984 } 985 } 986 } 987