• 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    * The rotation of the display relative to its natural orientation.
130    * May be one of {@link Surface#ROTATION_0},
131    * {@link Surface#ROTATION_90}, {@link Surface#ROTATION_180},
132    * {@link Surface#ROTATION_270}.
133    * <p>
134    * The value of this field is indeterminate if the logical display is presented on
135    * more than one physical display.
136    * </p>
137    */
138   @Surface.Rotation
139   public int rotation;
140 
141   /**
142    * The active display mode.
143    */
144   public int modeId;
145 
146   /**
147    * The default display mode.
148    */
149   public int defaultModeId;
150 
151   /**
152    * The supported modes of this display.
153    */
154   public Display.Mode[] supportedModes = new Display.Mode[0];
155 
156   /** The active color mode. */
157   public int colorMode;
158 
159   /** The list of supported color modes */
160   public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
161 
162   /** The display's HDR capabilities */
163   public Display.HdrCapabilities hdrCapabilities;
164 
165   /**
166    * The logical display density which is the basis for density-independent
167    * pixels.
168    */
169   public int logicalDensityDpi;
170 
171   /**
172    * The exact physical pixels per inch of the screen in the X dimension.
173    * <p>
174    * The value of this field is indeterminate if the logical display is presented on
175    * more than one physical display.
176    * </p>
177    */
178   public float physicalXDpi;
179 
180   /**
181    * The exact physical pixels per inch of the screen in the Y dimension.
182    * <p>
183    * The value of this field is indeterminate if the logical display is presented on
184    * more than one physical display.
185    * </p>
186    */
187   public float physicalYDpi;
188 
189   /**
190    * This is a positive value indicating the phase offset of the VSYNC events provided by
191    * Choreographer relative to the display refresh.  For example, if Choreographer reports
192    * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
193    */
194   public long appVsyncOffsetNanos;
195 
196   /**
197    * This is how far in advance a buffer must be queued for presentation at
198    * a given time.  If you want a buffer to appear on the screen at
199    * time N, you must submit the buffer before (N - bufferDeadlineNanos).
200    */
201   public long presentationDeadlineNanos;
202 
203   /**
204    * The state of the display, such as {@link Display#STATE_ON}.
205    */
206   public int state;
207 
208   /**
209    * The UID of the application that owns this display, or zero if it is owned by the system.
210    * <p>
211    * If the display is private, then only the owner can use it.
212    * </p>
213    */
214   public int ownerUid;
215 
216   /**
217    * The package name of the application that owns this display, or null if it is
218    * owned by the system.
219    * <p>
220    * If the display is private, then only the owner can use it.
221    * </p>
222    */
223   public String ownerPackageName;
224 
225   /**
226    * @hide
227    * Get current remove mode of the display - what actions should be performed with the display's
228    * content when it is removed.
229    *
230    * @see Display#getRemoveMode()
231    */
232   public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
233 
DisplayConfig()234   public DisplayConfig() {
235   }
236 
DisplayConfig(DisplayConfig other)237   public DisplayConfig(DisplayConfig other) {
238     copyFrom(other);
239   }
240 
DisplayConfig(DisplayInfo other)241   public DisplayConfig(DisplayInfo other) {
242     layerStack = other.layerStack;
243     flags = other.flags;
244     type = other.type;
245     if (RuntimeEnvironment.getApiLevel() >= Q) {
246       address = other.address;
247     }
248     name = other.name;
249     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
250       uniqueId = other.uniqueId;
251     }
252     appWidth = other.appWidth;
253     appHeight = other.appHeight;
254     smallestNominalAppWidth = other.smallestNominalAppWidth;
255     smallestNominalAppHeight = other.smallestNominalAppHeight;
256     largestNominalAppWidth = other.largestNominalAppWidth;
257     largestNominalAppHeight = other.largestNominalAppHeight;
258     logicalWidth = other.logicalWidth;
259     logicalHeight = other.logicalHeight;
260     rotation = other.rotation;
261     if (RuntimeEnvironment.getApiLevel() >= M) {
262       modeId = other.modeId;
263       defaultModeId = other.defaultModeId;
264       supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
265     }
266     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
267       colorMode = other.colorMode;
268       supportedColorModes = Arrays.copyOf(
269           other.supportedColorModes, other.supportedColorModes.length);
270     }
271     if (RuntimeEnvironment.getApiLevel() >= N) {
272       hdrCapabilities = other.hdrCapabilities;
273     }
274     logicalDensityDpi = other.logicalDensityDpi;
275     physicalXDpi = other.physicalXDpi;
276     physicalYDpi = other.physicalYDpi;
277     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) {
278       appVsyncOffsetNanos = other.appVsyncOffsetNanos;
279       presentationDeadlineNanos = other.presentationDeadlineNanos;
280       state = other.state;
281     }
282     if (RuntimeEnvironment.getApiLevel() >= KITKAT) {
283       ownerUid = other.ownerUid;
284       ownerPackageName = other.ownerPackageName;
285     }
286     if (RuntimeEnvironment.getApiLevel() >= O) {
287       removeMode = other.removeMode;
288     }
289   }
290 
291   @Override
equals(Object o)292   public boolean equals(Object o) {
293     return o instanceof DisplayConfig && equals((DisplayConfig)o);
294   }
295 
296   @SuppressWarnings("NonOverridingEquals")
equals(DisplayConfig other)297   public boolean equals(DisplayConfig other) {
298     return other != null
299         && layerStack == other.layerStack
300         && flags == other.flags
301         && type == other.type
302         && Objects.equals(address, other.address)
303         && Objects.equals(uniqueId, other.uniqueId)
304         && appWidth == other.appWidth
305         && appHeight == other.appHeight
306         && smallestNominalAppWidth == other.smallestNominalAppWidth
307         && smallestNominalAppHeight == other.smallestNominalAppHeight
308         && largestNominalAppWidth == other.largestNominalAppWidth
309         && largestNominalAppHeight == other.largestNominalAppHeight
310         && logicalWidth == other.logicalWidth
311         && logicalHeight == other.logicalHeight
312         && rotation == other.rotation
313         && modeId == other.modeId
314         && defaultModeId == other.defaultModeId
315         && colorMode == other.colorMode
316         && Arrays.equals(supportedColorModes, other.supportedColorModes)
317         && Objects.equals(hdrCapabilities, other.hdrCapabilities)
318         && logicalDensityDpi == other.logicalDensityDpi
319         && physicalXDpi == other.physicalXDpi
320         && physicalYDpi == other.physicalYDpi
321         && appVsyncOffsetNanos == other.appVsyncOffsetNanos
322         && presentationDeadlineNanos == other.presentationDeadlineNanos
323         && state == other.state
324         && ownerUid == other.ownerUid
325         && Objects.equals(ownerPackageName, other.ownerPackageName)
326         && removeMode == other.removeMode;
327   }
328 
329   @Override
hashCode()330   public int hashCode() {
331     return 0; // don't care
332   }
333 
copyFrom(DisplayConfig other)334   public void copyFrom(DisplayConfig other) {
335     layerStack = other.layerStack;
336     flags = other.flags;
337     type = other.type;
338     address = other.address;
339     name = other.name;
340     uniqueId = other.uniqueId;
341     appWidth = other.appWidth;
342     appHeight = other.appHeight;
343     smallestNominalAppWidth = other.smallestNominalAppWidth;
344     smallestNominalAppHeight = other.smallestNominalAppHeight;
345     largestNominalAppWidth = other.largestNominalAppWidth;
346     largestNominalAppHeight = other.largestNominalAppHeight;
347     logicalWidth = other.logicalWidth;
348     logicalHeight = other.logicalHeight;
349     rotation = other.rotation;
350     modeId = other.modeId;
351     defaultModeId = other.defaultModeId;
352     supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
353     colorMode = other.colorMode;
354     supportedColorModes = Arrays.copyOf(
355         other.supportedColorModes, other.supportedColorModes.length);
356     hdrCapabilities = other.hdrCapabilities;
357     logicalDensityDpi = other.logicalDensityDpi;
358     physicalXDpi = other.physicalXDpi;
359     physicalYDpi = other.physicalYDpi;
360     appVsyncOffsetNanos = other.appVsyncOffsetNanos;
361     presentationDeadlineNanos = other.presentationDeadlineNanos;
362     state = other.state;
363     ownerUid = other.ownerUid;
364     ownerPackageName = other.ownerPackageName;
365     removeMode = other.removeMode;
366   }
367 
copyTo(DisplayInfo other)368   public void copyTo(DisplayInfo other) {
369     other.layerStack = layerStack;
370     other.flags = flags;
371     other.type = type;
372     if (RuntimeEnvironment.getApiLevel() >= Q) {
373       other.address = address;
374     }
375     other.name = name;
376     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP_MR1) {
377       other.uniqueId = uniqueId;
378     }
379     other.appWidth = appWidth;
380     other.appHeight = appHeight;
381     other.smallestNominalAppWidth = smallestNominalAppWidth;
382     other.smallestNominalAppHeight = smallestNominalAppHeight;
383     other.largestNominalAppWidth = largestNominalAppWidth;
384     other.largestNominalAppHeight = largestNominalAppHeight;
385     other.logicalWidth = logicalWidth;
386     other.logicalHeight = logicalHeight;
387     other.rotation = rotation;
388     if (RuntimeEnvironment.getApiLevel() >= M) {
389       other.modeId = modeId;
390       other.defaultModeId = defaultModeId;
391       other.supportedModes = Arrays.copyOf(supportedModes, supportedModes.length);
392     }
393     if (RuntimeEnvironment.getApiLevel() >= N_MR1) {
394       other.colorMode = colorMode;
395       other.supportedColorModes = Arrays.copyOf(
396           supportedColorModes, supportedColorModes.length);
397     }
398     if (RuntimeEnvironment.getApiLevel() >= N) {
399       other.hdrCapabilities = hdrCapabilities;
400     }
401     other.logicalDensityDpi = logicalDensityDpi;
402     other.physicalXDpi = physicalXDpi;
403     other.physicalYDpi = physicalYDpi;
404     if (RuntimeEnvironment.getApiLevel() >= LOLLIPOP) {
405       other.appVsyncOffsetNanos = appVsyncOffsetNanos;
406       other.presentationDeadlineNanos = presentationDeadlineNanos;
407       other.state = state;
408     }
409     if (RuntimeEnvironment.getApiLevel() >= KITKAT) {
410       other.ownerUid = ownerUid;
411       other.ownerPackageName = ownerPackageName;
412     }
413     if (RuntimeEnvironment.getApiLevel() >= O) {
414       other.removeMode = removeMode;
415     }
416   }
417 
418   // For debugging purposes
419   @Override
toString()420   public String toString() {
421     StringBuilder sb = new StringBuilder();
422     sb.append("DisplayConfig{\"");
423     sb.append(name);
424     sb.append("\", uniqueId \"");
425     sb.append(uniqueId);
426     sb.append("\", app ");
427     sb.append(appWidth);
428     sb.append(" x ");
429     sb.append(appHeight);
430     sb.append(", real ");
431     sb.append(logicalWidth);
432     sb.append(" x ");
433     sb.append(logicalHeight);
434     sb.append(", largest app ");
435     sb.append(largestNominalAppWidth);
436     sb.append(" x ");
437     sb.append(largestNominalAppHeight);
438     sb.append(", smallest app ");
439     sb.append(smallestNominalAppWidth);
440     sb.append(" x ");
441     sb.append(smallestNominalAppHeight);
442     sb.append(", mode ");
443     sb.append(modeId);
444     sb.append(", defaultMode ");
445     sb.append(defaultModeId);
446     sb.append(", modes ");
447     sb.append(Arrays.toString(supportedModes));
448     sb.append(", colorMode ");
449     sb.append(colorMode);
450     sb.append(", supportedColorModes ");
451     sb.append(Arrays.toString(supportedColorModes));
452     sb.append(", hdrCapabilities ");
453     sb.append(hdrCapabilities);
454     sb.append(", rotation ");
455     sb.append(rotation);
456     sb.append(", density ");
457     sb.append(logicalDensityDpi);
458     sb.append(" (");
459     sb.append(physicalXDpi);
460     sb.append(" x ");
461     sb.append(physicalYDpi);
462     sb.append(") dpi, layerStack ");
463     sb.append(layerStack);
464     sb.append(", appVsyncOff ");
465     sb.append(appVsyncOffsetNanos);
466     sb.append(", presDeadline ");
467     sb.append(presentationDeadlineNanos);
468     sb.append(", type ");
469     sb.append(Display.typeToString(type));
470     if (address != null) {
471       sb.append(", address ").append(address);
472     }
473     sb.append(", state ");
474     sb.append(Display.stateToString(state));
475     if (ownerUid != 0 || ownerPackageName != null) {
476       sb.append(", owner ").append(ownerPackageName);
477       sb.append(" (uid ").append(ownerUid).append(")");
478     }
479     sb.append(flagsToString(flags));
480     sb.append(", removeMode ");
481     sb.append(removeMode);
482     sb.append("}");
483     return sb.toString();
484   }
485 
flagsToString(int flags)486   private static String flagsToString(int flags) {
487     StringBuilder result = new StringBuilder();
488     if ((flags & Display.FLAG_SECURE) != 0) {
489       result.append(", FLAG_SECURE");
490     }
491     if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
492       result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
493     }
494     if ((flags & Display.FLAG_PRIVATE) != 0) {
495       result.append(", FLAG_PRIVATE");
496     }
497     if ((flags & Display.FLAG_PRESENTATION) != 0) {
498       result.append(", FLAG_PRESENTATION");
499     }
500     if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
501       result.append(", FLAG_SCALING_DISABLED");
502     }
503     if ((flags & Display.FLAG_ROUND) != 0) {
504       result.append(", FLAG_ROUND");
505     }
506     return result.toString();
507   }
508 }
509