FileDocCategorySizeDatePackage
LogicalDisplay.javaAPI DocAndroid 5.1 API15587Thu Mar 12 22:22:42 GMT 2015com.android.server.display

LogicalDisplay

public final class LogicalDisplay extends Object
Describes how a logical display is configured.

At this time, we only support logical displays that are coupled to a particular primary display device from which the logical display derives its basic properties such as its size, density and refresh rate.

A logical display may be mirrored onto multiple display devices in addition to its primary display device. Note that the contents of a logical display may not always be visible, even on its primary display device, such as in the case where the primary display device is currently mirroring content from a different logical display.

This object is designed to encapsulate as much of the policy of logical displays as possible. The idea is to make it easy to implement new kinds of logical displays mostly by making local changes to this class.

Note: The display manager architecture does not actually require logical displays to be associated with any individual display device. Logical displays and display devices are orthogonal concepts. Some mapping will exist between logical displays and display devices but it can be many-to-many and and some might have no relation at all.

Logical displays are guarded by the {@link DisplayManagerService.SyncRoot} lock.

Fields Summary
private final android.view.DisplayInfo
mBaseDisplayInfo
private static final int
BLANK_LAYER_STACK
private final int
mDisplayId
private final int
mLayerStack
private android.view.DisplayInfo
mOverrideDisplayInfo
private android.view.DisplayInfo
mInfo
private DisplayDevice
mPrimaryDisplayDevice
private DisplayDeviceInfo
mPrimaryDisplayDeviceInfo
private boolean
mHasContent
private float
mRequestedRefreshRate
private final android.graphics.Rect
mTempLayerStackRect
private final android.graphics.Rect
mTempDisplayRect
Constructors Summary
public LogicalDisplay(int displayId, int layerStack, DisplayDevice primaryDisplayDevice)


           
        mDisplayId = displayId;
        mLayerStack = layerStack;
        mPrimaryDisplayDevice = primaryDisplayDevice;
    
Methods Summary
public voidconfigureDisplayInTransactionLocked(DisplayDevice device, boolean isBlanked)
Applies the layer stack and transformation to the given display device so that it shows the contents of this logical display. We know that the given display device is only ever showing the contents of a single logical display, so this method is expected to blow away all of its transformation properties to make it happen regardless of what the display device was previously showing. The caller must have an open Surface transaction. The display device may not be the primary display device, in the case where the display is being mirrored.

param
device The display device to modify.
param
isBlanked True if the device is being blanked.

        final DisplayInfo displayInfo = getDisplayInfoLocked();
        final DisplayDeviceInfo displayDeviceInfo = device.getDisplayDeviceInfoLocked();

        // Set the layer stack.
        device.setLayerStackInTransactionLocked(isBlanked ? BLANK_LAYER_STACK : mLayerStack);

        // Set the refresh rate
        device.requestRefreshRateLocked(mRequestedRefreshRate);

        // Set the viewport.
        // This is the area of the logical display that we intend to show on the
        // display device.  For now, it is always the full size of the logical display.
        mTempLayerStackRect.set(0, 0, displayInfo.logicalWidth, displayInfo.logicalHeight);

        // Set the orientation.
        // The orientation specifies how the physical coordinate system of the display
        // is rotated when the contents of the logical display are rendered.
        int orientation = Surface.ROTATION_0;
        if ((displayDeviceInfo.flags & DisplayDeviceInfo.FLAG_ROTATES_WITH_CONTENT) != 0) {
            orientation = displayInfo.rotation;
        }

        // Apply the physical rotation of the display device itself.
        orientation = (orientation + displayDeviceInfo.rotation) % 4;

        // Set the frame.
        // The frame specifies the rotated physical coordinates into which the viewport
        // is mapped.  We need to take care to preserve the aspect ratio of the viewport.
        // Currently we maximize the area to fill the display, but we could try to be
        // more clever and match resolutions.
        boolean rotated = (orientation == Surface.ROTATION_90
                || orientation == Surface.ROTATION_270);
        int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
        int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;

        // Determine whether the width or height is more constrained to be scaled.
        //    physWidth / displayInfo.logicalWidth    => letter box
        // or physHeight / displayInfo.logicalHeight  => pillar box
        //
        // We avoid a division (and possible floating point imprecision) here by
        // multiplying the fractions by the product of their denominators before
        // comparing them.
        int displayRectWidth, displayRectHeight;
        if (physWidth * displayInfo.logicalHeight
                < physHeight * displayInfo.logicalWidth) {
            // Letter box.
            displayRectWidth = physWidth;
            displayRectHeight = displayInfo.logicalHeight * physWidth / displayInfo.logicalWidth;
        } else {
            // Pillar box.
            displayRectWidth = displayInfo.logicalWidth * physHeight / displayInfo.logicalHeight;
            displayRectHeight = physHeight;
        }
        int displayRectTop = (physHeight - displayRectHeight) / 2;
        int displayRectLeft = (physWidth - displayRectWidth) / 2;
        mTempDisplayRect.set(displayRectLeft, displayRectTop,
                displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);

        device.setProjectionInTransactionLocked(orientation, mTempLayerStackRect, mTempDisplayRect);
    
