• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 static android.view.DisplayInfoProto.APP_HEIGHT;
20 import static android.view.DisplayInfoProto.APP_WIDTH;
21 import static android.view.DisplayInfoProto.FLAGS;
22 import static android.view.DisplayInfoProto.LOGICAL_HEIGHT;
23 import static android.view.DisplayInfoProto.LOGICAL_WIDTH;
24 import static android.view.DisplayInfoProto.NAME;
25 
26 import android.annotation.Nullable;
27 import android.app.WindowConfiguration;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.content.res.CompatibilityInfo;
30 import android.content.res.Configuration;
31 import android.graphics.Rect;
32 import android.hardware.display.DeviceProductInfo;
33 import android.os.Build;
34 import android.os.Parcel;
35 import android.os.Parcelable;
36 import android.os.Process;
37 import android.util.ArraySet;
38 import android.util.DisplayMetrics;
39 import android.util.proto.ProtoOutputStream;
40 
41 import java.util.Arrays;
42 import java.util.Objects;
43 
44 /**
45  * Describes the characteristics of a particular logical display.
46  * @hide
47  */
48 public final class DisplayInfo implements Parcelable {
49     /**
50      * The surface flinger layer stack associated with this logical display.
51      */
52     public int layerStack;
53 
54     /**
55      * Display flags.
56      */
57     public int flags;
58 
59     /**
60      * Display type.
61      */
62     public int type;
63 
64     /**
65      * Logical display identifier.
66      */
67     public int displayId;
68 
69     /**
70      * Display Group identifier.
71      */
72     public int displayGroupId;
73 
74     /**
75      * Display address, or null if none.
76      * Interpretation varies by display type.
77      */
78     public DisplayAddress address;
79 
80     /**
81      * Product-specific information about the display or the directly connected device on the
82      * display chain. For example, if the display is transitively connected, this field may contain
83      * product information about the intermediate device.
84      */
85     public DeviceProductInfo deviceProductInfo;
86 
87     /**
88      * The human-readable name of the display.
89      */
90     public String name;
91 
92     /**
93      * Unique identifier for the display. Shouldn't be displayed to the user.
94      */
95     public String uniqueId;
96 
97     /**
98      * The width of the portion of the display that is available to applications, in pixels.
99      * Represents the size of the display minus any system decorations.
100      */
101     public int appWidth;
102 
103     /**
104      * The height of the portion of the display that is available to applications, in pixels.
105      * Represents the size of the display minus any system decorations.
106      */
107     public int appHeight;
108 
109     /**
110      * The smallest value of {@link #appWidth} that an application is likely to encounter,
111      * in pixels, excepting cases where the width may be even smaller due to the presence
112      * of a soft keyboard, for example.
113      */
114     public int smallestNominalAppWidth;
115 
116     /**
117      * The smallest value of {@link #appHeight} that an application is likely to encounter,
118      * in pixels, excepting cases where the height may be even smaller due to the presence
119      * of a soft keyboard, for example.
120      */
121     public int smallestNominalAppHeight;
122 
123     /**
124      * The largest value of {@link #appWidth} that an application is likely to encounter,
125      * in pixels, excepting cases where the width may be even larger due to system decorations
126      * such as the status bar being hidden, for example.
127      */
128     public int largestNominalAppWidth;
129 
130     /**
131      * The largest value of {@link #appHeight} that an application is likely to encounter,
132      * in pixels, excepting cases where the height may be even larger due to system decorations
133      * such as the status bar being hidden, for example.
134      */
135     public int largestNominalAppHeight;
136 
137     /**
138      * The logical width of the display, in pixels.
139      * Represents the usable size of the display which may be smaller than the
140      * physical size when the system is emulating a smaller display.
141      */
142     @UnsupportedAppUsage
143     public int logicalWidth;
144 
145     /**
146      * The logical height of the display, in pixels.
147      * Represents the usable size of the display which may be smaller than the
148      * physical size when the system is emulating a smaller display.
149      */
150     @UnsupportedAppUsage
151     public int logicalHeight;
152 
153     /**
154      * The {@link DisplayCutout} if present, otherwise {@code null}.
155      *
156      * @hide
157      */
158     // Remark on @UnsupportedAppUsage: Display.getCutout should be used instead
159     @Nullable
160     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
161     public DisplayCutout displayCutout;
162 
163     /**
164      * The rotation of the display relative to its natural orientation.
165      * May be one of {@link android.view.Surface#ROTATION_0},
166      * {@link android.view.Surface#ROTATION_90}, {@link android.view.Surface#ROTATION_180},
167      * {@link android.view.Surface#ROTATION_270}.
168      * <p>
169      * The value of this field is indeterminate if the logical display is presented on
170      * more than one physical display.
171      * </p>
172      */
173     @Surface.Rotation
174     @UnsupportedAppUsage
175     public int rotation;
176 
177     /**
178      * The active display mode.
179      */
180     public int modeId;
181 
182     /**
183      * The default display mode.
184      */
185     public int defaultModeId;
186 
187     /**
188      * The supported modes of this display.
189      */
190     public Display.Mode[] supportedModes = Display.Mode.EMPTY_ARRAY;
191 
192     /** The active color mode. */
193     public int colorMode;
194 
195     /** The list of supported color modes */
196     public int[] supportedColorModes = { Display.COLOR_MODE_DEFAULT };
197 
198     /** The display's HDR capabilities */
199     public Display.HdrCapabilities hdrCapabilities;
200 
201     /** The formats disabled by user **/
202     public int[] userDisabledHdrTypes = {};
203 
204     /**
205      * Indicates whether the display can be switched into a mode with minimal post
206      * processing.
207      *
208      * @see android.view.Display#isMinimalPostProcessingSupported
209      */
210     public boolean minimalPostProcessingSupported;
211 
212     /**
213      * The logical display density which is the basis for density-independent
214      * pixels.
215      */
216     public int logicalDensityDpi;
217 
218     /**
219      * The exact physical pixels per inch of the screen in the X dimension.
220      * <p>
221      * The value of this field is indeterminate if the logical display is presented on
222      * more than one physical display.
223      * </p>
224      */
225     public float physicalXDpi;
226 
227     /**
228      * The exact physical pixels per inch of the screen in the Y dimension.
229      * <p>
230      * The value of this field is indeterminate if the logical display is presented on
231      * more than one physical display.
232      * </p>
233      */
234     public float physicalYDpi;
235 
236     /**
237      * This is a positive value indicating the phase offset of the VSYNC events provided by
238      * Choreographer relative to the display refresh.  For example, if Choreographer reports
239      * that the refresh occurred at time N, it actually occurred at (N - appVsyncOffsetNanos).
240      */
241     public long appVsyncOffsetNanos;
242 
243     /**
244      * This is how far in advance a buffer must be queued for presentation at
245      * a given time.  If you want a buffer to appear on the screen at
246      * time N, you must submit the buffer before (N - bufferDeadlineNanos).
247      */
248     public long presentationDeadlineNanos;
249 
250     /**
251      * The state of the display, such as {@link android.view.Display#STATE_ON}.
252      */
253     public int state;
254 
255     /**
256      * The current committed state of the display. For example, this becomes
257      * {@link android.view.Display#STATE_ON} only after the power state ON is fully committed.
258      */
259     public int committedState;
260 
261     /**
262      * The UID of the application that owns this display, or zero if it is owned by the system.
263      * <p>
264      * If the display is private, then only the owner can use it.
265      * </p>
266      */
267     public int ownerUid;
268 
269     /**
270      * The package name of the application that owns this display, or null if it is
271      * owned by the system.
272      * <p>
273      * If the display is private, then only the owner can use it.
274      * </p>
275      */
276     public String ownerPackageName;
277 
278     /**
279      * The refresh rate override for this app. 0 means no override.
280      */
281     public float refreshRateOverride;
282 
283     /**
284      * @hide
285      * Get current remove mode of the display - what actions should be performed with the display's
286      * content when it is removed.
287      *
288      * @see Display#getRemoveMode()
289      */
290     // TODO (b/114338689): Remove the flag and use IWindowManager#getRemoveContentMode
291     public int removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
292 
293     /**
294      * @hide
295      * The current minimum brightness constraint of the display. Value between 0.0 and 1.0,
296      * derived from the config constraints of the display device of this logical display.
297      */
298     public float brightnessMinimum;
299 
300     /**
301      * @hide
302      * The current maximum brightness constraint of the display. Value between 0.0 and 1.0,
303      * derived from the config constraints of the display device of this logical display.
304      */
305     public float brightnessMaximum;
306 
307     /**
308      * @hide
309      * The current default brightness of the display. Value between 0.0 and 1.0,
310      * derived from the configuration of the display device of this logical display.
311      */
312     public float brightnessDefault;
313 
314     /**
315      * The {@link RoundedCorners} if present, otherwise {@code null}.
316      */
317     @Nullable
318     public RoundedCorners roundedCorners;
319 
320     /**
321      * Install orientation of the display relative to its natural orientation.
322      */
323     @Surface.Rotation
324     public int installOrientation;
325 
326     public static final @android.annotation.NonNull Creator<DisplayInfo> CREATOR = new Creator<DisplayInfo>() {
327         @Override
328         public DisplayInfo createFromParcel(Parcel source) {
329             return new DisplayInfo(source);
330         }
331 
332         @Override
333         public DisplayInfo[] newArray(int size) {
334             return new DisplayInfo[size];
335         }
336     };
337 
338     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123769467)
DisplayInfo()339     public DisplayInfo() {
340     }
341 
DisplayInfo(DisplayInfo other)342     public DisplayInfo(DisplayInfo other) {
343         copyFrom(other);
344     }
345 
DisplayInfo(Parcel source)346     private DisplayInfo(Parcel source) {
347         readFromParcel(source);
348     }
349 
350     @Override
equals(@ullable Object o)351     public boolean equals(@Nullable Object o) {
352         return o instanceof DisplayInfo && equals((DisplayInfo)o);
353     }
354 
equals(DisplayInfo other)355     public boolean equals(DisplayInfo other) {
356         return other != null
357                 && layerStack == other.layerStack
358                 && flags == other.flags
359                 && type == other.type
360                 && displayId == other.displayId
361                 && displayGroupId == other.displayGroupId
362                 && Objects.equals(address, other.address)
363                 && Objects.equals(deviceProductInfo, other.deviceProductInfo)
364                 && Objects.equals(uniqueId, other.uniqueId)
365                 && appWidth == other.appWidth
366                 && appHeight == other.appHeight
367                 && smallestNominalAppWidth == other.smallestNominalAppWidth
368                 && smallestNominalAppHeight == other.smallestNominalAppHeight
369                 && largestNominalAppWidth == other.largestNominalAppWidth
370                 && largestNominalAppHeight == other.largestNominalAppHeight
371                 && logicalWidth == other.logicalWidth
372                 && logicalHeight == other.logicalHeight
373                 && Objects.equals(displayCutout, other.displayCutout)
374                 && rotation == other.rotation
375                 && modeId == other.modeId
376                 && defaultModeId == other.defaultModeId
377                 && Arrays.equals(supportedModes, other.supportedModes)
378                 && colorMode == other.colorMode
379                 && Arrays.equals(supportedColorModes, other.supportedColorModes)
380                 && Objects.equals(hdrCapabilities, other.hdrCapabilities)
381                 && Arrays.equals(userDisabledHdrTypes, other.userDisabledHdrTypes)
382                 && minimalPostProcessingSupported == other.minimalPostProcessingSupported
383                 && logicalDensityDpi == other.logicalDensityDpi
384                 && physicalXDpi == other.physicalXDpi
385                 && physicalYDpi == other.physicalYDpi
386                 && appVsyncOffsetNanos == other.appVsyncOffsetNanos
387                 && presentationDeadlineNanos == other.presentationDeadlineNanos
388                 && state == other.state
389                 && committedState == other.committedState
390                 && ownerUid == other.ownerUid
391                 && Objects.equals(ownerPackageName, other.ownerPackageName)
392                 && removeMode == other.removeMode
393                 && getRefreshRate() == other.getRefreshRate()
394                 && brightnessMinimum == other.brightnessMinimum
395                 && brightnessMaximum == other.brightnessMaximum
396                 && brightnessDefault == other.brightnessDefault
397                 && Objects.equals(roundedCorners, other.roundedCorners)
398                 && installOrientation == other.installOrientation;
399     }
400 
401     @Override
hashCode()402     public int hashCode() {
403         return 0; // don't care
404     }
405 
copyFrom(DisplayInfo other)406     public void copyFrom(DisplayInfo other) {
407         layerStack = other.layerStack;
408         flags = other.flags;
409         type = other.type;
410         displayId = other.displayId;
411         displayGroupId = other.displayGroupId;
412         address = other.address;
413         deviceProductInfo = other.deviceProductInfo;
414         name = other.name;
415         uniqueId = other.uniqueId;
416         appWidth = other.appWidth;
417         appHeight = other.appHeight;
418         smallestNominalAppWidth = other.smallestNominalAppWidth;
419         smallestNominalAppHeight = other.smallestNominalAppHeight;
420         largestNominalAppWidth = other.largestNominalAppWidth;
421         largestNominalAppHeight = other.largestNominalAppHeight;
422         logicalWidth = other.logicalWidth;
423         logicalHeight = other.logicalHeight;
424         displayCutout = other.displayCutout;
425         rotation = other.rotation;
426         modeId = other.modeId;
427         defaultModeId = other.defaultModeId;
428         supportedModes = Arrays.copyOf(other.supportedModes, other.supportedModes.length);
429         colorMode = other.colorMode;
430         supportedColorModes = Arrays.copyOf(
431                 other.supportedColorModes, other.supportedColorModes.length);
432         hdrCapabilities = other.hdrCapabilities;
433         userDisabledHdrTypes = other.userDisabledHdrTypes;
434         minimalPostProcessingSupported = other.minimalPostProcessingSupported;
435         logicalDensityDpi = other.logicalDensityDpi;
436         physicalXDpi = other.physicalXDpi;
437         physicalYDpi = other.physicalYDpi;
438         appVsyncOffsetNanos = other.appVsyncOffsetNanos;
439         presentationDeadlineNanos = other.presentationDeadlineNanos;
440         state = other.state;
441         committedState = other.committedState;
442         ownerUid = other.ownerUid;
443         ownerPackageName = other.ownerPackageName;
444         removeMode = other.removeMode;
445         refreshRateOverride = other.refreshRateOverride;
446         brightnessMinimum = other.brightnessMinimum;
447         brightnessMaximum = other.brightnessMaximum;
448         brightnessDefault = other.brightnessDefault;
449         roundedCorners = other.roundedCorners;
450         installOrientation = other.installOrientation;
451     }
452 
readFromParcel(Parcel source)453     public void readFromParcel(Parcel source) {
454         layerStack = source.readInt();
455         flags = source.readInt();
456         type = source.readInt();
457         displayId = source.readInt();
458         displayGroupId = source.readInt();
459         address = source.readParcelable(null, android.view.DisplayAddress.class);
460         deviceProductInfo = source.readParcelable(null, android.hardware.display.DeviceProductInfo.class);
461         name = source.readString8();
462         appWidth = source.readInt();
463         appHeight = source.readInt();
464         smallestNominalAppWidth = source.readInt();
465         smallestNominalAppHeight = source.readInt();
466         largestNominalAppWidth = source.readInt();
467         largestNominalAppHeight = source.readInt();
468         logicalWidth = source.readInt();
469         logicalHeight = source.readInt();
470         displayCutout = DisplayCutout.ParcelableWrapper.readCutoutFromParcel(source);
471         rotation = source.readInt();
472         modeId = source.readInt();
473         defaultModeId = source.readInt();
474         int nModes = source.readInt();
475         supportedModes = new Display.Mode[nModes];
476         for (int i = 0; i < nModes; i++) {
477             supportedModes[i] = Display.Mode.CREATOR.createFromParcel(source);
478         }
479         colorMode = source.readInt();
480         int nColorModes = source.readInt();
481         supportedColorModes = new int[nColorModes];
482         for (int i = 0; i < nColorModes; i++) {
483             supportedColorModes[i] = source.readInt();
484         }
485         hdrCapabilities = source.readParcelable(null, android.view.Display.HdrCapabilities.class);
486         minimalPostProcessingSupported = source.readBoolean();
487         logicalDensityDpi = source.readInt();
488         physicalXDpi = source.readFloat();
489         physicalYDpi = source.readFloat();
490         appVsyncOffsetNanos = source.readLong();
491         presentationDeadlineNanos = source.readLong();
492         state = source.readInt();
493         committedState = source.readInt();
494         ownerUid = source.readInt();
495         ownerPackageName = source.readString8();
496         uniqueId = source.readString8();
497         removeMode = source.readInt();
498         refreshRateOverride = source.readFloat();
499         brightnessMinimum = source.readFloat();
500         brightnessMaximum = source.readFloat();
501         brightnessDefault = source.readFloat();
502         roundedCorners = source.readTypedObject(RoundedCorners.CREATOR);
503         int numUserDisabledFormats = source.readInt();
504         userDisabledHdrTypes = new int[numUserDisabledFormats];
505         for (int i = 0; i < numUserDisabledFormats; i++) {
506             userDisabledHdrTypes[i] = source.readInt();
507         }
508         installOrientation = source.readInt();
509     }
510 
511     @Override
writeToParcel(Parcel dest, int flags)512     public void writeToParcel(Parcel dest, int flags) {
513         dest.writeInt(layerStack);
514         dest.writeInt(this.flags);
515         dest.writeInt(type);
516         dest.writeInt(displayId);
517         dest.writeInt(displayGroupId);
518         dest.writeParcelable(address, flags);
519         dest.writeParcelable(deviceProductInfo, flags);
520         dest.writeString8(name);
521         dest.writeInt(appWidth);
522         dest.writeInt(appHeight);
523         dest.writeInt(smallestNominalAppWidth);
524         dest.writeInt(smallestNominalAppHeight);
525         dest.writeInt(largestNominalAppWidth);
526         dest.writeInt(largestNominalAppHeight);
527         dest.writeInt(logicalWidth);
528         dest.writeInt(logicalHeight);
529         DisplayCutout.ParcelableWrapper.writeCutoutToParcel(displayCutout, dest, flags);
530         dest.writeInt(rotation);
531         dest.writeInt(modeId);
532         dest.writeInt(defaultModeId);
533         dest.writeInt(supportedModes.length);
534         for (int i = 0; i < supportedModes.length; i++) {
535             supportedModes[i].writeToParcel(dest, flags);
536         }
537         dest.writeInt(colorMode);
538         dest.writeInt(supportedColorModes.length);
539         for (int i = 0; i < supportedColorModes.length; i++) {
540             dest.writeInt(supportedColorModes[i]);
541         }
542         dest.writeParcelable(hdrCapabilities, flags);
543         dest.writeBoolean(minimalPostProcessingSupported);
544         dest.writeInt(logicalDensityDpi);
545         dest.writeFloat(physicalXDpi);
546         dest.writeFloat(physicalYDpi);
547         dest.writeLong(appVsyncOffsetNanos);
548         dest.writeLong(presentationDeadlineNanos);
549         dest.writeInt(state);
550         dest.writeInt(committedState);
551         dest.writeInt(ownerUid);
552         dest.writeString8(ownerPackageName);
553         dest.writeString8(uniqueId);
554         dest.writeInt(removeMode);
555         dest.writeFloat(refreshRateOverride);
556         dest.writeFloat(brightnessMinimum);
557         dest.writeFloat(brightnessMaximum);
558         dest.writeFloat(brightnessDefault);
559         dest.writeTypedObject(roundedCorners, flags);
560         dest.writeInt(userDisabledHdrTypes.length);
561         for (int i = 0; i < userDisabledHdrTypes.length; i++) {
562             dest.writeInt(userDisabledHdrTypes[i]);
563         }
564         dest.writeInt(installOrientation);
565     }
566 
567     @Override
describeContents()568     public int describeContents() {
569         return 0;
570     }
571 
572     /**
573      * Returns the refresh rate the application would experience.
574      */
getRefreshRate()575     public float getRefreshRate() {
576         if (refreshRateOverride > 0) {
577             return refreshRateOverride;
578         }
579 
580         return getMode().getRefreshRate();
581     }
582 
getMode()583     public Display.Mode getMode() {
584         return findMode(modeId);
585     }
586 
getDefaultMode()587     public Display.Mode getDefaultMode() {
588         return findMode(defaultModeId);
589     }
590 
findMode(int id)591     private Display.Mode findMode(int id) {
592         for (int i = 0; i < supportedModes.length; i++) {
593             if (supportedModes[i].getModeId() == id) {
594                 return supportedModes[i];
595             }
596         }
597         throw new IllegalStateException("Unable to locate mode " + id);
598     }
599 
600     /**
601      * Returns the id of the "default" mode with the given refresh rate, or {@code 0} if no suitable
602      * mode could be found.
603      */
604     @Nullable
findDefaultModeByRefreshRate(float refreshRate)605     public Display.Mode findDefaultModeByRefreshRate(float refreshRate) {
606         Display.Mode[] modes = supportedModes;
607         Display.Mode defaultMode = getDefaultMode();
608         for (int i = 0; i < modes.length; i++) {
609             if (modes[i].matches(
610                     defaultMode.getPhysicalWidth(), defaultMode.getPhysicalHeight(), refreshRate)) {
611                 return modes[i];
612             }
613         }
614         return null;
615     }
616 
617     /**
618      * Returns the list of supported refresh rates in the default mode.
619      */
getDefaultRefreshRates()620     public float[] getDefaultRefreshRates() {
621         Display.Mode[] modes = supportedModes;
622         ArraySet<Float> rates = new ArraySet<>();
623         Display.Mode defaultMode = getDefaultMode();
624         for (int i = 0; i < modes.length; i++) {
625             Display.Mode mode = modes[i];
626             if (mode.getPhysicalWidth() == defaultMode.getPhysicalWidth()
627                     && mode.getPhysicalHeight() == defaultMode.getPhysicalHeight()) {
628                 rates.add(mode.getRefreshRate());
629             }
630         }
631         float[] result = new float[rates.size()];
632         int i = 0;
633         for (Float rate : rates) {
634             result[i++] = rate;
635         }
636         return result;
637     }
638 
getAppMetrics(DisplayMetrics outMetrics)639     public void getAppMetrics(DisplayMetrics outMetrics) {
640         getAppMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null);
641     }
642 
getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments)643     public void getAppMetrics(DisplayMetrics outMetrics, DisplayAdjustments displayAdjustments) {
644         getMetricsWithSize(outMetrics, displayAdjustments.getCompatibilityInfo(),
645                 displayAdjustments.getConfiguration(), appWidth, appHeight);
646     }
647 
getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci, Configuration configuration)648     public void getAppMetrics(DisplayMetrics outMetrics, CompatibilityInfo ci,
649             Configuration configuration) {
650         getMetricsWithSize(outMetrics, ci, configuration, appWidth, appHeight);
651     }
652 
653     /**
654      * Populates {@code outMetrics} with details of the logical display. Bounds are limited
655      * by the logical size of the display.
656      *
657      * @param outMetrics the {@link DisplayMetrics} to be populated
658      * @param compatInfo the {@link CompatibilityInfo} to be applied
659      * @param configuration the {@link Configuration}
660      */
getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)661     public void getLogicalMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
662             Configuration configuration) {
663         getMetricsWithSize(outMetrics, compatInfo, configuration, logicalWidth, logicalHeight);
664     }
665 
666     /**
667      * Similar to {@link #getLogicalMetrics}, but the limiting bounds are determined from
668      * {@link WindowConfiguration#getMaxBounds()}
669      */
getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration)670     public void getMaxBoundsMetrics(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
671             Configuration configuration) {
672         Rect bounds = configuration.windowConfiguration.getMaxBounds();
673         // Pass in null configuration to ensure width and height are not overridden to app bounds.
674         getMetricsWithSize(outMetrics, compatInfo, /* configuration= */ null,
675                 bounds.width(), bounds.height());
676     }
677 
getNaturalWidth()678     public int getNaturalWidth() {
679         return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
680                 logicalWidth : logicalHeight;
681     }
682 
getNaturalHeight()683     public int getNaturalHeight() {
684         return rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180 ?
685                 logicalHeight : logicalWidth;
686     }
687 
isHdr()688     public boolean isHdr() {
689         int[] types = hdrCapabilities != null ? hdrCapabilities.getSupportedHdrTypes() : null;
690         return types != null && types.length > 0;
691     }
692 
isWideColorGamut()693     public boolean isWideColorGamut() {
694         for (int colorMode : supportedColorModes) {
695             if (colorMode == Display.COLOR_MODE_DCI_P3 || colorMode > Display.COLOR_MODE_SRGB) {
696                 return true;
697             }
698         }
699         return false;
700     }
701 
702     /**
703      * Returns true if the specified UID has access to this display.
704      */
hasAccess(int uid)705     public boolean hasAccess(int uid) {
706         return Display.hasAccess(uid, flags, ownerUid, displayId);
707     }
708 
getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo, Configuration configuration, int width, int height)709     private void getMetricsWithSize(DisplayMetrics outMetrics, CompatibilityInfo compatInfo,
710             Configuration configuration, int width, int height) {
711         outMetrics.densityDpi = outMetrics.noncompatDensityDpi = logicalDensityDpi;
712         outMetrics.density = outMetrics.noncompatDensity =
713                 logicalDensityDpi * DisplayMetrics.DENSITY_DEFAULT_SCALE;
714         outMetrics.scaledDensity = outMetrics.noncompatScaledDensity = outMetrics.density;
715         outMetrics.xdpi = outMetrics.noncompatXdpi = physicalXDpi;
716         outMetrics.ydpi = outMetrics.noncompatYdpi = physicalYDpi;
717 
718         final Rect appBounds = configuration != null
719                 ? configuration.windowConfiguration.getAppBounds() : null;
720         width = appBounds != null ? appBounds.width() : width;
721         height = appBounds != null ? appBounds.height() : height;
722 
723         outMetrics.noncompatWidthPixels  = outMetrics.widthPixels = width;
724         outMetrics.noncompatHeightPixels = outMetrics.heightPixels = height;
725 
726         if (!compatInfo.equals(CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO)) {
727             compatInfo.applyToDisplayMetrics(outMetrics);
728         }
729     }
730 
731     // For debugging purposes
732     @Override
toString()733     public String toString() {
734         StringBuilder sb = new StringBuilder();
735         sb.append("DisplayInfo{\"");
736         sb.append(name);
737         sb.append("\", displayId ");
738         sb.append(displayId);
739         sb.append("\", displayGroupId ");
740         sb.append(displayGroupId);
741         sb.append(flagsToString(flags));
742         sb.append(", real ");
743         sb.append(logicalWidth);
744         sb.append(" x ");
745         sb.append(logicalHeight);
746         sb.append(", largest app ");
747         sb.append(largestNominalAppWidth);
748         sb.append(" x ");
749         sb.append(largestNominalAppHeight);
750         sb.append(", smallest app ");
751         sb.append(smallestNominalAppWidth);
752         sb.append(" x ");
753         sb.append(smallestNominalAppHeight);
754         sb.append(", appVsyncOff ");
755         sb.append(appVsyncOffsetNanos);
756         sb.append(", presDeadline ");
757         sb.append(presentationDeadlineNanos);
758         sb.append(", mode ");
759         sb.append(modeId);
760         sb.append(", defaultMode ");
761         sb.append(defaultModeId);
762         sb.append(", modes ");
763         sb.append(Arrays.toString(supportedModes));
764         sb.append(", hdrCapabilities ");
765         sb.append(hdrCapabilities);
766         sb.append(", userDisabledHdrTypes ");
767         sb.append(Arrays.toString(userDisabledHdrTypes));
768         sb.append(", minimalPostProcessingSupported ");
769         sb.append(minimalPostProcessingSupported);
770         sb.append(", rotation ");
771         sb.append(rotation);
772         sb.append(", state ");
773         sb.append(Display.stateToString(state));
774         sb.append(", committedState ");
775         sb.append(Display.stateToString(committedState));
776 
777         if (Process.myUid() != Process.SYSTEM_UID) {
778             sb.append("}");
779             return sb.toString();
780         }
781 
782         sb.append(", type ");
783         sb.append(Display.typeToString(type));
784         sb.append(", uniqueId \"");
785         sb.append(uniqueId);
786         sb.append("\", app ");
787         sb.append(appWidth);
788         sb.append(" x ");
789         sb.append(appHeight);
790         sb.append(", density ");
791         sb.append(logicalDensityDpi);
792         sb.append(" (");
793         sb.append(physicalXDpi);
794         sb.append(" x ");
795         sb.append(physicalYDpi);
796         sb.append(") dpi, layerStack ");
797         sb.append(layerStack);
798         sb.append(", colorMode ");
799         sb.append(colorMode);
800         sb.append(", supportedColorModes ");
801         sb.append(Arrays.toString(supportedColorModes));
802         if (address != null) {
803             sb.append(", address ").append(address);
804         }
805         sb.append(", deviceProductInfo ");
806         sb.append(deviceProductInfo);
807         if (ownerUid != 0 || ownerPackageName != null) {
808             sb.append(", owner ").append(ownerPackageName);
809             sb.append(" (uid ").append(ownerUid).append(")");
810         }
811         sb.append(", removeMode ");
812         sb.append(removeMode);
813         sb.append(", refreshRateOverride ");
814         sb.append(refreshRateOverride);
815         sb.append(", brightnessMinimum ");
816         sb.append(brightnessMinimum);
817         sb.append(", brightnessMaximum ");
818         sb.append(brightnessMaximum);
819         sb.append(", brightnessDefault ");
820         sb.append(brightnessDefault);
821         sb.append(", installOrientation ");
822         sb.append(Surface.rotationToString(installOrientation));
823         sb.append("}");
824         return sb.toString();
825     }
826 
827     /**
828      * Write to a protocol buffer output stream.
829      * Protocol buffer message definition at {@link android.view.DisplayInfoProto}
830      *
831      * @param protoOutputStream Stream to write the Rect object to.
832      * @param fieldId           Field Id of the DisplayInfoProto as defined in the parent message
833      */
dumpDebug(ProtoOutputStream protoOutputStream, long fieldId)834     public void dumpDebug(ProtoOutputStream protoOutputStream, long fieldId) {
835         final long token = protoOutputStream.start(fieldId);
836         protoOutputStream.write(LOGICAL_WIDTH, logicalWidth);
837         protoOutputStream.write(LOGICAL_HEIGHT, logicalHeight);
838         protoOutputStream.write(APP_WIDTH, appWidth);
839         protoOutputStream.write(APP_HEIGHT, appHeight);
840         protoOutputStream.write(NAME, name);
841         protoOutputStream.write(FLAGS, flags);
842         protoOutputStream.end(token);
843     }
844 
flagsToString(int flags)845     private static String flagsToString(int flags) {
846         StringBuilder result = new StringBuilder();
847         if ((flags & Display.FLAG_SECURE) != 0) {
848             result.append(", FLAG_SECURE");
849         }
850         if ((flags & Display.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
851             result.append(", FLAG_SUPPORTS_PROTECTED_BUFFERS");
852         }
853         if ((flags & Display.FLAG_PRIVATE) != 0) {
854             result.append(", FLAG_PRIVATE");
855         }
856         if ((flags & Display.FLAG_PRESENTATION) != 0) {
857             result.append(", FLAG_PRESENTATION");
858         }
859         if ((flags & Display.FLAG_SCALING_DISABLED) != 0) {
860             result.append(", FLAG_SCALING_DISABLED");
861         }
862         if ((flags & Display.FLAG_ROUND) != 0) {
863             result.append(", FLAG_ROUND");
864         }
865         if ((flags & Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
866             result.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD");
867         }
868         if ((flags & Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) {
869             result.append(", FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS");
870         }
871         if ((flags & Display.FLAG_TRUSTED) != 0) {
872             result.append(", FLAG_TRUSTED");
873         }
874         if ((flags & Display.FLAG_OWN_DISPLAY_GROUP) != 0) {
875             result.append(", FLAG_OWN_DISPLAY_GROUP");
876         }
877         if ((flags & Display.FLAG_ALWAYS_UNLOCKED) != 0) {
878             result.append(", FLAG_ALWAYS_UNLOCKED");
879         }
880         if ((flags & Display.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) {
881             result.append(", FLAG_TOUCH_FEEDBACK_DISABLED");
882         }
883         return result.toString();
884     }
885 }
886