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