DisplayInfo.java revision 1c9977b762b4bac46b4470f04c898bfd17da5d90
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.content.res.Configuration;
21import android.os.Parcel;
22import android.os.Parcelable;
23import android.util.ArraySet;
24import android.util.DisplayMetrics;
25
26import java.util.Arrays;
27
28import libcore.util.Objects;
29
30/**
31 * Describes the characteristics of a particular logical display.
32 * @hide
33 */
34public 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 active display mode.
159     */
160    public int modeId;
161
162    /**
163     * The default display mode.
164     */
165    public int defaultModeId;
166
167    /**
168     * The supported modes of this display.
169     */
170    public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
171
172    /** The active color mode. */
173    public int colorMode;
174
175    /** The list of supported color modes */
176    public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
177
178    /** The display's HDR capabilities */
179    public Display.HdrCapabilities hdrCapabilities;
180
181    /**
182     * The logical display density which is the basis for density-independent
183     * pixels.
184     */
185    public int logicalDensityDpi;
186
187    /**
188     * The exact physical pixels per inch of the screen in the X dimension.
189     * <p>
190     * The value of this field is indeterminate if the logical display is presented on
191     * more than one physical display.
192     * </p>
193     */
194    public float physicalXDpi;
195
196    /**
197     * The exact physical pixels per inch of the screen in the Y dimension.
198     * <p>
199     * The value of this field is indeterminate if the logical display is presented on
200     * more than one physical display.
201     * </p>
202     */
203    public float physicalYDpi;
204
205    /**
206     * This is a positive value indicating the phase offset of the VSYNC events provided by
207     * Choreographer relative to the display refresh.  For example, if Choreographer reports
208     * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
209     */
210    public long appVsyncOffsetNanos;
211
212    /**
213     * This is how far in advance a buffer must be queued for presentation at
214     * a given time.  If you want a buffer to appear on the screen at
215     * time N, you must submit the buffer before (N - bufferDeadlineNanos).
216     */
217    public long presentationDeadlineNanos;
218
219    /**
220     * The state of the display, such as {@link android.view.Display#STATE_ON}.
221     */
222    public int state;
223
224    /**
225     * The UID of the application that owns this display, or zero if it is owned by the system.
226     * <p>
227     * If the display is private, then only the owner can use it.
228     * </p>
229     */
230    public int ownerUid;
231
232    /**
233     * The package name of the application that owns this display, or null if it is
234     * owned by the system.
235     * <p>
236     * If the display is private, then only the owner can use it.
237     * </p>
238     */
239    public String ownerPackageName;
240
241    public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
242        @Override
243        public DisplayInfo createFromParcel(Parcel source) {
244            return new DisplayInfo(source);
245        }
246
247        @Override
248        public DisplayInfo[] newArray(int size) {
249            return new DisplayInfo[size];
250        }
251    };
252
253    public DisplayInfo() {
254    }
255
256    public DisplayInfo(DisplayInfo other) {
257        copyFrom(other);
258    }
259
260    private DisplayInfo(Parcel source) {
261        readFromParcel(source);
262    }
263
264    @Override
265    public boolean equals(Object o) {
266        return o instanceof DisplayInfo && equals((DisplayInfo)o);
267    }
268
269    public boolean equals(DisplayInfo other) {
270        return other != null
271                && layerStack == other.layerStack
272                && flags == other.flags
273                && type == other.type
274                && Objects.equal(address, other.address)
275                && Objects.equal(uniqueId, other.uniqueId)
276                && appWidth == other.appWidth
277                && appHeight == other.appHeight
278                && smallestNominalAppWidth == other.smallestNominalAppWidth
279                && smallestNominalAppHeight == other.smallestNominalAppHeight
280                && largestNominalAppWidth == other.largestNominalAppWidth
281                && largestNominalAppHeight == other.largestNominalAppHeight
282                && logicalWidth == other.logicalWidth
283                && logicalHeight == other.logicalHeight
284                && overscanLeft == other.overscanLeft
285                && overscanTop == other.overscanTop
286                && overscanRight == other.overscanRight
287                && overscanBottom == other.overscanBottom
288                && rotation == other.rotation
289                && modeId == other.modeId
290                && defaultModeId == other.defaultModeId
291                && colorMode == other.colorMode
292                && Objects.equal(supportedColorModes, other.supportedColorModes)
293                && Objects.equal(hdrCapabilities, other.hdrCapabilities)
294                && logicalDensityDpi == other.logicalDensityDpi
295                && physicalXDpi == other.physicalXDpi
296                && physicalYDpi == other.physicalYDpi
297                && appVsyncOffsetNanos == other.appVsyncOffsetNanos
298                && presentationDeadlineNanos == other.presentationDeadlineNanos
299                && state == other.state
300                && ownerUid == other.ownerUid
301                && Objects.equal(ownerPackageName, other.ownerPackageName);
302    }
303
304    @Override
305    public int hashCode() {
306        return 0; // don't care
307    }
308
309    public void copyFrom(DisplayInfo other) {
310        layerStack = other.layerStack;
311        flags = other.flags;
312        type = other.type;
313        address = other.address;
314        name = other.name;
315        uniqueId = other.uniqueId;
316        appWidth = other.appWidth;
317        appHeight = other.appHeight;
318        smallestNominalAppWidth = other.smallestNominalAppWidth;
319        smallestNominalAppHeight = other.smallestNominalAppHeight;
320        largestNominalAppWidth = other.largestNominalAppWidth;
321        largestNominalAppHeight = other.largestNominalAppHeight;
322        logicalWidth = other.logicalWidth;
323        logicalHeight = other.logicalHeight;
324        overscanLeft = other.overscanLeft;
325        overscanTop = other.overscanTop;
326        overscanRight = other.overscanRight;
327        overscanBottom = other.overscanBottom;
328        rotation = other.rotation;
329        modeId = other.modeId;
330        defaultModeId = other.defaultModeId;
331        supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
332        colorMode = other.colorMode;
333        supportedColorModes = Arrays.copyOf(
334                other.supportedColorModes, other.supportedColorModes.length);
335        hdrCapabilities = other.hdrCapabilities;
336        logicalDensityDpi = other.logicalDensityDpi;
337        physicalXDpi = other.physicalXDpi;
338        physicalYDpi = other.physicalYDpi;
339        appVsyncOffsetNanos = other.appVsyncOffsetNanos;
340        presentationDeadlineNanos = other.presentationDeadlineNanos;
341        state = other.state;
342        ownerUid = other.ownerUid;
343        ownerPackageName = other.ownerPackageName;
344    }
345
346    public void readFromParcel(Parcel source) {
347        layerStack = source.readInt();
348        flags = source.readInt();
349        type = source.readInt();
350        address = source.readString();
351        name = source.readString();
352        appWidth = source.readInt();
353        appHeight = source.readInt();
354        smallestNominalAppWidth = source.readInt();
355        smallestNominalAppHeight = source.readInt();
356        largestNominalAppWidth = source.readInt();
357        largestNominalAppHeight = source.readInt();
358        logicalWidth = source.readInt();
359        logicalHeight = source.readInt();
360        overscanLeft = source.readInt();
361        overscanTop = source.readInt();
362        overscanRight = source.readInt();
363        overscanBottom = source.readInt();
364        rotation = source.readInt();
365        modeId = source.readInt();
366        defaultModeId = source.readInt();
367        int nModes = source.readInt();
368        supportedModes = new Display.Mode[nModes];
369        for (int i = 0; i < nModes; i++) {
370            supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
371        }
372        colorMode = source.readInt();
373        int nColorModes = source.readInt();
374        supportedColorModes = new int[nColorModes];
375        for (int i = 0; i < nColorModes; i++) {
376            supportedColorModes[i] = source.readInt();
377        }
378        hdrCapabilities = source.readParcelable(null);
379        logicalDensityDpi = source.readInt();
380        physicalXDpi = source.readFloat();
381        physicalYDpi = source.readFloat();
382        appVsyncOffsetNanos = source.readLong();
383        presentationDeadlineNanos = source.readLong();
384        state = source.readInt();
385        ownerUid = source.readInt();
386        ownerPackageName = source.readString();
387        uniqueId = source.readString();
388    }
389
390    @Override
391    public void writeToParcel(Parcel dest, int flags) {
392        dest.writeInt(layerStack);
393        dest.writeInt(this.flags);
394        dest.writeInt(type);
395        dest.writeString(address);
396        dest.writeString(name);
397        dest.writeInt(appWidth);
398        dest.writeInt(appHeight);
399        dest.writeInt(smallestNominalAppWidth);
400        dest.writeInt(smallestNominalAppHeight);
401        dest.writeInt(largestNominalAppWidth);
402        dest.writeInt(largestNominalAppHeight);
403        dest.writeInt(logicalWidth);
404        dest.writeInt(logicalHeight);
405        dest.writeInt(overscanLeft);
406        dest.writeInt(overscanTop);
407        dest.writeInt(overscanRight);
408        dest.writeInt(overscanBottom);
409        dest.writeInt(rotation);
410        dest.writeInt(modeId);
411        dest.writeInt(defaultModeId);
412        dest.writeInt(supportedModes.length);
413        for (int i = 0; i < supportedModes.length; i++) {
414            supportedModes[i].writeToParcel(dest, flags);
415        }
416        dest.writeInt(colorMode);
417        dest.writeInt(supportedColorModes.length);
418        for (int i = 0; i < supportedColorModes.length; i++) {
419            dest.writeInt(supportedColorModes[i]);
420        }
421        dest.writeParcelable(hdrCapabilities, flags);
422        dest.writeInt(logicalDensityDpi);
423        dest.writeFloat(physicalXDpi);
424        dest.writeFloat(physicalYDpi);
425        dest.writeLong(appVsyncOffsetNanos);
426        dest.writeLong(presentationDeadlineNanos);
427        dest.writeInt(state);
428        dest.writeInt(ownerUid);
429        dest.writeString(ownerPackageName);
430        dest.writeString(uniqueId);
431    }
432
433    @Override
434    public int describeContents() {
435        return 0;
436    }
437
438    public Display.Mode getMode() {
439        return findMode(modeId);
440    }
441
442    public Display.Mode getDefaultMode() {
443        return findMode(defaultModeId);
444    }
445
446    private Display.Mode findMode(int id) {
447        for (int i = 0; i < supportedModes.length; i++) {
448            if (supportedModes[i].getModeId() == id) {
449                return supportedModes[i];
450            }
451        }
452        throw new IllegalStateException("Unable to locate mode " + id);
453    }
454
455    /**
456     * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable
457     * mode could be found.
458     */
459    public int findDefaultModeByRefreshRate(float refreshRate) {
460        Display.Mode[] modes = supportedModes;
461        Display.Mode defaultMode = getDefaultMode();
462        for (int i = 0; i < modes.length; i++) {
463            if (modes[i].matches(
464                    defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) {
465                return modes[i].getModeId();
466            }
467        }
468        return 0;
469    }
470
471    /**
472     * Returns the list of supported refresh rates in the default mode.
473     */
474    public float[] getDefaultRefreshRates() {
475        Display.Mode[] modes = supportedModes;
476        ArraySet<Float> rates = new ArraySet<>();
477        Display.Mode defaultMode = getDefaultMode();
478        for (int i = 0; i < modes.length; i++) {
479            Display.Mode mode = modes[i];
480            if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth()
481                    && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) {
482                rates.add(mode.getRefreshRate());
483            }
484        }
485        float[] result = new float[rates.size()];
486        int i = 0;
487        for (Float rate : rates) {
488            result[i++] = rate;
489        }
490        return result;
491    }
492
493    public void getAppMetrics(DisplayMetrics outMetrics) {
494        getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
495    }
496
497    public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
498        getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
499                displayAdjustments.getConfiguration(), appWidth, appHeight);
500    }
501
502    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci,
503            Configuration configuration) {
504        getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
505    }
506
507    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
508            Configuration configuration) {
509        getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
510    }
511
512    public int getNaturalWidth() {
513        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
514                logicalWidth : logicalHeight;
515    }
516
517    public int getNaturalHeight() {
518        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
519                logicalHeight : logicalWidth;
520    }
521
522    /**
523     * Returns true if the specified UID has access to this display.
524     */
525    public boolean hasAccess(int uid) {
526        return Display.hasAccess(uid, flags, ownerUid);
527    }
528
529    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
530            Configuration configuration, int width, int height) {
531        outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
532        outMetrics.density = outMetrics.noncompatDensity =
533                logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
534        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
535        outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
536        outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
537
538        width = (configuration != null
539                && configuration.screenWidthDp != Configuration.SCREEN_WIDTH_DP_UNDEFINED)
540                ? (int)((configuration.screenWidthDp * outMetrics.density) + 0.5f) : width;
541        height = (configuration != null
542                && configuration.screenHeightDp != Configuration.SCREEN_HEIGHT_DP_UNDEFINED)
543                ? (int)((configuration.screenHeightDp * outMetrics.density) + 0.5f) : height;
544
545        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
546        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
547
548        if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
549            compatInfo.applyToDisplayMetrics(outMetrics);
550        }
551    }
552
553    // For debugging purposes
554    @Override
555    public String toString() {
556        StringBuilder sb = new StringBuilder();
557        sb.append("DisplayInfo{\"");
558        sb.append(name);
559        sb.append("\", uniqueId \"");
560        sb.append(uniqueId);
561        sb.append("\", app ");
562        sb.append(appWidth);
563        sb.append(" x ");
564        sb.append(appHeight);
565        sb.append(", real ");
566        sb.append(logicalWidth);
567        sb.append(" x ");
568        sb.append(logicalHeight);
569        if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) {
570            sb.append(", overscan (");
571            sb.append(overscanLeft);
572            sb.append(",");
573            sb.append(overscanTop);
574            sb.append(",");
575            sb.append(overscanRight);
576            sb.append(",");
577            sb.append(overscanBottom);
578            sb.append(")");
579        }
580        sb.append(", largest app ");
581        sb.append(largestNominalAppWidth);
582        sb.append(" x ");
583        sb.append(largestNominalAppHeight);
584        sb.append(", smallest app ");
585        sb.append(smallestNominalAppWidth);
586        sb.append(" x ");
587        sb.append(smallestNominalAppHeight);
588        sb.append(", mode ");
589        sb.append(modeId);
590        sb.append(", defaultMode ");
591        sb.append(defaultModeId);
592        sb.append(", modes ");
593        sb.append(Arrays.toString(supportedModes));
594        sb.append(", colorMode ");
595        sb.append(colorMode);
596        sb.append(", supportedColorModes ");
597        sb.append(Arrays.toString(supportedColorModes));
598        sb.append(", hdrCapabilities ");
599        sb.append(hdrCapabilities);
600        sb.append(", rotation ");
601        sb.append(rotation);
602        sb.append(", density ");
603        sb.append(logicalDensityDpi);
604        sb.append(" (");
605        sb.append(physicalXDpi);
606        sb.append(" x ");
607        sb.append(physicalYDpi);
608        sb.append(") dpi, layerStack ");
609        sb.append(layerStack);
610        sb.append(", appVsyncOff ");
611        sb.append(appVsyncOffsetNanos);
612        sb.append(", presDeadline ");
613        sb.append(presentationDeadlineNanos);
614        sb.append(", type ");
615        sb.append(Display.typeToString(type));
616        if (address != null) {
617            sb.append(", address ").append(address);
618        }
619        sb.append(", state ");
620        sb.append(Display.stateToString(state));
621        if (ownerUid != 0 || ownerPackageName != null) {
622            sb.append(", owner ").append(ownerPackageName);
623            sb.append(" (uid ").append(ownerUid).append(")");
624        }
625        sb.append(flagsToString(flags));
626        sb.append("}");
627        return sb.toString();
628    }
629
630    private static String flagsToString(int flags) {
631        StringBuilder result = new StringBuilder();
632        if ((flags & Display.FLAG_SECURE) != 0) {
633            result.append(", FLAG_SECURE");
634        }
635        if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
636            result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
637        }
638        if ((flags & Display.FLAG_PRIVATE) != 0) {
639            result.append(", FLAG_PRIVATE");
640        }
641        if ((flags & Display.FLAG_PRESENTATION) != 0) {
642            result.append(", FLAG_PRESENTATION");
643        }
644        if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
645            result.append(", FLAG_SCALING_DISABLED");
646        }
647        if ((flags & Display.FLAG_ROUND) != 0) {
648            result.append(", FLAG_ROUND");
649        }
650        return result.toString();
651    }
652}
653