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