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