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 android.view;
18
19import android.content.res.CompatibilityInfo;
20import android.os.IBinder;
21import android.os.Parcel;
22import android.os.Parcelable;
23import android.os.Process;
24import android.util.DisplayMetrics;
25
26import libcore.util.Objects;
27
28/**
29 * Describes the characteristics of a particular logical display.
30 * @hide
31 */
32public final class DisplayInfo implements Parcelable {
33    /**
34     * The surface flinger layer stack associated with this logical display.
35     */
36    public int layerStack;
37
38    /**
39     * Display flags.
40     */
41    public int flags;
42
43    /**
44     * Display type.
45     */
46    public int type;
47
48    /**
49     * Display address, or null if none.
50     * Interpretation varies by display type.
51     */
52    public String address;
53
54    /**
55     * The human-readable name of the display.
56     */
57    public String name;
58
59    /**
60     * The width of the portion of the display that is available to applications, in pixels.
61     * Represents the size of the display minus any system decorations.
62     */
63    public int appWidth;
64
65    /**
66     * The height of the portion of the display that is available to applications, in pixels.
67     * Represents the size of the display minus any system decorations.
68     */
69    public int appHeight;
70
71    /**
72     * The smallest value of {@link #appWidth} that an application is likely to encounter,
73     * in pixels, excepting cases where the width may be even smaller due to the presence
74     * of a soft keyboard, for example.
75     */
76    public int smallestNominalAppWidth;
77
78    /**
79     * The smallest value of {@link #appHeight} that an application is likely to encounter,
80     * in pixels, excepting cases where the height may be even smaller due to the presence
81     * of a soft keyboard, for example.
82     */
83    public int smallestNominalAppHeight;
84
85    /**
86     * The largest value of {@link #appWidth} that an application is likely to encounter,
87     * in pixels, excepting cases where the width may be even larger due to system decorations
88     * such as the status bar being hidden, for example.
89     */
90    public int largestNominalAppWidth;
91
92    /**
93     * The largest value of {@link #appHeight} that an application is likely to encounter,
94     * in pixels, excepting cases where the height may be even larger due to system decorations
95     * such as the status bar being hidden, for example.
96     */
97    public int largestNominalAppHeight;
98
99    /**
100     * The logical width of the display, in pixels.
101     * Represents the usable size of the display which may be smaller than the
102     * physical size when the system is emulating a smaller display.
103     */
104    public int logicalWidth;
105
106    /**
107     * The logical height of the display, in pixels.
108     * Represents the usable size of the display which may be smaller than the
109     * physical size when the system is emulating a smaller display.
110     */
111    public int logicalHeight;
112
113    /**
114     * @hide
115     * Number of overscan pixels on the left side of the display.
116     */
117    public int overscanLeft;
118
119    /**
120     * @hide
121     * Number of overscan pixels on the top side of the display.
122     */
123    public int overscanTop;
124
125    /**
126     * @hide
127     * Number of overscan pixels on the right side of the display.
128     */
129    public int overscanRight;
130
131    /**
132     * @hide
133     * Number of overscan pixels on the bottom side of the display.
134     */
135    public int overscanBottom;
136
137    /**
138     * The rotation of the display relative to its natural orientation.
139     * May be one of {@link android.view.Surface#ROTATION_0},
140     * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
141     * {@link android.view.Surface#ROTATION_270}.
142     * <p>
143     * The value of this field is indeterminate if the logical display is presented on
144     * more than one physical display.
145     * </p>
146     */
147    public int rotation;
148
149    /**
150     * The refresh rate of this display in frames per second.
151     * <p>
152     * The value of this field is indeterminate if the logical display is presented on
153     * more than one physical display.
154     * </p>
155     */
156    public float refreshRate;
157
158    /**
159     * The logical display density which is the basis for density-independent
160     * pixels.
161     */
162    public int logicalDensityDpi;
163
164    /**
165     * The exact physical pixels per inch of the screen in the X dimension.
166     * <p>
167     * The value of this field is indeterminate if the logical display is presented on
168     * more than one physical display.
169     * </p>
170     */
171    public float physicalXDpi;
172
173    /**
174     * The exact physical pixels per inch of the screen in the Y dimension.
175     * <p>
176     * The value of this field is indeterminate if the logical display is presented on
177     * more than one physical display.
178     * </p>
179     */
180    public float physicalYDpi;
181
182    /**
183     * The UID of the application that owns this display, or zero if it is owned by the system.
184     * <p>
185     * If the display is private, then only the owner can use it.
186     * </p>
187     */
188    public int ownerUid;
189
190    /**
191     * The package name of the application that owns this display, or null if it is
192     * owned by the system.
193     * <p>
194     * If the display is private, then only the owner can use it.
195     * </p>
196     */
197    public String ownerPackageName;
198
199    public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
200        @Override
201        public DisplayInfo createFromParcel(Parcel source) {
202            return new DisplayInfo(source);
203        }
204
205        @Override
206        public DisplayInfo[] newArray(int size) {
207            return new DisplayInfo[size];
208        }
209    };
210
211    public DisplayInfo() {
212    }
213
214    public DisplayInfo(DisplayInfo other) {
215        copyFrom(other);
216    }
217
218    private DisplayInfo(Parcel source) {
219        readFromParcel(source);
220    }
221
222    @Override
223    public boolean equals(Object o) {
224        return o instanceof DisplayInfo && equals((DisplayInfo)o);
225    }
226
227    public boolean equals(DisplayInfo other) {
228        return other != null
229                && layerStack == other.layerStack
230                && flags == other.flags
231                && type == other.type
232                && Objects.equal(address, other.address)
233                && Objects.equal(name, other.name)
234                && appWidth == other.appWidth
235                && appHeight == other.appHeight
236                && smallestNominalAppWidth == other.smallestNominalAppWidth
237                && smallestNominalAppHeight == other.smallestNominalAppHeight
238                && largestNominalAppWidth == other.largestNominalAppWidth
239                && largestNominalAppHeight == other.largestNominalAppHeight
240                && logicalWidth == other.logicalWidth
241                && logicalHeight == other.logicalHeight
242                && overscanLeft == other.overscanLeft
243                && overscanTop == other.overscanTop
244                && overscanRight == other.overscanRight
245                && overscanBottom == other.overscanBottom
246                && rotation == other.rotation
247                && refreshRate == other.refreshRate
248                && logicalDensityDpi == other.logicalDensityDpi
249                && physicalXDpi == other.physicalXDpi
250                && physicalYDpi == other.physicalYDpi
251                && ownerUid == other.ownerUid
252                && Objects.equal(ownerPackageName, other.ownerPackageName);
253    }
254
255    @Override
256    public int hashCode() {
257        return 0; // don't care
258    }
259
260    public void copyFrom(DisplayInfo other) {
261        layerStack = other.layerStack;
262        flags = other.flags;
263        type = other.type;
264        address = other.address;
265        name = other.name;
266        appWidth = other.appWidth;
267        appHeight = other.appHeight;
268        smallestNominalAppWidth = other.smallestNominalAppWidth;
269        smallestNominalAppHeight = other.smallestNominalAppHeight;
270        largestNominalAppWidth = other.largestNominalAppWidth;
271        largestNominalAppHeight = other.largestNominalAppHeight;
272        logicalWidth = other.logicalWidth;
273        logicalHeight = other.logicalHeight;
274        overscanLeft = other.overscanLeft;
275        overscanTop = other.overscanTop;
276        overscanRight = other.overscanRight;
277        overscanBottom = other.overscanBottom;
278        rotation = other.rotation;
279        refreshRate = other.refreshRate;
280        logicalDensityDpi = other.logicalDensityDpi;
281        physicalXDpi = other.physicalXDpi;
282        physicalYDpi = other.physicalYDpi;
283        ownerUid = other.ownerUid;
284        ownerPackageName = other.ownerPackageName;
285    }
286
287    public void readFromParcel(Parcel source) {
288        layerStack = source.readInt();
289        flags = source.readInt();
290        type = source.readInt();
291        address = source.readString();
292        name = source.readString();
293        appWidth = source.readInt();
294        appHeight = source.readInt();
295        smallestNominalAppWidth = source.readInt();
296        smallestNominalAppHeight = source.readInt();
297        largestNominalAppWidth = source.readInt();
298        largestNominalAppHeight = source.readInt();
299        logicalWidth = source.readInt();
300        logicalHeight = source.readInt();
301        overscanLeft = source.readInt();
302        overscanTop = source.readInt();
303        overscanRight = source.readInt();
304        overscanBottom = source.readInt();
305        rotation = source.readInt();
306        refreshRate = source.readFloat();
307        logicalDensityDpi = source.readInt();
308        physicalXDpi = source.readFloat();
309        physicalYDpi = source.readFloat();
310        ownerUid = source.readInt();
311        ownerPackageName = source.readString();
312    }
313
314    @Override
315    public void writeToParcel(Parcel dest, int flags) {
316        dest.writeInt(layerStack);
317        dest.writeInt(this.flags);
318        dest.writeInt(type);
319        dest.writeString(address);
320        dest.writeString(name);
321        dest.writeInt(appWidth);
322        dest.writeInt(appHeight);
323        dest.writeInt(smallestNominalAppWidth);
324        dest.writeInt(smallestNominalAppHeight);
325        dest.writeInt(largestNominalAppWidth);
326        dest.writeInt(largestNominalAppHeight);
327        dest.writeInt(logicalWidth);
328        dest.writeInt(logicalHeight);
329        dest.writeInt(overscanLeft);
330        dest.writeInt(overscanTop);
331        dest.writeInt(overscanRight);
332        dest.writeInt(overscanBottom);
333        dest.writeInt(rotation);
334        dest.writeFloat(refreshRate);
335        dest.writeInt(logicalDensityDpi);
336        dest.writeFloat(physicalXDpi);
337        dest.writeFloat(physicalYDpi);
338        dest.writeInt(ownerUid);
339        dest.writeString(ownerPackageName);
340    }
341
342    @Override
343    public int describeContents() {
344        return 0;
345    }
346
347    public void getAppMetrics(DisplayMetrics outMetrics) {
348        getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
349    }
350
351    public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
352        getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
353                displayAdjustments.getActivityToken(), appWidth, appHeight);
354    }
355
356    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, IBinder token) {
357        getMetricsWithSize(outMetrics, ci, token, appWidth, appHeight);
358    }
359
360    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
361            IBinder token) {
362        getMetricsWithSize(outMetrics, compatInfo, token, logicalWidth, logicalHeight);
363    }
364
365    public int getNaturalWidth() {
366        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
367                logicalWidth : logicalHeight;
368    }
369
370    public int getNaturalHeight() {
371        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
372                logicalHeight : logicalWidth;
373    }
374
375    /**
376     * Returns true if the specified UID has access to this display.
377     */
378    public boolean hasAccess(int uid) {
379        return Display.hasAccess(uid, flags, ownerUid);
380    }
381
382    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
383            IBinder token, int width, int height) {
384        outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
385        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
386        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
387
388        outMetrics.density = outMetrics.noncompatDensity =
389                logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
390        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
391        outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
392        outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
393
394        if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
395            compatInfo.applyToDisplayMetrics(outMetrics);
396        }
397    }
398
399    // For debugging purposes
400    @Override
401    public String toString() {
402        StringBuilder sb = new StringBuilder();
403        sb.append("DisplayInfo{\"");
404        sb.append(name);
405        sb.append("\", app ");
406        sb.append(appWidth);
407        sb.append(" x ");
408        sb.append(appHeight);
409        sb.append(", real ");
410        sb.append(logicalWidth);
411        sb.append(" x ");
412        sb.append(logicalHeight);
413        if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) {
414            sb.append(", overscan (");
415            sb.append(overscanLeft);
416            sb.append(",");
417            sb.append(overscanTop);
418            sb.append(",");
419            sb.append(overscanRight);
420            sb.append(",");
421            sb.append(overscanBottom);
422            sb.append(")");
423        }
424        sb.append(", largest app ");
425        sb.append(largestNominalAppWidth);
426        sb.append(" x ");
427        sb.append(largestNominalAppHeight);
428        sb.append(", smallest app ");
429        sb.append(smallestNominalAppWidth);
430        sb.append(" x ");
431        sb.append(smallestNominalAppHeight);
432        sb.append(", ");
433        sb.append(refreshRate);
434        sb.append(" fps, rotation");
435        sb.append(rotation);
436        sb.append(", density ");
437        sb.append(logicalDensityDpi);
438        sb.append(" (");
439        sb.append(physicalXDpi);
440        sb.append(" x ");
441        sb.append(physicalYDpi);
442        sb.append(") dpi, layerStack ");
443        sb.append(layerStack);
444        sb.append(", type ");
445        sb.append(Display.typeToString(type));
446        if (address != null) {
447            sb.append(", address ").append(address);
448        }
449        if (ownerUid != 0 || ownerPackageName != null) {
450            sb.append(", owner ").append(ownerPackageName);
451            sb.append(" (uid ").append(ownerUid).append(")");
452        }
453        sb.append(flagsToString(flags));
454        sb.append("}");
455        return sb.toString();
456    }
457
458    private static String flagsToString(int flags) {
459        StringBuilder result = new StringBuilder();
460        if ((flags & Display.FLAG_SECURE) != 0) {
461            result.append(", FLAG_SECURE");
462        }
463        if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
464            result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
465        }
466        if ((flags & Display.FLAG_PRIVATE) != 0) {
467            result.append(", FLAG_PRIVATE");
468        }
469        if ((flags & Display.FLAG_PRESENTATION) != 0) {
470            result.append(", FLAG_PRESENTATION");
471        }
472        return result.toString();
473    }
474}
475