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