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