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 com.android.server.display;
18 
19 import static com.android.server.display.DisplayDeviceInfo.TOUCH_NONE;
20 import static com.android.server.wm.utils.DisplayInfoOverrides.WM_OVERRIDE_FIELDS;
21 import static com.android.server.wm.utils.DisplayInfoOverrides.copyDisplayInfoFields;
22 
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.graphics.Point;
26 import android.graphics.Rect;
27 import android.hardware.display.DisplayManagerInternal;
28 import android.util.ArraySet;
29 import android.util.SparseArray;
30 import android.view.Display;
31 import android.view.DisplayEventReceiver;
32 import android.view.DisplayInfo;
33 import android.view.Surface;
34 import android.view.SurfaceControl;
35 
36 import com.android.server.display.layout.Layout;
37 import com.android.server.display.mode.DisplayModeDirector;
38 import com.android.server.display.mode.SyntheticModeManager;
39 import com.android.server.wm.utils.InsetUtils;
40 
41 import java.io.PrintWriter;
42 import java.io.StringWriter;
43 import java.util.Arrays;
44 import java.util.Objects;
45 
46 /**
47  * Describes how a logical display is configured.
48  * <p>
49  * At this time, we only support logical displays that are coupled to a particular
50  * primary display device from which the logical display derives its basic properties
51  * such as its size, density and refresh rate.
52  * </p><p>
53  * A logical display may be mirrored onto multiple display devices in addition to its
54  * primary display device.  Note that the contents of a logical display may not
55  * always be visible, even on its primary display device, such as in the case where
56  * the primary display device is currently mirroring content from a different
57  * logical display.
58  * </p><p>
59  * This object is designed to encapsulate as much of the policy of logical
60  * displays as possible.  The idea is to make it easy to implement new kinds of
61  * logical displays mostly by making local changes to this class.
62  * </p><p>
63  * Note: The display manager architecture does not actually require logical displays
64  * to be associated with any individual display device.  Logical displays and
65  * display devices are orthogonal concepts.  Some mapping will exist between
66  * logical displays and display devices but it can be many-to-many and
67  * and some might have no relation at all.
68  * </p><p>
69  * Logical displays are guarded by the {@link DisplayManagerService.SyncRoot} lock.
70  * </p>
71  */
72 final class LogicalDisplay {
73     private static final String TAG = "LogicalDisplay";
74     // The layer stack we use when the display has been blanked to prevent any
75     // of its content from appearing.
76     private static final int BLANK_LAYER_STACK = -1;
77 
78     private static final DisplayInfo EMPTY_DISPLAY_INFO = new DisplayInfo();
79 
80     private final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
81     private final int mDisplayId;
82     private final int mLayerStack;
83 
84     // Indicates which display leads this logical display, in terms of brightness or other
85     // properties.
86     // {@link Layout.NO_LEAD_DISPLAY} means that this display is not lead by any others, and could
87     // be a leader itself.
88     private int mLeadDisplayId = Layout.NO_LEAD_DISPLAY;
89 
90     private int mDisplayGroupId = Display.INVALID_DISPLAY_GROUP;
91 
92     /**
93      * Override information set by the window manager. Will be reported instead of {@link #mInfo}
94      * if not null.
95      * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
96      * @see #getDisplayInfoLocked()
97      */
98     private DisplayInfo mOverrideDisplayInfo;
99     /**
100      * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
101      * needs to be updated.
102      * @see #getDisplayInfoLocked()
103      */
104     private final DisplayInfoProxy mInfo = new DisplayInfoProxy(null);
105 
106     // The display device that this logical display is based on and which
107     // determines the base metrics that it uses.
108     private DisplayDevice mPrimaryDisplayDevice;
109     private DisplayDeviceInfo mPrimaryDisplayDeviceInfo;
110 
111     // True if the logical display has unique content.
112     private boolean mHasContent;
113 
114     private int mRequestedColorMode;
115     private boolean mRequestedMinimalPostProcessing;
116 
117     private int[] mUserDisabledHdrTypes = {};
118 
119     private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs =
120             new DisplayModeDirector.DesiredDisplayModeSpecs();
121 
122     // The display offsets to apply to the display projection.
123     private int mDisplayOffsetX;
124     private int mDisplayOffsetY;
125 
126     /**
127      * The position of the display projection sent to SurfaceFlinger
128      */
129     private final Point mDisplayPosition = new Point();
130 
131     /**
132      * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode
133      * is used.
134      * @see #isDisplayScalingDisabled()
135      * @see #setDisplayScalingDisabledLocked(boolean)
136      */
137     private boolean mDisplayScalingDisabled;
138 
139     // Temporary rectangle used when needed.
140     private final Rect mTempLayerStackRect = new Rect();
141     private final Rect mTempDisplayRect = new Rect();
142 
143     /** A session token that controls the offloading operations of this logical display. */
144     private DisplayOffloadSessionImpl mDisplayOffloadSession;
145 
146     /**
147      * Name of a display group to which the display is assigned.
148      */
149     private String mDisplayGroupName;
150 
151     /**
152      * The UID mappings for refresh rate override
153      */
154     private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides;
155 
156     /**
157      * Holds a set of UIDs that their frame rate override changed and needs to be notified
158      */
159     private ArraySet<Integer> mPendingFrameRateOverrideUids;
160 
161     /**
162      * Temporary frame rate override list, used when needed.
163      */
164     private final SparseArray<Float> mTempFrameRateOverride;
165 
166     // Indicates the display is enabled (allowed to be ON).
167     private boolean mIsEnabled;
168 
169     // Indicates the display is part of a transition from one device-state ({@link
170     // DeviceStateManager}) to another. Being a "part" of a transition means that either
171     // the {@link mIsEnabled} is changing, or the underlying mPrimaryDisplayDevice is changing.
172     private boolean mIsInTransition;
173 
174     // Indicates the position of the display, POSITION_UNKNOWN could mean it hasn't been specified,
175     // or this is a virtual display etc.
176     private int mDevicePosition = Layout.Display.POSITION_UNKNOWN;
177 
178     // Indicates that something other than the primary display device info has changed and needs to
179     // be handled in the next update.
180     private boolean mDirty = false;
181 
182     /**
183      * The ID of the thermal brightness throttling data that should be used. This can change e.g.
184      * in concurrent displays mode in which a stricter brightness throttling policy might need to
185      * be used.
186      */
187     private String mThermalBrightnessThrottlingDataId;
188 
189     /**
190      * Refresh rate range limitation based on the current device layout
191      */
192     @Nullable
193     private SurfaceControl.RefreshRateRange mLayoutLimitedRefreshRate;
194 
195     /**
196      * The ID of the power throttling data that should be used.
197      */
198     private String mPowerThrottlingDataId;
199 
200     /**
201      * RefreshRateRange limitation for @Temperature.ThrottlingStatus
202      */
203     @NonNull
204     private SparseArray<SurfaceControl.RefreshRateRange> mThermalRefreshRateThrottling =
205             new SparseArray<>();
206 
207     /**
208      * If enabled, will not check for {@link Display#FLAG_ROTATES_WITH_CONTENT} in LogicalDisplay
209      * and simply use the {@link DisplayInfo#rotation} supplied by WindowManager via
210      * {@link #setDisplayInfoOverrideFromWindowManagerLocked}
211      */
212     private boolean mAlwaysRotateDisplayDeviceEnabled;
213 
214     /**
215      * If the aspect ratio of the resolution of the display does not match the physical aspect
216      * ratio of the display, then without this feature enabled, picture would appear stretched to
217      * the user. This is because applications assume that they are rendered on square pixels
218      * (meaning density of pixels in x and y directions are equal). This would result into circles
219      * appearing as ellipses to the user.
220      * To compensate for non-square (anisotropic) pixels, if this feature is enabled:
221      * 1. LogicalDisplay will add more pixels for the applications to render on, as if the pixels
222      * were square and occupied the full display.
223      * 2. SurfaceFlinger will squeeze this taller/wider surface into the available number of
224      * physical pixels in the current display resolution.
225      * 3. If a setting on the display itself is set to "fill the entire display panel" then the
226      * display will stretch the pixels to fill the display fully.
227      */
228     private final boolean mIsAnisotropyCorrectionEnabled;
229 
LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice)230     LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
231         this(displayId, layerStack, primaryDisplayDevice, false, false);
232     }
233 
LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice, boolean isAnisotropyCorrectionEnabled, boolean isAlwaysRotateDisplayDeviceEnabled)234     LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice,
235             boolean isAnisotropyCorrectionEnabled, boolean isAlwaysRotateDisplayDeviceEnabled) {
236         mDisplayId = displayId;
237         mLayerStack = layerStack;
238         mPrimaryDisplayDevice = primaryDisplayDevice;
239         mPendingFrameRateOverrideUids = new ArraySet<>();
240         mTempFrameRateOverride = new SparseArray<>();
241         mIsEnabled = true;
242         mIsInTransition = false;
243         mThermalBrightnessThrottlingDataId = DisplayDeviceConfig.DEFAULT_ID;
244         mPowerThrottlingDataId = DisplayDeviceConfig.DEFAULT_ID;
245         mBaseDisplayInfo.thermalBrightnessThrottlingDataId = mThermalBrightnessThrottlingDataId;
246         mIsAnisotropyCorrectionEnabled = isAnisotropyCorrectionEnabled;
247         mAlwaysRotateDisplayDeviceEnabled = isAlwaysRotateDisplayDeviceEnabled;
248     }
249 
setDevicePositionLocked(int position)250     public void setDevicePositionLocked(int position) {
251         if (mDevicePosition != position) {
252             mDevicePosition = position;
253             mDirty = true;
254         }
255     }
getDevicePositionLocked()256     public int getDevicePositionLocked() {
257         return mDevicePosition;
258     }
259 
260     /**
261      * Gets the logical display id of this logical display.
262      *
263      * @return The logical display id.
264      */
getDisplayIdLocked()265     public int getDisplayIdLocked() {
266         return mDisplayId;
267     }
268 
269     /**
270      * Gets the primary display device associated with this logical display.
271      *
272      * @return The primary display device.
273      */
getPrimaryDisplayDeviceLocked()274     public DisplayDevice getPrimaryDisplayDeviceLocked() {
275         return mPrimaryDisplayDevice;
276     }
277 
278     /**
279      * Gets information about the logical display.
280      *
281      * @return The device info, which should be treated as immutable by the caller.
282      * The logical display should allocate a new display info object whenever
283      * the data changes.
284      */
getDisplayInfoLocked()285     public DisplayInfo getDisplayInfoLocked() {
286         if (mInfo.get() == null) {
287             DisplayInfo info = new DisplayInfo();
288             copyDisplayInfoFields(info, mBaseDisplayInfo, mOverrideDisplayInfo,
289                     WM_OVERRIDE_FIELDS);
290             mInfo.set(info);
291         }
292         return mInfo.get();
293     }
294 
295     /**
296      * Returns the frame rate overrides list
297      */
getFrameRateOverrides()298     public DisplayEventReceiver.FrameRateOverride[] getFrameRateOverrides() {
299         return mFrameRateOverrides;
300     }
301 
302     /**
303      * Returns the list of uids that needs to be updated about their frame rate override
304      */
getPendingFrameRateOverrideUids()305     public ArraySet<Integer> getPendingFrameRateOverrideUids() {
306         return mPendingFrameRateOverrideUids;
307     }
308 
309     /**
310      * Clears the list of uids that needs to be updated about their frame rate override
311      */
clearPendingFrameRateOverrideUids()312     public void clearPendingFrameRateOverrideUids() {
313         mPendingFrameRateOverrideUids = new ArraySet<>();
314     }
315 
316     /**
317      * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
318      */
getNonOverrideDisplayInfoLocked(DisplayInfo outInfo)319     void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) {
320         outInfo.copyFrom(mBaseDisplayInfo);
321     }
322 
323     /**
324      * Sets overridden logical display information from the window manager.
325      * This method can be used to adjust application insets, rotation, and other
326      * properties that the window manager takes care of.
327      *
328      * @param info The logical display information, may be null.
329      */
setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info)330     public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
331         if (info != null) {
332             if (mOverrideDisplayInfo == null) {
333                 mOverrideDisplayInfo = new DisplayInfo(info);
334                 mInfo.set(null);
335                 return true;
336             } else if (!mOverrideDisplayInfo.equals(info)) {
337                 mOverrideDisplayInfo.copyFrom(info);
338                 mInfo.set(null);
339                 return true;
340             }
341         } else if (mOverrideDisplayInfo != null) {
342             mOverrideDisplayInfo = null;
343             mInfo.set(null);
344             return true;
345         }
346         return false;
347     }
348 
349     /**
350      * Returns true if the logical display is in a valid state.
351      * This method should be checked after calling {@link #updateLocked} to handle the
352      * case where a logical display should be removed because all of its associated
353      * display devices are gone or if it is otherwise no longer needed.
354      *
355      * @return True if the logical display is still valid.
356      */
isValidLocked()357     public boolean isValidLocked() {
358         return mPrimaryDisplayDevice != null;
359     }
360 
isDirtyLocked()361     boolean isDirtyLocked() {
362         return mDirty;
363     }
364 
365     /**
366      * Updates the {@link DisplayGroup} to which the logical display belongs.
367      *
368      * @param groupId Identifier for the {@link DisplayGroup}.
369      */
updateDisplayGroupIdLocked(int groupId)370     public void updateDisplayGroupIdLocked(int groupId) {
371         if (groupId != mDisplayGroupId) {
372             mDisplayGroupId = groupId;
373             mDirty = true;
374         }
375     }
376 
377     /**
378      * Updates layoutLimitedRefreshRate
379      *
380      * @param layoutLimitedRefreshRate refresh rate limited by layout or null.
381      */
updateLayoutLimitedRefreshRateLocked( @ullable SurfaceControl.RefreshRateRange layoutLimitedRefreshRate)382     public void updateLayoutLimitedRefreshRateLocked(
383             @Nullable SurfaceControl.RefreshRateRange layoutLimitedRefreshRate) {
384         if (!Objects.equals(layoutLimitedRefreshRate, mLayoutLimitedRefreshRate)) {
385             mLayoutLimitedRefreshRate = layoutLimitedRefreshRate;
386             mDirty = true;
387         }
388     }
389     /**
390      * Updates thermalRefreshRateThrottling
391      *
392      * @param refreshRanges new thermalRefreshRateThrottling ranges limited by layout or default
393      */
updateThermalRefreshRateThrottling( @ullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges)394     public void updateThermalRefreshRateThrottling(
395             @Nullable SparseArray<SurfaceControl.RefreshRateRange> refreshRanges) {
396         if (refreshRanges == null) {
397             refreshRanges = new SparseArray<>();
398         }
399         if (!mThermalRefreshRateThrottling.contentEquals(refreshRanges)) {
400             mThermalRefreshRateThrottling = refreshRanges;
401             mDirty = true;
402         }
403     }
404 
405     /**
406      * Updates the state of the logical display based on the available display devices.
407      * The logical display might become invalid if it is attached to a display device
408      * that no longer exists.
409      *
410      * @param deviceRepo Repository of active {@link DisplayDevice}s.
411      */
updateLocked(DisplayDeviceRepository deviceRepo, SyntheticModeManager syntheticModeManager)412     public void updateLocked(DisplayDeviceRepository deviceRepo,
413             SyntheticModeManager syntheticModeManager) {
414         // Nothing to update if already invalid.
415         if (mPrimaryDisplayDevice == null) {
416             return;
417         }
418 
419         // Check whether logical display has become invalid.
420         if (!deviceRepo.containsLocked(mPrimaryDisplayDevice)) {
421             setPrimaryDisplayDeviceLocked(null);
422             return;
423         }
424 
425         // Bootstrap the logical display using its associated primary physical display.
426         // We might use more elaborate configurations later.  It's possible that the
427         // configuration of several physical displays might be used to determine the
428         // logical display that they are sharing.  (eg. Adjust size for pixel-perfect
429         // mirroring over HDMI.)
430         DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked();
431         DisplayDeviceConfig config = mPrimaryDisplayDevice.getDisplayDeviceConfig();
432         if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo) || mDirty) {
433             mBaseDisplayInfo.layerStack = mLayerStack;
434             mBaseDisplayInfo.flags = 0;
435             // Displays default to moving content to the primary display when removed
436             mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_MOVE_CONTENT_TO_PRIMARY;
437             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
438                 mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
439             }
440             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) {
441                 mBaseDisplayInfo.flags |= Display.FLAG_SECURE;
442             }
443             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) {
444                 mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE;
445                 // For private displays by default content is destroyed on removal.
446                 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
447             }
448             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_DESTROY_CONTENT_ON_REMOVAL) != 0) {
449                 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
450             }
451             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRESENTATION) != 0) {
452                 mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION;
453             }
454             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROUND) != 0) {
455                 mBaseDisplayInfo.flags |= Display.FLAG_ROUND;
456             }
457             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
458                 mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
459             }
460             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) {
461                 mBaseDisplayInfo.flags |= Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
462             }
463             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TRUSTED) != 0) {
464                 mBaseDisplayInfo.flags |= Display.FLAG_TRUSTED;
465             }
466             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) {
467                 mBaseDisplayInfo.flags |= Display.FLAG_OWN_DISPLAY_GROUP;
468             }
469             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ALWAYS_UNLOCKED) != 0) {
470                 mBaseDisplayInfo.flags |= Display.FLAG_ALWAYS_UNLOCKED;
471             }
472             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
473                 mBaseDisplayInfo.flags |= Display.FLAG_ROTATES_WITH_CONTENT;
474             }
475             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TOUCH_FEEDBACK_DISABLED) != 0) {
476                 mBaseDisplayInfo.flags |= Display.FLAG_TOUCH_FEEDBACK_DISABLED;
477             }
478             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_FOCUS) != 0) {
479                 mBaseDisplayInfo.flags |= Display.FLAG_OWN_FOCUS;
480             }
481             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_STEAL_TOP_FOCUS_DISABLED) != 0) {
482                 mBaseDisplayInfo.flags |= Display.FLAG_STEAL_TOP_FOCUS_DISABLED;
483             }
484             Rect maskingInsets = getMaskingInsets(deviceInfo);
485             int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right;
486             int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom;
487 
488             if (mIsAnisotropyCorrectionEnabled && deviceInfo.type == Display.TYPE_EXTERNAL
489                         && deviceInfo.xDpi > 0 && deviceInfo.yDpi > 0) {
490                 if (deviceInfo.xDpi > deviceInfo.yDpi * DisplayDevice.MAX_ANISOTROPY) {
491                     maskedHeight = (int) (maskedHeight * deviceInfo.xDpi / deviceInfo.yDpi + 0.5);
492                 } else if (deviceInfo.xDpi * DisplayDevice.MAX_ANISOTROPY < deviceInfo.yDpi) {
493                     maskedWidth = (int) (maskedWidth * deviceInfo.yDpi / deviceInfo.xDpi + 0.5);
494                 }
495             }
496 
497             mBaseDisplayInfo.type = deviceInfo.type;
498             mBaseDisplayInfo.address = deviceInfo.address;
499             mBaseDisplayInfo.deviceProductInfo = deviceInfo.deviceProductInfo;
500             mBaseDisplayInfo.name = deviceInfo.name;
501             mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId;
502             mBaseDisplayInfo.appWidth = maskedWidth;
503             mBaseDisplayInfo.appHeight = maskedHeight;
504             mBaseDisplayInfo.logicalWidth = maskedWidth;
505             mBaseDisplayInfo.logicalHeight = maskedHeight;
506             mBaseDisplayInfo.rotation = Surface.ROTATION_0;
507             mBaseDisplayInfo.modeId = deviceInfo.modeId;
508             mBaseDisplayInfo.renderFrameRate = deviceInfo.renderFrameRate;
509             mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
510             mBaseDisplayInfo.userPreferredModeId = deviceInfo.userPreferredModeId;
511             mBaseDisplayInfo.supportedModes = Arrays.copyOf(
512                     deviceInfo.supportedModes, deviceInfo.supportedModes.length);
513             mBaseDisplayInfo.appsSupportedModes = syntheticModeManager.createAppSupportedModes(
514                     config, mBaseDisplayInfo.supportedModes
515             );
516             mBaseDisplayInfo.colorMode = deviceInfo.colorMode;
517             mBaseDisplayInfo.supportedColorModes = Arrays.copyOf(
518                     deviceInfo.supportedColorModes,
519                     deviceInfo.supportedColorModes.length);
520             mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities;
521             mBaseDisplayInfo.userDisabledHdrTypes = mUserDisabledHdrTypes;
522             mBaseDisplayInfo.minimalPostProcessingSupported =
523                     deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported;
524             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
525             mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
526             mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
527             mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;
528             mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;
529             mBaseDisplayInfo.state = deviceInfo.state;
530             mBaseDisplayInfo.committedState = deviceInfo.committedState;
531             mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth;
532             mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight;
533             mBaseDisplayInfo.largestNominalAppWidth = maskedWidth;
534             mBaseDisplayInfo.largestNominalAppHeight = maskedHeight;
535             mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
536             mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;
537             boolean maskCutout =
538                     (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
539             mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout;
540             mBaseDisplayInfo.displayId = mDisplayId;
541             mBaseDisplayInfo.displayGroupId = mDisplayGroupId;
542             updateFrameRateOverrides(deviceInfo);
543             mBaseDisplayInfo.brightnessMinimum = deviceInfo.brightnessMinimum;
544             mBaseDisplayInfo.brightnessMaximum = deviceInfo.brightnessMaximum;
545             mBaseDisplayInfo.brightnessDefault = deviceInfo.brightnessDefault;
546             mBaseDisplayInfo.hdrSdrRatio = deviceInfo.hdrSdrRatio;
547             mBaseDisplayInfo.roundedCorners = deviceInfo.roundedCorners;
548             mBaseDisplayInfo.installOrientation = deviceInfo.installOrientation;
549             mBaseDisplayInfo.displayShape = deviceInfo.displayShape;
550 
551             if (mDevicePosition == Layout.Display.POSITION_REAR) {
552                 // A rear display is meant to host a specific experience that is essentially
553                 // a presentation to another user or users other than the main user since they
554                 // can't actually see that display. Given that, it's a suitable display for
555                 // presentations but the content should be destroyed rather than moved to a non-rear
556                 // display when the rear display is removed.
557                 mBaseDisplayInfo.flags |= Display.FLAG_REAR;
558                 mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION;
559                 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
560             }
561 
562             mBaseDisplayInfo.layoutLimitedRefreshRate = mLayoutLimitedRefreshRate;
563             mBaseDisplayInfo.thermalRefreshRateThrottling = mThermalRefreshRateThrottling;
564             mBaseDisplayInfo.thermalBrightnessThrottlingDataId = mThermalBrightnessThrottlingDataId;
565 
566             mPrimaryDisplayDeviceInfo = deviceInfo;
567             mInfo.set(null);
568             mDirty = false;
569         }
570     }
571 
updateFrameRateOverrides(DisplayDeviceInfo deviceInfo)572     private void updateFrameRateOverrides(DisplayDeviceInfo deviceInfo) {
573         mTempFrameRateOverride.clear();
574         if (mFrameRateOverrides != null) {
575             for (DisplayEventReceiver.FrameRateOverride frameRateOverride
576                     : mFrameRateOverrides) {
577                 mTempFrameRateOverride.put(frameRateOverride.uid,
578                         frameRateOverride.frameRateHz);
579             }
580         }
581         mFrameRateOverrides = deviceInfo.frameRateOverrides;
582         if (mFrameRateOverrides != null) {
583             for (DisplayEventReceiver.FrameRateOverride frameRateOverride
584                     : mFrameRateOverrides) {
585                 float refreshRate = mTempFrameRateOverride.get(frameRateOverride.uid, 0f);
586                 if (refreshRate == 0 || frameRateOverride.frameRateHz != refreshRate) {
587                     mTempFrameRateOverride.put(frameRateOverride.uid,
588                             frameRateOverride.frameRateHz);
589                 } else {
590                     mTempFrameRateOverride.delete(frameRateOverride.uid);
591                 }
592             }
593         }
594         for (int i = 0; i < mTempFrameRateOverride.size(); i++) {
595             mPendingFrameRateOverrideUids.add(mTempFrameRateOverride.keyAt(i));
596         }
597     }
598 
599     /**
600      * Return the insets currently applied to the display.
601      *
602      * Note that the base DisplayInfo already takes these insets into account, so if you want to
603      * find out the <b>true</b> size of the display, you need to add them back to the logical
604      * dimensions.
605      */
getInsets()606     public Rect getInsets() {
607         return getMaskingInsets(mPrimaryDisplayDeviceInfo);
608     }
609 
610     /**
611      * Returns insets in ROTATION_0 for areas that are masked.
612      */
getMaskingInsets(DisplayDeviceInfo deviceInfo)613     private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) {
614         boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
615         if (maskCutout && deviceInfo.displayCutout != null) {
616             // getSafeInsets is fixed at creation time and cannot change
617             return deviceInfo.displayCutout.getSafeInsets();
618         } else {
619             return new Rect();
620         }
621     }
622 
623     /**
624      * Returns the position of the display's projection.
625      *
626      * @return The x, y coordinates of the display. The return object must be treated as immutable.
627      */
getDisplayPosition()628     Point getDisplayPosition() {
629         // Allocate a new object to avoid a data race.
630         return new Point(mDisplayPosition);
631     }
632 
633     /**
634      * Applies the layer stack and transformation to the given display device
635      * so that it shows the contents of this logical display.
636      *
637      * We know that the given display device is only ever showing the contents of
638      * a single logical display, so this method is expected to blow away all of its
639      * transformation properties to make it happen regardless of what the
640      * display device was previously showing.
641      *
642      * The caller must have an open Surface transaction.
643      *
644      * The display device may not be the primary display device, in the case
645      * where the display is being mirrored.
646      *
647      * @param device The display device to modify.
648      * @param isBlanked True if the device is being blanked.
649      */
configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device, boolean isBlanked)650     public void configureDisplayLocked(SurfaceControl.Transaction t,
651             DisplayDevice device,
652             boolean isBlanked) {
653         // Set the layer stack.
654         device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack, mDisplayId);
655         // Also inform whether the device is the same one sent to inputflinger for its layerstack.
656         // Prevent displays that are disabled from receiving input.
657         // TODO(b/188914255): Remove once input can dispatch against device vs layerstack.
658         device.setDisplayFlagsLocked(t,
659                 (isEnabledLocked() && device.getDisplayDeviceInfoLocked().touch != TOUCH_NONE)
660                         ? SurfaceControl.DISPLAY_RECEIVES_INPUT
661                         : 0);
662 
663         // Set the color mode and allowed display mode.
664         if (device == mPrimaryDisplayDevice) {
665             device.setDesiredDisplayModeSpecsLocked(mDesiredDisplayModeSpecs);
666             device.setRequestedColorModeLocked(mRequestedColorMode);
667         } else {
668             // Reset to default for non primary displays
669             device.setDesiredDisplayModeSpecsLocked(
670                     new DisplayModeDirector.DesiredDisplayModeSpecs());
671             device.setRequestedColorModeLocked(0);
672         }
673 
674         device.setAutoLowLatencyModeLocked(mRequestedMinimalPostProcessing);
675         device.setGameContentTypeLocked(mRequestedMinimalPostProcessing);
676 
677         // Only grab the display info now as it may have been changed based on the requests above.
678         final DisplayInfo displayInfo = getDisplayInfoLocked();
679         final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
680 
681         // Set the viewport.
682         // This is the area of the logical display that we intend to show on the
683         // display device.  For now, it is always the full size of the logical display.
684         mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
685 
686         // Set the orientation.
687         // The orientation specifies how the physical coordinate system of the display
688         // is rotated when the contents of the logical display are rendered.
689         int orientation = Surface.ROTATION_0;
690 
691         // FLAG_ROTATES_WITH_CONTENT is now handled in DisplayContent. When the flag
692         // mAlwaysRotateDisplayDeviceEnabled is removed, we should also remove this check for
693         // ROTATES_WITH_CONTENT here and always set the orientation.
694         if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0
695                     || mAlwaysRotateDisplayDeviceEnabled) {
696             orientation = displayInfo.rotation;
697         }
698 
699         // Apply the physical rotation of the display device itself.
700         orientation = (orientation + displayDeviceInfo.rotation) % 4;
701 
702         // Set the frame.
703         // The frame specifies the rotated physical coordinates into which the viewport
704         // is mapped.  We need to take care to preserve the aspect ratio of the viewport.
705         // Currently we maximize the area to fill the display, but we could try to be
706         // more clever and match resolutions.
707         boolean rotated = (orientation == Surface.ROTATION_90
708                 || orientation == Surface.ROTATION_270);
709         int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
710         int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
711 
712         Rect maskingInsets = getMaskingInsets(displayDeviceInfo);
713         InsetUtils.rotateInsets(maskingInsets, orientation);
714         // Don't consider the masked area as available when calculating the scaling below.
715         physWidth -= maskingInsets.left + maskingInsets.right;
716         physHeight -= maskingInsets.top + maskingInsets.bottom;
717 
718         var displayLogicalWidth = displayInfo.logicalWidth;
719         var displayLogicalHeight = displayInfo.logicalHeight;
720 
721         if (mIsAnisotropyCorrectionEnabled && displayDeviceInfo.type == Display.TYPE_EXTERNAL
722                     && displayDeviceInfo.xDpi > 0 && displayDeviceInfo.yDpi > 0) {
723             if (displayDeviceInfo.xDpi > displayDeviceInfo.yDpi * DisplayDevice.MAX_ANISOTROPY) {
724                 var scalingFactor = displayDeviceInfo.yDpi / displayDeviceInfo.xDpi;
725                 if (rotated) {
726                     displayLogicalWidth = (int) ((float) displayLogicalWidth * scalingFactor + 0.5);
727                 } else {
728                     displayLogicalHeight = (int) ((float) displayLogicalHeight * scalingFactor
729                                                           + 0.5);
730                 }
731             } else if (displayDeviceInfo.xDpi * DisplayDevice.MAX_ANISOTROPY
732                                < displayDeviceInfo.yDpi) {
733                 var scalingFactor = displayDeviceInfo.xDpi / displayDeviceInfo.yDpi;
734                 if (rotated) {
735                     displayLogicalHeight = (int) ((float) displayLogicalHeight * scalingFactor
736                                                           + 0.5);
737                 } else {
738                     displayLogicalWidth = (int) ((float) displayLogicalWidth * scalingFactor + 0.5);
739                 }
740             }
741         }
742 
743         // Determine whether the width or height is more constrained to be scaled.
744         //    physWidth / displayInfo.logicalWidth    => letter box
745         // or physHeight / displayInfo.logicalHeight  => pillar box
746         //
747         // We avoid a division (and possible floating point imprecision) here by
748         // multiplying the fractions by the product of their denominators before
749         // comparing them.
750         int displayRectWidth, displayRectHeight;
751         if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0 || mDisplayScalingDisabled) {
752             displayRectWidth = displayLogicalWidth;
753             displayRectHeight = displayLogicalHeight;
754         } else if (physWidth * displayLogicalHeight
755                 < physHeight * displayLogicalWidth) {
756             // Letter box.
757             displayRectWidth = physWidth;
758             displayRectHeight = displayLogicalHeight * physWidth / displayLogicalWidth;
759         } else {
760             // Pillar box.
761             displayRectWidth = displayLogicalWidth * physHeight / displayLogicalHeight;
762             displayRectHeight = physHeight;
763         }
764         int displayRectTop = (physHeight - displayRectHeight) / 2;
765         int displayRectLeft = (physWidth - displayRectWidth) / 2;
766         mTempDisplayRect.set(displayRectLeft, displayRectTop,
767                 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
768 
769         // Now add back the offset for the masked area.
770         mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top);
771 
772         if (orientation == Surface.ROTATION_0) {
773             mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY);
774         } else if (orientation == Surface.ROTATION_90) {
775             mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX);
776         } else if (orientation == Surface.ROTATION_180) {
777             mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY);
778         } else {  // Surface.ROTATION_270
779             mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX);
780         }
781 
782         mDisplayPosition.set(mTempDisplayRect.left, mTempDisplayRect.top);
783         device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect);
784     }
785 
786     /**
787      * Returns true if the logical display has unique content.
788      * <p>
789      * If the display has unique content then we will try to ensure that it is
790      * visible on at least its primary display device.  Otherwise we will ignore the
791      * logical display and perhaps show mirrored content on the primary display device.
792      * </p>
793      *
794      * @return True if the display has unique content.
795      */
hasContentLocked()796     public boolean hasContentLocked() {
797         return mHasContent;
798     }
799 
800     /**
801      * Sets whether the logical display has unique content.
802      *
803      * @param hasContent True if the display has unique content.
804      */
setHasContentLocked(boolean hasContent)805     public void setHasContentLocked(boolean hasContent) {
806         mHasContent = hasContent;
807     }
808 
809     /**
810      * Sets the display configs the system can use.
811      */
setDesiredDisplayModeSpecsLocked( DisplayModeDirector.DesiredDisplayModeSpecs specs)812     public void setDesiredDisplayModeSpecsLocked(
813             DisplayModeDirector.DesiredDisplayModeSpecs specs) {
814         mDesiredDisplayModeSpecs = specs;
815     }
816 
817     /**
818      * Returns the display configs the system can choose.
819      */
getDesiredDisplayModeSpecsLocked()820     public DisplayModeDirector.DesiredDisplayModeSpecs getDesiredDisplayModeSpecsLocked() {
821         return mDesiredDisplayModeSpecs;
822     }
823 
824     /**
825      * Requests the given color mode.
826      */
setRequestedColorModeLocked(int colorMode)827     public void setRequestedColorModeLocked(int colorMode) {
828         mRequestedColorMode = colorMode;
829     }
830 
831     /**
832      * Returns the last requested minimal post processing setting.
833      */
getRequestedMinimalPostProcessingLocked()834     public boolean getRequestedMinimalPostProcessingLocked() {
835         return mRequestedMinimalPostProcessing;
836     }
837 
838     /**
839      * Instructs the connected display to do minimal post processing. This is implemented either
840      * via HDMI 2.1 ALLM or HDMI 1.4 ContentType=Game.
841      *
842      * @param on Whether to set minimal post processing on/off on the connected display.
843      */
setRequestedMinimalPostProcessingLocked(boolean on)844     public void setRequestedMinimalPostProcessingLocked(boolean on) {
845         mRequestedMinimalPostProcessing = on;
846     }
847 
848     /** Returns the pending requested color mode. */
getRequestedColorModeLocked()849     public int getRequestedColorModeLocked() {
850         return mRequestedColorMode;
851     }
852 
853     /**
854      * Gets the burn-in offset in X.
855      */
getDisplayOffsetXLocked()856     public int getDisplayOffsetXLocked() {
857         return mDisplayOffsetX;
858     }
859 
860     /**
861      * Gets the burn-in offset in Y.
862      */
getDisplayOffsetYLocked()863     public int getDisplayOffsetYLocked() {
864         return mDisplayOffsetY;
865     }
866 
867     /**
868      * Sets the burn-in offsets.
869      */
setDisplayOffsetsLocked(int x, int y)870     public void setDisplayOffsetsLocked(int x, int y) {
871         mDisplayOffsetX = x;
872         mDisplayOffsetY = y;
873     }
874 
875     /**
876      * @return {@code true} if display scaling is disabled, or {@code false} if the default scaling
877      * mode is used.
878      */
isDisplayScalingDisabled()879     public boolean isDisplayScalingDisabled() {
880         return mDisplayScalingDisabled;
881     }
882 
883     /**
884      * Disables scaling for a display.
885      *
886      * @param disableScaling {@code true} to disable scaling,
887      * {@code false} to use the default scaling behavior of the logical display.
888      */
setDisplayScalingDisabledLocked(boolean disableScaling)889     public void setDisplayScalingDisabledLocked(boolean disableScaling) {
890         mDisplayScalingDisabled = disableScaling;
891     }
892 
setUserDisabledHdrTypes(@onNull int[] userDisabledHdrTypes)893     public void setUserDisabledHdrTypes(@NonNull int[] userDisabledHdrTypes) {
894         if (mUserDisabledHdrTypes != userDisabledHdrTypes) {
895             mUserDisabledHdrTypes = userDisabledHdrTypes;
896             mBaseDisplayInfo.userDisabledHdrTypes = userDisabledHdrTypes;
897             mInfo.set(null);
898         }
899     }
900 
901     /**
902      * Swap the underlying {@link DisplayDevice} with the specified LogicalDisplay.
903      *
904      * @param targetDisplay The display with which to swap display-devices.
905      * @return {@code true} if the displays were swapped, {@code false} otherwise.
906      */
swapDisplaysLocked(@onNull LogicalDisplay targetDisplay)907     public void swapDisplaysLocked(@NonNull LogicalDisplay targetDisplay) {
908         final DisplayDevice oldTargetDevice =
909                 targetDisplay.setPrimaryDisplayDeviceLocked(mPrimaryDisplayDevice);
910         setPrimaryDisplayDeviceLocked(oldTargetDevice);
911     }
912 
913     /**
914      * Sets the primary display device to the specified device.
915      *
916      * @param device The new device to set.
917      * @return The previously set display device.
918      */
setPrimaryDisplayDeviceLocked(@ullable DisplayDevice device)919     public DisplayDevice setPrimaryDisplayDeviceLocked(@Nullable DisplayDevice device) {
920         final DisplayDevice old = mPrimaryDisplayDevice;
921         mPrimaryDisplayDevice = device;
922 
923         // Reset all our display info data
924         mPrimaryDisplayDeviceInfo = null;
925         mBaseDisplayInfo.copyFrom(EMPTY_DISPLAY_INFO);
926         mInfo.set(null);
927 
928         return old;
929     }
930 
931     /**
932      * @return {@code true} if the LogicalDisplay is enabled or {@code false}
933      * if disabled indicating that the display should be hidden from the rest of the apps and
934      * framework.
935      */
isEnabledLocked()936     public boolean isEnabledLocked() {
937         return mIsEnabled;
938     }
939 
940     /**
941      * Sets the display as enabled.
942      *
943      * @param enabled True if enabled, false otherwise.
944      */
setEnabledLocked(boolean enabled)945     public void setEnabledLocked(boolean enabled) {
946         if (enabled != mIsEnabled) {
947             mDirty = true;
948             mIsEnabled = enabled;
949         }
950     }
951 
952     /**
953      * @return {@code true} if the LogicalDisplay is in a transition phase. This is used to indicate
954      * that we are getting ready to swap the underlying display-device and the display should be
955      * rendered appropriately to reduce jank.
956      */
isInTransitionLocked()957     public boolean isInTransitionLocked() {
958         return mIsInTransition;
959     }
960 
961     /**
962      * Sets the transition phase.
963      * @param isInTransition True if it display is in transition.
964      */
setIsInTransitionLocked(boolean isInTransition)965     public void setIsInTransitionLocked(boolean isInTransition) {
966         mIsInTransition = isInTransition;
967     }
968 
969     /**
970      * @param brightnessThrottlingDataId The ID of the brightness throttling data that this
971      *                                  display should use.
972      */
setThermalBrightnessThrottlingDataIdLocked(String brightnessThrottlingDataId)973     public void setThermalBrightnessThrottlingDataIdLocked(String brightnessThrottlingDataId) {
974         if (!Objects.equals(brightnessThrottlingDataId, mThermalBrightnessThrottlingDataId)) {
975             mThermalBrightnessThrottlingDataId = brightnessThrottlingDataId;
976             mDirty = true;
977         }
978     }
979 
980     /**
981      * @param powerThrottlingDataId The ID of the brightness throttling data that this
982      *                                  display should use.
983      */
setPowerThrottlingDataIdLocked(String powerThrottlingDataId)984     public void setPowerThrottlingDataIdLocked(String powerThrottlingDataId) {
985         if (!Objects.equals(powerThrottlingDataId, mPowerThrottlingDataId)) {
986             mPowerThrottlingDataId = powerThrottlingDataId;
987             mDirty = true;
988         }
989     }
990 
991     /**
992      * Returns powerThrottlingDataId which is the ID of the brightness
993      * throttling data that this display should use.
994      */
getPowerThrottlingDataIdLocked()995     public String getPowerThrottlingDataIdLocked() {
996         return mPowerThrottlingDataId;
997     }
998 
999     /**
1000      * Sets the display of which this display is a follower, regarding brightness or other
1001      * properties. If set to {@link Layout#NO_LEAD_DISPLAY}, this display does not follow any
1002      * others, and has the potential to be a lead display to others.
1003      *
1004      * A display cannot be a leader or follower of itself, and there cannot be cycles.
1005      * A display cannot be both a leader and a follower, ie, there must not be any chains.
1006      *
1007      * @param displayId logical display id
1008      */
setLeadDisplayLocked(int displayId)1009     public void setLeadDisplayLocked(int displayId) {
1010         if (mDisplayId != mLeadDisplayId && mDisplayId != displayId) {
1011             mLeadDisplayId = displayId;
1012         }
1013     }
1014 
getLeadDisplayIdLocked()1015     public int getLeadDisplayIdLocked() {
1016         return mLeadDisplayId;
1017     }
1018 
1019     /**
1020      * Sets the name of display group to which the display is assigned.
1021      */
setDisplayGroupNameLocked(String displayGroupName)1022     public void setDisplayGroupNameLocked(String displayGroupName) {
1023         mDisplayGroupName = displayGroupName;
1024     }
1025 
1026     /**
1027      * Gets the name of display group to which the display is assigned.
1028      */
getDisplayGroupNameLocked()1029     public String getDisplayGroupNameLocked() {
1030         return mDisplayGroupName;
1031     }
1032 
setDisplayOffloadSessionLocked(DisplayOffloadSessionImpl session)1033     public void setDisplayOffloadSessionLocked(DisplayOffloadSessionImpl session) {
1034         mDisplayOffloadSession = session;
1035     }
1036 
getDisplayOffloadSessionLocked()1037     public DisplayOffloadSessionImpl getDisplayOffloadSessionLocked() {
1038         return mDisplayOffloadSession;
1039     }
1040 
dumpLocked(PrintWriter pw)1041     public void dumpLocked(PrintWriter pw) {
1042         pw.println("mDisplayId=" + mDisplayId);
1043         pw.println("mIsEnabled=" + mIsEnabled);
1044         pw.println("mIsInTransition=" + mIsInTransition);
1045         pw.println("mLayerStack=" + mLayerStack);
1046         pw.println("mPosition=" + mDevicePosition);
1047         pw.println("mHasContent=" + mHasContent);
1048         pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
1049         pw.println("mRequestedColorMode=" + mRequestedColorMode);
1050         pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
1051         pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled);
1052         pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
1053                 mPrimaryDisplayDevice.getNameLocked() : "null"));
1054         pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
1055         pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo);
1056         pw.println("mRequestedMinimalPostProcessing=" + mRequestedMinimalPostProcessing);
1057         pw.println("mFrameRateOverrides=" + Arrays.toString(mFrameRateOverrides));
1058         pw.println("mPendingFrameRateOverrideUids=" + mPendingFrameRateOverrideUids);
1059         pw.println("mDisplayGroupName=" + mDisplayGroupName);
1060         pw.println("mThermalBrightnessThrottlingDataId=" + mThermalBrightnessThrottlingDataId);
1061         pw.println("mLeadDisplayId=" + mLeadDisplayId);
1062         pw.println("mLayoutLimitedRefreshRate=" + mLayoutLimitedRefreshRate);
1063         pw.println("mThermalRefreshRateThrottling=" + mThermalRefreshRateThrottling);
1064         pw.println("mPowerThrottlingDataId=" + mPowerThrottlingDataId);
1065     }
1066 
1067     @Override
toString()1068     public String toString() {
1069         StringWriter sw = new StringWriter();
1070         dumpLocked(new PrintWriter(sw));
1071         return sw.toString();
1072     }
1073 }
1074