• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.android.internal;
2 
3 import static android.os.Build.VERSION_CODES.LOLLIPOP_MR1;
4 import static android.os.Build.VERSION_CODES.M;
5 import static android.os.Build.VERSION_CODES.N;
6 import static android.os.Build.VERSION_CODES.N_MR1;
7 import static android.os.Build.VERSION_CODES.O;
8 import static android.os.Build.VERSION_CODES.Q;
9 import static android.os.Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
10 
11 import android.view.Display;
12 import android.view.DisplayCutout;
13 import android.view.DisplayInfo;
14 import android.view.Surface;
15 import java.util.Arrays;
16 import java.util.Objects;
17 import org.robolectric.RuntimeEnvironment;
18 
19 /**
20  * Describes the characteristics of a particular logical display.
21  *
22  * <p>Robolectric internal (for now), do not use.
23  */
24 public final class DisplayConfig {
25   /** The surface flinger layer stack associated with this logical display. */
26   public int layerStack;
27 
28   /** Display flags. */
29   public int flags;
30 
31   /** Display type. */
32   public int type;
33 
34   /** Display address, or null if none. Interpretation varies by display type. */
35   // public String address;
36 
37   /** The human-readable name of the display. */
38   public String name;
39 
40   /** Unique identifier for the display. Shouldn't be displayed to the user. */
41   public String uniqueId;
42 
43   /**
44    * The width of the portion of the display that is available to applications, in pixels.
45    * Represents the size of the display minus any system decorations.
46    */
47   public int appWidth;
48 
49   /**
50    * The height of the portion of the display that is available to applications, in pixels.
51    * Represents the size of the display minus any system decorations.
52    */
53   public int appHeight;
54 
55   /**
56    * The smallest value of {@link #appWidth} that an application is likely to encounter, in pixels,
57    * excepting cases where the width may be even smaller due to the presence of a soft keyboard, for
58    * example.
59    */
60   public int smallestNominalAppWidth;
61 
62   /**
63    * The smallest value of {@link #appHeight} that an application is likely to encounter, in pixels,
64    * excepting cases where the height may be even smaller due to the presence of a soft keyboard,
65    * for example.
66    */
67   public int smallestNominalAppHeight;
68 
69   /**
70    * The largest value of {@link #appWidth} that an application is likely to encounter, in pixels,
71    * excepting cases where the width may be even larger due to system decorations such as the status
72    * bar being hidden, for example.
73    */
74   public int largestNominalAppWidth;
75 
76   /**
77    * The largest value of {@link #appHeight} that an application is likely to encounter, in pixels,
78    * excepting cases where the height may be even larger due to system decorations such as the
79    * status bar being hidden, for example.
80    */
81   public int largestNominalAppHeight;
82 
83   /**
84    * The logical width of the display, in pixels. Represents the usable size of the display which
85    * may be smaller than the physical size when the system is emulating a smaller display.
86    */
87   public int logicalWidth;
88 
89   /**
90    * The logical height of the display, in pixels. Represents the usable size of the display which
91    * may be smaller than the physical size when the system is emulating a smaller display.
92    */
93   public int logicalHeight;
94 
95   /**
96    * The rotation of the display relative to its natural orientation. May be one of {@link
97    * Surface#ROTATION_0}, {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180}, {@link
98    * Surface#ROTATION_270}.
99    *
100    * <p>The value of this field is indeterminate if the logical display is presented on more than
101    * one physical display.
102    */
103   @Surface.Rotation public int rotation;
104 
105   /** The active display mode. */
106   public int modeId;
107 
108   /** The default display mode. */
109   public int defaultModeId;
110 
111   /** The supported modes of this display. */
112   public Display.Mode[] supportedModes = new Display.Mode[0];
113 
114   /** The active color mode. */
115   public int colorMode;
116 
117   /** The list of supported color modes */
118   public int[] supportedColorModes = {Display.COLOR_MODE_DEFAULT};
119 
120   /** The display's HDR capabilities */
121   public Display.HdrCapabilities hdrCapabilities;
122 
123   /**
124    * The current hdr/sdr ratio expressed as the ratio of targetHdrPeakBrightnessInNits /
125    * targetSdrWhitePointInNits. A setting of {@code NaN} corresponds to {@link
126    * Display#isHdrSdrRatioAvailable} as false.
127    */
128   public float hdrSdrRatio = Float.NaN;
129 
130   /** The logical display density which is the basis for density-independent pixels. */
131   public int logicalDensityDpi;
132 
133   /**
134    * The exact physical pixels per inch of the screen in the X dimension.
135    *
136    * <p>The value of this field is indeterminate if the logical display is presented on more than
137    * one physical display.
138    */
139   public float physicalXDpi;
140 
141   /**
142    * The exact physical pixels per inch of the screen in the Y dimension.
143    *
144    * <p>The value of this field is indeterminate if the logical display is presented on more than
145    * one physical display.
146    */
147   public float physicalYDpi;
148 
149   /**
150    * This is a positive value indicating the phase offset of the VSYNC events provided by
151    * Choreographer relative to the display refresh. For example, if Choreographer reports that the
152    * refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
153    */
154   public long appVsyncOffsetNanos;
155 
156   /**
157    * This is how far in advance a buffer must be queued for presentation at a given time. If you
158    * want a buffer to appear on the screen at time N, you must submit the buffer before (N -
159    * bufferDeadlineNanos).
160    */
161   public long presentationDeadlineNanos;
162 
163   /** The state of the display, such as {@link Display#STATE_ON}. */
164   public int state;
165 
166   /**
167    * The UID of the application that owns this display, or zero if it is owned by the system.
168    *
169    * <p>If the display is private, then only the owner can use it.
170    */
171   public int ownerUid;
172 
173   /**
174    * The package name of the application that owns this display, or null if it is owned by the
175    * system.
176    *
177    * <p>If the display is private, then only the owner can use it.
178    */
179   public String ownerPackageName;
180 
181   /**
182    * @hide Get current remove mode of the display - what actions should be performed with the
183    *     display's content when it is removed.
184    * @see Display#getRemoveMode()
185    */
186   public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
187 
188   /** The area of the display that is not functional for displaying content */
189   public Object displayCutout;
190 
DisplayConfig()191   public DisplayConfig() {}
192 
DisplayConfig(DisplayConfig other)193   public DisplayConfig(DisplayConfig other) {
194     copyFrom(other);
195   }
196 
DisplayConfig(DisplayInfo other)197   public DisplayConfig(DisplayInfo other) {
198     layerStack = other.layerStack;
199     flags = other.flags;
200     type = other.type;
201     // address = other.address;
202     name = other.name;
203     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
204       uniqueId = other.uniqueId;
205     }
206     appWidth = other.appWidth;
207     appHeight = other.appHeight;
208     smallestNominalAppWidth = other.smallestNominalAppWidth;
209     smallestNominalAppHeight = other.smallestNominalAppHeight;
210     largestNominalAppWidth = other.largestNominalAppWidth;
211     largestNominalAppHeight = other.largestNominalAppHeight;
212     logicalWidth = other.logicalWidth;
213     logicalHeight = other.logicalHeight;
214     rotation = other.rotation;
215     if (RuntimeEnvironment.getApiLevel() >= M) {
216       modeId = other.modeId;
217       defaultModeId = other.defaultModeId;
218       supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
219     }
220     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
221       colorMode = other.colorMode;
222       supportedColorModes =
223           Arrays.copyOf(other.supportedColorModes, other.supportedColorModes.length);
224     }
225     if (RuntimeEnvironment.getApiLevel() >= N) {
226       hdrCapabilities = other.hdrCapabilities;
227     }
228     if (RuntimeEnvironment.getApiLevel() >= UPSIDE_DOWN_CAKE) {
229       hdrSdrRatio = other.hdrSdrRatio;
230     }
231     logicalDensityDpi = other.logicalDensityDpi;
232     physicalXDpi = other.physicalXDpi;
233     physicalYDpi = other.physicalYDpi;
234     appVsyncOffsetNanos = other.appVsyncOffsetNanos;
235     presentationDeadlineNanos = other.presentationDeadlineNanos;
236     state = other.state;
237     ownerUid = other.ownerUid;
238     ownerPackageName = other.ownerPackageName;
239     if (RuntimeEnvironment.getApiLevel() >= O) {
240       removeMode = other.removeMode;
241     }
242     if (RuntimeEnvironment.getApiLevel() >= Q) {
243       displayCutout = other.displayCutout;
244     }
245   }
246 
247   @Override
equals(Object o)248   public boolean equals(Object o) {
249     return o instanceof DisplayConfig && equals((DisplayConfig) o);
250   }
251 
252   @SuppressWarnings("NonOverridingEquals")
equals(DisplayConfig other)253   public boolean equals(DisplayConfig other) {
254     return other != null
255         && layerStack == other.layerStack
256         && flags == other.flags
257         && type == other.type
258         // && Objects.equals(address, other.address)
259         && Objects.equals(uniqueId, other.uniqueId)
260         && appWidth == other.appWidth
261         && appHeight == other.appHeight
262         && smallestNominalAppWidth == other.smallestNominalAppWidth
263         && smallestNominalAppHeight == other.smallestNominalAppHeight
264         && largestNominalAppWidth == other.largestNominalAppWidth
265         && largestNominalAppHeight == other.largestNominalAppHeight
266         && logicalWidth == other.logicalWidth
267         && logicalHeight == other.logicalHeight
268         && rotation == other.rotation
269         && modeId == other.modeId
270         && defaultModeId == other.defaultModeId
271         && colorMode == other.colorMode
272         && Arrays.equals(supportedColorModes, other.supportedColorModes)
273         && Objects.equals(hdrCapabilities, other.hdrCapabilities)
274         && logicalDensityDpi == other.logicalDensityDpi
275         && physicalXDpi == other.physicalXDpi
276         && physicalYDpi == other.physicalYDpi
277         && appVsyncOffsetNanos == other.appVsyncOffsetNanos
278         && presentationDeadlineNanos == other.presentationDeadlineNanos
279         && state == other.state
280         && ownerUid == other.ownerUid
281         && Objects.equals(ownerPackageName, other.ownerPackageName)
282         && removeMode == other.removeMode
283         && Objects.equals(displayCutout, other.displayCutout)
284         && hdrSdrRatio == other.hdrSdrRatio;
285   }
286 
287   @Override
hashCode()288   public int hashCode() {
289     return 0; // don't care
290   }
291 
copyFrom(DisplayConfig other)292   public void copyFrom(DisplayConfig other) {
293     layerStack = other.layerStack;
294     flags = other.flags;
295     type = other.type;
296     // address = other.address;
297     name = other.name;
298     uniqueId = other.uniqueId;
299     appWidth = other.appWidth;
300     appHeight = other.appHeight;
301     smallestNominalAppWidth = other.smallestNominalAppWidth;
302     smallestNominalAppHeight = other.smallestNominalAppHeight;
303     largestNominalAppWidth = other.largestNominalAppWidth;
304     largestNominalAppHeight = other.largestNominalAppHeight;
305     logicalWidth = other.logicalWidth;
306     logicalHeight = other.logicalHeight;
307     rotation = other.rotation;
308     modeId = other.modeId;
309     defaultModeId = other.defaultModeId;
310     supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
311     colorMode = other.colorMode;
312     supportedColorModes =
313         Arrays.copyOf(other.supportedColorModes, other.supportedColorModes.length);
314     hdrCapabilities = other.hdrCapabilities;
315     hdrSdrRatio = other.hdrSdrRatio;
316     logicalDensityDpi = other.logicalDensityDpi;
317     physicalXDpi = other.physicalXDpi;
318     physicalYDpi = other.physicalYDpi;
319     appVsyncOffsetNanos = other.appVsyncOffsetNanos;
320     presentationDeadlineNanos = other.presentationDeadlineNanos;
321     state = other.state;
322     ownerUid = other.ownerUid;
323     ownerPackageName = other.ownerPackageName;
324     removeMode = other.removeMode;
325     displayCutout = other.displayCutout;
326   }
327 
copyTo(DisplayInfo other)328   public void copyTo(DisplayInfo other) {
329     other.layerStack = layerStack;
330     other.flags = flags;
331     other.type = type;
332     // other.address = address;
333     other.name = name;
334     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
335       other.uniqueId = uniqueId;
336     }
337     other.appWidth = appWidth;
338     other.appHeight = appHeight;
339     other.smallestNominalAppWidth = smallestNominalAppWidth;
340     other.smallestNominalAppHeight = smallestNominalAppHeight;
341     other.largestNominalAppWidth = largestNominalAppWidth;
342     other.largestNominalAppHeight = largestNominalAppHeight;
343     other.logicalWidth = logicalWidth;
344     other.logicalHeight = logicalHeight;
345     other.rotation = rotation;
346     if (RuntimeEnvironment.getApiLevel() >= M) {
347       other.modeId = modeId;
348       other.defaultModeId = defaultModeId;
349       other.supportedModes = Arrays.copyOf(supportedModes, supportedModes.length);
350     }
351     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
352       other.colorMode = colorMode;
353       other.supportedColorModes = Arrays.copyOf(supportedColorModes, supportedColorModes.length);
354     }
355     if (RuntimeEnvironment.getApiLevel() >= N) {
356       other.hdrCapabilities = hdrCapabilities;
357     }
358     if (RuntimeEnvironment.getApiLevel() >= UPSIDE_DOWN_CAKE) {
359       other.hdrSdrRatio = hdrSdrRatio;
360     }
361     other.logicalDensityDpi = logicalDensityDpi;
362     other.physicalXDpi = physicalXDpi;
363     other.physicalYDpi = physicalYDpi;
364     other.appVsyncOffsetNanos = appVsyncOffsetNanos;
365     other.presentationDeadlineNanos = presentationDeadlineNanos;
366     other.state = state;
367     other.ownerUid = ownerUid;
368     other.ownerPackageName = ownerPackageName;
369     if (RuntimeEnvironment.getApiLevel() >= O) {
370       other.removeMode = removeMode;
371     }
372     if (RuntimeEnvironment.getApiLevel() >= Q) {
373       other.displayCutout = (DisplayCutout) displayCutout;
374     }
375   }
376 
377   // For debugging purposes
378   @Override
toString()379   public String toString() {
380     StringBuilder sb = new StringBuilder();
381     sb.append("DisplayConfig{\"");
382     sb.append(name);
383     sb.append("\", uniqueId \"");
384     sb.append(uniqueId);
385     sb.append("\", app ");
386     sb.append(appWidth);
387     sb.append(" x ");
388     sb.append(appHeight);
389     sb.append(", real ");
390     sb.append(logicalWidth);
391     sb.append(" x ");
392     sb.append(logicalHeight);
393     sb.append(", largest app ");
394     sb.append(largestNominalAppWidth);
395     sb.append(" x ");
396     sb.append(largestNominalAppHeight);
397     sb.append(", smallest app ");
398     sb.append(smallestNominalAppWidth);
399     sb.append(" x ");
400     sb.append(smallestNominalAppHeight);
401     sb.append(", mode ");
402     sb.append(modeId);
403     sb.append(", defaultMode ");
404     sb.append(defaultModeId);
405     sb.append(", modes ");
406     sb.append(Arrays.toString(supportedModes));
407     sb.append(", colorMode ");
408     sb.append(colorMode);
409     sb.append(", supportedColorModes ");
410     sb.append(Arrays.toString(supportedColorModes));
411     sb.append(", hdrCapabilities ");
412     sb.append(hdrCapabilities);
413     sb.append(", hdrSdrRatio ");
414     sb.append(hdrSdrRatio);
415     sb.append(", rotation ");
416     sb.append(rotation);
417     sb.append(", density ");
418     sb.append(logicalDensityDpi);
419     sb.append(" (");
420     sb.append(physicalXDpi);
421     sb.append(" x ");
422     sb.append(physicalYDpi);
423     sb.append(") dpi, layerStack ");
424     sb.append(layerStack);
425     sb.append(", appVsyncOff ");
426     sb.append(appVsyncOffsetNanos);
427     sb.append(", presDeadline ");
428     sb.append(presentationDeadlineNanos);
429     sb.append(", type ");
430     sb.append(Display.typeToString(type));
431     // if (address != null) {
432     //   sb.append(", address ").append(address);
433     // }
434     sb.append(", state ");
435     sb.append(Display.stateToString(state));
436     if (ownerUid != 0 || ownerPackageName != null) {
437       sb.append(", owner ").append(ownerPackageName);
438       sb.append(" (uid ").append(ownerUid).append(")");
439     }
440     sb.append(flagsToString(flags));
441     sb.append(", removeMode ");
442     sb.append(removeMode);
443     sb.append(", displayCutout ");
444     sb.append(displayCutout);
445     sb.append("}");
446     return sb.toString();
447   }
448 
flagsToString(int flags)449   private static String flagsToString(int flags) {
450     StringBuilder result = new StringBuilder();
451     if ((flags & Display.FLAG_SECURE) != 0) {
452       result.append(", FLAG_SECURE");
453     }
454     if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
455       result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
456     }
457     if ((flags & Display.FLAG_PRIVATE) != 0) {
458       result.append(", FLAG_PRIVATE");
459     }
460     if ((flags & Display.FLAG_PRESENTATION) != 0) {
461       result.append(", FLAG_PRESENTATION");
462     }
463     if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
464       result.append(", FLAG_SCALING_DISABLED");
465     }
466     if ((flags & Display.FLAG_ROUND) != 0) {
467       result.append(", FLAG_ROUND");
468     }
469     return result.toString();
470   }
471 }
472