• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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