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