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 com.android.server.display;
18 
19 import android.hardware.display.DisplayViewport;
20 import android.util.DisplayMetrics;
21 import android.view.Display;
22 import android.view.Surface;
23 
24 import java.util.Arrays;
25 
26 import libcore.util.Objects;
27 
28 /**
29  * Describes the characteristics of a physical display device.
30  */
31 final class DisplayDeviceInfo {
32     /**
33      * Flag: Indicates that this display device should be considered the default display
34      * device of the system.
35      */
36     public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
37 
38     /**
39      * Flag: Indicates that the orientation of this display device is coupled to the
40      * rotation of its associated logical display.
41      * <p>
42      * This flag should be applied to the default display to indicate that the user
43      * physically rotates the display when content is presented in a different orientation.
44      * The display manager will apply a coordinate transformation assuming that the
45      * physical orientation of the display matches the logical orientation of its content.
46      * </p><p>
47      * The flag should not be set when the display device is mounted in a fixed orientation
48      * such as on a desk.  The display manager will apply a coordinate transformation
49      * such as a scale and translation to letterbox or pillarbox format under the
50      * assumption that the physical orientation of the display is invariant.
51      * </p>
52      */
53     public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1;
54 
55     /**
56      * Flag: Indicates that this display device has secure video output, such as HDCP.
57      */
58     public static final int FLAG_SECURE = 1 << 2;
59 
60     /**
61      * Flag: Indicates that this display device supports compositing
62      * from gralloc protected buffers.
63      */
64     public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3;
65 
66     /**
67      * Flag: Indicates that the display device is owned by a particular application
68      * and that no other application should be able to interact with it.
69      * Should typically be used together with {@link #FLAG_OWN_CONTENT_ONLY}.
70      */
71     public static final int FLAG_PRIVATE = 1 << 4;
72 
73     /**
74      * Flag: Indicates that the display device is not blanked automatically by
75      * the power manager.
76      */
77     public static final int FLAG_NEVER_BLANK = 1 << 5;
78 
79     /**
80      * Flag: Indicates that the display is suitable for presentations.
81      */
82     public static final int FLAG_PRESENTATION = 1 << 6;
83 
84     /**
85      * Flag: Only show this display's own content; do not mirror
86      * the content of another display.
87      */
88     public static final int FLAG_OWN_CONTENT_ONLY = 1 << 7;
89 
90     /**
91      * Flag: This display device has a round shape.
92      */
93     public static final int FLAG_ROUND = 1 << 8;
94 
95     /**
96      * Touch attachment: Display does not receive touch.
97      */
98     public static final int TOUCH_NONE = 0;
99 
100     /**
101      * Touch attachment: Touch input is via the internal interface.
102      */
103     public static final int TOUCH_INTERNAL = 1;
104 
105     /**
106      * Touch attachment: Touch input is via an external interface, such as USB.
107      */
108     public static final int TOUCH_EXTERNAL = 2;
109 
110     /**
111      * Diff result: The {@link #state} fields differ.
112      */
113     public static final int DIFF_STATE = 1 << 0;
114 
115     /**
116      * Diff result: Other fields differ.
117      */
118     public static final int DIFF_OTHER = 1 << 1;
119 
120     /**
121      * Gets the name of the display device, which may be derived from EDID or
122      * other sources. The name may be localized and displayed to the user.
123      */
124     public String name;
125 
126     /**
127      * Unique Id of display device.
128      */
129     public String uniqueId;
130 
131     /**
132      * The width of the display in its natural orientation, in pixels.
133      * This value is not affected by display rotation.
134      */
135     public int width;
136 
137     /**
138      * The height of the display in its natural orientation, in pixels.
139      * This value is not affected by display rotation.
140      */
141     public int height;
142 
143     /**
144      * The active mode of the display.
145      */
146     public int modeId;
147 
148     /**
149      * The default mode of the display.
150      */
151     public int defaultModeId;
152 
153     /**
154      * The supported modes of the display.
155      */
156     public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
157 
158     /** The active color transform of the display */
159     public int colorTransformId;
160 
161     /** The default color transform of the display */
162     public int defaultColorTransformId;
163 
164     /** The supported color transforms of the display */
165     public Display.ColorTransform[] supportedColorTransforms = Display.ColorTransform.EMPTY_ARRAY;
166 
167     /**
168      * The HDR capabilities this display claims to support.
169      */
170     public Display.HdrCapabilities hdrCapabilities;
171 
172     /**
173      * The nominal apparent density of the display in DPI used for layout calculations.
174      * This density is sensitive to the viewing distance.  A big TV and a tablet may have
175      * the same apparent density even though the pixels on the TV are much bigger than
176      * those on the tablet.
177      */
178     public int densityDpi;
179 
180     /**
181      * The physical density of the display in DPI in the X direction.
182      * This density should specify the physical size of each pixel.
183      */
184     public float xDpi;
185 
186     /**
187      * The physical density of the display in DPI in the X direction.
188      * This density should specify the physical size of each pixel.
189      */
190     public float yDpi;
191 
192     /**
193      * This is a positive value indicating the phase offset of the VSYNC events provided by
194      * Choreographer relative to the display refresh.  For example, if Choreographer reports
195      * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
196      */
197     public long appVsyncOffsetNanos;
198 
199     /**
200      * This is how far in advance a buffer must be queued for presentation at
201      * a given time.  If you want a buffer to appear on the screen at
202      * time N, you must submit the buffer before (N - bufferDeadlineNanos).
203      */
204     public long presentationDeadlineNanos;
205 
206     /**
207      * Display flags.
208      */
209     public int flags;
210 
211     /**
212      * The touch attachment, per {@link DisplayViewport#touch}.
213      */
214     public int touch;
215 
216     /**
217      * The additional rotation to apply to all content presented on the display device
218      * relative to its physical coordinate system.  Default is {@link Surface#ROTATION_0}.
219      * <p>
220      * This field can be used to compensate for the fact that the display has been
221      * physically rotated relative to its natural orientation such as an HDMI monitor
222      * that has been mounted sideways to appear to be portrait rather than landscape.
223      * </p>
224      */
225     public int rotation = Surface.ROTATION_0;
226 
227     /**
228      * Display type.
229      */
230     public int type;
231 
232     /**
233      * Display address, or null if none.
234      * Interpretation varies by display type.
235      */
236     public String address;
237 
238     /**
239      * Display state.
240      */
241     public int state = Display.STATE_ON;
242 
243     /**
244      * The UID of the application that owns this display, or zero if it is owned by the system.
245      * <p>
246      * If the display is private, then only the owner can use it.
247      * </p>
248      */
249     public int ownerUid;
250 
251     /**
252      * The package name of the application that owns this display, or null if it is
253      * owned by the system.
254      * <p>
255      * If the display is private, then only the owner can use it.
256      * </p>
257      */
258     public String ownerPackageName;
259 
setAssumedDensityForExternalDisplay(int width, int height)260     public void setAssumedDensityForExternalDisplay(int width, int height) {
261         densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
262         // Technically, these values should be smaller than the apparent density
263         // but we don't know the physical size of the display.
264         xDpi = densityDpi;
265         yDpi = densityDpi;
266     }
267 
268     @Override
equals(Object o)269     public boolean equals(Object o) {
270         return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o);
271     }
272 
equals(DisplayDeviceInfo other)273     public boolean equals(DisplayDeviceInfo other) {
274         return other != null && diff(other) == 0;
275     }
276 
277     /**
278      * Computes the difference between display device infos.
279      * Assumes other is not null.
280      */
diff(DisplayDeviceInfo other)281     public int diff(DisplayDeviceInfo other) {
282         int diff = 0;
283         if (state != other.state) {
284             diff |= DIFF_STATE;
285         }
286         if (!Objects.equal(name, other.name)
287                 || !Objects.equal(uniqueId, other.uniqueId)
288                 || width != other.width
289                 || height != other.height
290                 || modeId != other.modeId
291                 || defaultModeId != other.defaultModeId
292                 || !Arrays.equals(supportedModes, other.supportedModes)
293                 || colorTransformId != other.colorTransformId
294                 || defaultColorTransformId != other.defaultColorTransformId
295                 || !Arrays.equals(supportedColorTransforms, other.supportedColorTransforms)
296                 || !Objects.equal(hdrCapabilities, other.hdrCapabilities)
297                 || densityDpi != other.densityDpi
298                 || xDpi != other.xDpi
299                 || yDpi != other.yDpi
300                 || appVsyncOffsetNanos != other.appVsyncOffsetNanos
301                 || presentationDeadlineNanos != other.presentationDeadlineNanos
302                 || flags != other.flags
303                 || touch != other.touch
304                 || rotation != other.rotation
305                 || type != other.type
306                 || !Objects.equal(address, other.address)
307                 || ownerUid != other.ownerUid
308                 || !Objects.equal(ownerPackageName, other.ownerPackageName)) {
309             diff |= DIFF_OTHER;
310         }
311         return diff;
312     }
313 
314     @Override
hashCode()315     public int hashCode() {
316         return 0; // don't care
317     }
318 
copyFrom(DisplayDeviceInfo other)319     public void copyFrom(DisplayDeviceInfo other) {
320         name = other.name;
321         uniqueId = other.uniqueId;
322         width = other.width;
323         height = other.height;
324         modeId = other.modeId;
325         defaultModeId = other.defaultModeId;
326         supportedModes = other.supportedModes;
327         colorTransformId = other.colorTransformId;
328         defaultColorTransformId = other.defaultColorTransformId;
329         supportedColorTransforms = other.supportedColorTransforms;
330         hdrCapabilities = other.hdrCapabilities;
331         densityDpi = other.densityDpi;
332         xDpi = other.xDpi;
333         yDpi = other.yDpi;
334         appVsyncOffsetNanos = other.appVsyncOffsetNanos;
335         presentationDeadlineNanos = other.presentationDeadlineNanos;
336         flags = other.flags;
337         touch = other.touch;
338         rotation = other.rotation;
339         type = other.type;
340         address = other.address;
341         state = other.state;
342         ownerUid = other.ownerUid;
343         ownerPackageName = other.ownerPackageName;
344     }
345 
346     // For debugging purposes
347     @Override
toString()348     public String toString() {
349         StringBuilder sb = new StringBuilder();
350         sb.append("DisplayDeviceInfo{\"");
351         sb.append(name).append("\": uniqueId=\"").append(uniqueId).append("\", ");
352         sb.append(width).append(" x ").append(height);
353         sb.append(", modeId ").append(modeId);
354         sb.append(", defaultModeId ").append(defaultModeId);
355         sb.append(", supportedModes ").append(Arrays.toString(supportedModes));
356         sb.append(", colorTransformId ").append(colorTransformId);
357         sb.append(", defaultColorTransformId ").append(defaultColorTransformId);
358         sb.append(", supportedColorTransforms ").append(Arrays.toString(supportedColorTransforms));
359         sb.append(", HdrCapabilities ").append(hdrCapabilities);
360         sb.append(", density ").append(densityDpi);
361         sb.append(", ").append(xDpi).append(" x ").append(yDpi).append(" dpi");
362         sb.append(", appVsyncOff ").append(appVsyncOffsetNanos);
363         sb.append(", presDeadline ").append(presentationDeadlineNanos);
364         sb.append(", touch ").append(touchToString(touch));
365         sb.append(", rotation ").append(rotation);
366         sb.append(", type ").append(Display.typeToString(type));
367         if (address != null) {
368             sb.append(", address ").append(address);
369         }
370         sb.append(", state ").append(Display.stateToString(state));
371         if (ownerUid != 0 || ownerPackageName != null) {
372             sb.append(", owner ").append(ownerPackageName);
373             sb.append(" (uid ").append(ownerUid).append(")");
374         }
375         sb.append(flagsToString(flags));
376         sb.append("}");
377         return sb.toString();
378     }
379 
touchToString(int touch)380     private static String touchToString(int touch) {
381         switch (touch) {
382             case TOUCH_NONE:
383                 return "NONE";
384             case TOUCH_INTERNAL:
385                 return "INTERNAL";
386             case TOUCH_EXTERNAL:
387                 return "EXTERNAL";
388             default:
389                 return Integer.toString(touch);
390         }
391     }
392 
flagsToString(int flags)393     private static String flagsToString(int flags) {
394         StringBuilder msg = new StringBuilder();
395         if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
396             msg.append(", FLAG_DEFAULT_DISPLAY");
397         }
398         if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
399             msg.append(", FLAG_ROTATES_WITH_CONTENT");
400         }
401         if ((flags & FLAG_SECURE) != 0) {
402             msg.append(", FLAG_SECURE");
403         }
404         if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
405             msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
406         }
407         if ((flags & FLAG_PRIVATE) != 0) {
408             msg.append(", FLAG_PRIVATE");
409         }
410         if ((flags & FLAG_NEVER_BLANK) != 0) {
411             msg.append(", FLAG_NEVER_BLANK");
412         }
413         if ((flags & FLAG_PRESENTATION) != 0) {
414             msg.append(", FLAG_PRESENTATION");
415         }
416         if ((flags & FLAG_OWN_CONTENT_ONLY) != 0) {
417             msg.append(", FLAG_OWN_CONTENT_ONLY");
418         }
419         if ((flags & FLAG_ROUND) != 0) {
420             msg.append(", FLAG_ROUND");
421         }
422         return msg.toString();
423     }
424 }
425