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.Nullable; 20 import android.content.Context; 21 import android.graphics.Point; 22 import android.graphics.Rect; 23 import android.hardware.display.DisplayViewport; 24 import android.os.IBinder; 25 import android.view.Display; 26 import android.view.DisplayAddress; 27 import android.view.Surface; 28 import android.view.SurfaceControl; 29 30 import java.io.PrintWriter; 31 32 /** 33 * Represents a physical display device such as the built-in display 34 * an external monitor, or a WiFi display. 35 * <p> 36 * Display devices are guarded by the {@link DisplayManagerService.SyncRoot} lock. 37 * </p> 38 */ 39 abstract class DisplayDevice { 40 private final DisplayAdapter mDisplayAdapter; 41 private final IBinder mDisplayToken; 42 private final String mUniqueId; 43 44 protected DisplayDeviceConfig mDisplayDeviceConfig; 45 // The display device does not manage these properties itself, they are set by 46 // the display manager service. The display device shouldn't really be looking at these. 47 private int mCurrentLayerStack = -1; 48 private int mCurrentFlags = 0; 49 private int mCurrentOrientation = -1; 50 private Rect mCurrentLayerStackRect; 51 private Rect mCurrentDisplayRect; 52 private final Context mContext; 53 54 // The display device owns its surface, but it should only set it 55 // within a transaction from performTraversalLocked. 56 private Surface mCurrentSurface; 57 58 // DEBUG STATE: Last device info which was written to the log, or null if none. 59 // Do not use for any other purpose. 60 DisplayDeviceInfo mDebugLastLoggedDeviceInfo; 61 DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId, Context context)62 public DisplayDevice(DisplayAdapter displayAdapter, IBinder displayToken, String uniqueId, 63 Context context) { 64 mDisplayAdapter = displayAdapter; 65 mDisplayToken = displayToken; 66 mUniqueId = uniqueId; 67 mDisplayDeviceConfig = null; 68 mContext = context; 69 } 70 71 /** 72 * Gets the display adapter that owns the display device. 73 * 74 * @return The display adapter. 75 */ getAdapterLocked()76 public final DisplayAdapter getAdapterLocked() { 77 return mDisplayAdapter; 78 } 79 80 /* 81 * Gets the DisplayDeviceConfig for this DisplayDevice. 82 * 83 * @return The DisplayDeviceConfig; {@code null} if not overridden. 84 */ getDisplayDeviceConfig()85 public DisplayDeviceConfig getDisplayDeviceConfig() { 86 if (mDisplayDeviceConfig == null) { 87 mDisplayDeviceConfig = loadDisplayDeviceConfig(); 88 } 89 return mDisplayDeviceConfig; 90 } 91 92 /** 93 * Gets the Surface Flinger display token for this display. 94 * 95 * @return The display token, or null if the display is not being managed 96 * by Surface Flinger. 97 */ getDisplayTokenLocked()98 public final IBinder getDisplayTokenLocked() { 99 return mDisplayToken; 100 } 101 102 /** 103 * Gets the id of the display to mirror. 104 */ getDisplayIdToMirrorLocked()105 public int getDisplayIdToMirrorLocked() { 106 return Display.DEFAULT_DISPLAY; 107 } 108 109 /** 110 * Returns the window token of the level of the WindowManager hierarchy to mirror, or null 111 * if layer mirroring by SurfaceFlinger should not be performed. 112 * For now, only used for mirroring started from MediaProjection. 113 */ 114 @Nullable getWindowTokenClientToMirrorLocked()115 public IBinder getWindowTokenClientToMirrorLocked() { 116 return null; 117 } 118 119 /** 120 * Updates the window token of the level of the level of the WindowManager hierarchy to mirror. 121 * If windowToken is null, then no layer mirroring by SurfaceFlinger to should be performed. 122 * For now, only used for mirroring started from MediaProjection. 123 */ setWindowTokenClientToMirrorLocked(IBinder windowToken)124 public void setWindowTokenClientToMirrorLocked(IBinder windowToken) { 125 } 126 127 /** 128 * Returns the default size of the surface associated with the display, or null if the surface 129 * is not provided for layer mirroring by SurfaceFlinger. 130 * For now, only used for mirroring started from MediaProjection. 131 */ 132 @Nullable getDisplaySurfaceDefaultSize()133 public Point getDisplaySurfaceDefaultSize() { 134 return null; 135 } 136 137 /** 138 * Gets the name of the display device. 139 * 140 * @return The display device name. 141 */ getNameLocked()142 public final String getNameLocked() { 143 return getDisplayDeviceInfoLocked().name; 144 } 145 146 /** 147 * Returns the unique id of the display device. 148 */ getUniqueId()149 public final String getUniqueId() { 150 return mUniqueId; 151 } 152 153 /** 154 * Returns whether the unique id of the device is stable across reboots. 155 */ hasStableUniqueId()156 public abstract boolean hasStableUniqueId(); 157 158 /** 159 * Gets information about the display device. 160 * 161 * The information returned should not change between calls unless the display 162 * adapter sent a {@link DisplayAdapter#DISPLAY_DEVICE_EVENT_CHANGED} event and 163 * {@link #applyPendingDisplayDeviceInfoChangesLocked()} has been called to apply 164 * the pending changes. 165 * 166 * @return The display device info, which should be treated as immutable by the caller. 167 * The display device should allocate a new display device info object whenever 168 * the data changes. 169 */ getDisplayDeviceInfoLocked()170 public abstract DisplayDeviceInfo getDisplayDeviceInfoLocked(); 171 172 /** 173 * Applies any pending changes to the observable state of the display device 174 * if the display adapter sent a {@link DisplayAdapter#DISPLAY_DEVICE_EVENT_CHANGED} event. 175 */ applyPendingDisplayDeviceInfoChangesLocked()176 public void applyPendingDisplayDeviceInfoChangesLocked() { 177 } 178 179 /** 180 * Gives the display device a chance to update its properties while in a transaction. 181 */ performTraversalLocked(SurfaceControl.Transaction t)182 public void performTraversalLocked(SurfaceControl.Transaction t) { 183 } 184 185 /** 186 * Sets the display state, if supported. 187 * 188 * @param state The new display state. 189 * @param brightnessState The new display brightnessState. 190 * @param sdrBrightnessState The new display brightnessState for SDR layers. 191 * @return A runnable containing work to be deferred until after we have 192 * exited the critical section, or null if none. 193 */ requestDisplayStateLocked(int state, float brightnessState, float sdrBrightnessState)194 public Runnable requestDisplayStateLocked(int state, float brightnessState, 195 float sdrBrightnessState) { 196 return null; 197 } 198 199 /** 200 * Sets the display mode specs. 201 * 202 * Not all display devices will automatically switch between modes, so it's important that the 203 * default modeId is set correctly. 204 */ setDesiredDisplayModeSpecsLocked( DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs)205 public void setDesiredDisplayModeSpecsLocked( 206 DisplayModeDirector.DesiredDisplayModeSpecs displayModeSpecs) {} 207 208 /** 209 * Sets the requested color mode. 210 */ setRequestedColorModeLocked(int colorMode)211 public void setRequestedColorModeLocked(int colorMode) { 212 } 213 214 /** 215 * Sends the Auto Low Latency Mode (ALLM) signal over HDMI, or requests an internal display to 216 * switch to a low-latency mode. 217 * 218 * @param on Whether to set ALLM on or off. 219 */ setAutoLowLatencyModeLocked(boolean on)220 public void setAutoLowLatencyModeLocked(boolean on) { 221 } 222 223 /** 224 * Sends a ContentType=Game signal over HDMI, or requests an internal display to switch to a 225 * game mode (generally lower latency). 226 * 227 * @param on Whether to send a ContentType=Game signal or not 228 */ setGameContentTypeLocked(boolean on)229 public void setGameContentTypeLocked(boolean on) { 230 } 231 onOverlayChangedLocked()232 public void onOverlayChangedLocked() { 233 } 234 235 /** 236 * Sets the display layer stack while in a transaction. 237 */ setLayerStackLocked(SurfaceControl.Transaction t, int layerStack)238 public final void setLayerStackLocked(SurfaceControl.Transaction t, int layerStack) { 239 if (mCurrentLayerStack != layerStack) { 240 mCurrentLayerStack = layerStack; 241 t.setDisplayLayerStack(mDisplayToken, layerStack); 242 } 243 } 244 245 /** 246 * Sets the display flags while in a transaction. 247 * 248 * Valid display flags: 249 * {@link SurfaceControl#DISPLAY_RECEIVES_INPUT} 250 */ setDisplayFlagsLocked(SurfaceControl.Transaction t, int flags)251 public final void setDisplayFlagsLocked(SurfaceControl.Transaction t, int flags) { 252 if (mCurrentFlags != flags) { 253 mCurrentFlags = flags; 254 t.setDisplayFlags(mDisplayToken, flags); 255 } 256 } 257 258 /** 259 * Sets the display projection while in a transaction. 260 * 261 * @param orientation defines the display's orientation 262 * @param layerStackRect defines which area of the window manager coordinate 263 * space will be used 264 * @param displayRect defines where on the display will layerStackRect be 265 * mapped to. displayRect is specified post-orientation, that is 266 * it uses the orientation seen by the end-user 267 */ setProjectionLocked(SurfaceControl.Transaction t, int orientation, Rect layerStackRect, Rect displayRect)268 public final void setProjectionLocked(SurfaceControl.Transaction t, int orientation, 269 Rect layerStackRect, Rect displayRect) { 270 if (mCurrentOrientation != orientation 271 || mCurrentLayerStackRect == null 272 || !mCurrentLayerStackRect.equals(layerStackRect) 273 || mCurrentDisplayRect == null 274 || !mCurrentDisplayRect.equals(displayRect)) { 275 mCurrentOrientation = orientation; 276 277 if (mCurrentLayerStackRect == null) { 278 mCurrentLayerStackRect = new Rect(); 279 } 280 mCurrentLayerStackRect.set(layerStackRect); 281 282 if (mCurrentDisplayRect == null) { 283 mCurrentDisplayRect = new Rect(); 284 } 285 mCurrentDisplayRect.set(displayRect); 286 287 t.setDisplayProjection(mDisplayToken, 288 orientation, layerStackRect, displayRect); 289 } 290 } 291 292 /** 293 * Sets the display surface while in a transaction. 294 */ setSurfaceLocked(SurfaceControl.Transaction t, Surface surface)295 public final void setSurfaceLocked(SurfaceControl.Transaction t, Surface surface) { 296 if (mCurrentSurface != surface) { 297 mCurrentSurface = surface; 298 t.setDisplaySurface(mDisplayToken, surface); 299 } 300 } 301 302 /** 303 * Populates the specified viewport object with orientation, 304 * physical and logical rects based on the display's current projection. 305 */ populateViewportLocked(DisplayViewport viewport)306 public final void populateViewportLocked(DisplayViewport viewport) { 307 viewport.orientation = mCurrentOrientation; 308 309 if (mCurrentLayerStackRect != null) { 310 viewport.logicalFrame.set(mCurrentLayerStackRect); 311 } else { 312 viewport.logicalFrame.setEmpty(); 313 } 314 315 if (mCurrentDisplayRect != null) { 316 viewport.physicalFrame.set(mCurrentDisplayRect); 317 } else { 318 viewport.physicalFrame.setEmpty(); 319 } 320 321 boolean isRotated = (mCurrentOrientation == Surface.ROTATION_90 322 || mCurrentOrientation == Surface.ROTATION_270); 323 DisplayDeviceInfo info = getDisplayDeviceInfoLocked(); 324 viewport.deviceWidth = isRotated ? info.height : info.width; 325 viewport.deviceHeight = isRotated ? info.width : info.height; 326 327 viewport.uniqueId = info.uniqueId; 328 329 if (info.address instanceof DisplayAddress.Physical) { 330 viewport.physicalPort = ((DisplayAddress.Physical) info.address).getPort(); 331 } else { 332 viewport.physicalPort = null; 333 } 334 } 335 336 /** 337 * Dumps the local state of the display device. 338 * Does not need to dump the display device info because that is already dumped elsewhere. 339 */ dumpLocked(PrintWriter pw)340 public void dumpLocked(PrintWriter pw) { 341 pw.println("mAdapter=" + mDisplayAdapter.getName()); 342 pw.println("mUniqueId=" + mUniqueId); 343 pw.println("mDisplayToken=" + mDisplayToken); 344 pw.println("mCurrentLayerStack=" + mCurrentLayerStack); 345 pw.println("mCurrentFlags=" + mCurrentFlags); 346 pw.println("mCurrentOrientation=" + mCurrentOrientation); 347 pw.println("mCurrentLayerStackRect=" + mCurrentLayerStackRect); 348 pw.println("mCurrentDisplayRect=" + mCurrentDisplayRect); 349 pw.println("mCurrentSurface=" + mCurrentSurface); 350 } 351 loadDisplayDeviceConfig()352 private DisplayDeviceConfig loadDisplayDeviceConfig() { 353 return DisplayDeviceConfig.create(mContext, false); 354 } 355 } 356