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