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.hardware.display;
18 
19 import static android.view.Display.DEFAULT_DISPLAY;
20 
21 import android.annotation.FloatRange;
22 import android.annotation.IntRange;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.hardware.display.DisplayManager.VirtualDisplayFlag;
26 import android.media.projection.MediaProjection;
27 import android.os.Handler;
28 import android.os.Parcel;
29 import android.os.Parcelable;
30 import android.util.ArraySet;
31 import android.view.Display;
32 import android.view.Surface;
33 
34 import java.util.Collections;
35 import java.util.Objects;
36 import java.util.Set;
37 
38 /**
39  * Holds configuration used to create {@link VirtualDisplay} instances.
40  *
41  * @see DisplayManager#createVirtualDisplay(VirtualDisplayConfig, Handler, VirtualDisplay.Callback)
42  * @see MediaProjection#createVirtualDisplay
43  */
44 public final class VirtualDisplayConfig implements Parcelable {
45 
46     private final String mName;
47     private final int mWidth;
48     private final int mHeight;
49     private final int mDensityDpi;
50     private final int mFlags;
51     private final Surface mSurface;
52     private final String mUniqueId;
53     private final int mDisplayIdToMirror;
54     private final boolean mWindowManagerMirroringEnabled;
55     private ArraySet<String> mDisplayCategories = null;
56     private final float mRequestedRefreshRate;
57 
VirtualDisplayConfig( @onNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi, @VirtualDisplayFlag int flags, @Nullable Surface surface, @Nullable String uniqueId, int displayIdToMirror, boolean windowManagerMirroringEnabled, @NonNull ArraySet<String> displayCategories, float requestedRefreshRate)58     private VirtualDisplayConfig(
59             @NonNull String name,
60             @IntRange(from = 1) int width,
61             @IntRange(from = 1) int height,
62             @IntRange(from = 1) int densityDpi,
63             @VirtualDisplayFlag int flags,
64             @Nullable Surface surface,
65             @Nullable String uniqueId,
66             int displayIdToMirror,
67             boolean windowManagerMirroringEnabled,
68             @NonNull ArraySet<String> displayCategories,
69             float requestedRefreshRate) {
70         mName = name;
71         mWidth = width;
72         mHeight = height;
73         mDensityDpi = densityDpi;
74         mFlags = flags;
75         mSurface = surface;
76         mUniqueId = uniqueId;
77         mDisplayIdToMirror = displayIdToMirror;
78         mWindowManagerMirroringEnabled = windowManagerMirroringEnabled;
79         mDisplayCategories = displayCategories;
80         mRequestedRefreshRate = requestedRefreshRate;
81     }
82 
83     /**
84      * Returns the name of the virtual display.
85      */
86     @NonNull
getName()87     public String getName() {
88         return mName;
89     }
90 
91     /**
92      * Returns the width of the virtual display in pixels.
93      */
getWidth()94     public int getWidth() {
95         return mWidth;
96     }
97 
98     /**
99      * Returns the height of the virtual display in pixels.
100      */
getHeight()101     public int getHeight() {
102         return mHeight;
103     }
104 
105     /**
106      * Returns the density of the virtual display in dpi.
107      */
getDensityDpi()108     public int getDensityDpi() {
109         return mDensityDpi;
110     }
111 
112     /**
113      * Returns the virtual display flags.
114      *
115      * @see Builder#setFlags
116      */
getFlags()117     public int getFlags() {
118         return mFlags;
119     }
120 
121     /**
122      * Returns the surface to which the content of the virtual display should be rendered, if any.
123      *
124      * @see Builder#setSurface
125      */
126     @Nullable
getSurface()127     public Surface getSurface() {
128         return mSurface;
129     }
130 
131     /**
132      * Returns the unique identifier for the display. Shouldn't be displayed to the user.
133      * @hide
134      */
135     @Nullable
getUniqueId()136     public String getUniqueId() {
137         return mUniqueId;
138     }
139 
140     /**
141      * Returns the id of the display that the virtual display should mirror, or
142      * {@link android.view.Display#DEFAULT_DISPLAY} if there is none.
143      * @hide
144      */
getDisplayIdToMirror()145     public int getDisplayIdToMirror() {
146         return mDisplayIdToMirror;
147     }
148 
149     /**
150      * Whether if WindowManager is responsible for mirroring content to this VirtualDisplay, or
151      * if DisplayManager should record contents instead.
152      * @hide
153      */
isWindowManagerMirroringEnabled()154     public boolean isWindowManagerMirroringEnabled() {
155         return mWindowManagerMirroringEnabled;
156     }
157 
158     /**
159      * Returns the display categories.
160      *
161      * @see Builder#setDisplayCategories
162      */
163     @NonNull
getDisplayCategories()164     public Set<String> getDisplayCategories() {
165         return Collections.unmodifiableSet(mDisplayCategories);
166     }
167 
168     /**
169      * Returns the refresh rate of a virtual display in frames per second, or zero if it is using a
170      * default refresh rate chosen by the system.
171      *
172      * @see Builder#setRequestedRefreshRate
173      */
getRequestedRefreshRate()174     public float getRequestedRefreshRate() {
175         return mRequestedRefreshRate;
176     }
177 
178     @Override
writeToParcel(@onNull Parcel dest, int flags)179     public void writeToParcel(@NonNull Parcel dest, int flags) {
180         dest.writeString8(mName);
181         dest.writeInt(mWidth);
182         dest.writeInt(mHeight);
183         dest.writeInt(mDensityDpi);
184         dest.writeInt(mFlags);
185         dest.writeTypedObject(mSurface, flags);
186         dest.writeString8(mUniqueId);
187         dest.writeInt(mDisplayIdToMirror);
188         dest.writeBoolean(mWindowManagerMirroringEnabled);
189         dest.writeArraySet(mDisplayCategories);
190         dest.writeFloat(mRequestedRefreshRate);
191     }
192 
193     @Override
describeContents()194     public int describeContents() { return 0; }
195 
196     @Override
equals(Object o)197     public boolean equals(Object o) {
198         if (this == o) {
199             return true;
200         }
201         if (!(o instanceof VirtualDisplayConfig)) {
202             return false;
203         }
204         VirtualDisplayConfig that = (VirtualDisplayConfig) o;
205         return Objects.equals(mName, that.mName)
206                 && mWidth == that.mWidth
207                 && mHeight == that.mHeight
208                 && mDensityDpi == that.mDensityDpi
209                 && mFlags == that.mFlags
210                 && Objects.equals(mSurface, that.mSurface)
211                 && Objects.equals(mUniqueId, that.mUniqueId)
212                 && mDisplayIdToMirror == that.mDisplayIdToMirror
213                 && mWindowManagerMirroringEnabled == that.mWindowManagerMirroringEnabled
214                 && Objects.equals(mDisplayCategories, that.mDisplayCategories)
215                 && mRequestedRefreshRate == that.mRequestedRefreshRate;
216     }
217 
218     @Override
hashCode()219     public int hashCode() {
220         int hashCode = Objects.hash(
221                 mName, mWidth, mHeight, mDensityDpi, mFlags, mSurface, mUniqueId,
222                 mDisplayIdToMirror, mWindowManagerMirroringEnabled, mDisplayCategories,
223                 mRequestedRefreshRate);
224         return hashCode;
225     }
226 
227     @Override
228     @NonNull
toString()229     public String toString() {
230         return "VirtualDisplayConfig("
231                 + " mName=" + mName
232                 + " mHeight=" + mHeight
233                 + " mWidth=" + mWidth
234                 + " mDensityDpi=" + mDensityDpi
235                 + " mFlags=" + mFlags
236                 + " mSurface=" + mSurface
237                 + " mUniqueId=" + mUniqueId
238                 + " mDisplayIdToMirror=" + mDisplayIdToMirror
239                 + " mWindowManagerMirroringEnabled=" + mWindowManagerMirroringEnabled
240                 + " mDisplayCategories=" + mDisplayCategories
241                 + " mRequestedRefreshRate=" + mRequestedRefreshRate
242                 + ")";
243     }
244 
VirtualDisplayConfig(@onNull Parcel in)245     private VirtualDisplayConfig(@NonNull Parcel in) {
246         mName = in.readString8();
247         mWidth = in.readInt();
248         mHeight = in.readInt();
249         mDensityDpi = in.readInt();
250         mFlags = in.readInt();
251         mSurface = in.readTypedObject(Surface.CREATOR);
252         mUniqueId = in.readString8();
253         mDisplayIdToMirror = in.readInt();
254         mWindowManagerMirroringEnabled = in.readBoolean();
255         mDisplayCategories = (ArraySet<String>) in.readArraySet(null);
256         mRequestedRefreshRate = in.readFloat();
257     }
258 
259     @NonNull
260     public static final Parcelable.Creator<VirtualDisplayConfig> CREATOR
261             = new Parcelable.Creator<VirtualDisplayConfig>() {
262         @Override
263         public VirtualDisplayConfig[] newArray(int size) {
264             return new VirtualDisplayConfig[size];
265         }
266 
267         @Override
268         public VirtualDisplayConfig createFromParcel(@NonNull Parcel in) {
269             return new VirtualDisplayConfig(in);
270         }
271     };
272 
273     /**
274      * A builder for {@link VirtualDisplayConfig}.
275      */
276     public static final class Builder {
277         private final String mName;
278         private final int mWidth;
279         private final int mHeight;
280         private final int mDensityDpi;
281         private int mFlags = 0;
282         private Surface mSurface = null;
283         private String mUniqueId = null;
284         private int mDisplayIdToMirror = DEFAULT_DISPLAY;
285         private boolean mWindowManagerMirroringEnabled = false;
286         private ArraySet<String> mDisplayCategories = new ArraySet<>();
287         private float mRequestedRefreshRate = 0.0f;
288 
289         /**
290          * Creates a new Builder.
291          *
292          * @param name The name of the virtual display, must be non-empty.
293          * @param width The width of the virtual display in pixels. Must be greater than 0.
294          * @param height The height of the virtual display in pixels. Must be greater than 0.
295          * @param densityDpi The density of the virtual display in dpi. Must be greater than 0.
296          */
Builder( @onNull String name, @IntRange(from = 1) int width, @IntRange(from = 1) int height, @IntRange(from = 1) int densityDpi)297         public Builder(
298                 @NonNull String name,
299                 @IntRange(from = 1) int width,
300                 @IntRange(from = 1) int height,
301                 @IntRange(from = 1) int densityDpi) {
302             if (name == null) {
303                 throw new IllegalArgumentException("Virtual display name is required");
304             }
305             if (width <= 0) {
306                 throw new IllegalArgumentException("Virtual display width must be positive");
307             }
308             if (height <= 0) {
309                 throw new IllegalArgumentException("Virtual display height must be positive");
310             }
311             if (densityDpi <= 0) {
312                 throw new IllegalArgumentException("Virtual display density must be positive");
313             }
314             mName = name;
315             mWidth = width;
316             mHeight = height;
317             mDensityDpi = densityDpi;
318         }
319 
320         /**
321          * Sets the virtual display flags, a combination of
322          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PUBLIC},
323          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_PRESENTATION},
324          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_SECURE},
325          * {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY},
326          * or {@link DisplayManager#VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}.
327          */
328         @NonNull
setFlags(@irtualDisplayFlag int flags)329         public Builder setFlags(@VirtualDisplayFlag int flags) {
330             mFlags = flags;
331             return this;
332         }
333 
334         /**
335          * Sets the surface to which the content of the virtual display should be rendered.
336          *
337          * <p>The surface can also be set after the display creation using
338          * {@link VirtualDisplay#setSurface(Surface)}.
339          */
340         @NonNull
setSurface(@ullable Surface surface)341         public Builder setSurface(@Nullable Surface surface) {
342             mSurface = surface;
343             return this;
344         }
345 
346         /**
347          * Sets the unique identifier for the display.
348          * @hide
349          */
350         @NonNull
setUniqueId(@ullable String uniqueId)351         public Builder setUniqueId(@Nullable String uniqueId) {
352             mUniqueId = uniqueId;
353             return this;
354         }
355 
356         /**
357          * Sets the id of the display that the virtual display should mirror.
358          * @hide
359          */
360         @NonNull
setDisplayIdToMirror(int displayIdToMirror)361         public Builder setDisplayIdToMirror(int displayIdToMirror) {
362             mDisplayIdToMirror = displayIdToMirror;
363             return this;
364         }
365 
366         /**
367          * Sets whether WindowManager is responsible for mirroring content to this VirtualDisplay.
368          * If unset or false, DisplayManager should record contents instead.
369          * @hide
370          */
371         @NonNull
setWindowManagerMirroringEnabled(boolean windowManagerMirroringEnabled)372         public Builder setWindowManagerMirroringEnabled(boolean windowManagerMirroringEnabled) {
373             mWindowManagerMirroringEnabled = windowManagerMirroringEnabled;
374             return this;
375         }
376 
377         /**
378          * Sets the display categories.
379          *
380          * <p>The categories of the display indicate the type of activities allowed to run on that
381          * display. Activities can declare a display category using
382          * {@link android.content.pm.ActivityInfo#requiredDisplayCategory}.
383          */
384         @NonNull
setDisplayCategories(@onNull Set<String> displayCategories)385         public Builder setDisplayCategories(@NonNull Set<String> displayCategories) {
386             mDisplayCategories.clear();
387             mDisplayCategories.addAll(Objects.requireNonNull(displayCategories));
388             return this;
389         }
390 
391         /**
392          * Adds a display category.
393          *
394          * @see #setDisplayCategories
395          */
396         @NonNull
addDisplayCategory(@onNull String displayCategory)397         public Builder addDisplayCategory(@NonNull String displayCategory) {
398             mDisplayCategories.add(Objects.requireNonNull(displayCategory));
399             return this;
400         }
401 
402         /**
403          * Sets the refresh rate of a virtual display in frames per second.
404          *
405          * <p>For best results, specify a divisor of the physical refresh rate, e.g., 30 or 60 on
406          * a 120hz display. If an arbitrary refresh rate is specified, the rate will be rounded up
407          * to a divisor of the physical display. If unset or zero, the virtual display will be
408          * refreshed at the physical display refresh rate.
409          *
410          * @see Display#getRefreshRate()
411          */
412         @NonNull
setRequestedRefreshRate( @loatRangefrom = 0.0f) float requestedRefreshRate)413         public Builder setRequestedRefreshRate(
414                 @FloatRange(from = 0.0f) float requestedRefreshRate) {
415             if (requestedRefreshRate < 0.0f) {
416                 throw new IllegalArgumentException(
417                         "Virtual display requested refresh rate must be non-negative");
418             }
419             mRequestedRefreshRate = requestedRefreshRate;
420             return this;
421         }
422 
423         /**
424          * Builds the {@link VirtualDisplayConfig} instance.
425          */
426         @NonNull
build()427         public VirtualDisplayConfig build() {
428             return new VirtualDisplayConfig(
429                     mName,
430                     mWidth,
431                     mHeight,
432                     mDensityDpi,
433                     mFlags,
434                     mSurface,
435                     mUniqueId,
436                     mDisplayIdToMirror,
437                     mWindowManagerMirroringEnabled,
438                     mDisplayCategories,
439                     mRequestedRefreshRate);
440         }
441     }
442 }
443