1 /* 2 * Copyright (C) 2018 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.view; 18 19 import static android.graphics.GraphicsProtos.dumpPointProto; 20 import static android.view.RemoteAnimationTargetProto.CLIP_RECT; 21 import static android.view.RemoteAnimationTargetProto.CONTENT_INSETS; 22 import static android.view.RemoteAnimationTargetProto.IS_TRANSLUCENT; 23 import static android.view.RemoteAnimationTargetProto.LEASH; 24 import static android.view.RemoteAnimationTargetProto.LOCAL_BOUNDS; 25 import static android.view.RemoteAnimationTargetProto.MODE; 26 import static android.view.RemoteAnimationTargetProto.POSITION; 27 import static android.view.RemoteAnimationTargetProto.PREFIX_ORDER_INDEX; 28 import static android.view.RemoteAnimationTargetProto.SCREEN_SPACE_BOUNDS; 29 import static android.view.RemoteAnimationTargetProto.SOURCE_CONTAINER_BOUNDS; 30 import static android.view.RemoteAnimationTargetProto.START_BOUNDS; 31 import static android.view.RemoteAnimationTargetProto.START_LEASH; 32 import static android.view.RemoteAnimationTargetProto.TASK_ID; 33 import static android.view.RemoteAnimationTargetProto.WINDOW_CONFIGURATION; 34 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE; 35 36 import android.annotation.ColorInt; 37 import android.annotation.IntDef; 38 import android.annotation.Nullable; 39 import android.app.ActivityManager; 40 import android.app.TaskInfo; 41 import android.app.WindowConfiguration; 42 import android.compat.annotation.UnsupportedAppUsage; 43 import android.graphics.Point; 44 import android.graphics.Rect; 45 import android.os.Build; 46 import android.os.Parcel; 47 import android.os.Parcelable; 48 import android.util.proto.ProtoOutputStream; 49 import android.window.TaskSnapshot; 50 51 import java.io.PrintWriter; 52 import java.lang.annotation.Retention; 53 import java.lang.annotation.RetentionPolicy; 54 55 /** 56 * Describes an activity to be animated as part of a remote animation. 57 * 58 * @hide 59 */ 60 public class RemoteAnimationTarget implements Parcelable { 61 62 /** 63 * The app is in the set of opening apps of this transition. 64 */ 65 public static final int MODE_OPENING = 0; 66 67 /** 68 * The app is in the set of closing apps of this transition. 69 */ 70 public static final int MODE_CLOSING = 1; 71 72 /** 73 * The app is in the set of resizing apps (eg. mode change) of this transition. 74 */ 75 public static final int MODE_CHANGING = 2; 76 77 @IntDef(prefix = { "MODE_" }, value = { 78 MODE_OPENING, 79 MODE_CLOSING, 80 MODE_CHANGING 81 }) 82 @Retention(RetentionPolicy.SOURCE) 83 public @interface Mode {} 84 85 /** 86 * The {@link Mode} to describe whether this app is opening or closing. 87 */ 88 @UnsupportedAppUsage 89 public final @Mode int mode; 90 91 /** 92 * The id of the task this app belongs to. 93 */ 94 @UnsupportedAppUsage 95 public final int taskId; 96 97 /** 98 * The {@link SurfaceControl} object to actually control the transform of the app. 99 */ 100 @UnsupportedAppUsage 101 public final SurfaceControl leash; 102 103 /** 104 * The {@link SurfaceControl} for the starting state of a target if this transition is 105 * MODE_CHANGING, {@code null)} otherwise. This is relative to the app window. 106 */ 107 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 108 public final SurfaceControl startLeash; 109 110 /** 111 * Whether the app is translucent and may reveal apps behind. 112 */ 113 @UnsupportedAppUsage 114 public final boolean isTranslucent; 115 116 /** 117 * The clip rect window manager applies when clipping the app's main surface in screen space 118 * coordinates. This is just a hint to the animation runner: If running a clip-rect animation, 119 * anything that extends beyond these bounds will not have any effect. This implies that any 120 * clip-rect animation should likely stop at these bounds. 121 */ 122 @UnsupportedAppUsage 123 public final Rect clipRect; 124 125 /** 126 * The insets of the main app window. 127 */ 128 @UnsupportedAppUsage 129 public final Rect contentInsets; 130 131 /** 132 * The index of the element in the tree in prefix order. This should be used for z-layering 133 * to preserve original z-layer order in the hierarchy tree assuming no "boosting" needs to 134 * happen. 135 * @deprecated WindowManager may set a z-order different from the prefix order, and has set the 136 * correct layer for the animation leash already, so this should not be used for 137 * layer any more. 138 */ 139 @Deprecated 140 @UnsupportedAppUsage 141 public final int prefixOrderIndex; 142 143 /** 144 * The source position of the app, in screen spaces coordinates. If the position of the leash 145 * is modified from the controlling app, any animation transform needs to be offset by this 146 * amount. 147 * @deprecated Use {@link #localBounds} instead. 148 */ 149 @Deprecated 150 @UnsupportedAppUsage 151 public final Point position; 152 153 /** 154 * Bounds of the target relative to its parent. 155 * When the app target animating on its parent, we need to use the local coordinates relative to 156 * its parent with {@code localBounds.left} & {@code localBounds.top} rather than using 157 * {@code position} in screen coordinates. 158 */ 159 public final Rect localBounds; 160 161 /** 162 * The bounds of the source container the app lives in, in screen space coordinates. If the crop 163 * of the leash is modified from the controlling app, it needs to take the source container 164 * bounds into account when calculating the crop. 165 * @deprecated Renamed to {@link #screenSpaceBounds} 166 */ 167 @Deprecated 168 @UnsupportedAppUsage 169 public final Rect sourceContainerBounds; 170 171 /** 172 * Bounds of the target relative to the screen. If the crop of the leash is modified from the 173 * controlling app, it needs to take the screen space bounds into account when calculating the 174 * crop. 175 */ 176 public final Rect screenSpaceBounds; 177 178 /** 179 * The starting bounds of the source container in screen space coordinates. 180 * For {@link #MODE_OPENING}, this will be equivalent to {@link #screenSpaceBounds}. 181 * For {@link #MODE_CLOSING}, this will be equivalent to {@link #screenSpaceBounds} unless the 182 * closing container is also resizing. For example, when ActivityEmbedding split pair becomes 183 * stacked, the container on the back will be resized to fullscreen, but will also be covered 184 * (closing) by the container in the front. 185 * For {@link #MODE_CHANGING}, since this is the starting bounds, its size should be equivalent 186 * to the bounds of the starting thumbnail. 187 * 188 * Note that {@link #screenSpaceBounds} is the end bounds of a transition. 189 */ 190 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 191 public final Rect startBounds; 192 193 /** 194 * The window configuration for the target. 195 */ 196 @UnsupportedAppUsage 197 public final WindowConfiguration windowConfiguration; 198 199 /** 200 * Whether the task is not presented in Recents UI. 201 */ 202 @UnsupportedAppUsage 203 public boolean isNotInRecents; 204 205 /** 206 * {@link TaskInfo} to allow the controller to identify information about the task. 207 * 208 * TODO: add this to proto dump 209 */ 210 public ActivityManager.RunningTaskInfo taskInfo; 211 212 /** 213 * {@code true} if picture-in-picture permission is granted in {@link android.app.AppOpsManager} 214 */ 215 @UnsupportedAppUsage 216 public boolean allowEnterPip; 217 218 /** 219 * The {@link android.view.WindowManager.LayoutParams.WindowType} of this window. It's only used 220 * for non-app window. 221 */ 222 public final @WindowManager.LayoutParams.WindowType int windowType; 223 224 /** 225 * {@code true} if its parent is also a {@link RemoteAnimationTarget} in the same transition. 226 * 227 * For example, when a TaskFragment is resizing while one of its children is open/close, both 228 * windows will be animation targets. This value will be {@code true} for the child, so that 229 * the handler can choose to handle it differently. 230 */ 231 public boolean hasAnimatingParent; 232 233 /** 234 * Whether an activity has enabled {@link android.R.styleable#Animation_showBackdrop} for 235 * transition. 236 */ 237 public boolean showBackdrop; 238 239 /** 240 * The background color of animation in case the task info is not available if the transition 241 * is activity level. 242 */ 243 public @ColorInt int backgroundColor; 244 245 /** 246 * Whether the activity is going to show IME on the target window after the app transition. 247 * @see TaskSnapshot#hasImeSurface() that used the task snapshot during animating task. 248 */ 249 public boolean willShowImeOnTarget; 250 251 public int rotationChange; 252 RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, Rect localBounds, Rect screenSpaceBounds, WindowConfiguration windowConfig, boolean isNotInRecents, SurfaceControl startLeash, @Nullable Rect startBounds, ActivityManager.RunningTaskInfo taskInfo, boolean allowEnterPip)253 public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, 254 Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, 255 Rect localBounds, Rect screenSpaceBounds, 256 WindowConfiguration windowConfig, boolean isNotInRecents, 257 SurfaceControl startLeash, @Nullable Rect startBounds, 258 ActivityManager.RunningTaskInfo taskInfo, 259 boolean allowEnterPip) { 260 this(taskId, mode, leash, isTranslucent, clipRect, contentInsets, prefixOrderIndex, 261 position, localBounds, screenSpaceBounds, windowConfig, isNotInRecents, startLeash, 262 startBounds, taskInfo, allowEnterPip, INVALID_WINDOW_TYPE); 263 } 264 RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, Rect localBounds, Rect screenSpaceBounds, WindowConfiguration windowConfig, boolean isNotInRecents, SurfaceControl startLeash, @Nullable Rect startBounds, ActivityManager.RunningTaskInfo taskInfo, boolean allowEnterPip, @WindowManager.LayoutParams.WindowType int windowType)265 public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, 266 Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, 267 Rect localBounds, Rect screenSpaceBounds, 268 WindowConfiguration windowConfig, boolean isNotInRecents, 269 SurfaceControl startLeash, @Nullable Rect startBounds, 270 ActivityManager.RunningTaskInfo taskInfo, boolean allowEnterPip, 271 @WindowManager.LayoutParams.WindowType int windowType) { 272 this.mode = mode; 273 this.taskId = taskId; 274 this.leash = leash; 275 this.isTranslucent = isTranslucent; 276 this.clipRect = new Rect(clipRect); 277 this.contentInsets = new Rect(contentInsets); 278 this.prefixOrderIndex = prefixOrderIndex; 279 this.position = position == null ? new Point() : new Point(position); 280 this.localBounds = new Rect(localBounds); 281 this.sourceContainerBounds = new Rect(screenSpaceBounds); 282 this.screenSpaceBounds = new Rect(screenSpaceBounds); 283 this.windowConfiguration = windowConfig; 284 this.isNotInRecents = isNotInRecents; 285 this.startLeash = startLeash; 286 this.taskInfo = taskInfo; 287 this.allowEnterPip = allowEnterPip; 288 this.windowType = windowType; 289 // Same as screenSpaceBounds if the window is not resizing. 290 this.startBounds = startBounds == null 291 ? new Rect(screenSpaceBounds) 292 : new Rect(startBounds); 293 } 294 RemoteAnimationTarget(Parcel in)295 public RemoteAnimationTarget(Parcel in) { 296 taskId = in.readInt(); 297 mode = in.readInt(); 298 leash = in.readTypedObject(SurfaceControl.CREATOR); 299 isTranslucent = in.readBoolean(); 300 clipRect = in.readTypedObject(Rect.CREATOR); 301 contentInsets = in.readTypedObject(Rect.CREATOR); 302 prefixOrderIndex = in.readInt(); 303 position = in.readTypedObject(Point.CREATOR); 304 localBounds = in.readTypedObject(Rect.CREATOR); 305 sourceContainerBounds = in.readTypedObject(Rect.CREATOR); 306 screenSpaceBounds = in.readTypedObject(Rect.CREATOR); 307 windowConfiguration = in.readTypedObject(WindowConfiguration.CREATOR); 308 isNotInRecents = in.readBoolean(); 309 startLeash = in.readTypedObject(SurfaceControl.CREATOR); 310 startBounds = in.readTypedObject(Rect.CREATOR); 311 taskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR); 312 allowEnterPip = in.readBoolean(); 313 windowType = in.readInt(); 314 hasAnimatingParent = in.readBoolean(); 315 backgroundColor = in.readInt(); 316 showBackdrop = in.readBoolean(); 317 willShowImeOnTarget = in.readBoolean(); 318 rotationChange = in.readInt(); 319 } 320 setShowBackdrop(boolean shouldShowBackdrop)321 public void setShowBackdrop(boolean shouldShowBackdrop) { 322 showBackdrop = shouldShowBackdrop; 323 } 324 setWillShowImeOnTarget(boolean showImeOnTarget)325 public void setWillShowImeOnTarget(boolean showImeOnTarget) { 326 willShowImeOnTarget = showImeOnTarget; 327 } 328 willShowImeOnTarget()329 public boolean willShowImeOnTarget() { 330 return willShowImeOnTarget; 331 } 332 setRotationChange(int rotationChange)333 public void setRotationChange(int rotationChange) { 334 this.rotationChange = rotationChange; 335 } 336 getRotationChange()337 public int getRotationChange() { 338 return rotationChange; 339 } 340 341 @Override describeContents()342 public int describeContents() { 343 return 0; 344 } 345 346 @Override writeToParcel(Parcel dest, int flags)347 public void writeToParcel(Parcel dest, int flags) { 348 dest.writeInt(taskId); 349 dest.writeInt(mode); 350 dest.writeTypedObject(leash, 0 /* flags */); 351 dest.writeBoolean(isTranslucent); 352 dest.writeTypedObject(clipRect, 0 /* flags */); 353 dest.writeTypedObject(contentInsets, 0 /* flags */); 354 dest.writeInt(prefixOrderIndex); 355 dest.writeTypedObject(position, 0 /* flags */); 356 dest.writeTypedObject(localBounds, 0 /* flags */); 357 dest.writeTypedObject(sourceContainerBounds, 0 /* flags */); 358 dest.writeTypedObject(screenSpaceBounds, 0 /* flags */); 359 dest.writeTypedObject(windowConfiguration, 0 /* flags */); 360 dest.writeBoolean(isNotInRecents); 361 dest.writeTypedObject(startLeash, 0 /* flags */); 362 dest.writeTypedObject(startBounds, 0 /* flags */); 363 dest.writeTypedObject(taskInfo, 0 /* flags */); 364 dest.writeBoolean(allowEnterPip); 365 dest.writeInt(windowType); 366 dest.writeBoolean(hasAnimatingParent); 367 dest.writeInt(backgroundColor); 368 dest.writeBoolean(showBackdrop); 369 dest.writeBoolean(willShowImeOnTarget); 370 dest.writeInt(rotationChange); 371 } 372 dump(PrintWriter pw, String prefix)373 public void dump(PrintWriter pw, String prefix) { 374 pw.print(prefix); pw.print("mode="); pw.print(mode); 375 pw.print(" taskId="); pw.print(taskId); 376 pw.print(" isTranslucent="); pw.print(isTranslucent); 377 pw.print(" clipRect="); clipRect.printShortString(pw); 378 pw.print(" contentInsets="); contentInsets.printShortString(pw); 379 pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex); 380 pw.print(" position="); printPoint(position, pw); 381 pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw); 382 pw.print(" screenSpaceBounds="); screenSpaceBounds.printShortString(pw); 383 pw.print(" localBounds="); localBounds.printShortString(pw); 384 pw.println(); 385 pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration); 386 pw.print(prefix); pw.print("leash="); pw.println(leash); 387 pw.print(prefix); pw.print("taskInfo="); pw.println(taskInfo); 388 pw.print(prefix); pw.print("allowEnterPip="); pw.println(allowEnterPip); 389 pw.print(prefix); pw.print("windowType="); pw.print(windowType); 390 pw.print(prefix); pw.print("hasAnimatingParent="); pw.print(hasAnimatingParent); 391 pw.print(prefix); pw.print("backgroundColor="); pw.print(backgroundColor); 392 pw.print(prefix); pw.print("showBackdrop="); pw.print(showBackdrop); 393 pw.print(prefix); pw.print("willShowImeOnTarget="); pw.print(willShowImeOnTarget); 394 } 395 dumpDebug(ProtoOutputStream proto, long fieldId)396 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 397 final long token = proto.start(fieldId); 398 proto.write(TASK_ID, taskId); 399 proto.write(MODE, mode); 400 leash.dumpDebug(proto, LEASH); 401 proto.write(IS_TRANSLUCENT, isTranslucent); 402 clipRect.dumpDebug(proto, CLIP_RECT); 403 contentInsets.dumpDebug(proto, CONTENT_INSETS); 404 proto.write(PREFIX_ORDER_INDEX, prefixOrderIndex); 405 dumpPointProto(position, proto, POSITION); 406 sourceContainerBounds.dumpDebug(proto, SOURCE_CONTAINER_BOUNDS); 407 screenSpaceBounds.dumpDebug(proto, SCREEN_SPACE_BOUNDS); 408 localBounds.dumpDebug(proto, LOCAL_BOUNDS); 409 windowConfiguration.dumpDebug(proto, WINDOW_CONFIGURATION); 410 if (startLeash != null) { 411 startLeash.dumpDebug(proto, START_LEASH); 412 } 413 startBounds.dumpDebug(proto, START_BOUNDS); 414 proto.end(token); 415 } 416 printPoint(Point p, PrintWriter pw)417 private static void printPoint(Point p, PrintWriter pw) { 418 pw.print("["); pw.print(p.x); pw.print(","); pw.print(p.y); pw.print("]"); 419 } 420 421 public static final @android.annotation.NonNull Creator<RemoteAnimationTarget> CREATOR 422 = new Creator<RemoteAnimationTarget>() { 423 public RemoteAnimationTarget createFromParcel(Parcel in) { 424 return new RemoteAnimationTarget(in); 425 } 426 427 public RemoteAnimationTarget[] newArray(int size) { 428 return new RemoteAnimationTarget[size]; 429 } 430 }; 431 } 432