public voiddumpLocked(java.io.PrintWriter pw)

        pw.println("mDisplayId=" + mDisplayId);
        pw.println("mLayerStack=" + mLayerStack);
        pw.println("mHasContent=" + mHasContent);
        pw.println("mPrimaryDisplayDevice=" + (mPrimaryDisplayDevice != null ?
                mPrimaryDisplayDevice.getNameLocked() : "null"));
        pw.println("mBaseDisplayInfo=" + mBaseDisplayInfo);
        pw.println("mOverrideDisplayInfo=" + mOverrideDisplayInfo);
    
public intgetDisplayIdLocked()
Gets the logical display id of this logical display.

return
The logical display id.

        return mDisplayId;
    
public android.view.DisplayInfogetDisplayInfoLocked()
Gets information about the logical display.

return
The device info, which should be treated as immutable by the caller. The logical display should allocate a new display info object whenever the data changes.

        if (mInfo == null) {
            mInfo = new DisplayInfo();
            if (mOverrideDisplayInfo != null) {
                mInfo.copyFrom(mOverrideDisplayInfo);
                mInfo.layerStack = mBaseDisplayInfo.layerStack;
                mInfo.name = mBaseDisplayInfo.name;
                mInfo.uniqueId = mBaseDisplayInfo.uniqueId;
                mInfo.state = mBaseDisplayInfo.state;
            } else {
                mInfo.copyFrom(mBaseDisplayInfo);
            }
        }
        return mInfo;
    
public DisplayDevicegetPrimaryDisplayDeviceLocked()
Gets the primary display device associated with this logical display.

return
The primary display device.

        return mPrimaryDisplayDevice;
    
public floatgetRequestedRefreshRateLocked()
Gets the pending requested refresh rate.

return
The pending refresh rate requested

        return mRequestedRefreshRate;
    
public booleanhasContentLocked()
Returns true if the logical display has unique content.

If the display has unique content then we will try to ensure that it is visible on at least its primary display device. Otherwise we will ignore the logical display and perhaps show mirrored content on the primary display device.

return
True if the display has unique content.

        return mHasContent;
    
