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 android.annotation.NonNull; 20 import android.compat.annotation.UnsupportedAppUsage; 21 import android.content.ComponentName; 22 import android.content.res.Configuration; 23 import android.graphics.ColorSpace; 24 import android.graphics.GraphicBuffer; 25 import android.graphics.Point; 26 import android.graphics.Rect; 27 import android.hardware.HardwareBuffer; 28 import android.os.Build; 29 import android.os.Parcel; 30 import android.os.Parcelable; 31 import android.view.Surface; 32 import android.view.WindowInsetsController; 33 34 /** 35 * Represents a task snapshot. 36 * @hide 37 */ 38 public class TaskSnapshot implements Parcelable { 39 // Identifier of this snapshot 40 private final long mId; 41 // Top activity in task when snapshot was taken 42 private final ComponentName mTopActivityComponent; 43 private final HardwareBuffer mSnapshot; 44 /** Indicates whether task was in landscape or portrait */ 45 @Configuration.Orientation 46 private final int mOrientation; 47 /** See {@link android.view.Surface.Rotation} */ 48 @Surface.Rotation 49 private final int mRotation; 50 /** The size of the snapshot before scaling */ 51 private final Point mTaskSize; 52 private final Rect mContentInsets; 53 // Whether this snapshot is a down-sampled version of the high resolution snapshot, used 54 // mainly for loading snapshots quickly from disk when user is flinging fast 55 private final boolean mIsLowResolution; 56 // Whether or not the snapshot is a real snapshot or an app-theme generated snapshot due to 57 // the task having a secure window or having previews disabled 58 private final boolean mIsRealSnapshot; 59 private final int mWindowingMode; 60 private final @WindowInsetsController.Appearance 61 int mAppearance; 62 private final boolean mIsTranslucent; 63 private final boolean mHasImeSurface; 64 // Must be one of the named color spaces, otherwise, always use SRGB color space. 65 private final ColorSpace mColorSpace; 66 TaskSnapshot(long id, @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot, @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize, Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot, int windowingMode, @WindowInsetsController.Appearance int appearance, boolean isTranslucent, boolean hasImeSurface)67 public TaskSnapshot(long id, 68 @NonNull ComponentName topActivityComponent, HardwareBuffer snapshot, 69 @NonNull ColorSpace colorSpace, int orientation, int rotation, Point taskSize, 70 Rect contentInsets, boolean isLowResolution, boolean isRealSnapshot, 71 int windowingMode, @WindowInsetsController.Appearance int appearance, 72 boolean isTranslucent, boolean hasImeSurface) { 73 mId = id; 74 mTopActivityComponent = topActivityComponent; 75 mSnapshot = snapshot; 76 mColorSpace = colorSpace.getId() < 0 77 ? ColorSpace.get(ColorSpace.Named.SRGB) : colorSpace; 78 mOrientation = orientation; 79 mRotation = rotation; 80 mTaskSize = new Point(taskSize); 81 mContentInsets = new Rect(contentInsets); 82 mIsLowResolution = isLowResolution; 83 mIsRealSnapshot = isRealSnapshot; 84 mWindowingMode = windowingMode; 85 mAppearance = appearance; 86 mIsTranslucent = isTranslucent; 87 mHasImeSurface = hasImeSurface; 88 } 89 90 private TaskSnapshot(Parcel source) { 91 mId = source.readLong(); 92 mTopActivityComponent = ComponentName.readFromParcel(source); 93 mSnapshot = source.readTypedObject(HardwareBuffer.CREATOR); 94 int colorSpaceId = source.readInt(); 95 mColorSpace = colorSpaceId >= 0 && colorSpaceId < ColorSpace.Named.values().length 96 ? ColorSpace.get(ColorSpace.Named.values()[colorSpaceId]) 97 : ColorSpace.get(ColorSpace.Named.SRGB); 98 mOrientation = source.readInt(); 99 mRotation = source.readInt(); 100 mTaskSize = source.readTypedObject(Point.CREATOR); 101 mContentInsets = source.readTypedObject(Rect.CREATOR); 102 mIsLowResolution = source.readBoolean(); 103 mIsRealSnapshot = source.readBoolean(); 104 mWindowingMode = source.readInt(); 105 mAppearance = source.readInt(); 106 mIsTranslucent = source.readBoolean(); 107 mHasImeSurface = source.readBoolean(); 108 } 109 110 /** 111 * @return Identifier of this snapshot. 112 */ 113 public long getId() { 114 return mId; 115 } 116 117 /** 118 * @return The top activity component for the task at the point this snapshot was taken. 119 */ 120 public ComponentName getTopActivityComponent() { 121 return mTopActivityComponent; 122 } 123 124 /** 125 * @return The graphic buffer representing the screenshot. 126 * 127 * Note: Prefer {@link #getHardwareBuffer}, which returns the internal object. This version 128 * creates a new object. 129 */ 130 @UnsupportedAppUsage 131 public GraphicBuffer getSnapshot() { 132 return GraphicBuffer.createFromHardwareBuffer(mSnapshot); 133 } 134 135 /** 136 * @return The hardware buffer representing the screenshot. 137 */ 138 public HardwareBuffer getHardwareBuffer() { 139 return mSnapshot; 140 } 141 142 /** 143 * @return The color space of hardware buffer representing the screenshot. 144 */ 145 public ColorSpace getColorSpace() { 146 return mColorSpace; 147 } 148 149 /** 150 * @return The screen orientation the screenshot was taken in. 151 */ 152 @UnsupportedAppUsage 153 public int getOrientation() { 154 return mOrientation; 155 } 156 157 /** 158 * @return The screen rotation the screenshot was taken in. 159 */ 160 public int getRotation() { 161 return mRotation; 162 } 163 164 /** 165 * @return The size of the task at the point this snapshot was taken. 166 */ 167 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) 168 public Point getTaskSize() { 169 return mTaskSize; 170 } 171 172 /** 173 * @return The system/content insets on the snapshot. These can be clipped off in order to 174 * remove any areas behind system bars in the snapshot. 175 */ 176 @UnsupportedAppUsage 177 public Rect getContentInsets() { 178 return mContentInsets; 179 } 180 181 /** 182 * @return Whether this snapshot is a down-sampled version of the full resolution. 183 */ 184 @UnsupportedAppUsage 185 public boolean isLowResolution() { 186 return mIsLowResolution; 187 } 188 189 /** 190 * @return Whether or not the snapshot is a real snapshot or an app-theme generated snapshot 191 * due to the task having a secure window or having previews disabled. 192 */ 193 @UnsupportedAppUsage 194 public boolean isRealSnapshot() { 195 return mIsRealSnapshot; 196 } 197 198 /** 199 * @return Whether or not the snapshot is of a translucent app window (non-fullscreen or has 200 * a non-opaque pixel format). 201 */ 202 public boolean isTranslucent() { 203 return mIsTranslucent; 204 } 205 206 /** 207 * @return Whether or not the snapshot has the IME surface. 208 */ 209 public boolean hasImeSurface() { 210 return mHasImeSurface; 211 } 212 213 /** 214 * @return The windowing mode of the task when this snapshot was taken. 215 */ 216 public int getWindowingMode() { 217 return mWindowingMode; 218 } 219 220 /** 221 * @return The {@link WindowInsetsController.Appearance} flags for the top most visible 222 * fullscreen window at the time that the snapshot was taken. 223 */ 224 public @WindowInsetsController.Appearance 225 int getAppearance() { 226 return mAppearance; 227 } 228 229 @Override 230 public int describeContents() { 231 return 0; 232 } 233 234 @Override 235 public void writeToParcel(Parcel dest, int flags) { 236 dest.writeLong(mId); 237 ComponentName.writeToParcel(mTopActivityComponent, dest); 238 dest.writeTypedObject(mSnapshot != null && !mSnapshot.isClosed() ? mSnapshot : null, 0); 239 dest.writeInt(mColorSpace.getId()); 240 dest.writeInt(mOrientation); 241 dest.writeInt(mRotation); 242 dest.writeTypedObject(mTaskSize, 0); 243 dest.writeTypedObject(mContentInsets, 0); 244 dest.writeBoolean(mIsLowResolution); 245 dest.writeBoolean(mIsRealSnapshot); 246 dest.writeInt(mWindowingMode); 247 dest.writeInt(mAppearance); 248 dest.writeBoolean(mIsTranslucent); 249 dest.writeBoolean(mHasImeSurface); 250 } 251 252 @Override 253 public String toString() { 254 final int width = mSnapshot != null ? mSnapshot.getWidth() : 0; 255 final int height = mSnapshot != null ? mSnapshot.getHeight() : 0; 256 return "TaskSnapshot{" 257 + " mId=" + mId 258 + " mTopActivityComponent=" + mTopActivityComponent.flattenToShortString() 259 + " mSnapshot=" + mSnapshot + " (" + width + "x" + height + ")" 260 + " mColorSpace=" + mColorSpace.toString() 261 + " mOrientation=" + mOrientation 262 + " mRotation=" + mRotation 263 + " mTaskSize=" + mTaskSize.toString() 264 + " mContentInsets=" + mContentInsets.toShortString() 265 + " mIsLowResolution=" + mIsLowResolution 266 + " mIsRealSnapshot=" + mIsRealSnapshot 267 + " mWindowingMode=" + mWindowingMode 268 + " mAppearance=" + mAppearance 269 + " mIsTranslucent=" + mIsTranslucent 270 + " mHasImeSurface=" + mHasImeSurface; 271 } 272 273 public static final @NonNull Creator<TaskSnapshot> CREATOR = new Creator<TaskSnapshot>() { 274 public TaskSnapshot createFromParcel(Parcel source) { 275 return new TaskSnapshot(source); 276 } 277 public TaskSnapshot[] newArray(int size) { 278 return new TaskSnapshot[size]; 279 } 280 }; 281 282 /** Builder for a {@link TaskSnapshot} object */ 283 public static final class Builder { 284 private long mId; 285 private ComponentName mTopActivity; 286 private HardwareBuffer mSnapshot; 287 private ColorSpace mColorSpace; 288 private int mOrientation; 289 private int mRotation; 290 private Point mTaskSize; 291 private Rect mContentInsets; 292 private boolean mIsRealSnapshot; 293 private int mWindowingMode; 294 private @WindowInsetsController.Appearance 295 int mAppearance; 296 private boolean mIsTranslucent; 297 private boolean mHasImeSurface; 298 private int mPixelFormat; 299 300 public Builder setId(long id) { 301 mId = id; 302 return this; 303 } 304 305 public Builder setTopActivityComponent(ComponentName name) { 306 mTopActivity = name; 307 return this; 308 } 309 310 public Builder setSnapshot(HardwareBuffer buffer) { 311 mSnapshot = buffer; 312 return this; 313 } 314 315 public Builder setColorSpace(ColorSpace colorSpace) { 316 mColorSpace = colorSpace; 317 return this; 318 } 319 320 public Builder setOrientation(int orientation) { 321 mOrientation = orientation; 322 return this; 323 } 324 325 public Builder setRotation(int rotation) { 326 mRotation = rotation; 327 return this; 328 } 329 330 /** 331 * Sets the original size of the task 332 */ 333 public Builder setTaskSize(Point size) { 334 mTaskSize = size; 335 return this; 336 } 337 338 public Builder setContentInsets(Rect contentInsets) { 339 mContentInsets = contentInsets; 340 return this; 341 } 342 343 public Builder setIsRealSnapshot(boolean realSnapshot) { 344 mIsRealSnapshot = realSnapshot; 345 return this; 346 } 347 348 public Builder setWindowingMode(int windowingMode) { 349 mWindowingMode = windowingMode; 350 return this; 351 } 352 353 public Builder setAppearance(@WindowInsetsController.Appearance int appearance) { 354 mAppearance = appearance; 355 return this; 356 } 357 358 public Builder setIsTranslucent(boolean isTranslucent) { 359 mIsTranslucent = isTranslucent; 360 return this; 361 } 362 363 /** 364 * Sets the IME visibility when taking the snapshot of the task. 365 */ 366 public Builder setHasImeSurface(boolean hasImeSurface) { 367 mHasImeSurface = hasImeSurface; 368 return this; 369 } 370 371 public int getPixelFormat() { 372 return mPixelFormat; 373 } 374 375 public Builder setPixelFormat(int pixelFormat) { 376 mPixelFormat = pixelFormat; 377 return this; 378 } 379 380 public TaskSnapshot build() { 381 return new TaskSnapshot( 382 mId, 383 mTopActivity, 384 mSnapshot, 385 mColorSpace, 386 mOrientation, 387 mRotation, 388 mTaskSize, 389 mContentInsets, 390 // When building a TaskSnapshot with the Builder class, isLowResolution 391 // is always false. Low-res snapshots are only created when loading from 392 // disk. 393 false /* isLowResolution */, 394 mIsRealSnapshot, 395 mWindowingMode, 396 mAppearance, 397 mIsTranslucent, 398 mHasImeSurface); 399 400 } 401 } 402 } 403