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