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