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 */ 133 @UnsupportedAppUsage 134 public final int prefixOrderIndex; 135 136 /** 137 * The source position of the app, in screen spaces coordinates. If the position of the leash 138 * is modified from the controlling app, any animation transform needs to be offset by this 139 * amount. 140 * @deprecated Use {@link #localBounds} instead. 141 */ 142 @Deprecated 143 @UnsupportedAppUsage 144 public final Point position; 145 146 /** 147 * Bounds of the target relative to its parent. 148 * When the app target animating on its parent, we need to use the local coordinates relative to 149 * its parent with {@code localBounds.left} & {@code localBounds.top} rather than using 150 * {@code position} in screen coordinates. 151 */ 152 public final Rect localBounds; 153 154 /** 155 * The bounds of the source container the app lives in, in screen space coordinates. If the crop 156 * of the leash is modified from the controlling app, it needs to take the source container 157 * bounds into account when calculating the crop. 158 * @deprecated Renamed to {@link #screenSpaceBounds} 159 */ 160 @Deprecated 161 @UnsupportedAppUsage 162 public final Rect sourceContainerBounds; 163 164 /** 165 * Bounds of the target relative to the screen. If the crop of the leash is modified from the 166 * controlling app, it needs to take the screen space bounds into account when calculating the 167 * crop. 168 */ 169 public final Rect screenSpaceBounds; 170 171 /** 172 * The starting bounds of the source container in screen space coordinates. This is {@code null} 173 * if the animation target isn't MODE_CHANGING. Since this is the starting bounds, it's size 174 * should be equivalent to the size of the starting thumbnail. Note that sourceContainerBounds 175 * is the end bounds of a change transition. 176 */ 177 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 178 public final Rect startBounds; 179 180 /** 181 * The window configuration for the target. 182 */ 183 @UnsupportedAppUsage 184 public final WindowConfiguration windowConfiguration; 185 186 /** 187 * Whether the task is not presented in Recents UI. 188 */ 189 @UnsupportedAppUsage 190 public boolean isNotInRecents; 191 192 /** 193 * {@link TaskInfo} to allow the controller to identify information about the task. 194 * 195 * TODO: add this to proto dump 196 */ 197 public ActivityManager.RunningTaskInfo taskInfo; 198 199 /** 200 * The {@link android.view.WindowManager.LayoutParams.WindowType} of this window. It's only used 201 * for non-app window. 202 */ 203 public final @WindowManager.LayoutParams.WindowType int windowType; 204 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)205 public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, 206 Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, 207 Rect localBounds, Rect screenSpaceBounds, 208 WindowConfiguration windowConfig, boolean isNotInRecents, 209 SurfaceControl startLeash, Rect startBounds, ActivityManager.RunningTaskInfo taskInfo) { 210 this(taskId, mode, leash, isTranslucent, clipRect, contentInsets, prefixOrderIndex, 211 position, localBounds, screenSpaceBounds, windowConfig, isNotInRecents, startLeash, 212 startBounds, taskInfo, INVALID_WINDOW_TYPE); 213 } 214 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, @WindowManager.LayoutParams.WindowType int windowType)215 public RemoteAnimationTarget(int taskId, int mode, SurfaceControl leash, boolean isTranslucent, 216 Rect clipRect, Rect contentInsets, int prefixOrderIndex, Point position, 217 Rect localBounds, Rect screenSpaceBounds, 218 WindowConfiguration windowConfig, boolean isNotInRecents, 219 SurfaceControl startLeash, Rect startBounds, 220 ActivityManager.RunningTaskInfo taskInfo, 221 @WindowManager.LayoutParams.WindowType int windowType) { 222 this.mode = mode; 223 this.taskId = taskId; 224 this.leash = leash; 225 this.isTranslucent = isTranslucent; 226 this.clipRect = new Rect(clipRect); 227 this.contentInsets = new Rect(contentInsets); 228 this.prefixOrderIndex = prefixOrderIndex; 229 this.position = new Point(position); 230 this.localBounds = new Rect(localBounds); 231 this.sourceContainerBounds = new Rect(screenSpaceBounds); 232 this.screenSpaceBounds = new Rect(screenSpaceBounds); 233 this.windowConfiguration = windowConfig; 234 this.isNotInRecents = isNotInRecents; 235 this.startLeash = startLeash; 236 this.startBounds = startBounds == null ? null : new Rect(startBounds); 237 this.taskInfo = taskInfo; 238 this.windowType = windowType; 239 } 240 RemoteAnimationTarget(Parcel in)241 public RemoteAnimationTarget(Parcel in) { 242 taskId = in.readInt(); 243 mode = in.readInt(); 244 leash = in.readTypedObject(SurfaceControl.CREATOR); 245 isTranslucent = in.readBoolean(); 246 clipRect = in.readTypedObject(Rect.CREATOR); 247 contentInsets = in.readTypedObject(Rect.CREATOR); 248 prefixOrderIndex = in.readInt(); 249 position = in.readTypedObject(Point.CREATOR); 250 localBounds = in.readTypedObject(Rect.CREATOR); 251 sourceContainerBounds = in.readTypedObject(Rect.CREATOR); 252 screenSpaceBounds = in.readTypedObject(Rect.CREATOR); 253 windowConfiguration = in.readTypedObject(WindowConfiguration.CREATOR); 254 isNotInRecents = in.readBoolean(); 255 startLeash = in.readTypedObject(SurfaceControl.CREATOR); 256 startBounds = in.readTypedObject(Rect.CREATOR); 257 taskInfo = in.readTypedObject(ActivityManager.RunningTaskInfo.CREATOR); 258 windowType = in.readInt(); 259 } 260 261 @Override describeContents()262 public int describeContents() { 263 return 0; 264 } 265 266 @Override writeToParcel(Parcel dest, int flags)267 public void writeToParcel(Parcel dest, int flags) { 268 dest.writeInt(taskId); 269 dest.writeInt(mode); 270 dest.writeTypedObject(leash, 0 /* flags */); 271 dest.writeBoolean(isTranslucent); 272 dest.writeTypedObject(clipRect, 0 /* flags */); 273 dest.writeTypedObject(contentInsets, 0 /* flags */); 274 dest.writeInt(prefixOrderIndex); 275 dest.writeTypedObject(position, 0 /* flags */); 276 dest.writeTypedObject(localBounds, 0 /* flags */); 277 dest.writeTypedObject(sourceContainerBounds, 0 /* flags */); 278 dest.writeTypedObject(screenSpaceBounds, 0 /* flags */); 279 dest.writeTypedObject(windowConfiguration, 0 /* flags */); 280 dest.writeBoolean(isNotInRecents); 281 dest.writeTypedObject(startLeash, 0 /* flags */); 282 dest.writeTypedObject(startBounds, 0 /* flags */); 283 dest.writeTypedObject(taskInfo, 0 /* flags */); 284 dest.writeInt(windowType); 285 } 286 dump(PrintWriter pw, String prefix)287 public void dump(PrintWriter pw, String prefix) { 288 pw.print(prefix); pw.print("mode="); pw.print(mode); 289 pw.print(" taskId="); pw.print(taskId); 290 pw.print(" isTranslucent="); pw.print(isTranslucent); 291 pw.print(" clipRect="); clipRect.printShortString(pw); 292 pw.print(" contentInsets="); contentInsets.printShortString(pw); 293 pw.print(" prefixOrderIndex="); pw.print(prefixOrderIndex); 294 pw.print(" position="); printPoint(position, pw); 295 pw.print(" sourceContainerBounds="); sourceContainerBounds.printShortString(pw); 296 pw.print(" screenSpaceBounds="); screenSpaceBounds.printShortString(pw); 297 pw.print(" localBounds="); localBounds.printShortString(pw); 298 pw.println(); 299 pw.print(prefix); pw.print("windowConfiguration="); pw.println(windowConfiguration); 300 pw.print(prefix); pw.print("leash="); pw.println(leash); 301 pw.print(prefix); pw.print("taskInfo="); pw.println(taskInfo); 302 pw.print(prefix); pw.print("windowType="); pw.print(windowType); 303 } 304 dumpDebug(ProtoOutputStream proto, long fieldId)305 public void dumpDebug(ProtoOutputStream proto, long fieldId) { 306 final long token = proto.start(fieldId); 307 proto.write(TASK_ID, taskId); 308 proto.write(MODE, mode); 309 leash.dumpDebug(proto, LEASH); 310 proto.write(IS_TRANSLUCENT, isTranslucent); 311 clipRect.dumpDebug(proto, CLIP_RECT); 312 contentInsets.dumpDebug(proto, CONTENT_INSETS); 313 proto.write(PREFIX_ORDER_INDEX, prefixOrderIndex); 314 dumpPointProto(position, proto, POSITION); 315 sourceContainerBounds.dumpDebug(proto, SOURCE_CONTAINER_BOUNDS); 316 screenSpaceBounds.dumpDebug(proto, SCREEN_SPACE_BOUNDS); 317 localBounds.dumpDebug(proto, LOCAL_BOUNDS); 318 windowConfiguration.dumpDebug(proto, WINDOW_CONFIGURATION); 319 if (startLeash != null) { 320 startLeash.dumpDebug(proto, START_LEASH); 321 } 322 if (startBounds != null) { 323 startBounds.dumpDebug(proto, START_BOUNDS); 324 } 325 proto.end(token); 326 } 327 printPoint(Point p, PrintWriter pw)328 private static void printPoint(Point p, PrintWriter pw) { 329 pw.print("["); pw.print(p.x); pw.print(","); pw.print(p.y); pw.print("]"); 330 } 331 332 public static final @android.annotation.NonNull Creator<RemoteAnimationTarget> CREATOR 333 = new Creator<RemoteAnimationTarget>() { 334 public RemoteAnimationTarget createFromParcel(Parcel in) { 335 return new RemoteAnimationTarget(in); 336 } 337 338 public RemoteAnimationTarget[] newArray(int size) { 339 return new RemoteAnimationTarget[size]; 340 } 341 }; 342 } 343