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.util.DisplayMetrics;
20import android.view.Display;
21import android.view.Surface;
22
23import libcore.util.Objects;
24
25/**
26 * Describes the characteristics of a physical display device.
27 */
28final class DisplayDeviceInfo {
29    /**
30     * Flag: Indicates that this display device should be considered the default display
31     * device of the system.
32     */
33    public static final int FLAG_DEFAULT_DISPLAY = 1 << 0;
34
35    /**
36     * Flag: Indicates that the orientation of this display device is coupled to the
37     * rotation of its associated logical display.
38     * <p>
39     * This flag should be applied to the default display to indicate that the user
40     * physically rotates the display when content is presented in a different orientation.
41     * The display manager will apply a coordinate transformation assuming that the
42     * physical orientation of the display matches the logical orientation of its content.
43     * </p><p>
44     * The flag should not be set when the display device is mounted in a fixed orientation
45     * such as on a desk.  The display manager will apply a coordinate transformation
46     * such as a scale and translation to letterbox or pillarbox format under the
47     * assumption that the physical orientation of the display is invariant.
48     * </p>
49     */
50    public static final int FLAG_ROTATES_WITH_CONTENT = 1 << 1;
51
52    /**
53     * Flag: Indicates that this display device has secure video output, such as HDCP.
54     */
55    public static final int FLAG_SECURE = 1 << 2;
56
57    /**
58     * Flag: Indicates that this display device supports compositing
59     * from gralloc protected buffers.
60     */
61    public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 3;
62
63    /**
64     * Touch attachment: Display does not receive touch.
65     */
66    public static final int TOUCH_NONE = 0;
67
68    /**
69     * Touch attachment: Touch input is via the internal interface.
70     */
71    public static final int TOUCH_INTERNAL = 1;
72
73    /**
74     * Touch attachment: Touch input is via an external interface, such as USB.
75     */
76    public static final int TOUCH_EXTERNAL = 2;
77
78    /**
79     * Gets the name of the display device, which may be derived from
80     * EDID or other sources.  The name may be displayed to the user.
81     */
82    public String name;
83
84    /**
85     * The width of the display in its natural orientation, in pixels.
86     * This value is not affected by display rotation.
87     */
88    public int width;
89
90    /**
91     * The height of the display in its natural orientation, in pixels.
92     * This value is not affected by display rotation.
93     */
94    public int height;
95
96    /**
97     * The refresh rate of the display.
98     */
99    public float refreshRate;
100
101    /**
102     * The nominal apparent density of the display in DPI used for layout calculations.
103     * This density is sensitive to the viewing distance.  A big TV and a tablet may have
104     * the same apparent density even though the pixels on the TV are much bigger than
105     * those on the tablet.
106     */
107    public int densityDpi;
108
109    /**
110     * The physical density of the display in DPI in the X direction.
111     * This density should specify the physical size of each pixel.
112     */
113    public float xDpi;
114
115    /**
116     * The physical density of the display in DPI in the X direction.
117     * This density should specify the physical size of each pixel.
118     */
119    public float yDpi;
120
121    /**
122     * Display flags.
123     */
124    public int flags;
125
126    /**
127     * The touch attachment, per {@link DisplayViewport#touch}.
128     */
129    public int touch;
130
131    /**
132     * The additional rotation to apply to all content presented on the display device
133     * relative to its physical coordinate system.  Default is {@link Surface#ROTATION_0}.
134     * <p>
135     * This field can be used to compensate for the fact that the display has been
136     * physically rotated relative to its natural orientation such as an HDMI monitor
137     * that has been mounted sideways to appear to be portrait rather than landscape.
138     * </p>
139     */
140    public int rotation = Surface.ROTATION_0;
141
142    /**
143     * Display type.
144     */
145    public int type;
146
147    /**
148     * Display address, or null if none.
149     * Interpretation varies by display type.
150     */
151    public String address;
152
153    public void setAssumedDensityForExternalDisplay(int width, int height) {
154        densityDpi = Math.min(width, height) * DisplayMetrics.DENSITY_XHIGH / 1080;
155        // Technically, these values should be smaller than the apparent density
156        // but we don't know the physical size of the display.
157        xDpi = densityDpi;
158        yDpi = densityDpi;
159    }
160
161    @Override
162    public boolean equals(Object o) {
163        return o instanceof DisplayDeviceInfo && equals((DisplayDeviceInfo)o);
164    }
165
166    public boolean equals(DisplayDeviceInfo other) {
167        return other != null
168                && Objects.equal(name, other.name)
169                && width == other.width
170                && height == other.height
171                && refreshRate == other.refreshRate
172                && densityDpi == other.densityDpi
173                && xDpi == other.xDpi
174                && yDpi == other.yDpi
175                && flags == other.flags
176                && touch == other.touch
177                && rotation == other.rotation
178                && type == other.type
179                && Objects.equal(address, other.address);
180    }
181
182    @Override
183    public int hashCode() {
184        return 0; // don't care
185    }
186
187    public void copyFrom(DisplayDeviceInfo other) {
188        name = other.name;
189        width = other.width;
190        height = other.height;
191        refreshRate = other.refreshRate;
192        densityDpi = other.densityDpi;
193        xDpi = other.xDpi;
194        yDpi = other.yDpi;
195        flags = other.flags;
196        touch = other.touch;
197        rotation = other.rotation;
198        type = other.type;
199        address = other.address;
200    }
201
202    // For debugging purposes
203    @Override
204    public String toString() {
205        return "DisplayDeviceInfo{\"" + name + "\": " + width + " x " + height + ", "
206                + refreshRate + " fps, "
207                + "density " + densityDpi + ", " + xDpi + " x " + yDpi + " dpi"
208                + ", touch " + touchToString(touch) + flagsToString(flags)
209                + ", rotation " + rotation
210                + ", type " + Display.typeToString(type)
211                + ", address " + address
212                + "}";
213    }
214
215    private static String touchToString(int touch) {
216        switch (touch) {
217            case TOUCH_NONE:
218                return "NONE";
219            case TOUCH_INTERNAL:
220                return "INTERNAL";
221            case TOUCH_EXTERNAL:
222                return "EXTERNAL";
223            default:
224                return Integer.toString(touch);
225        }
226    }
227
228    private static String flagsToString(int flags) {
229        StringBuilder msg = new StringBuilder();
230        if ((flags & FLAG_DEFAULT_DISPLAY) != 0) {
231            msg.append(", FLAG_DEFAULT_DISPLAY");
232        }
233        if ((flags & FLAG_ROTATES_WITH_CONTENT) != 0) {
234            msg.append(", FLAG_ROTATES_WITH_CONTENT");
235        }
236        if ((flags & FLAG_SECURE) != 0) {
237            msg.append(", FLAG_SECURE");
238        }
239        if ((flags & FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
240            msg.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
241        }
242        return msg.toString();
243    }
244}
245