• 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 static android.view.Surface.ROTATION_270;
20 import static android.view.Surface.ROTATION_90;
21 
22 import android.annotation.Nullable;
23 import android.content.Context;
24 import android.graphics.Point;
25 import android.graphics.Rect;
26 import android.hardware.display.DisplayManagerInternal.DisplayOffloadSession;
27 import android.hardware.display.DisplayViewport;
28 import android.os.IBinder;
29 import android.util.ArraySet;
30 import android.util.Slog;
31 import android.view.Display;
32 import android.view.DisplayAddress;
33 import android.view.Surface;
34 import android.view.SurfaceControl;
35 
36 import com.android.server.display.mode.DisplayModeDirector;
37 
38 import java.io.PrintWriter;
39 import java.util.Arrays;
40 
41 /**
42  * Represents a display device such as the built-in display, an external monitor, a WiFi display,
43  * or a {@link android.hardware.display.VirtualDisplay}.
44  * <p>
45  * Display devices are guarded by the {@link DisplayManagerService.SyncRoot} lock.
46  * </p>
47  */
48 abstract class DisplayDevice {
49     /**
50      * Maximum acceptable anisotropy for the output image.
51      *
52      * Necessary to avoid unnecessary scaling when pixels are almost square, as they are non ideal
53      * anyway. For external displays, we expect an anisotropy of about 2% even if the pixels
54      * are, in fact, square due to the imprecision of the display's actual size (parsed from edid
55      * and rounded to the nearest cm).
56      */
57     static final float MAX_ANISOTROPY = 1.025f;
58     private static final String TAG = "DisplayDevice";
59     private static final Display.Mode EMPTY_DISPLAY_MODE = new Display.Mode.Builder().build();
60 
61     private final DisplayAdapter mDisplayAdapter;
62     private final IBinder mDisplayToken;
63     private final String mUniqueId;
64 
65     protected DisplayDeviceConfig mDisplayDeviceConfig;
66     // The display device does not manage these properties itself, they are set by
67     // the display manager service.  The display device shouldn't really be looking at these.
68     private int mCurrentLayerStack = -1;
69     private int mCurrentFlags = 0;
70     private int mCurrentOrientation = -1;
71     private int mLastDisplayWidth;
72     private int mLastDisplayHeight;
73     private Rect mCurrentLayerStackRect;
74     private Rect mCurrentDisplayRect;
75     private final Context mContext;
76 
77     // The display device owns its surface, but it should only set it
78     // within a transaction from performTraversalLocked.
79     private Surface mCurrentSurface;
80 
81     // DEBUG STATE: Last device info which was written to the log, or null if none.
82     // Do not use for any other purpose.
83     DisplayDeviceInfo mDebugLastLoggedDeviceInfo;
84 
85     private final boolean mIsAnisotropyCorrectionEnabled;
86 
DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId, Context context)87     DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId,
88             Context context) {
89         this(displayAdapter, displayToken, uniqueId, context, false);
90     }
91 
DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId, Context context, boolean isAnisotropyCorrectionEnabled)92     DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId,
93             Context context, boolean isAnisotropyCorrectionEnabled) {
94         mDisplayAdapter = displayAdapter;
95         mDisplayToken = displayToken;
96         mUniqueId = uniqueId;
97         mDisplayDeviceConfig = null;
98         mContext = context;
99         mIsAnisotropyCorrectionEnabled = isAnisotropyCorrectionEnabled;
100     }
101 
102     /**
103      * Gets the display adapter that owns the display device.
104      *
105      * @return The display adapter.
106      */
getAdapterLocked()107     public final DisplayAdapter getAdapterLocked() {
108         return mDisplayAdapter;
109     }
110 
111     /*
112      * Gets the DisplayDeviceConfig for this DisplayDevice.
113      *
114      * @return The DisplayDeviceConfig; {@code null} if not overridden.
115      */
getDisplayDeviceConfig()116     public DisplayDeviceConfig getDisplayDeviceConfig() {
117         if (mDisplayDeviceConfig == null) {
118             mDisplayDeviceConfig = loadDisplayDeviceConfig();
119         }
120         return mDisplayDeviceConfig;
121     }
122 
123     /**
124      * Gets the Surface Flinger display token for this display.
125      *
126      * @return The display token, or null if the display is not being managed
127      * by Surface Flinger.
128      */
getDisplayTokenLocked()129     public final IBinder getDisplayTokenLocked() {
130         return mDisplayToken;
131     }
132 
133     /**
134      * Gets the id of the display to mirror.
135      */
getDisplayIdToMirrorLocked()136     public int getDisplayIdToMirrorLocked() {
137         return Display.DEFAULT_DISPLAY;
138     }
139 
140     /**
141      * Returns the if WindowManager is responsible for mirroring on this display. If {@code false},
142      * then SurfaceFlinger performs no layer mirroring on this display.
143      * Only used for mirroring started from MediaProjection.
144      */
isWindowManagerMirroringLocked()145     public boolean isWindowManagerMirroringLocked() {
146         return false;
147     }
148 
149     /**
150      * Updates if WindowManager is responsible for mirroring on this display. If {@code false}, then
151      * SurfaceFlinger performs no layer mirroring to this display.
152      * Only used for mirroring started from MediaProjection.
153      */
setWindowManagerMirroringLocked(boolean isMirroring)154     public void setWindowManagerMirroringLocked(boolean isMirroring) {
155     }
156 
157     /**
158      * Returns the default size of the surface associated with the display, or null if the surface
159      * is not provided for layer mirroring by SurfaceFlinger. For non virtual displays, this will
160      * be the actual display device's size, reflecting the current rotation.
161      */
162     @Nullable
getDisplaySurfaceDefaultSizeLocked()163     public Point getDisplaySurfaceDefaultSizeLocked() {
164         DisplayDeviceInfo displayDeviceInfo = getDisplayDeviceInfoLocked();
165         var width = displayDeviceInfo.width;
166         var height = displayDeviceInfo.height;
167         if (mIsAnisotropyCorrectionEnabled && displayDeviceInfo.type == Display.TYPE_EXTERNAL
168                     && displayDeviceInfo.yDpi > 0 && displayDeviceInfo.xDpi > 0) {
169             if (displayDeviceInfo.xDpi > displayDeviceInfo.yDpi * MAX_ANISOTROPY) {
170                 height = (int) (height * displayDeviceInfo.xDpi / displayDeviceInfo.yDpi + 0.5);
171             } else if (displayDeviceInfo.xDpi * MAX_ANISOTROPY < displayDeviceInfo.yDpi) {
172                 width = (int) (width * displayDeviceInfo.yDpi / displayDeviceInfo.xDpi  + 0.5);
173             }
174         }
175         return isRotatedLocked() ? new Point(height, width) : new Point(width, height);
176     }
177 
178     /**
179      * Gets the name of the display device.
180      *
181      * @return The display device name.
182      */
getNameLocked()183     public final String getNameLocked() {
184         return getDisplayDeviceInfoLocked().name;
185     }
186 
187     /**
188      * Returns the unique id of the display device.
189      */
getUniqueId()190     public final String getUniqueId() {
191         return mUniqueId;
192     }
193 
194     /**
195      * Returns whether the unique id of the device is stable across reboots.
196      */
hasStableUniqueId()197     public abstract boolean hasStableUniqueId();
198 
199     /**
200      * Gets information about the display device.
201      *
202      * The information returned should not change between calls unless the display
203      * adapter sent a {@link DisplayAdapter#DISPLAY_DEVICE_EVENT_CHANGED} event and
204      * {@link #applyPendingDisplayDeviceInfoChangesLocked()} has been called to apply
205      * the pending changes.
206      *
207      * @return The display device info, which should be treated as immutable by the caller.
208      * The display device should allocate a new display device info object whenever
209      * the data changes.
210      */
getDisplayDeviceInfoLocked()211     public abstract DisplayDeviceInfo getDisplayDeviceInfoLocked();
212 
213     /**
214      * Applies any pending changes to the observable state of the display device
215      * if the display adapter sent a {@link DisplayAdapter#DISPLAY_DEVICE_EVENT_CHANGED} event.
216      */
applyPendingDisplayDeviceInfoChangesLocked()217     public void applyPendingDisplayDeviceInfoChangesLocked() {
218     }
219 
220     /**
221      * Updates the surface for the display.
222      */
configureSurfaceLocked(SurfaceControl.Transaction t)223     public void configureSurfaceLocked(SurfaceControl.Transaction t) {
224     }
225 
226     /**
227      * Sets the display state, if supported.
228      *
229      * @param state The new display state.
230      * @param brightnessState The new display brightnessState.
231      * @param sdrBrightnessState The new display brightnessState for SDR layers.
232      * @param displayOffloadSession {@link DisplayOffloadSession} associated with current device.
233      * @return A runnable containing work to be deferred until after we have exited the critical
234      *     section, or null if none.
235      */
requestDisplayStateLocked( int state, float brightnessState, float sdrBrightnessState, @Nullable DisplayOffloadSessionImpl displayOffloadSession)236     public Runnable requestDisplayStateLocked(
237             int state,
238             float brightnessState,
239             float sdrBrightnessState,
240             @Nullable DisplayOffloadSessionImpl displayOffloadSession) {
241         return null;
242     }
243 
244     /**
245      * Sets the display mode specs.
246      *
247      * Not all display devices will automatically switch between modes, so it's important that the
248      * default modeId is set correctly.
249      */
setDesiredDisplayModeSpecsLocked( DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs)250     public void setDesiredDisplayModeSpecsLocked(
251             DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {}
252 
253     /**
254      * Sets the user preferred display mode. Removes the user preferred display mode and sets
255      * default display mode as the mode chosen by HAL, if 'mode' is null
256      * Returns true if the mode set by user is supported by the display.
257      */
setUserPreferredDisplayModeLocked(Display.Mode mode)258     public void setUserPreferredDisplayModeLocked(Display.Mode mode) { }
259 
260     /**
261      * Returns the user preferred display mode.
262      */
getUserPreferredDisplayModeLocked()263     public Display.Mode getUserPreferredDisplayModeLocked() {
264         return EMPTY_DISPLAY_MODE;
265     }
266 
267     /**
268      * Returns the system preferred display mode.
269      */
getSystemPreferredDisplayModeLocked()270     public Display.Mode getSystemPreferredDisplayModeLocked() {
271         return EMPTY_DISPLAY_MODE;
272     }
273 
274     /**
275      * Returns the display mode that was being used when this display was first found by
276      * display manager.
277      * @hide
278      */
getActiveDisplayModeAtStartLocked()279     public Display.Mode getActiveDisplayModeAtStartLocked() {
280         return EMPTY_DISPLAY_MODE;
281     }
282 
283     /**
284      * Sets the requested color mode.
285      */
setRequestedColorModeLocked(int colorMode)286     public void setRequestedColorModeLocked(int colorMode) {
287     }
288 
289     /**
290      * Sends the Auto Low Latency Mode (ALLM) signal over HDMI, or requests an internal display to
291      * switch to a low-latency mode.
292      *
293      * @param on Whether to set ALLM on or off.
294      */
setAutoLowLatencyModeLocked(boolean on)295     public void setAutoLowLatencyModeLocked(boolean on) {
296     }
297 
298     /**
299      * Sends a ContentType=Game signal over HDMI, or requests an internal display to switch to a
300      * game mode (generally lower latency).
301      *
302      * @param on Whether to send a ContentType=Game signal or not
303      */
setGameContentTypeLocked(boolean on)304     public void setGameContentTypeLocked(boolean on) {
305     }
306 
onOverlayChangedLocked()307     public void onOverlayChangedLocked() {
308     }
309 
310     /**
311      * Returns if the display should only mirror another display rather than showing other content
312      * until it is destroyed.
313      */
shouldOnlyMirror()314     public boolean shouldOnlyMirror() {
315         return false;
316     }
317 
318     /**
319      * Sets the display layer stack while in a transaction.
320      */
setLayerStackLocked(SurfaceControl.Transaction t, int layerStack, int layerStackTag)321     public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack,
322             int layerStackTag) {
323         if (mCurrentLayerStack != layerStack) {
324             mCurrentLayerStack = layerStack;
325             t.setDisplayLayerStack(mDisplayToken, layerStack);
326             Slog.i(TAG, "[" + layerStackTag + "] Layerstack set to " + layerStack + " for "
327                     + mUniqueId);
328         }
329     }
330 
331     /**
332      * Sets the display flags while in a transaction.
333      *
334      * Valid display flags:
335      *  {@link SurfaceControl#DISPLAY_RECEIVES_INPUT}
336      */
setDisplayFlagsLocked(SurfaceControl.Transaction t, int flags)337     public final void setDisplayFlagsLocked(SurfaceControl.Transaction t, int flags) {
338         if (mCurrentFlags != flags) {
339             mCurrentFlags = flags;
340             t.setDisplayFlags(mDisplayToken, flags);
341         }
342     }
343 
344     /**
345      * Sets the display projection while in a transaction.
346      *
347      * @param orientation defines the display's orientation
348      * @param layerStackRect defines which area of the window manager coordinate
349      *            space will be used
350      * @param displayRect defines where on the display will layerStackRect be
351      *            mapped to. displayRect is specified post-orientation, that is
352      *            it uses the orientation seen by the end-user
353      */
setProjectionLocked(SurfaceControl.Transaction t, int orientation, Rect layerStackRect, Rect displayRect)354     public final void setProjectionLocked(SurfaceControl.Transaction t, int orientation,
355             Rect layerStackRect, Rect displayRect) {
356         if (mCurrentOrientation != orientation
357                 || mCurrentLayerStackRect == null
358                 || !mCurrentLayerStackRect.equals(layerStackRect)
359                 || mCurrentDisplayRect == null
360                 || !mCurrentDisplayRect.equals(displayRect)) {
361             mCurrentOrientation = orientation;
362 
363             if (mCurrentLayerStackRect == null) {
364                 mCurrentLayerStackRect = new Rect();
365             }
366             mCurrentLayerStackRect.set(layerStackRect);
367 
368             if (mCurrentDisplayRect == null) {
369                 mCurrentDisplayRect = new Rect();
370             }
371             mCurrentDisplayRect.set(displayRect);
372 
373             t.setDisplayProjection(mDisplayToken,
374                     orientation, layerStackRect, displayRect);
375         }
376     }
377 
378     /**
379      * Configure transaction with the display size.
380      */
configureDisplaySizeLocked(SurfaceControl.Transaction t)381     public void configureDisplaySizeLocked(SurfaceControl.Transaction t) {
382         DisplayDeviceInfo info = getDisplayDeviceInfoLocked();
383         boolean isInstalledRotated = info.installOrientation == ROTATION_90
384                 || info.installOrientation == ROTATION_270;
385         int displayWidth = isInstalledRotated ? info.height : info.width;
386         int displayHeight = isInstalledRotated ? info.width : info.height;
387         setDisplaySizeLocked(t, displayWidth, displayHeight);
388     }
389 
390     /**
391      * Sets display size while in a transaction.
392      */
setDisplaySizeLocked(SurfaceControl.Transaction t, int width, int height)393     public final void setDisplaySizeLocked(SurfaceControl.Transaction t, int width, int height) {
394         if (width != mLastDisplayWidth && height != mLastDisplayHeight) {
395             mLastDisplayWidth = width;
396             mLastDisplayHeight = height;
397             t.setDisplaySize(mDisplayToken, width, height);
398         }
399     }
400 
401     /**
402      * Sets the display surface while in a transaction.
403      */
setSurfaceLocked(SurfaceControl.Transaction t, Surface surface)404     public final void setSurfaceLocked(SurfaceControl.Transaction t, Surface surface) {
405         if (mCurrentSurface != surface) {
406             mCurrentSurface = surface;
407             t.setDisplaySurface(mDisplayToken, surface);
408         }
409     }
410 
411     /**
412      * Populates the specified viewport object with orientation,
413      * physical and logical rects based on the display's current projection.
414      */
populateViewportLocked(DisplayViewport viewport)415     public final void populateViewportLocked(DisplayViewport viewport) {
416         viewport.orientation = mCurrentOrientation;
417 
418         if (mCurrentLayerStackRect != null) {
419             viewport.logicalFrame.set(mCurrentLayerStackRect);
420         } else {
421             viewport.logicalFrame.setEmpty();
422         }
423 
424         if (mCurrentDisplayRect != null) {
425             viewport.physicalFrame.set(mCurrentDisplayRect);
426         } else {
427             viewport.physicalFrame.setEmpty();
428         }
429 
430         final boolean isRotated = isRotatedLocked();
431         DisplayDeviceInfo info = getDisplayDeviceInfoLocked();
432         viewport.deviceWidth = isRotated ? info.height : info.width;
433         viewport.deviceHeight = isRotated ? info.width : info.height;
434 
435         viewport.uniqueId = info.uniqueId;
436 
437         if (info.address instanceof DisplayAddress.Physical) {
438             viewport.physicalPort = ((DisplayAddress.Physical) info.address).getPort();
439         } else {
440             viewport.physicalPort = null;
441         }
442     }
443 
444     /**
445      * Dumps the local state of the display device.
446      * Does not need to dump the display device info because that is already dumped elsewhere.
447      */
dumpLocked(PrintWriter pw)448     public void dumpLocked(PrintWriter pw) {
449         pw.println("mAdapter=" + mDisplayAdapter.getName());
450         pw.println("mUniqueId=" + mUniqueId);
451         pw.println("mDisplayToken=" + mDisplayToken);
452         pw.println("mCurrentLayerStack=" + mCurrentLayerStack);
453         pw.println("mCurrentFlags=" + mCurrentFlags);
454         pw.println("mCurrentOrientation=" + mCurrentOrientation);
455         pw.println("mCurrentLayerStackRect=" + mCurrentLayerStackRect);
456         pw.println("mCurrentDisplayRect=" + mCurrentDisplayRect);
457         pw.println("mCurrentSurface=" + mCurrentSurface);
458     }
459 
460     /**
461      * @return whether the orientation is {@link ROTATION_90} or {@link ROTATION_270}.
462      */
isRotatedLocked()463     boolean isRotatedLocked() {
464         return mCurrentOrientation == ROTATION_90 || mCurrentOrientation == ROTATION_270;
465     }
466 
467     /**
468      * @return set of supported resolutions as an ascending sorted array.
469      */
getSupportedResolutionsLocked()470     Point[] getSupportedResolutionsLocked() {
471         ArraySet<Point> resolutions = new ArraySet<>(2);
472         Display.Mode[] supportedModes = getDisplayDeviceInfoLocked().supportedModes;
473         for (Display.Mode mode : supportedModes) {
474             resolutions.add(new Point(mode.getPhysicalWidth(), mode.getPhysicalHeight()));
475         }
476         Point[] sortedArray = new Point[resolutions.size()];
477         resolutions.toArray(sortedArray);
478         Arrays.sort(sortedArray, (p1, p2) -> p1.x * p1.y - p2.x * p2.y);
479         return sortedArray;
480     }
481 
loadDisplayDeviceConfig()482     private DisplayDeviceConfig loadDisplayDeviceConfig() {
483         return DisplayDeviceConfig.create(mContext, /* useConfigXml= */ false,
484                 mDisplayAdapter.getFeatureFlags());
485     }
486 }
487