/* * Copyright (C) 2006 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package android.view; import android.annotation.IntDef; import android.annotation.RequiresPermission; import android.content.Context; import android.content.res.CompatibilityInfo; import android.content.res.Resources; import android.graphics.PixelFormat; import android.graphics.Point; import android.graphics.Rect; import android.hardware.display.DisplayManagerGlobal; import android.os.Parcel; import android.os.Parcelable; import android.os.Process; import android.os.SystemClock; import android.util.DisplayMetrics; import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Arrays; import static android.Manifest.permission.CONFIGURE_DISPLAY_COLOR_TRANSFORM; /** * Provides information about the size and density of a logical display. *
* The display area is described in two different ways. *
* A logical display does not necessarily represent a particular physical display device * such as the built-in screen or an external monitor. The contents of a logical * display may be presented on one or more physical displays according to the devices * that are currently attached and whether mirroring has been enabled. *
*/ public final class Display { private static final String TAG = "Display"; private static final boolean DEBUG = false; private final DisplayManagerGlobal mGlobal; private final int mDisplayId; private final int mLayerStack; private final int mFlags; private final int mType; private final String mAddress; private final int mOwnerUid; private final String mOwnerPackageName; private final DisplayAdjustments mDisplayAdjustments; private DisplayInfo mDisplayInfo; // never null private boolean mIsValid; // Temporary display metrics structure used for compatibility mode. private final DisplayMetrics mTempMetrics = new DisplayMetrics(); // We cache the app width and height properties briefly between calls // to getHeight() and getWidth() to ensure that applications perceive // consistent results when the size changes (most of the time). // Applications should now be using getSize() instead. private static final int CACHED_APP_SIZE_DURATION_MILLIS = 20; private long mLastCachedAppSizeUpdate; private int mCachedAppWidthCompat; private int mCachedAppHeightCompat; /** * The default Display id, which is the id of the built-in primary display * assuming there is one. */ public static final int DEFAULT_DISPLAY = 0; /** * Invalid display id. */ public static final int INVALID_DISPLAY = -1; /** * Display flag: Indicates that the display supports compositing content * that is stored in protected graphics buffers. ** If this flag is set then the display device supports compositing protected buffers. *
* If this flag is not set then the display device may not support compositing * protected buffers; the user may see a blank region on the screen instead of * the protected content. *
* Secure (DRM) video decoders may allocate protected graphics buffers to request that * a hardware-protected path be provided between the video decoder and the external * display sink. If a hardware-protected path is not available, then content stored * in protected graphics buffers may not be composited. *
* An application can use the absence of this flag as a hint that it should not use protected * buffers for this display because the content may not be visible. For example, * if the flag is not set then the application may choose not to show content on this * display, show an informative error message, select an alternate content stream * or adopt a different strategy for decoding content that does not rely on * protected buffers. *
* * @see #getFlags */ public static final int FLAG_SUPPORTS_PROTECTED_BUFFERS = 1 << 0; /** * Display flag: Indicates that the display has a secure video output and * supports compositing secure surfaces. ** If this flag is set then the display device has a secure video output * and is capable of showing secure surfaces. It may also be capable of * showing {@link #FLAG_SUPPORTS_PROTECTED_BUFFERS protected buffers}. *
* If this flag is not set then the display device may not have a secure video * output; the user may see a blank region on the screen instead of * the contents of secure surfaces or protected buffers. *
* Secure surfaces are used to prevent content rendered into those surfaces * by applications from appearing in screenshots or from being viewed * on non-secure displays. Protected buffers are used by secure video decoders * for a similar purpose. *
* An application creates a window with a secure surface by specifying the * {@link WindowManager.LayoutParams#FLAG_SECURE} window flag. * Likewise, an application creates a {@link SurfaceView} with a secure surface * by calling {@link SurfaceView#setSecure} before attaching the secure view to * its containing window. *
* An application can use the absence of this flag as a hint that it should not create * secure surfaces or protected buffers on this display because the content may * not be visible. For example, if the flag is not set then the application may * choose not to show content on this display, show an informative error message, * select an alternate content stream or adopt a different strategy for decoding * content that does not rely on secure surfaces or protected buffers. *
* * @see #getFlags */ public static final int FLAG_SECURE = 1 << 1; /** * Display flag: Indicates that the display is private. Only the application that * owns the display can create windows on it. * * @see #getFlags */ public static final int FLAG_PRIVATE = 1 << 2; /** * Display flag: Indicates that the display is a presentation display. ** This flag identifies secondary displays that are suitable for * use as presentation displays such as HDMI or Wireless displays. Applications * may automatically project their content to presentation displays to provide * richer second screen experiences. *
* * @see #getFlags */ public static final int FLAG_PRESENTATION = 1 << 3; /** * Display flag: Indicates that the display has a round shape. ** This flag identifies displays that are circular, elliptical or otherwise * do not permit the user to see all the way to the logical corners of the display. *
* * @see #getFlags */ public static final int FLAG_ROUND = 1 << 4; /** * Display flag: Indicates that the contents of the display should not be scaled * to fit the physical screen dimensions. Used for development only to emulate * devices with smaller physicals screens while preserving density. * * @hide */ public static final int FLAG_SCALING_DISABLED = 1 << 30; /** * Display type: Unknown display type. * @hide */ public static final int TYPE_UNKNOWN = 0; /** * Display type: Built-in display. * @hide */ public static final int TYPE_BUILT_IN = 1; /** * Display type: HDMI display. * @hide */ public static final int TYPE_HDMI = 2; /** * Display type: WiFi display. * @hide */ public static final int TYPE_WIFI = 3; /** * Display type: Overlay display. * @hide */ public static final int TYPE_OVERLAY = 4; /** * Display type: Virtual display. * @hide */ public static final int TYPE_VIRTUAL = 5; /** * Display state: The display state is unknown. * * @see #getState */ public static final int STATE_UNKNOWN = 0; /** * Display state: The display is off. * * @see #getState */ public static final int STATE_OFF = 1; /** * Display state: The display is on. * * @see #getState */ public static final int STATE_ON = 2; /** * Display state: The display is dozing in a low power state; it is still * on but is optimized for showing system-provided content while the * device is non-interactive. * * @see #getState * @see android.os.PowerManager#isInteractive */ public static final int STATE_DOZE = 3; /** * Display state: The display is dozing in a suspended low power state; it is still * on but is optimized for showing static system-provided content while the device * is non-interactive. This mode may be used to conserve even more power by allowing * the hardware to stop applying frame buffer updates from the graphics subsystem or * to take over the display and manage it autonomously to implement low power always-on * display functionality. * * @see #getState * @see android.os.PowerManager#isInteractive */ public static final int STATE_DOZE_SUSPEND = 4; /** * Internal method to create a display. * Applications should use {@link android.view.WindowManager#getDefaultDisplay()} * or {@link android.hardware.display.DisplayManager#getDisplay} * to get a display object. * * @hide */ public Display(DisplayManagerGlobal global, int displayId, DisplayInfo displayInfo /*not null*/, DisplayAdjustments daj) { mGlobal = global; mDisplayId = displayId; mDisplayInfo = displayInfo; mDisplayAdjustments = new DisplayAdjustments(daj); mIsValid = true; // Cache properties that cannot change as long as the display is valid. mLayerStack = displayInfo.layerStack; mFlags = displayInfo.flags; mType = displayInfo.type; mAddress = displayInfo.address; mOwnerUid = displayInfo.ownerUid; mOwnerPackageName = displayInfo.ownerPackageName; } /** * Gets the display id. ** Each logical display has a unique id. * The default display has id {@link #DEFAULT_DISPLAY}. *
*/ public int getDisplayId() { return mDisplayId; } /** * Returns true if this display is still valid, false if the display has been removed. * * If the display is invalid, then the methods of this class will * continue to report the most recently observed display information. * However, it is unwise (and rather fruitless) to continue using a * {@link Display} object after the display's demise. * * It's possible for a display that was previously invalid to become * valid again if a display with the same id is reconnected. * * @return True if the display is still valid. */ public boolean isValid() { synchronized (this) { updateDisplayInfoLocked(); return mIsValid; } } /** * Gets a full copy of the display information. * * @param outDisplayInfo The object to receive the copy of the display information. * @return True if the display is still valid. * @hide */ public boolean getDisplayInfo(DisplayInfo outDisplayInfo) { synchronized (this) { updateDisplayInfoLocked(); outDisplayInfo.copyFrom(mDisplayInfo); return mIsValid; } } /** * Gets the display's layer stack. * * Each display has its own independent layer stack upon which surfaces * are placed to be managed by surface flinger. * * @return The display's layer stack number. * @hide */ public int getLayerStack() { return mLayerStack; } /** * Returns a combination of flags that describe the capabilities of the display. * * @return The display flags. * * @see #FLAG_SUPPORTS_PROTECTED_BUFFERS * @see #FLAG_SECURE * @see #FLAG_PRIVATE */ public int getFlags() { return mFlags; } /** * Gets the display type. * * @return The display type. * * @see #TYPE_UNKNOWN * @see #TYPE_BUILT_IN * @see #TYPE_HDMI * @see #TYPE_WIFI * @see #TYPE_OVERLAY * @see #TYPE_VIRTUAL * @hide */ public int getType() { return mType; } /** * Gets the display address, or null if none. * Interpretation varies by display type. * * @return The display address. * @hide */ public String getAddress() { return mAddress; } /** * Gets the UID of the application that owns this display, or zero if it is * owned by the system. ** If the display is private, then only the owner can use it. *
* * @hide */ public int getOwnerUid() { return mOwnerUid; } /** * Gets the package name of the application that owns this display, or null if it is * owned by the system. ** If the display is private, then only the owner can use it. *
* * @hide */ public String getOwnerPackageName() { return mOwnerPackageName; } /** * Gets the compatibility info used by this display instance. * * @return The display adjustments holder, or null if none is required. * @hide */ public DisplayAdjustments getDisplayAdjustments() { return mDisplayAdjustments; } /** * Gets the name of the display. ** Note that some displays may be renamed by the user. *
* * @return The display's name. */ public String getName() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.name; } } /** * Gets the size of the display, in pixels. ** Note that this value should not be used for computing layouts, * since a device will typically have screen decoration (such as a status bar) * along the edges of the display that reduce the amount of application * space available from the size returned here. Layouts should instead use * the window size. *
* The size is adjusted based on the current rotation of the display. *
* The size returned by this method does not necessarily represent the * actual raw size (native resolution) of the display. The returned size may * be adjusted to exclude certain system decoration elements that are always visible. * It may also be scaled to provide compatibility with older applications that * were originally designed for smaller displays. *
* * @param outSize A {@link Point} object to receive the size information. */ public void getSize(Point outSize) { synchronized (this) { updateDisplayInfoLocked(); mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); outSize.x = mTempMetrics.widthPixels; outSize.y = mTempMetrics.heightPixels; } } /** * Gets the size of the display as a rectangle, in pixels. * * @param outSize A {@link Rect} object to receive the size information. * @see #getSize(Point) */ public void getRectSize(Rect outSize) { synchronized (this) { updateDisplayInfoLocked(); mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); outSize.set(0, 0, mTempMetrics.widthPixels, mTempMetrics.heightPixels); } } /** * Return the range of display sizes an application can expect to encounter * under normal operation, as long as there is no physical change in screen * size. This is basically the sizes you will see as the orientation * changes, taking into account whatever screen decoration there is in * each rotation. For example, the status bar is always at the top of the * screen, so it will reduce the height both in landscape and portrait, and * the smallest height returned here will be the smaller of the two. * * This is intended for applications to get an idea of the range of sizes * they will encounter while going through device rotations, to provide a * stable UI through rotation. The sizes here take into account all standard * system decorations that reduce the size actually available to the * application: the status bar, navigation bar, system bar, etc. It does * not take into account more transient elements like an IME * soft keyboard. * * @param outSmallestSize Filled in with the smallest width and height * that the application will encounter, in pixels (not dp units). The x * (width) dimension here directly corresponds to * {@link android.content.res.Configuration#smallestScreenWidthDp * Configuration.smallestScreenWidthDp}, except the value here is in raw * screen pixels rather than dp units. Your application may of course * still get smaller space yet if, for example, a soft keyboard is * being displayed. * @param outLargestSize Filled in with the largest width and height * that the application will encounter, in pixels (not dp units). Your * application may of course still get larger space than this if, * for example, screen decorations like the status bar are being hidden. */ public void getCurrentSizeRange(Point outSmallestSize, Point outLargestSize) { synchronized (this) { updateDisplayInfoLocked(); outSmallestSize.x = mDisplayInfo.smallestNominalAppWidth; outSmallestSize.y = mDisplayInfo.smallestNominalAppHeight; outLargestSize.x = mDisplayInfo.largestNominalAppWidth; outLargestSize.y = mDisplayInfo.largestNominalAppHeight; } } /** * Return the maximum screen size dimension that will happen. This is * mostly for wallpapers. * @hide */ public int getMaximumSizeDimension() { synchronized (this) { updateDisplayInfoLocked(); return Math.max(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight); } } /** * @deprecated Use {@link #getSize(Point)} instead. */ @Deprecated public int getWidth() { synchronized (this) { updateCachedAppSizeIfNeededLocked(); return mCachedAppWidthCompat; } } /** * @deprecated Use {@link #getSize(Point)} instead. */ @Deprecated public int getHeight() { synchronized (this) { updateCachedAppSizeIfNeededLocked(); return mCachedAppHeightCompat; } } /** * @hide * Return a rectangle defining the insets of the overscan region of the display. * Each field of the rectangle is the number of pixels the overscan area extends * into the display on that side. */ public void getOverscanInsets(Rect outRect) { synchronized (this) { updateDisplayInfoLocked(); outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop, mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom); } } /** * Returns the rotation of the screen from its "natural" orientation. * The returned value may be {@link Surface#ROTATION_0 Surface.ROTATION_0} * (no rotation), {@link Surface#ROTATION_90 Surface.ROTATION_90}, * {@link Surface#ROTATION_180 Surface.ROTATION_180}, or * {@link Surface#ROTATION_270 Surface.ROTATION_270}. For * example, if a device has a naturally tall screen, and the user has * turned it on its side to go into a landscape orientation, the value * returned here may be either {@link Surface#ROTATION_90 Surface.ROTATION_90} * or {@link Surface#ROTATION_270 Surface.ROTATION_270} depending on * the direction it was turned. The angle is the rotation of the drawn * graphics on the screen, which is the opposite direction of the physical * rotation of the device. For example, if the device is rotated 90 * degrees counter-clockwise, to compensate rendering will be rotated by * 90 degrees clockwise and thus the returned value here will be * {@link Surface#ROTATION_90 Surface.ROTATION_90}. */ @Surface.Rotation public int getRotation() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.rotation; } } /** * @deprecated use {@link #getRotation} * @return orientation of this display. */ @Deprecated @Surface.Rotation public int getOrientation() { return getRotation(); } /** * Gets the pixel format of the display. * @return One of the constants defined in {@link android.graphics.PixelFormat}. * * @deprecated This method is no longer supported. * The result is always {@link PixelFormat#RGBA_8888}. */ @Deprecated public int getPixelFormat() { return PixelFormat.RGBA_8888; } /** * Gets the refresh rate of this display in frames per second. */ public float getRefreshRate() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.getMode().getRefreshRate(); } } /** * Get the supported refresh rates of this display in frames per second. ** This method only returns refresh rates for the display's default modes. For more options, use * {@link #getSupportedModes()}. * * @deprecated use {@link #getSupportedModes()} instead */ @Deprecated public float[] getSupportedRefreshRates() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.getDefaultRefreshRates(); } } /** * Returns the active mode of the display. */ public Mode getMode() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.getMode(); } } /** * Gets the supported modes of this display. */ public Mode[] getSupportedModes() { synchronized (this) { updateDisplayInfoLocked(); final Display.Mode[] modes = mDisplayInfo.supportedModes; return Arrays.copyOf(modes, modes.length); } } /** * Request the display applies a color transform. * @hide */ @RequiresPermission(CONFIGURE_DISPLAY_COLOR_TRANSFORM) public void requestColorTransform(ColorTransform colorTransform) { mGlobal.requestColorTransform(mDisplayId, colorTransform.getId()); } /** * Returns the active color transform of this display * @hide */ public ColorTransform getColorTransform() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.getColorTransform(); } } /** * Returns the default color transform of this display * @hide */ public ColorTransform getDefaultColorTransform() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.getDefaultColorTransform(); } } /** * Returns the display's HDR capabilities. */ public HdrCapabilities getHdrCapabilities() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.hdrCapabilities; } } /** * Gets the supported color transforms of this device. * @hide */ public ColorTransform[] getSupportedColorTransforms() { synchronized (this) { updateDisplayInfoLocked(); ColorTransform[] transforms = mDisplayInfo.supportedColorTransforms; return Arrays.copyOf(transforms, transforms.length); } } /** * Gets the app VSYNC offset, in nanoseconds. This is a positive value indicating * the phase offset of the VSYNC events provided by Choreographer relative to the * display refresh. For example, if Choreographer reports that the refresh occurred * at time N, it actually occurred at (N - appVsyncOffset). *
* Apps generally do not need to be aware of this. It's only useful for fine-grained * A/V synchronization. */ public long getAppVsyncOffsetNanos() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.appVsyncOffsetNanos; } } /** * This is how far in advance a buffer must be queued for presentation at * a given time. If you want a buffer to appear on the screen at * time N, you must submit the buffer before (N - presentationDeadline). *
* The desired presentation time for GLES rendering may be set with * {@link android.opengl.EGLExt#eglPresentationTimeANDROID}. For video decoding, use * {@link android.media.MediaCodec#releaseOutputBuffer(int, long)}. Times are * expressed in nanoseconds, using the system monotonic clock * ({@link System#nanoTime}). */ public long getPresentationDeadlineNanos() { synchronized (this) { updateDisplayInfoLocked(); return mDisplayInfo.presentationDeadlineNanos; } } /** * Gets display metrics that describe the size and density of this display. * The size returned by this method does not necessarily represent the * actual raw size (native resolution) of the display. *
* 1. The returned size may be adjusted to exclude certain system decor elements * that are always visible. *
* 2. It may be scaled to provide compatibility with older applications that * were originally designed for smaller displays. *
* 3. It can be different depending on the WindowManager to which the display belongs. *
* - If requested from non-Activity context (e.g. Application context via * {@code (WindowManager) getApplicationContext().getSystemService(Context.WINDOW_SERVICE)}) * metrics will report real size of the display based on current rotation. * - If requested from activity resulting metrics will correspond to current window metrics. * In this case the size can be smaller than physical size in multi-window mode. ** * * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. */ public void getMetrics(DisplayMetrics outMetrics) { synchronized (this) { updateDisplayInfoLocked(); mDisplayInfo.getAppMetrics(outMetrics, mDisplayAdjustments); } } /** * Gets the real size of the display without subtracting any window decor or * applying any compatibility scale factors. *
* The size is adjusted based on the current rotation of the display. *
* The real size may be smaller than the physical size of the screen when the * window manager is emulating a smaller display (using adb shell am display-size). *
* * @param outSize Set to the real size of the display. */ public void getRealSize(Point outSize) { synchronized (this) { updateDisplayInfoLocked(); outSize.x = mDisplayInfo.logicalWidth; outSize.y = mDisplayInfo.logicalHeight; } } /** * Gets display metrics based on the real size of this display. ** The size is adjusted based on the current rotation of the display. *
* The real size may be smaller than the physical size of the screen when the * window manager is emulating a smaller display (using adb shell wm size). *
* * @param outMetrics A {@link DisplayMetrics} object to receive the metrics. */ public void getRealMetrics(DisplayMetrics outMetrics) { synchronized (this) { updateDisplayInfoLocked(); mDisplayInfo.getLogicalMetrics(outMetrics, CompatibilityInfo.DEFAULT_COMPATIBILITY_INFO, null); } } /** * Gets the state of the display, such as whether it is on or off. * * @return The state of the display: one of {@link #STATE_OFF}, {@link #STATE_ON}, * {@link #STATE_DOZE}, {@link #STATE_DOZE_SUSPEND}, or {@link #STATE_UNKNOWN}. */ public int getState() { synchronized (this) { updateDisplayInfoLocked(); return mIsValid ? mDisplayInfo.state : STATE_UNKNOWN; } } /** * Returns true if the specified UID has access to this display. * @hide */ public boolean hasAccess(int uid) { return Display.hasAccess(uid, mFlags, mOwnerUid); } /** @hide */ public static boolean hasAccess(int uid, int flags, int ownerUid) { return (flags & Display.FLAG_PRIVATE) == 0 || uid == ownerUid || uid == Process.SYSTEM_UID || uid == 0; } /** * Returns true if the display is a public presentation display. * @hide */ public boolean isPublicPresentation() { return (mFlags & (Display.FLAG_PRIVATE | Display.FLAG_PRESENTATION)) == Display.FLAG_PRESENTATION; } private void updateDisplayInfoLocked() { // Note: The display manager caches display info objects on our behalf. DisplayInfo newInfo = mGlobal.getDisplayInfo(mDisplayId); if (newInfo == null) { // Preserve the old mDisplayInfo after the display is removed. if (mIsValid) { mIsValid = false; if (DEBUG) { Log.d(TAG, "Logical display " + mDisplayId + " was removed."); } } } else { // Use the new display info. (It might be the same object if nothing changed.) mDisplayInfo = newInfo; if (!mIsValid) { mIsValid = true; if (DEBUG) { Log.d(TAG, "Logical display " + mDisplayId + " was recreated."); } } } } private void updateCachedAppSizeIfNeededLocked() { long now = SystemClock.uptimeMillis(); if (now > mLastCachedAppSizeUpdate + CACHED_APP_SIZE_DURATION_MILLIS) { updateDisplayInfoLocked(); mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); mCachedAppWidthCompat = mTempMetrics.widthPixels; mCachedAppHeightCompat = mTempMetrics.heightPixels; mLastCachedAppSizeUpdate = now; } } // For debugging purposes @Override public String toString() { synchronized (this) { updateDisplayInfoLocked(); mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments); return "Display id " + mDisplayId + ": " + mDisplayInfo + ", " + mTempMetrics + ", isValid=" + mIsValid; } } /** * @hide */ public static String typeToString(int type) { switch (type) { case TYPE_UNKNOWN: return "UNKNOWN"; case TYPE_BUILT_IN: return "BUILT_IN"; case TYPE_HDMI: return "HDMI"; case TYPE_WIFI: return "WIFI"; case TYPE_OVERLAY: return "OVERLAY"; case TYPE_VIRTUAL: return "VIRTUAL"; default: return Integer.toString(type); } } /** * @hide */ public static String stateToString(int state) { switch (state) { case STATE_UNKNOWN: return "UNKNOWN"; case STATE_OFF: return "OFF"; case STATE_ON: return "ON"; case STATE_DOZE: return "DOZE"; case STATE_DOZE_SUSPEND: return "DOZE_SUSPEND"; default: return Integer.toString(state); } } /** * Returns true if display updates may be suspended while in the specified * display power state. * @hide */ public static boolean isSuspendedState(int state) { return state == STATE_OFF || state == STATE_DOZE_SUSPEND; } /** * A mode supported by a given display. * * @see Display#getSupportedModes() */ public static final class Mode implements Parcelable { /** * @hide */ public static final Mode[] EMPTY_ARRAY = new Mode[0]; private final int mModeId; private final int mWidth; private final int mHeight; private final float mRefreshRate; /** * @hide */ public Mode(int modeId, int width, int height, float refreshRate) { mModeId = modeId; mWidth = width; mHeight = height; mRefreshRate = refreshRate; } /** * Returns this mode's id. */ public int getModeId() { return mModeId; } /** * Returns the physical width of the display in pixels when configured in this mode's * resolution. ** Note that due to application UI scaling, the number of pixels made available to * applications when the mode is active (as reported by {@link Display#getWidth()} may * differ from the mode's actual resolution (as reported by this function). *
* For example, applications running on a 4K display may have their UI laid out and rendered * in 1080p and then scaled up. Applications can take advantage of the extra resolution by * rendering content through a {@link android.view.SurfaceView} using full size buffers. */ public int getPhysicalWidth() { return mWidth; } /** * Returns the physical height of the display in pixels when configured in this mode's * resolution. *
* Note that due to application UI scaling, the number of pixels made available to * applications when the mode is active (as reported by {@link Display#getHeight()} may * differ from the mode's actual resolution (as reported by this function). *
* For example, applications running on a 4K display may have their UI laid out and rendered
* in 1080p and then scaled up. Applications can take advantage of the extra resolution by
* rendering content through a {@link android.view.SurfaceView} using full size buffers.
*/
public int getPhysicalHeight() {
return mHeight;
}
/**
* Returns the refresh rate in frames per second.
*/
public float getRefreshRate() {
return mRefreshRate;
}
/**
* Returns {@code true} if this mode matches the given parameters.
*
* @hide
*/
public boolean matches(int width, int height, float refreshRate) {
return mWidth == width &&
mHeight == height &&
Float.floatToIntBits(mRefreshRate) == Float.floatToIntBits(refreshRate);
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof Mode)) {
return false;
}
Mode that = (Mode) other;
return mModeId == that.mModeId && matches(that.mWidth, that.mHeight, that.mRefreshRate);
}
@Override
public int hashCode() {
int hash = 1;
hash = hash * 17 + mModeId;
hash = hash * 17 + mWidth;
hash = hash * 17 + mHeight;
hash = hash * 17 + Float.floatToIntBits(mRefreshRate);
return hash;
}
@Override
public String toString() {
return new StringBuilder("{")
.append("id=").append(mModeId)
.append(", width=").append(mWidth)
.append(", height=").append(mHeight)
.append(", fps=").append(mRefreshRate)
.append("}")
.toString();
}
@Override
public int describeContents() {
return 0;
}
private Mode(Parcel in) {
this(in.readInt(), in.readInt(), in.readInt(), in.readFloat());
}
@Override
public void writeToParcel(Parcel out, int parcelableFlags) {
out.writeInt(mModeId);
out.writeInt(mWidth);
out.writeInt(mHeight);
out.writeFloat(mRefreshRate);
}
@SuppressWarnings("hiding")
public static final Parcelable.Creator You can get an instance for a given {@link Display} object with
* {@link Display#getHdrCapabilities getHdrCapabilities()}.
*/
public static final class HdrCapabilities implements Parcelable {
/**
* Invalid luminance value.
*/
public static final float INVALID_LUMINANCE = -1;
/**
* Dolby Vision high dynamic range (HDR) display.
*/
public static final int HDR_TYPE_DOLBY_VISION = 1;
/**
* HDR10 display.
*/
public static final int HDR_TYPE_HDR10 = 2;
/**
* Hybrid Log-Gamma HDR display.
*/
public static final int HDR_TYPE_HLG = 3;
/** @hide */
@IntDef({
HDR_TYPE_DOLBY_VISION,
HDR_TYPE_HDR10,
HDR_TYPE_HLG,
})
@Retention(RetentionPolicy.SOURCE)
public @interface HdrType {}
private @HdrType int[] mSupportedHdrTypes = new int[0];
private float mMaxLuminance = INVALID_LUMINANCE;
private float mMaxAverageLuminance = INVALID_LUMINANCE;
private float mMinLuminance = INVALID_LUMINANCE;
/**
* @hide
*/
public HdrCapabilities() {
}
/**
* @hide
*/
public HdrCapabilities(int[] supportedHdrTypes, float maxLuminance,
float maxAverageLuminance, float minLuminance) {
mSupportedHdrTypes = supportedHdrTypes;
mMaxLuminance = maxLuminance;
mMaxAverageLuminance = maxAverageLuminance;
mMinLuminance = minLuminance;
}
/**
* Gets the supported HDR types of this display.
* Returns empty array if HDR is not supported by the display.
*/
public @HdrType int[] getSupportedHdrTypes() {
return mSupportedHdrTypes;
}
/**
* Returns the desired content max luminance data in cd/m2 for this display.
*/
public float getDesiredMaxLuminance() {
return mMaxLuminance;
}
/**
* Returns the desired content max frame-average luminance data in cd/m2 for this display.
*/
public float getDesiredMaxAverageLuminance() {
return mMaxAverageLuminance;
}
/**
* Returns the desired content min luminance data in cd/m2 for this display.
*/
public float getDesiredMinLuminance() {
return mMinLuminance;
}
public static final Creator