public booleanisValidLocked()
Returns true if the logical display is in a valid state. This method should be checked after calling {@link #updateLocked} to handle the case where a logical display should be removed because all of its associated display devices are gone or if it is otherwise no longer needed.

return
True if the logical display is still valid.

        return mPrimaryDisplayDevice != null;
    
public booleansetDisplayInfoOverrideFromWindowManagerLocked(android.view.DisplayInfo info)
Sets overridden logical display information from the window manager. This method can be used to adjust application insets, rotation, and other properties that the window manager takes care of.

param
info The logical display information, may be null.

        if (info != null) {
            if (mOverrideDisplayInfo == null) {
                mOverrideDisplayInfo = new DisplayInfo(info);
                mInfo = null;
                return true;
            }
            if (!mOverrideDisplayInfo.equals(info)) {
                mOverrideDisplayInfo.copyFrom(info);
                mInfo = null;
                return true;
            }
        } else if (mOverrideDisplayInfo != null) {
            mOverrideDisplayInfo = null;
            mInfo = null;
            return true;
        }
        return false;
    
public voidsetHasContentLocked(boolean hasContent)
Sets whether the logical display has unique content.

param
hasContent True if the display has unique content.

        mHasContent = hasContent;
    
public voidsetRequestedRefreshRateLocked(float requestedRefreshRate)
Requests the given refresh rate.

param
requestedRefreshRate The desired refresh rate.

        mRequestedRefreshRate = requestedRefreshRate;
    
public voidupdateLocked(java.util.List devices)
Updates the state of the logical display based on the available display devices. The logical display might become invalid if it is attached to a display device that no longer exists.

param
devices The list of all connected display devices.

        // Nothing to update if already invalid.
        if (mPrimaryDisplayDevice == null) {
            return;
        }

        // Check whether logical display has become invalid.
        if (!devices.contains(mPrimaryDisplayDevice)) {
            mPrimaryDisplayDevice = null;
            return;
        }

        // Bootstrap the logical display using its associated primary physical display.
        // We might use more elaborate configurations later.  It's possible that the
        // configuration of several physical displays might be used to determine the
        // logical display that they are sharing.  (eg. Adjust size for pixel-perfect
        // mirroring over HDMI.)
        DisplayDeviceInfo deviceInfo = mPrimaryDisplayDevice.getDisplayDeviceInfoLocked();
        if (!Objects.equal(mPrimaryDisplayDeviceInfo, deviceInfo)) {
            mBaseDisplayInfo.layerStack = mLayerStack;
            mBaseDisplayInfo.flags = 0;
            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS) != 0) {
                mBaseDisplayInfo.flags |= Display.FLAG_SUPPORTS_PROTECTED_BUFFERS;
            }
            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_SECURE) != 0) {
                mBaseDisplayInfo.flags |= Display.FLAG_SECURE;
            }
            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRIVATE) != 0) {
                mBaseDisplayInfo.flags |= Display.FLAG_PRIVATE;
            }
            if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_PRESENTATION) != 0) {
                mBaseDisplayInfo.flags |= Display.FLAG_PRESENTATION;
            }
            mBaseDisplayInfo.type = deviceInfo.type;
            mBaseDisplayInfo.address = deviceInfo.address;
            mBaseDisplayInfo.name = deviceInfo.name;
            mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId;
            mBaseDisplayInfo.appWidth = deviceInfo.width;
            mBaseDisplayInfo.appHeight = deviceInfo.height;
            mBaseDisplayInfo.logicalWidth = deviceInfo.width;
            mBaseDisplayInfo.logicalHeight = deviceInfo.height;
            mBaseDisplayInfo.rotation = Surface.ROTATION_0;
            mBaseDisplayInfo.refreshRate = deviceInfo.refreshRate;
            mBaseDisplayInfo.supportedRefreshRates = Arrays.copyOf(
                    deviceInfo.supportedRefreshRates, deviceInfo.supportedRefreshRates.length);
            mBaseDisplayInfo.logicalDensityDpi = deviceInfo.densityDpi;
            mBaseDisplayInfo.physicalXDpi = deviceInfo.xDpi;
            mBaseDisplayInfo.physicalYDpi = deviceInfo.yDpi;
            mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;
            mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;
            mBaseDisplayInfo.state = deviceInfo.state;
            mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
            mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
            mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
            mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height;
            mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
            mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;

            mPrimaryDisplayDeviceInfo = deviceInfo;
            mInfo = null;
        }