• 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 com.android.server.display;
18 
19 import android.annotation.IntDef;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.graphics.Point;
23 import android.graphics.Rect;
24 import android.hardware.display.DisplayManagerInternal;
25 import android.util.ArraySet;
26 import android.util.SparseArray;
27 import android.view.Display;
28 import android.view.DisplayEventReceiver;
29 import android.view.DisplayInfo;
30 import android.view.Surface;
31 import android.view.SurfaceControl;
32 
33 import com.android.server.wm.utils.InsetUtils;
34 
35 import java.io.PrintWriter;
36 import java.io.StringWriter;
37 import java.util.Arrays;
38 import java.util.Objects;
39 
40 /**
41  * Describes how a logical display is configured.
42  * <p>
43  * At this time, we only support logical displays that are coupled to a particular
44  * primary display device from which the logical display derives its basic properties
45  * such as its size, density and refresh rate.
46  * </p><p>
47  * A logical display may be mirrored onto multiple display devices in addition to its
48  * primary display device.  Note that the contents of a logical display may not
49  * always be visible, even on its primary display device, such as in the case where
50  * the primary display device is currently mirroring content from a different
51  * logical display.
52  * </p><p>
53  * This object is designed to encapsulate as much of the policy of logical
54  * displays as possible.  The idea is to make it easy to implement new kinds of
55  * logical displays mostly by making local changes to this class.
56  * </p><p>
57  * Note: The display manager architecture does not actually require logical displays
58  * to be associated with any individual display device.  Logical displays and
59  * display devices are orthogonal concepts.  Some mapping will exist between
60  * logical displays and display devices but it can be many-to-many and
61  * and some might have no relation at all.
62  * </p><p>
63  * Logical displays are guarded by the {@link DisplayManagerService.SyncRoot} lock.
64  * </p>
65  */
66 final class LogicalDisplay {
67     private static final String TAG = "LogicalDisplay";
68 
69     /**
70      * Phase indicating the logical display's existence is hidden from the rest of the framework.
71      * This can happen if the current layout has specifically requested to keep this display
72      * disabled.
73      */
74     static final int DISPLAY_PHASE_DISABLED = -1;
75 
76     /**
77      * Phase indicating that the logical display is going through a layout transition.
78      * When in this phase, other systems can choose to special case power-state handling of a
79      * display that might be in a transition.
80      */
81     static final int DISPLAY_PHASE_LAYOUT_TRANSITION = 0;
82 
83     /**
84      * The display is exposed to the rest of the system and its power state is determined by a
85      * power-request from PowerManager.
86      */
87     static final int DISPLAY_PHASE_ENABLED = 1;
88 
89     @IntDef(prefix = {"DISPLAY_PHASE" }, value = {
90         DISPLAY_PHASE_DISABLED,
91         DISPLAY_PHASE_LAYOUT_TRANSITION,
92         DISPLAY_PHASE_ENABLED
93     })
94     @interface DisplayPhase {}
95 
96     // The layer stack we use when the display has been blanked to prevent any
97     // of its content from appearing.
98     private static final int BLANK_LAYER_STACK = -1;
99 
100     private static final DisplayInfo EMPTY_DISPLAY_INFO = new DisplayInfo();
101 
102     private final DisplayInfo mBaseDisplayInfo = new DisplayInfo();
103     private final int mDisplayId;
104     private final int mLayerStack;
105 
106     private int mDisplayGroupId = Display.INVALID_DISPLAY_GROUP;
107 
108     /**
109      * Override information set by the window manager. Will be reported instead of {@link #mInfo}
110      * if not null.
111      * @see #setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo)
112      * @see #getDisplayInfoLocked()
113      */
114     private DisplayInfo mOverrideDisplayInfo;
115     /**
116      * Current display info. Initialized with {@link #mBaseDisplayInfo}. Set to {@code null} if
117      * needs to be updated.
118      * @see #getDisplayInfoLocked()
119      */
120     private final DisplayInfoProxy mInfo = new DisplayInfoProxy(null);
121 
122     // The display device that this logical display is based on and which
123     // determines the base metrics that it uses.
124     private DisplayDevice mPrimaryDisplayDevice;
125     private DisplayDeviceInfo mPrimaryDisplayDeviceInfo;
126 
127     // True if the logical display has unique content.
128     private boolean mHasContent;
129 
130     private int mRequestedColorMode;
131     private boolean mRequestedMinimalPostProcessing;
132 
133     private int[] mUserDisabledHdrTypes = {};
134 
135     private DisplayModeDirector.DesiredDisplayModeSpecs mDesiredDisplayModeSpecs =
136             new DisplayModeDirector.DesiredDisplayModeSpecs();
137 
138     // The display offsets to apply to the display projection.
139     private int mDisplayOffsetX;
140     private int mDisplayOffsetY;
141 
142     /**
143      * The position of the display projection sent to SurfaceFlinger
144      */
145     private final Point mDisplayPosition = new Point();
146 
147     /**
148      * {@code true} if display scaling is disabled, or {@code false} if the default scaling mode
149      * is used.
150      * @see #isDisplayScalingDisabled()
151      * @see #setDisplayScalingDisabledLocked(boolean)
152      */
153     private boolean mDisplayScalingDisabled;
154 
155     // Temporary rectangle used when needed.
156     private final Rect mTempLayerStackRect = new Rect();
157     private final Rect mTempDisplayRect = new Rect();
158 
159     /**
160      * Indicates the current phase of the display. Generally, phases supersede any
161      * requests from PowerManager in DPC's calculation for the display state. Only when the
162      * phase is ENABLED does PowerManager's request for the display take effect.
163      */
164     @DisplayPhase
165     private int mPhase = DISPLAY_PHASE_ENABLED;
166 
167     /**
168      * The UID mappings for refresh rate override
169      */
170     private DisplayEventReceiver.FrameRateOverride[] mFrameRateOverrides;
171 
172     /**
173      * Holds a set of UIDs that their frame rate override changed and needs to be notified
174      */
175     private ArraySet<Integer> mPendingFrameRateOverrideUids;
176 
177     /**
178      * Temporary frame rate override list, used when needed.
179      */
180     private final SparseArray<Float> mTempFrameRateOverride;
181 
LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice)182     public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice) {
183         mDisplayId = displayId;
184         mLayerStack = layerStack;
185         mPrimaryDisplayDevice = primaryDisplayDevice;
186         mPendingFrameRateOverrideUids = new ArraySet<>();
187         mTempFrameRateOverride = new SparseArray<>();
188     }
189 
190     /**
191      * Gets the logical display id of this logical display.
192      *
193      * @return The logical display id.
194      */
getDisplayIdLocked()195     public int getDisplayIdLocked() {
196         return mDisplayId;
197     }
198 
199     /**
200      * Gets the primary display device associated with this logical display.
201      *
202      * @return The primary display device.
203      */
getPrimaryDisplayDeviceLocked()204     public DisplayDevice getPrimaryDisplayDeviceLocked() {
205         return mPrimaryDisplayDevice;
206     }
207 
208     /**
209      * Gets information about the logical display.
210      *
211      * @return The device info, which should be treated as immutable by the caller.
212      * The logical display should allocate a new display info object whenever
213      * the data changes.
214      */
getDisplayInfoLocked()215     public DisplayInfo getDisplayInfoLocked() {
216         if (mInfo.get() == null) {
217             DisplayInfo info = new DisplayInfo();
218             info.copyFrom(mBaseDisplayInfo);
219             if (mOverrideDisplayInfo != null) {
220                 info.appWidth = mOverrideDisplayInfo.appWidth;
221                 info.appHeight = mOverrideDisplayInfo.appHeight;
222                 info.smallestNominalAppWidth = mOverrideDisplayInfo.smallestNominalAppWidth;
223                 info.smallestNominalAppHeight = mOverrideDisplayInfo.smallestNominalAppHeight;
224                 info.largestNominalAppWidth = mOverrideDisplayInfo.largestNominalAppWidth;
225                 info.largestNominalAppHeight = mOverrideDisplayInfo.largestNominalAppHeight;
226                 info.logicalWidth = mOverrideDisplayInfo.logicalWidth;
227                 info.logicalHeight = mOverrideDisplayInfo.logicalHeight;
228                 info.rotation = mOverrideDisplayInfo.rotation;
229                 info.displayCutout = mOverrideDisplayInfo.displayCutout;
230                 info.logicalDensityDpi = mOverrideDisplayInfo.logicalDensityDpi;
231                 info.physicalXDpi = mOverrideDisplayInfo.physicalXDpi;
232                 info.physicalYDpi = mOverrideDisplayInfo.physicalYDpi;
233                 info.roundedCorners = mOverrideDisplayInfo.roundedCorners;
234             }
235             mInfo.set(info);
236         }
237         return mInfo.get();
238     }
239 
240     /**
241      * Returns the frame rate overrides list
242      */
getFrameRateOverrides()243     public DisplayEventReceiver.FrameRateOverride[] getFrameRateOverrides() {
244         return mFrameRateOverrides;
245     }
246 
247     /**
248      * Returns the list of uids that needs to be updated about their frame rate override
249      */
getPendingFrameRateOverrideUids()250     public ArraySet<Integer> getPendingFrameRateOverrideUids() {
251         return mPendingFrameRateOverrideUids;
252     }
253 
254     /**
255      * Clears the list of uids that needs to be updated about their frame rate override
256      */
clearPendingFrameRateOverrideUids()257     public void clearPendingFrameRateOverrideUids() {
258         mPendingFrameRateOverrideUids = new ArraySet<>();
259     }
260 
261     /**
262      * @see DisplayManagerInternal#getNonOverrideDisplayInfo(int, DisplayInfo)
263      */
getNonOverrideDisplayInfoLocked(DisplayInfo outInfo)264     void getNonOverrideDisplayInfoLocked(DisplayInfo outInfo) {
265         outInfo.copyFrom(mBaseDisplayInfo);
266     }
267 
268     /**
269      * Sets overridden logical display information from the window manager.
270      * This method can be used to adjust application insets, rotation, and other
271      * properties that the window manager takes care of.
272      *
273      * @param info The logical display information, may be null.
274      */
setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info)275     public boolean setDisplayInfoOverrideFromWindowManagerLocked(DisplayInfo info) {
276         if (info != null) {
277             if (mOverrideDisplayInfo == null) {
278                 mOverrideDisplayInfo = new DisplayInfo(info);
279                 mInfo.set(null);
280                 return true;
281             } else if (!mOverrideDisplayInfo.equals(info)) {
282                 mOverrideDisplayInfo.copyFrom(info);
283                 mInfo.set(null);
284                 return true;
285             }
286         } else if (mOverrideDisplayInfo != null) {
287             mOverrideDisplayInfo = null;
288             mInfo.set(null);
289             return true;
290         }
291         return false;
292     }
293 
294     /**
295      * Returns true if the logical display is in a valid state.
296      * This method should be checked after calling {@link #updateLocked} to handle the
297      * case where a logical display should be removed because all of its associated
298      * display devices are gone or if it is otherwise no longer needed.
299      *
300      * @return True if the logical display is still valid.
301      */
isValidLocked()302     public boolean isValidLocked() {
303         return mPrimaryDisplayDevice != null;
304     }
305 
306     /**
307      * Updates the {@link DisplayGroup} to which the logical display belongs.
308      *
309      * @param groupId Identifier for the {@link DisplayGroup}.
310      */
updateDisplayGroupIdLocked(int groupId)311     public void updateDisplayGroupIdLocked(int groupId) {
312         if (groupId != mDisplayGroupId) {
313             mDisplayGroupId = groupId;
314             mBaseDisplayInfo.displayGroupId = groupId;
315             mInfo.set(null);
316         }
317     }
318 
319     /**
320      * Updates the state of the logical display based on the available display devices.
321      * The logical display might become invalid if it is attached to a display device
322      * that no longer exists.
323      *
324      * @param deviceRepo Repository of active {@link DisplayDevice}s.
325      */
updateLocked(DisplayDeviceRepository deviceRepo)326     public void updateLocked(DisplayDeviceRepository deviceRepo) {
327         // Nothing to update if already invalid.
328         if (mPrimaryDisplayDevice == null) {
329             return;
330         }
331 
332         // Check whether logical display has become invalid.
333         if (!deviceRepo.containsLocked(mPrimaryDisplayDevice)) {
334             setPrimaryDisplayDeviceLocked(null);
335             return;
336         }
337 
338         // Bootstrap the logical display using its associated primary physical display.
339         // We might use more elaborate configurations later.  It's possible that the
340         // configuration of several physical displays might be used to determine the
341         // logical display that they are sharing.  (eg. Adjust size for pixel-perfect
342         // mirroring over HDMI.)
343         DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked();
344         if (!Objects.equals(mPrimaryDisplayDeviceInfo, deviceInfo)) {
345             mBaseDisplayInfo.layerStack = mLayerStack;
346             mBaseDisplayInfo.flags = 0;
347             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
348                 mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
349             }
350             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) {
351                 mBaseDisplayInfo.flags |= Display.FLAG_SECURE;
352             }
353             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) {
354                 mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE;
355                 // For private displays by default content is destroyed on removal.
356                 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
357             }
358             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_DESTROY_CONTENT_ON_REMOVAL) != 0) {
359                 mBaseDisplayInfo.removeMode = Display.REMOVE_MODE_DESTROY_CONTENT;
360             }
361             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRESENTATION) != 0) {
362                 mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION;
363             }
364             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_ROUND) != 0) {
365                 mBaseDisplayInfo.flags |= Display.FLAG_ROUND;
366             }
367             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
368                 mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
369             }
370             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS) != 0) {
371                 mBaseDisplayInfo.flags |= Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
372             }
373             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_TRUSTED) != 0) {
374                 mBaseDisplayInfo.flags |= Display.FLAG_TRUSTED;
375             }
376             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_OWN_DISPLAY_GROUP) != 0) {
377                 mBaseDisplayInfo.flags |= Display.FLAG_OWN_DISPLAY_GROUP;
378             }
379             Rect maskingInsets = getMaskingInsets(deviceInfo);
380             int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right;
381             int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom;
382 
383             mBaseDisplayInfo.type = deviceInfo.type;
384             mBaseDisplayInfo.address = deviceInfo.address;
385             mBaseDisplayInfo.deviceProductInfo = deviceInfo.deviceProductInfo;
386             mBaseDisplayInfo.name = deviceInfo.name;
387             mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId;
388             mBaseDisplayInfo.appWidth = maskedWidth;
389             mBaseDisplayInfo.appHeight = maskedHeight;
390             mBaseDisplayInfo.logicalWidth = maskedWidth;
391             mBaseDisplayInfo.logicalHeight = maskedHeight;
392             mBaseDisplayInfo.rotation = Surface.ROTATION_0;
393             mBaseDisplayInfo.modeId = deviceInfo.modeId;
394             mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
395             mBaseDisplayInfo.supportedModes = Arrays.copyOf(
396                     deviceInfo.supportedModes, deviceInfo.supportedModes.length);
397             mBaseDisplayInfo.colorMode = deviceInfo.colorMode;
398             mBaseDisplayInfo.supportedColorModes = Arrays.copyOf(
399                     deviceInfo.supportedColorModes,
400                     deviceInfo.supportedColorModes.length);
401             mBaseDisplayInfo.hdrCapabilities = deviceInfo.hdrCapabilities;
402             mBaseDisplayInfo.userDisabledHdrTypes = mUserDisabledHdrTypes;
403             mBaseDisplayInfo.minimalPostProcessingSupported =
404                     deviceInfo.allmSupported || deviceInfo.gameContentTypeSupported;
405             mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
406             mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
407             mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
408             mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;
409             mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;
410             mBaseDisplayInfo.state = deviceInfo.state;
411             mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth;
412             mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight;
413             mBaseDisplayInfo.largestNominalAppWidth = maskedWidth;
414             mBaseDisplayInfo.largestNominalAppHeight = maskedHeight;
415             mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
416             mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;
417             boolean maskCutout =
418                     (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
419             mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout;
420             mBaseDisplayInfo.displayId = mDisplayId;
421             mBaseDisplayInfo.displayGroupId = mDisplayGroupId;
422             updateFrameRateOverrides(deviceInfo);
423             mBaseDisplayInfo.brightnessMinimum = deviceInfo.brightnessMinimum;
424             mBaseDisplayInfo.brightnessMaximum = deviceInfo.brightnessMaximum;
425             mBaseDisplayInfo.brightnessDefault = deviceInfo.brightnessDefault;
426             mBaseDisplayInfo.roundedCorners = deviceInfo.roundedCorners;
427             mPrimaryDisplayDeviceInfo = deviceInfo;
428             mInfo.set(null);
429         }
430     }
431 
updateFrameRateOverrides(DisplayDeviceInfo deviceInfo)432     private void updateFrameRateOverrides(DisplayDeviceInfo deviceInfo) {
433         mTempFrameRateOverride.clear();
434         if (mFrameRateOverrides != null) {
435             for (DisplayEventReceiver.FrameRateOverride frameRateOverride
436                     : mFrameRateOverrides) {
437                 mTempFrameRateOverride.put(frameRateOverride.uid,
438                         frameRateOverride.frameRateHz);
439             }
440         }
441         mFrameRateOverrides = deviceInfo.frameRateOverrides;
442         if (mFrameRateOverrides != null) {
443             for (DisplayEventReceiver.FrameRateOverride frameRateOverride
444                     : mFrameRateOverrides) {
445                 float refreshRate = mTempFrameRateOverride.get(frameRateOverride.uid, 0f);
446                 if (refreshRate == 0 || frameRateOverride.frameRateHz != refreshRate) {
447                     mTempFrameRateOverride.put(frameRateOverride.uid,
448                             frameRateOverride.frameRateHz);
449                 } else {
450                     mTempFrameRateOverride.delete(frameRateOverride.uid);
451                 }
452             }
453         }
454         for (int i = 0; i < mTempFrameRateOverride.size(); i++) {
455             mPendingFrameRateOverrideUids.add(mTempFrameRateOverride.keyAt(i));
456         }
457     }
458 
459     /**
460      * Return the insets currently applied to the display.
461      *
462      * Note that the base DisplayInfo already takes these insets into account, so if you want to
463      * find out the <b>true</b> size of the display, you need to add them back to the logical
464      * dimensions.
465      */
getInsets()466     public Rect getInsets() {
467         return getMaskingInsets(mPrimaryDisplayDeviceInfo);
468     }
469 
470     /**
471      * Returns insets in ROTATION_0 for areas that are masked.
472      */
getMaskingInsets(DisplayDeviceInfo deviceInfo)473     private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) {
474         boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
475         if (maskCutout && deviceInfo.displayCutout != null) {
476             // getSafeInsets is fixed at creation time and cannot change
477             return deviceInfo.displayCutout.getSafeInsets();
478         } else {
479             return new Rect();
480         }
481     }
482 
483     /**
484      * Returns the position of the display's projection.
485      *
486      * @return The x, y coordinates of the display. The return object must be treated as immutable.
487      */
getDisplayPosition()488     Point getDisplayPosition() {
489         // Allocate a new object to avoid a data race.
490         return new Point(mDisplayPosition);
491     }
492 
493     /**
494      * Applies the layer stack and transformation to the given display device
495      * so that it shows the contents of this logical display.
496      *
497      * We know that the given display device is only ever showing the contents of
498      * a single logical display, so this method is expected to blow away all of its
499      * transformation properties to make it happen regardless of what the
500      * display device was previously showing.
501      *
502      * The caller must have an open Surface transaction.
503      *
504      * The display device may not be the primary display device, in the case
505      * where the display is being mirrored.
506      *
507      * @param device The display device to modify.
508      * @param isBlanked True if the device is being blanked.
509      */
configureDisplayLocked(SurfaceControl.Transaction t, DisplayDevice device, boolean isBlanked)510     public void configureDisplayLocked(SurfaceControl.Transaction t,
511             DisplayDevice device,
512             boolean isBlanked) {
513         // Set the layer stack.
514         device.setLayerStackLocked(t, isBlanked ? BLANK_LAYER_STACK : mLayerStack);
515 
516         // Set the color mode and allowed display mode.
517         if (device == mPrimaryDisplayDevice) {
518             device.setDesiredDisplayModeSpecsLocked(mDesiredDisplayModeSpecs);
519             device.setRequestedColorModeLocked(mRequestedColorMode);
520         } else {
521             // Reset to default for non primary displays
522             device.setDesiredDisplayModeSpecsLocked(
523                     new DisplayModeDirector.DesiredDisplayModeSpecs());
524             device.setRequestedColorModeLocked(0);
525         }
526 
527         device.setAutoLowLatencyModeLocked(mRequestedMinimalPostProcessing);
528         device.setGameContentTypeLocked(mRequestedMinimalPostProcessing);
529 
530         // Only grab the display info now as it may have been changed based on the requests above.
531         final DisplayInfo displayInfo = getDisplayInfoLocked();
532         final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();
533 
534         // Set the viewport.
535         // This is the area of the logical display that we intend to show on the
536         // display device.  For now, it is always the full size of the logical display.
537         mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);
538 
539         // Set the orientation.
540         // The orientation specifies how the physical coordinate system of the display
541         // is rotated when the contents of the logical display are rendered.
542         int orientation = Surface.ROTATION_0;
543         if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
544             orientation = displayInfo.rotation;
545         }
546 
547         // Apply the physical rotation of the display device itself.
548         orientation = (orientation + displayDeviceInfo.rotation) % 4;
549 
550         // Set the frame.
551         // The frame specifies the rotated physical coordinates into which the viewport
552         // is mapped.  We need to take care to preserve the aspect ratio of the viewport.
553         // Currently we maximize the area to fill the display, but we could try to be
554         // more clever and match resolutions.
555         boolean rotated = (orientation == Surface.ROTATION_90
556                 || orientation == Surface.ROTATION_270);
557         int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
558         int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
559 
560         Rect maskingInsets = getMaskingInsets(displayDeviceInfo);
561         InsetUtils.rotateInsets(maskingInsets, orientation);
562         // Don't consider the masked area as available when calculating the scaling below.
563         physWidth -= maskingInsets.left + maskingInsets.right;
564         physHeight -= maskingInsets.top + maskingInsets.bottom;
565 
566         // Determine whether the width or height is more constrained to be scaled.
567         //    physWidth / displayInfo.logicalWidth    => letter box
568         // or physHeight / displayInfo.logicalHeight  => pillar box
569         //
570         // We avoid a division (and possible floating point imprecision) here by
571         // multiplying the fractions by the product of their denominators before
572         // comparing them.
573         int displayRectWidth, displayRectHeight;
574         if ((displayInfo.flags & Display.FLAG_SCALING_DISABLED) != 0 || mDisplayScalingDisabled) {
575             displayRectWidth = displayInfo.logicalWidth;
576             displayRectHeight = displayInfo.logicalHeight;
577         } else if (physWidth * displayInfo.logicalHeight
578                 < physHeight * displayInfo.logicalWidth) {
579             // Letter box.
580             displayRectWidth = physWidth;
581             displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;
582         } else {
583             // Pillar box.
584             displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;
585             displayRectHeight = physHeight;
586         }
587         int displayRectTop = (physHeight - displayRectHeight) / 2;
588         int displayRectLeft = (physWidth - displayRectWidth) / 2;
589         mTempDisplayRect.set(displayRectLeft, displayRectTop,
590                 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
591 
592         // Now add back the offset for the masked area.
593         mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top);
594 
595         if (orientation == Surface.ROTATION_0) {
596             mTempDisplayRect.offset(mDisplayOffsetX, mDisplayOffsetY);
597         } else if (orientation == Surface.ROTATION_90) {
598             mTempDisplayRect.offset(mDisplayOffsetY, -mDisplayOffsetX);
599         } else if (orientation == Surface.ROTATION_180) {
600             mTempDisplayRect.offset(-mDisplayOffsetX, -mDisplayOffsetY);
601         } else {  // Surface.ROTATION_270
602             mTempDisplayRect.offset(-mDisplayOffsetY, mDisplayOffsetX);
603         }
604 
605         mDisplayPosition.set(mTempDisplayRect.left, mTempDisplayRect.top);
606         device.setProjectionLocked(t, orientation, mTempLayerStackRect, mTempDisplayRect);
607     }
608 
609     /**
610      * Returns true if the logical display has unique content.
611      * <p>
612      * If the display has unique content then we will try to ensure that it is
613      * visible on at least its primary display device.  Otherwise we will ignore the
614      * logical display and perhaps show mirrored content on the primary display device.
615      * </p>
616      *
617      * @return True if the display has unique content.
618      */
hasContentLocked()619     public boolean hasContentLocked() {
620         return mHasContent;
621     }
622 
623     /**
624      * Sets whether the logical display has unique content.
625      *
626      * @param hasContent True if the display has unique content.
627      */
setHasContentLocked(boolean hasContent)628     public void setHasContentLocked(boolean hasContent) {
629         mHasContent = hasContent;
630     }
631 
632     /**
633      * Sets the display configs the system can use.
634      */
setDesiredDisplayModeSpecsLocked( DisplayModeDirector.DesiredDisplayModeSpecs specs)635     public void setDesiredDisplayModeSpecsLocked(
636             DisplayModeDirector.DesiredDisplayModeSpecs specs) {
637         mDesiredDisplayModeSpecs = specs;
638     }
639 
640     /**
641      * Returns the display configs the system can choose.
642      */
getDesiredDisplayModeSpecsLocked()643     public DisplayModeDirector.DesiredDisplayModeSpecs getDesiredDisplayModeSpecsLocked() {
644         return mDesiredDisplayModeSpecs;
645     }
646 
647     /**
648      * Requests the given color mode.
649      */
setRequestedColorModeLocked(int colorMode)650     public void setRequestedColorModeLocked(int colorMode) {
651         mRequestedColorMode = colorMode;
652     }
653 
654     /**
655      * Returns the last requested minimal post processing setting.
656      */
getRequestedMinimalPostProcessingLocked()657     public boolean getRequestedMinimalPostProcessingLocked() {
658         return mRequestedMinimalPostProcessing;
659     }
660 
661     /**
662      * Instructs the connected display to do minimal post processing. This is implemented either
663      * via HDMI 2.1 ALLM or HDMI 1.4 ContentType=Game.
664      *
665      * @param on Whether to set minimal post processing on/off on the connected display.
666      */
setRequestedMinimalPostProcessingLocked(boolean on)667     public void setRequestedMinimalPostProcessingLocked(boolean on) {
668         mRequestedMinimalPostProcessing = on;
669     }
670 
671     /** Returns the pending requested color mode. */
getRequestedColorModeLocked()672     public int getRequestedColorModeLocked() {
673         return mRequestedColorMode;
674     }
675 
676     /**
677      * Gets the burn-in offset in X.
678      */
getDisplayOffsetXLocked()679     public int getDisplayOffsetXLocked() {
680         return mDisplayOffsetX;
681     }
682 
683     /**
684      * Gets the burn-in offset in Y.
685      */
getDisplayOffsetYLocked()686     public int getDisplayOffsetYLocked() {
687         return mDisplayOffsetY;
688     }
689 
690     /**
691      * Sets the burn-in offsets.
692      */
setDisplayOffsetsLocked(int x, int y)693     public void setDisplayOffsetsLocked(int x, int y) {
694         mDisplayOffsetX = x;
695         mDisplayOffsetY = y;
696     }
697 
698     /**
699      * @return {@code true} if display scaling is disabled, or {@code false} if the default scaling
700      * mode is used.
701      */
isDisplayScalingDisabled()702     public boolean isDisplayScalingDisabled() {
703         return mDisplayScalingDisabled;
704     }
705 
706     /**
707      * Disables scaling for a display.
708      *
709      * @param disableScaling {@code true} to disable scaling,
710      * {@code false} to use the default scaling behavior of the logical display.
711      */
setDisplayScalingDisabledLocked(boolean disableScaling)712     public void setDisplayScalingDisabledLocked(boolean disableScaling) {
713         mDisplayScalingDisabled = disableScaling;
714     }
715 
setUserDisabledHdrTypes(@onNull int[] userDisabledHdrTypes)716     public void setUserDisabledHdrTypes(@NonNull int[] userDisabledHdrTypes) {
717         if (mUserDisabledHdrTypes != userDisabledHdrTypes) {
718             mUserDisabledHdrTypes = userDisabledHdrTypes;
719             mBaseDisplayInfo.userDisabledHdrTypes = userDisabledHdrTypes;
720             mInfo.set(null);
721         }
722     }
723 
724     /**
725      * Swap the underlying {@link DisplayDevice} with the specified LogicalDisplay.
726      *
727      * @param targetDisplay The display with which to swap display-devices.
728      * @return {@code true} if the displays were swapped, {@code false} otherwise.
729      */
swapDisplaysLocked(@onNull LogicalDisplay targetDisplay)730     public void swapDisplaysLocked(@NonNull LogicalDisplay targetDisplay) {
731         final DisplayDevice oldTargetDevice =
732                 targetDisplay.setPrimaryDisplayDeviceLocked(mPrimaryDisplayDevice);
733         setPrimaryDisplayDeviceLocked(oldTargetDevice);
734     }
735 
736     /**
737      * Sets the primary display device to the specified device.
738      *
739      * @param device The new device to set.
740      * @return The previously set display device.
741      */
setPrimaryDisplayDeviceLocked(@ullable DisplayDevice device)742     public DisplayDevice setPrimaryDisplayDeviceLocked(@Nullable DisplayDevice device) {
743         final DisplayDevice old = mPrimaryDisplayDevice;
744         mPrimaryDisplayDevice = device;
745 
746         // Reset all our display info data
747         mPrimaryDisplayDeviceInfo = null;
748         mBaseDisplayInfo.copyFrom(EMPTY_DISPLAY_INFO);
749         mInfo.set(null);
750 
751         return old;
752     }
753 
setPhase(@isplayPhase int phase)754     public void setPhase(@DisplayPhase int phase) {
755         mPhase = phase;
756     }
757 
758     /**
759      * Returns the currently set phase for this LogicalDisplay. Phases are used when transitioning
760      * from one device state to another. {@see LogicalDisplayMapper}.
761      */
762     @DisplayPhase
getPhase()763     public int getPhase() {
764         return mPhase;
765     }
766 
767     /**
768      * @return {@code true} if the LogicalDisplay is enabled or {@code false}
769      * if disabled indicating that the display should be hidden from the rest of the apps and
770      * framework.
771      */
isEnabled()772     public boolean isEnabled() {
773         // DISPLAY_PHASE_LAYOUT_TRANSITION is still considered an 'enabled' phase.
774         return mPhase == DISPLAY_PHASE_ENABLED || mPhase == DISPLAY_PHASE_LAYOUT_TRANSITION;
775     }
776 
dumpLocked(PrintWriter pw)777     public void dumpLocked(PrintWriter pw) {
778         pw.println("mDisplayId=" + mDisplayId);
779         pw.println("mPhase=" + mPhase);
780         pw.println("mLayerStack=" + mLayerStack);
781         pw.println("mHasContent=" + mHasContent);
782         pw.println("mDesiredDisplayModeSpecs={" + mDesiredDisplayModeSpecs + "}");
783         pw.println("mRequestedColorMode=" + mRequestedColorMode);
784         pw.println("mDisplayOffset=(" + mDisplayOffsetX + ", " + mDisplayOffsetY + ")");
785         pw.println("mDisplayScalingDisabled=" + mDisplayScalingDisabled);
786         pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
787                 mPrimaryDisplayDevice.getNameLocked() : "null"));
788         pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
789         pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo);
790         pw.println("mRequestedMinimalPostProcessing=" + mRequestedMinimalPostProcessing);
791         pw.println("mFrameRateOverrides=" + Arrays.toString(mFrameRateOverrides));
792         pw.println("mPendingFrameRateOverrideUids=" + mPendingFrameRateOverrideUids);
793     }
794 
795     @Override
toString()796     public String toString() {
797         StringWriter sw = new StringWriter();
798         dumpLocked(new PrintWriter(sw));
799         return sw.toString();
800     }
801 }
802