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 static android.view.DisplayInfoProto.APP_HEIGHT;
20import static android.view.DisplayInfoProto.APP_WIDTH;
21import static android.view.DisplayInfoProto.LOGICAL_HEIGHT;
22import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
23import static android.view.DisplayInfoProto.NAME;
24
25import android.content.res.CompatibilityInfo;
26import android.content.res.Configuration;
27import android.graphics.Rect;
28import android.os.Parcel;
29import android.os.Parcelable;
30import android.util.ArraySet;
31import android.util.DisplayMetrics;
32import android.util.proto.ProtoOutputStream;
33
34import java.util.Arrays;
35import java.util.Objects;
36
37/**
38 * Describes the characteristics of a particular logical display.
39 * @hide
40 */
41public final class DisplayInfo implements Parcelable {
42    /**
43     * The surface flinger layer stack associated with this logical display.
44     */
45    public int layerStack;
46
47    /**
48     * Display flags.
49     */
50    public int flags;
51
52    /**
53     * Display type.
54     */
55    public int type;
56
57    /**
58     * Display address, or null if none.
59     * Interpretation varies by display type.
60     */
61    public String address;
62
63    /**
64     * The human-readable name of the display.
65     */
66    public String name;
67
68    /**
69     * Unique identifier for the display. Shouldn't be displayed to the user.
70     */
71    public String uniqueId;
72
73    /**
74     * The width of the portion of the display that is available to applications, in pixels.
75     * Represents the size of the display minus any system decorations.
76     */
77    public int appWidth;
78
79    /**
80     * The height of the portion of the display that is available to applications, in pixels.
81     * Represents the size of the display minus any system decorations.
82     */
83    public int appHeight;
84
85    /**
86     * The smallest value of {@link #appWidth} that an application is likely to encounter,
87     * in pixels, excepting cases where the width may be even smaller due to the presence
88     * of a soft keyboard, for example.
89     */
90    public int smallestNominalAppWidth;
91
92    /**
93     * The smallest value of {@link #appHeight} that an application is likely to encounter,
94     * in pixels, excepting cases where the height may be even smaller due to the presence
95     * of a soft keyboard, for example.
96     */
97    public int smallestNominalAppHeight;
98
99    /**
100     * The largest value of {@link #appWidth} that an application is likely to encounter,
101     * in pixels, excepting cases where the width may be even larger due to system decorations
102     * such as the status bar being hidden, for example.
103     */
104    public int largestNominalAppWidth;
105
106    /**
107     * The largest value of {@link #appHeight} that an application is likely to encounter,
108     * in pixels, excepting cases where the height may be even larger due to system decorations
109     * such as the status bar being hidden, for example.
110     */
111    public int largestNominalAppHeight;
112
113    /**
114     * The logical width 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 logicalWidth;
119
120    /**
121     * The logical height of the display, in pixels.
122     * Represents the usable size of the display which may be smaller than the
123     * physical size when the system is emulating a smaller display.
124     */
125    public int logicalHeight;
126
127    /**
128     * @hide
129     * Number of overscan pixels on the left side of the display.
130     */
131    public int overscanLeft;
132
133    /**
134     * @hide
135     * Number of overscan pixels on the top side of the display.
136     */
137    public int overscanTop;
138
139    /**
140     * @hide
141     * Number of overscan pixels on the right side of the display.
142     */
143    public int overscanRight;
144
145    /**
146     * @hide
147     * Number of overscan pixels on the bottom side of the display.
148     */
149    public int overscanBottom;
150
151    /**
152     * The {@link DisplayCutout} if present, otherwise {@code null}.
153     *
154     * @hide
155     */
156    public DisplayCutout displayCutout;
157
158    /**
159     * The rotation of the display relative to its natural orientation.
160     * May be one of {@link android.view.Surface#ROTATION_0},
161     * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
162     * {@link android.view.Surface#ROTATION_270}.
163     * <p>
164     * The value of this field is indeterminate if the logical display is presented on
165     * more than one physical display.
166     * </p>
167     */
168    @Surface.Rotation
169    public int rotation;
170
171    /**
172     * The active display mode.
173     */
174    public int modeId;
175
176    /**
177     * The default display mode.
178     */
179    public int defaultModeId;
180
181    /**
182     * The supported modes of this display.
183     */
184    public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
185
186    /** The active color mode. */
187    public int colorMode;
188
189    /** The list of supported color modes */
190    public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
191
192    /** The display's HDR capabilities */
193    public Display.HdrCapabilities hdrCapabilities;
194
195    /**
196     * The logical display density which is the basis for density-independent
197     * pixels.
198     */
199    public int logicalDensityDpi;
200
201    /**
202     * The exact physical pixels per inch of the screen in the X dimension.
203     * <p>
204     * The value of this field is indeterminate if the logical display is presented on
205     * more than one physical display.
206     * </p>
207     */
208    public float physicalXDpi;
209
210    /**
211     * The exact physical pixels per inch of the screen in the Y dimension.
212     * <p>
213     * The value of this field is indeterminate if the logical display is presented on
214     * more than one physical display.
215     * </p>
216     */
217    public float physicalYDpi;
218
219    /**
220     * This is a positive value indicating the phase offset of the VSYNC events provided by
221     * Choreographer relative to the display refresh.  For example, if Choreographer reports
222     * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
223     */
224    public long appVsyncOffsetNanos;
225
226    /**
227     * This is how far in advance a buffer must be queued for presentation at
228     * a given time.  If you want a buffer to appear on the screen at
229     * time N, you must submit the buffer before (N - bufferDeadlineNanos).
230     */
231    public long presentationDeadlineNanos;
232
233    /**
234     * The state of the display, such as {@link android.view.Display#STATE_ON}.
235     */
236    public int state;
237
238    /**
239     * The UID of the application that owns this display, or zero if it is owned by the system.
240     * <p>
241     * If the display is private, then only the owner can use it.
242     * </p>
243     */
244    public int ownerUid;
245
246    /**
247     * The package name of the application that owns this display, or null if it is
248     * owned by the system.
249     * <p>
250     * If the display is private, then only the owner can use it.
251     * </p>
252     */
253    public String ownerPackageName;
254
255    /**
256     * @hide
257     * Get current remove mode of the display - what actions should be performed with the display's
258     * content when it is removed.
259     *
260     * @see Display#getRemoveMode()
261     */
262    public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
263
264    public static final Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
265        @Override
266        public DisplayInfo createFromParcel(Parcel source) {
267            return new DisplayInfo(source);
268        }
269
270        @Override
271        public DisplayInfo[] newArray(int size) {
272            return new DisplayInfo[size];
273        }
274    };
275
276    public DisplayInfo() {
277    }
278
279    public DisplayInfo(DisplayInfo other) {
280        copyFrom(other);
281    }
282
283    private DisplayInfo(Parcel source) {
284        readFromParcel(source);
285    }
286
287    @Override
288    public boolean equals(Object o) {
289        return o instanceof DisplayInfo && equals((DisplayInfo)o);
290    }
291
292    public boolean equals(DisplayInfo other) {
293        return other != null
294                && layerStack == other.layerStack
295                && flags == other.flags
296                && type == other.type
297                && Objects.equals(address, other.address)
298                && Objects.equals(uniqueId, other.uniqueId)
299                && appWidth == other.appWidth
300                && appHeight == other.appHeight
301                && smallestNominalAppWidth == other.smallestNominalAppWidth
302                && smallestNominalAppHeight == other.smallestNominalAppHeight
303                && largestNominalAppWidth == other.largestNominalAppWidth
304                && largestNominalAppHeight == other.largestNominalAppHeight
305                && logicalWidth == other.logicalWidth
306                && logicalHeight == other.logicalHeight
307                && overscanLeft == other.overscanLeft
308                && overscanTop == other.overscanTop
309                && overscanRight == other.overscanRight
310                && overscanBottom == other.overscanBottom
311                && Objects.equals(displayCutout, other.displayCutout)
312                && rotation == other.rotation
313                && modeId == other.modeId
314                && defaultModeId == other.defaultModeId
315                && colorMode == other.colorMode
316                && Arrays.equals(supportedColorModes, other.supportedColorModes)
317                && Objects.equals(hdrCapabilities, other.hdrCapabilities)
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                && Objects.equals(ownerPackageName, other.ownerPackageName)
326                && removeMode == other.removeMode;
327    }
328
329    @Override
330    public int hashCode() {
331        return 0; // don't care
332    }
333
334    public void copyFrom(DisplayInfo other) {
335        layerStack = other.layerStack;
336        flags = other.flags;
337        type = other.type;
338        address = other.address;
339        name = other.name;
340        uniqueId = other.uniqueId;
341        appWidth = other.appWidth;
342        appHeight = other.appHeight;
343        smallestNominalAppWidth = other.smallestNominalAppWidth;
344        smallestNominalAppHeight = other.smallestNominalAppHeight;
345        largestNominalAppWidth = other.largestNominalAppWidth;
346        largestNominalAppHeight = other.largestNominalAppHeight;
347        logicalWidth = other.logicalWidth;
348        logicalHeight = other.logicalHeight;
349        overscanLeft = other.overscanLeft;
350        overscanTop = other.overscanTop;
351        overscanRight = other.overscanRight;
352        overscanBottom = other.overscanBottom;
353        displayCutout = other.displayCutout;
354        rotation = other.rotation;
355        modeId = other.modeId;
356        defaultModeId = other.defaultModeId;
357        supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
358        colorMode = other.colorMode;
359        supportedColorModes = Arrays.copyOf(
360                other.supportedColorModes, other.supportedColorModes.length);
361        hdrCapabilities = other.hdrCapabilities;
362        logicalDensityDpi = other.logicalDensityDpi;
363        physicalXDpi = other.physicalXDpi;
364        physicalYDpi = other.physicalYDpi;
365        appVsyncOffsetNanos = other.appVsyncOffsetNanos;
366        presentationDeadlineNanos = other.presentationDeadlineNanos;
367        state = other.state;
368        ownerUid = other.ownerUid;
369        ownerPackageName = other.ownerPackageName;
370        removeMode = other.removeMode;
371    }
372
373    public void readFromParcel(Parcel source) {
374        layerStack = source.readInt();
375        flags = source.readInt();
376        type = source.readInt();
377        address = source.readString();
378        name = source.readString();
379        appWidth = source.readInt();
380        appHeight = source.readInt();
381        smallestNominalAppWidth = source.readInt();
382        smallestNominalAppHeight = source.readInt();
383        largestNominalAppWidth = source.readInt();
384        largestNominalAppHeight = source.readInt();
385        logicalWidth = source.readInt();
386        logicalHeight = source.readInt();
387        overscanLeft = source.readInt();
388        overscanTop = source.readInt();
389        overscanRight = source.readInt();
390        overscanBottom = source.readInt();
391        displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source);
392        rotation = source.readInt();
393        modeId = source.readInt();
394        defaultModeId = source.readInt();
395        int nModes = source.readInt();
396        supportedModes = new Display.Mode[nModes];
397        for (int i = 0; i < nModes; i++) {
398            supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
399        }
400        colorMode = source.readInt();
401        int nColorModes = source.readInt();
402        supportedColorModes = new int[nColorModes];
403        for (int i = 0; i < nColorModes; i++) {
404            supportedColorModes[i] = source.readInt();
405        }
406        hdrCapabilities = source.readParcelable(null);
407        logicalDensityDpi = source.readInt();
408        physicalXDpi = source.readFloat();
409        physicalYDpi = source.readFloat();
410        appVsyncOffsetNanos = source.readLong();
411        presentationDeadlineNanos = source.readLong();
412        state = source.readInt();
413        ownerUid = source.readInt();
414        ownerPackageName = source.readString();
415        uniqueId = source.readString();
416        removeMode = source.readInt();
417    }
418
419    @Override
420    public void writeToParcel(Parcel dest, int flags) {
421        dest.writeInt(layerStack);
422        dest.writeInt(this.flags);
423        dest.writeInt(type);
424        dest.writeString(address);
425        dest.writeString(name);
426        dest.writeInt(appWidth);
427        dest.writeInt(appHeight);
428        dest.writeInt(smallestNominalAppWidth);
429        dest.writeInt(smallestNominalAppHeight);
430        dest.writeInt(largestNominalAppWidth);
431        dest.writeInt(largestNominalAppHeight);
432        dest.writeInt(logicalWidth);
433        dest.writeInt(logicalHeight);
434        dest.writeInt(overscanLeft);
435        dest.writeInt(overscanTop);
436        dest.writeInt(overscanRight);
437        dest.writeInt(overscanBottom);
438        DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags);
439        dest.writeInt(rotation);
440        dest.writeInt(modeId);
441        dest.writeInt(defaultModeId);
442        dest.writeInt(supportedModes.length);
443        for (int i = 0; i < supportedModes.length; i++) {
444            supportedModes[i].writeToParcel(dest, flags);
445        }
446        dest.writeInt(colorMode);
447        dest.writeInt(supportedColorModes.length);
448        for (int i = 0; i < supportedColorModes.length; i++) {
449            dest.writeInt(supportedColorModes[i]);
450        }
451        dest.writeParcelable(hdrCapabilities, flags);
452        dest.writeInt(logicalDensityDpi);
453        dest.writeFloat(physicalXDpi);
454        dest.writeFloat(physicalYDpi);
455        dest.writeLong(appVsyncOffsetNanos);
456        dest.writeLong(presentationDeadlineNanos);
457        dest.writeInt(state);
458        dest.writeInt(ownerUid);
459        dest.writeString(ownerPackageName);
460        dest.writeString(uniqueId);
461        dest.writeInt(removeMode);
462    }
463
464    @Override
465    public int describeContents() {
466        return 0;
467    }
468
469    public Display.Mode getMode() {
470        return findMode(modeId);
471    }
472
473    public Display.Mode getDefaultMode() {
474        return findMode(defaultModeId);
475    }
476
477    private Display.Mode findMode(int id) {
478        for (int i = 0; i < supportedModes.length; i++) {
479            if (supportedModes[i].getModeId() == id) {
480                return supportedModes[i];
481            }
482        }
483        throw new IllegalStateException("Unable to locate mode " + id);
484    }
485
486    /**
487     * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable
488     * mode could be found.
489     */
490    public int findDefaultModeByRefreshRate(float refreshRate) {
491        Display.Mode[] modes = supportedModes;
492        Display.Mode defaultMode = getDefaultMode();
493        for (int i = 0; i < modes.length; i++) {
494            if (modes[i].matches(
495                    defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) {
496                return modes[i].getModeId();
497            }
498        }
499        return 0;
500    }
501
502    /**
503     * Returns the list of supported refresh rates in the default mode.
504     */
505    public float[] getDefaultRefreshRates() {
506        Display.Mode[] modes = supportedModes;
507        ArraySet<Float> rates = new ArraySet<>();
508        Display.Mode defaultMode = getDefaultMode();
509        for (int i = 0; i < modes.length; i++) {
510            Display.Mode mode = modes[i];
511            if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth()
512                    && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) {
513                rates.add(mode.getRefreshRate());
514            }
515        }
516        float[] result = new float[rates.size()];
517        int i = 0;
518        for (Float rate : rates) {
519            result[i++] = rate;
520        }
521        return result;
522    }
523
524    public void getAppMetrics(DisplayMetrics outMetrics) {
525        getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
526    }
527
528    public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
529        getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
530                displayAdjustments.getConfiguration(), appWidth, appHeight);
531    }
532
533    public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci,
534            Configuration configuration) {
535        getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
536    }
537
538    public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
539            Configuration configuration) {
540        getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
541    }
542
543    public int getNaturalWidth() {
544        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
545                logicalWidth : logicalHeight;
546    }
547
548    public int getNaturalHeight() {
549        return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
550                logicalHeight : logicalWidth;
551    }
552
553    public boolean isHdr() {
554        int[] types = hdrCapabilities != null ? hdrCapabilities.getSupportedHdrTypes() : null;
555        return types != null && types.length > 0;
556    }
557
558    public boolean isWideColorGamut() {
559        for (int colorMode : supportedColorModes) {
560            if (colorMode == Display.COLOR_MODE_DCI_P3 || colorMode > Display.COLOR_MODE_SRGB) {
561                return true;
562            }
563        }
564        return false;
565    }
566
567    /**
568     * Returns true if the specified UID has access to this display.
569     */
570    public boolean hasAccess(int uid) {
571        return Display.hasAccess(uid, flags, ownerUid);
572    }
573
574    private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
575            Configuration configuration, int width, int height) {
576        outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
577        outMetrics.density = outMetrics.noncompatDensity =
578                logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
579        outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
580        outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
581        outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
582
583        final Rect appBounds = configuration != null
584                ? configuration.windowConfiguration.getAppBounds() : null;
585        width = appBounds != null ? appBounds.width() : width;
586        height = appBounds != null ? appBounds.height() : height;
587
588        outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
589        outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
590
591        if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
592            compatInfo.applyToDisplayMetrics(outMetrics);
593        }
594    }
595
596    // For debugging purposes
597    @Override
598    public String toString() {
599        StringBuilder sb = new StringBuilder();
600        sb.append("DisplayInfo{\"");
601        sb.append(name);
602        sb.append("\", uniqueId \"");
603        sb.append(uniqueId);
604        sb.append("\", app ");
605        sb.append(appWidth);
606        sb.append(" x ");
607        sb.append(appHeight);
608        sb.append(", real ");
609        sb.append(logicalWidth);
610        sb.append(" x ");
611        sb.append(logicalHeight);
612        if (overscanLeft != 0 || overscanTop != 0 || overscanRight != 0 || overscanBottom != 0) {
613            sb.append(", overscan (");
614            sb.append(overscanLeft);
615            sb.append(",");
616            sb.append(overscanTop);
617            sb.append(",");
618            sb.append(overscanRight);
619            sb.append(",");
620            sb.append(overscanBottom);
621            sb.append(")");
622        }
623        sb.append(", largest app ");
624        sb.append(largestNominalAppWidth);
625        sb.append(" x ");
626        sb.append(largestNominalAppHeight);
627        sb.append(", smallest app ");
628        sb.append(smallestNominalAppWidth);
629        sb.append(" x ");
630        sb.append(smallestNominalAppHeight);
631        sb.append(", mode ");
632        sb.append(modeId);
633        sb.append(", defaultMode ");
634        sb.append(defaultModeId);
635        sb.append(", modes ");
636        sb.append(Arrays.toString(supportedModes));
637        sb.append(", colorMode ");
638        sb.append(colorMode);
639        sb.append(", supportedColorModes ");
640        sb.append(Arrays.toString(supportedColorModes));
641        sb.append(", hdrCapabilities ");
642        sb.append(hdrCapabilities);
643        sb.append(", rotation ");
644        sb.append(rotation);
645        sb.append(", density ");
646        sb.append(logicalDensityDpi);
647        sb.append(" (");
648        sb.append(physicalXDpi);
649        sb.append(" x ");
650        sb.append(physicalYDpi);
651        sb.append(") dpi, layerStack ");
652        sb.append(layerStack);
653        sb.append(", appVsyncOff ");
654        sb.append(appVsyncOffsetNanos);
655        sb.append(", presDeadline ");
656        sb.append(presentationDeadlineNanos);
657        sb.append(", type ");
658        sb.append(Display.typeToString(type));
659        if (address != null) {
660            sb.append(", address ").append(address);
661        }
662        sb.append(", state ");
663        sb.append(Display.stateToString(state));
664        if (ownerUid != 0 || ownerPackageName != null) {
665            sb.append(", owner ").append(ownerPackageName);
666            sb.append(" (uid ").append(ownerUid).append(")");
667        }
668        sb.append(flagsToString(flags));
669        sb.append(", removeMode ");
670        sb.append(removeMode);
671        sb.append("}");
672        return sb.toString();
673    }
674
675    /**
676     * Write to a protocol buffer output stream.
677     * Protocol buffer message definition at {@link android.view.DisplayInfoProto}
678     *
679     * @param protoOutputStream Stream to write the Rect object to.
680     * @param fieldId           Field Id of the DisplayInfoProto as defined in the parent message
681     */
682    public void writeToProto(ProtoOutputStream protoOutputStream, long fieldId) {
683        final long token = protoOutputStream.start(fieldId);
684        protoOutputStream.write(LOGICAL_WIDTH, logicalWidth);
685        protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight);
686        protoOutputStream.write(APP_WIDTH, appWidth);
687        protoOutputStream.write(APP_HEIGHT, appHeight);
688        protoOutputStream.write(NAME, name);
689        protoOutputStream.end(token);
690    }
691
692    private static String flagsToString(int flags) {
693        StringBuilder result = new StringBuilder();
694        if ((flags & Display.FLAG_SECURE) != 0) {
695            result.append(", FLAG_SECURE");
696        }
697        if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
698            result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
699        }
700        if ((flags & Display.FLAG_PRIVATE) != 0) {
701            result.append(", FLAG_PRIVATE");
702        }
703        if ((flags & Display.FLAG_PRESENTATION) != 0) {
704            result.append(", FLAG_PRESENTATION");
705        }
706        if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
707            result.append(", FLAG_SCALING_DISABLED");
708        }
709        if ((flags & Display.FLAG_ROUND) != 0) {
710            result.append(", FLAG_ROUND");
711        }
712        return result.toString();
713    }
714}
715