| /* |
| * Copyright (C) 2012 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.hardware.display; |
| |
| import static android.view.Display.DEFAULT_DISPLAY; |
| import static android.view.Display.HdrCapabilities.HdrType; |
| |
| import android.Manifest; |
| import android.annotation.FloatRange; |
| import android.annotation.IntDef; |
| import android.annotation.IntRange; |
| import android.annotation.LongDef; |
| import android.annotation.NonNull; |
| import android.annotation.Nullable; |
| import android.annotation.RequiresPermission; |
| import android.annotation.SystemApi; |
| import android.annotation.SystemService; |
| import android.annotation.TestApi; |
| import android.app.KeyguardManager; |
| import android.compat.annotation.UnsupportedAppUsage; |
| import android.content.Context; |
| import android.content.res.Resources; |
| import android.graphics.Point; |
| import android.media.projection.MediaProjection; |
| import android.os.Build; |
| import android.os.Handler; |
| import android.os.HandlerExecutor; |
| import android.os.Looper; |
| import android.util.Pair; |
| import android.util.Slog; |
| import android.util.SparseArray; |
| import android.view.Display; |
| import android.view.Surface; |
| |
| import java.lang.annotation.Retention; |
| import java.lang.annotation.RetentionPolicy; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.concurrent.Executor; |
| |
| |
| /** |
| * Manages the properties of attached displays. |
| */ |
| @SystemService(Context.DISPLAY_SERVICE) |
| public final class DisplayManager { |
| private static final String TAG = "DisplayManager"; |
| private static final boolean DEBUG = false; |
| |
| private final Context mContext; |
| private final DisplayManagerGlobal mGlobal; |
| |
| private final Object mLock = new Object(); |
| private final SparseArray<Display> mDisplays = new SparseArray<Display>(); |
| |
| private final ArrayList<Display> mTempDisplays = new ArrayList<Display>(); |
| |
| /** |
| * Broadcast receiver that indicates when the Wifi display status changes. |
| * <p> |
| * The status is provided as a {@link WifiDisplayStatus} object in the |
| * {@link #EXTRA_WIFI_DISPLAY_STATUS} extra. |
| * </p><p> |
| * This broadcast is only sent to registered receivers and can only be sent by the system. |
| * </p> |
| * @hide |
| */ |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public static final String ACTION_WIFI_DISPLAY_STATUS_CHANGED = |
| "android.hardware.display.action.WIFI_DISPLAY_STATUS_CHANGED"; |
| |
| /** |
| * Contains a {@link WifiDisplayStatus} object. |
| * @hide |
| */ |
| @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) |
| public static final String EXTRA_WIFI_DISPLAY_STATUS = |
| "android.hardware.display.extra.WIFI_DISPLAY_STATUS"; |
| |
| /** |
| * Display category: Presentation displays. |
| * <p> |
| * This category can be used to identify secondary displays that are suitable for |
| * use as presentation displays such as external or wireless displays. Applications |
| * may automatically project their content to presentation displays to provide |
| * richer second screen experiences. |
| * </p> |
| * |
| * @see android.app.Presentation |
| * @see Display#FLAG_PRESENTATION |
| * @see #getDisplays(String) |
| */ |
| public static final String DISPLAY_CATEGORY_PRESENTATION = |
| "android.hardware.display.category.PRESENTATION"; |
| |
| /** |
| * Display category: All displays, including disabled displays. |
| * <p> |
| * This returns all displays, including currently disabled and inaccessible displays. |
| * |
| * @see #getDisplays(String) |
| * @hide |
| */ |
| public static final String DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED = |
| "android.hardware.display.category.ALL_INCLUDING_DISABLED"; |
| |
| /** @hide **/ |
| @IntDef(prefix = "VIRTUAL_DISPLAY_FLAG_", flag = true, value = { |
| VIRTUAL_DISPLAY_FLAG_PUBLIC, |
| VIRTUAL_DISPLAY_FLAG_PRESENTATION, |
| VIRTUAL_DISPLAY_FLAG_SECURE, |
| VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY, |
| VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, |
| VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD, |
| VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH, |
| VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT, |
| VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL, |
| VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS, |
| VIRTUAL_DISPLAY_FLAG_TRUSTED, |
| VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP, |
| VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED, |
| VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface VirtualDisplayFlag {} |
| |
| /** |
| * Virtual display flag: Create a public display. |
| * |
| * <h3>Public virtual displays</h3> |
| * <p> |
| * When this flag is set, the virtual display is public. |
| * </p><p> |
| * A public virtual display behaves just like most any other display that is connected |
| * to the system such as an external or wireless display. Applications can open |
| * windows on the display and the system may mirror the contents of other displays |
| * onto it. |
| * </p><p> |
| * Creating a public virtual display that isn't restricted to own-content only implicitly |
| * creates an auto-mirroring display. See {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR} for |
| * restrictions on who is allowed to create an auto-mirroring display. |
| * </p> |
| * |
| * <h3>Private virtual displays</h3> |
| * <p> |
| * When this flag is not set, the virtual display is private as defined by the |
| * {@link Display#FLAG_PRIVATE} display flag. |
| * </p> |
| * |
| * <p> |
| * A private virtual display belongs to the application that created it. Only the a owner of a |
| * private virtual display and the apps that are already on that display are allowed to place |
| * windows upon it. The private virtual display also does not participate in display mirroring: |
| * it will neither receive mirrored content from another display nor allow its own content to be |
| * mirrored elsewhere. More precisely, the only processes that are allowed to enumerate or |
| * interact with the private display are those that have the same UID as the application that |
| * originally created the private virtual display or as the activities that are already on that |
| * display. |
| * </p> |
| * |
| * @see #createVirtualDisplay |
| * @see #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY |
| * @see #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_PUBLIC = 1 << 0; |
| |
| /** |
| * Virtual display flag: Create a presentation display. |
| * |
| * <h3>Presentation virtual displays</h3> |
| * <p> |
| * When this flag is set, the virtual display is registered as a presentation |
| * display in the {@link #DISPLAY_CATEGORY_PRESENTATION presentation display category}. |
| * Applications may automatically project their content to presentation displays |
| * to provide richer second screen experiences. |
| * </p> |
| * |
| * <h3>Non-presentation virtual displays</h3> |
| * <p> |
| * When this flag is not set, the virtual display is not registered as a presentation |
| * display. Applications can still project their content on the display but they |
| * will typically not do so automatically. This option is appropriate for |
| * more special-purpose displays. |
| * </p> |
| * |
| * @see android.app.Presentation |
| * @see #createVirtualDisplay |
| * @see #DISPLAY_CATEGORY_PRESENTATION |
| * @see Display#FLAG_PRESENTATION |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_PRESENTATION = 1 << 1; |
| |
| /** |
| * Virtual display flag: Create a secure display. |
| * |
| * <h3>Secure virtual displays</h3> |
| * <p> |
| * When this flag is set, the virtual display is considered secure as defined |
| * by the {@link Display#FLAG_SECURE} display flag. The caller promises to take |
| * reasonable measures, such as over-the-air encryption, to prevent the contents |
| * of the display from being intercepted or recorded on a persistent medium. |
| * </p><p> |
| * Creating a secure virtual display requires the CAPTURE_SECURE_VIDEO_OUTPUT permission. |
| * This permission is reserved for use by system components and is not available to |
| * third-party applications. |
| * </p> |
| * |
| * <h3>Non-secure virtual displays</h3> |
| * <p> |
| * When this flag is not set, the virtual display is considered unsecure. |
| * The content of secure windows will be blanked if shown on this display. |
| * </p> |
| * |
| * @see Display#FLAG_SECURE |
| * @see #createVirtualDisplay |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_SECURE = 1 << 2; |
| |
| /** |
| * Virtual display flag: Only show this display's own content; do not mirror |
| * the content of another display. |
| * |
| * <p> |
| * This flag is used in conjunction with {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. |
| * Ordinarily public virtual displays will automatically mirror the content of the |
| * default display if they have no windows of their own. When this flag is |
| * specified, the virtual display will only ever show its own content and |
| * will be blanked instead if it has no windows. |
| * </p> |
| * |
| * <p> |
| * This flag is mutually exclusive with {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. If both |
| * flags are specified then the own-content only behavior will be applied. |
| * </p> |
| * |
| * <p> |
| * This behavior of this flag is implied whenever neither {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC} |
| * nor {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR} have been set. This flag is only required to |
| * override the default behavior when creating a public display. |
| * </p> |
| * |
| * @see #createVirtualDisplay |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY = 1 << 3; |
| |
| |
| /** |
| * Virtual display flag: Allows content to be mirrored on private displays when no content is |
| * being shown. |
| * |
| * <p> |
| * This flag is mutually exclusive with {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}. |
| * If both flags are specified then the own-content only behavior will be applied. |
| * </p> |
| * |
| * <p> |
| * The behavior of this flag is implied whenever {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC} is set |
| * and {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY} has not been set. This flag is only |
| * required to override the default behavior when creating a private display. |
| * </p> |
| * |
| * <p> |
| * Creating an auto-mirroing virtual display requires the CAPTURE_VIDEO_OUTPUT |
| * or CAPTURE_SECURE_VIDEO_OUTPUT permission. |
| * These permissions are reserved for use by system components and are not available to |
| * third-party applications. |
| * |
| * Alternatively, an appropriate {@link MediaProjection} may be used to create an |
| * auto-mirroring virtual display. |
| * </p> |
| * |
| * @see #createVirtualDisplay |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR = 1 << 4; |
| |
| /** |
| * Virtual display flag: Allows content to be displayed on private virtual displays when |
| * keyguard is shown but is insecure. |
| * |
| * <p> |
| * This might be used in a case when the content of a virtual display is captured and sent to an |
| * external hardware display that is not visible to the system directly. This flag will allow |
| * the continued display of content while other displays will be covered by a keyguard which |
| * doesn't require providing credentials to unlock. This means that there is either no password |
| * or other authentication method set, or the device is in a trusted state - |
| * {@link android.service.trust.TrustAgentService} has available and active trust agent. |
| * </p><p> |
| * This flag can only be applied to private displays as defined by the |
| * {@link Display#FLAG_PRIVATE} display flag. It is mutually exclusive with |
| * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}. If both flags are specified then this flag's behavior |
| * will not be applied. |
| * </p> |
| * |
| * @see #createVirtualDisplay |
| * @see KeyguardManager#isDeviceSecure() |
| * @see KeyguardManager#isDeviceLocked() |
| * @hide |
| */ |
| // TODO (b/114338689): Remove the flag and use IWindowManager#shouldShowWithInsecureKeyguard |
| // TODO: Update name and documentation and un-hide the flag. Don't change the value before that. |
| public static final int VIRTUAL_DISPLAY_FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD = 1 << 5; |
| |
| /** |
| * Virtual display flag: Specifies that the virtual display can be associated with a |
| * touchpad device that matches its uniqueId. |
| * |
| * @see #createVirtualDisplay |
| * @hide |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_SUPPORTS_TOUCH = 1 << 6; |
| |
| /** |
| * Virtual display flag: Indicates that the orientation of this display device is coupled to |
| * the rotation of its associated logical display. |
| * |
| * @see #createVirtualDisplay |
| * @hide |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_ROTATES_WITH_CONTENT = 1 << 7; |
| |
| /** |
| * Virtual display flag: Indicates that the contents will be destroyed once |
| * the display is removed. |
| * |
| * Public virtual displays without this flag will move their content to main display |
| * stack once they're removed. Private vistual displays will always destroy their |
| * content on removal even without this flag. |
| * |
| * @see #createVirtualDisplay |
| * @hide |
| */ |
| // TODO (b/114338689): Remove the flag and use WindowManager#REMOVE_CONTENT_MODE_DESTROY |
| public static final int VIRTUAL_DISPLAY_FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 8; |
| |
| /** |
| * Virtual display flag: Indicates that the display should support system decorations. Virtual |
| * displays without this flag shouldn't show home, IME or any other system decorations. |
| * <p>This flag doesn't work without {@link #VIRTUAL_DISPLAY_FLAG_TRUSTED}</p> |
| * |
| * @see #createVirtualDisplay |
| * @see #VIRTUAL_DISPLAY_FLAG_TRUSTED |
| * @hide |
| */ |
| // TODO (b/114338689): Remove the flag and use IWindowManager#setShouldShowSystemDecors |
| @TestApi |
| public static final int VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS = 1 << 9; |
| |
| /** |
| * Virtual display flags: Indicates that the display is trusted to show system decorations and |
| * receive inputs without users' touch. |
| * |
| * @see #createVirtualDisplay |
| * @see #VIRTUAL_DISPLAY_FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS |
| * @hide |
| */ |
| @SystemApi |
| public static final int VIRTUAL_DISPLAY_FLAG_TRUSTED = 1 << 10; |
| |
| /** |
| * Virtual display flags: Indicates that the display should not be a part of the default |
| * DisplayGroup and instead be part of a new DisplayGroup. |
| * |
| * @see #createVirtualDisplay |
| * @hide |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP = 1 << 11; |
| |
| /** |
| * Virtual display flags: Indicates that the virtual display should always be unlocked and not |
| * have keyguard displayed on it. Only valid for virtual displays that aren't in the default |
| * display group. |
| * |
| * @see #createVirtualDisplay |
| * @see #VIRTUAL_DISPLAY_FLAG_OWN_DISPLAY_GROUP |
| * @hide |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_ALWAYS_UNLOCKED = 1 << 12; |
| |
| /** |
| * Virtual display flags: Indicates that the display should not play sound effects or perform |
| * haptic feedback when the user touches the screen. |
| * |
| * @see #createVirtualDisplay |
| * @hide |
| */ |
| public static final int VIRTUAL_DISPLAY_FLAG_TOUCH_FEEDBACK_DISABLED = 1 << 13; |
| |
| /** @hide */ |
| @IntDef(prefix = {"MATCH_CONTENT_FRAMERATE_"}, value = { |
| MATCH_CONTENT_FRAMERATE_UNKNOWN, |
| MATCH_CONTENT_FRAMERATE_NEVER, |
| MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY, |
| MATCH_CONTENT_FRAMERATE_ALWAYS, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface MatchContentFrameRateType {} |
| |
| /** |
| * Match content frame rate user preference is unknown. |
| */ |
| public static final int MATCH_CONTENT_FRAMERATE_UNKNOWN = -1; |
| |
| /** |
| * No mode switching is allowed. |
| */ |
| public static final int MATCH_CONTENT_FRAMERATE_NEVER = 0; |
| |
| /** |
| * Only refresh rate switches without visual interruptions are allowed. |
| */ |
| public static final int MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY = 1; |
| |
| /** |
| * Refresh rate switches between all refresh rates are allowed even if they have visual |
| * interruptions for the user. |
| */ |
| public static final int MATCH_CONTENT_FRAMERATE_ALWAYS = 2; |
| |
| /** @hide */ |
| @IntDef(prefix = {"SWITCHING_TYPE_"}, value = { |
| SWITCHING_TYPE_NONE, |
| SWITCHING_TYPE_WITHIN_GROUPS, |
| SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS, |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface SwitchingType {} |
| |
| /** |
| * No mode switching will happen. |
| * @hide |
| */ |
| @TestApi |
| public static final int SWITCHING_TYPE_NONE = 0; |
| |
| /** |
| * Allow only refresh rate switching between modes in the same configuration group. This way |
| * only switches without visual interruptions for the user will be allowed. |
| * @hide |
| */ |
| @TestApi |
| public static final int SWITCHING_TYPE_WITHIN_GROUPS = 1; |
| |
| /** |
| * Allow refresh rate switching between all refresh rates even if the switch with have visual |
| * interruptions for the user. |
| * @hide |
| */ |
| @TestApi |
| public static final int SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS = 2; |
| |
| /** |
| * @hide |
| */ |
| @LongDef(flag = true, prefix = {"EVENT_FLAG_"}, value = { |
| EVENT_FLAG_DISPLAY_ADDED, |
| EVENT_FLAG_DISPLAY_CHANGED, |
| EVENT_FLAG_DISPLAY_REMOVED, |
| EVENT_FLAG_DISPLAY_BRIGHTNESS |
| }) |
| @Retention(RetentionPolicy.SOURCE) |
| public @interface EventsMask {} |
| |
| /** |
| * Event type for when a new display is added. |
| * |
| * @see #registerDisplayListener(DisplayListener, Handler, long) |
| * |
| * @hide |
| */ |
| public static final long EVENT_FLAG_DISPLAY_ADDED = 1L << 0; |
| |
| /** |
| * Event type for when a display is removed. |
| * |
| * @see #registerDisplayListener(DisplayListener, Handler, long) |
| * |
| * @hide |
| */ |
| public static final long EVENT_FLAG_DISPLAY_REMOVED = 1L << 1; |
| |
| /** |
| * Event type for when a display is changed. |
| * |
| * @see #registerDisplayListener(DisplayListener, Handler, long) |
| * |
| * @hide |
| */ |
| public static final long EVENT_FLAG_DISPLAY_CHANGED = 1L << 2; |
| |
| /** |
| * Event flag to register for a display's brightness changes. This notification is sent |
| * through the {@link DisplayListener#onDisplayChanged} callback method. New brightness |
| * values can be retrieved via {@link android.view.Display#getBrightnessInfo()}. |
| * |
| * @see #registerDisplayListener(DisplayListener, Handler, long) |
| * |
| * @hide |
| */ |
| public static final long EVENT_FLAG_DISPLAY_BRIGHTNESS = 1L << 3; |
| |
| /** @hide */ |
| public DisplayManager(Context context) { |
| mContext = context; |
| mGlobal = DisplayManagerGlobal.getInstance(); |
| } |
| |
| /** |
| * Gets information about a logical display. |
| * |
| * The display metrics may be adjusted to provide compatibility |
| * for legacy applications. |
| * |
| * @param displayId The logical display id. |
| * @return The display object, or null if there is no valid display with the given id. |
| */ |
| public Display getDisplay(int displayId) { |
| synchronized (mLock) { |
| return getOrCreateDisplayLocked(displayId, false /*assumeValid*/); |
| } |
| } |
| |
| /** |
| * Gets all currently valid logical displays. |
| * |
| * @return An array containing all displays. |
| */ |
| public Display[] getDisplays() { |
| return getDisplays(null); |
| } |
| |
| /** |
| * Gets all currently valid logical displays of the specified category. |
| * <p> |
| * When there are multiple displays in a category the returned displays are sorted |
| * of preference. For example, if the requested category is |
| * {@link #DISPLAY_CATEGORY_PRESENTATION} and there are multiple presentation displays |
| * then the displays are sorted so that the first display in the returned array |
| * is the most preferred presentation display. The application may simply |
| * use the first display or allow the user to choose. |
| * </p> |
| * |
| * @param category The requested display category or null to return all displays. |
| * @return An array containing all displays sorted by order of preference. |
| * |
| * @see #DISPLAY_CATEGORY_PRESENTATION |
| */ |
| public Display[] getDisplays(String category) { |
| final int[] displayIds = mGlobal.getDisplayIds(); |
| synchronized (mLock) { |
| try { |
| if (category == null |
| || DISPLAY_CATEGORY_ALL_INCLUDING_DISABLED.equals(category)) { |
| addAllDisplaysLocked(mTempDisplays, displayIds); |
| } else if (category.equals(DISPLAY_CATEGORY_PRESENTATION)) { |
| addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_WIFI); |
| addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_EXTERNAL); |
| addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_OVERLAY); |
| addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_VIRTUAL); |
| addPresentationDisplaysLocked(mTempDisplays, displayIds, Display.TYPE_INTERNAL); |
| } |
| return mTempDisplays.toArray(new Display[mTempDisplays.size()]); |
| } finally { |
| mTempDisplays.clear(); |
| } |
| } |
| } |
| |
| private void addAllDisplaysLocked(ArrayList<Display> displays, int[] displayIds) { |
| for (int i = 0; i < displayIds.length; i++) { |
| Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); |
| if (display != null) { |
| displays.add(display); |
| } |
| } |
| } |
| |
| private void addPresentationDisplaysLocked( |
| ArrayList<Display> displays, int[] displayIds, int matchType) { |
| for (int i = 0; i < displayIds.length; i++) { |
| if (displayIds[i] == DEFAULT_DISPLAY) { |
| continue; |
| } |
| Display display = getOrCreateDisplayLocked(displayIds[i], true /*assumeValid*/); |
| if (display != null |
| && (display.getFlags() & Display.FLAG_PRESENTATION) != 0 |
| && display.getType() == matchType) { |
| displays.add(display); |
| } |
| } |
| } |
| |
| private Display getOrCreateDisplayLocked(int displayId, boolean assumeValid) { |
| Display display = mDisplays.get(displayId); |
| if (display == null) { |
| // TODO: We cannot currently provide any override configurations for metrics on displays |
| // other than the display the context is associated with. |
| final Resources resources = mContext.getDisplayId() == displayId |
| ? mContext.getResources() : null; |
| |
| display = mGlobal.getCompatibleDisplay(displayId, resources); |
| if (display != null) { |
| mDisplays.put(displayId, display); |
| } |
| } else if (!assumeValid && !display.isValid()) { |
| display = null; |
| } |
| return display; |
| } |
| |
| /** |
| * Registers a display listener to receive notifications about when |
| * displays are added, removed or changed. |
| * |
| * @param listener The listener to register. |
| * @param handler The handler on which the listener should be invoked, or null |
| * if the listener should be invoked on the calling thread's looper. |
| * |
| * @see #unregisterDisplayListener |
| */ |
| public void registerDisplayListener(DisplayListener listener, Handler handler) { |
| registerDisplayListener(listener, handler, EVENT_FLAG_DISPLAY_ADDED |
| | EVENT_FLAG_DISPLAY_CHANGED | EVENT_FLAG_DISPLAY_REMOVED); |
| } |
| |
| /** |
| * Registers a display listener to receive notifications about given display event types. |
| * |
| * @param listener The listener to register. |
| * @param handler The handler on which the listener should be invoked, or null |
| * if the listener should be invoked on the calling thread's looper. |
| * @param eventsMask A bitmask of the event types for which this listener is subscribed. |
| * |
| * @see #EVENT_FLAG_DISPLAY_ADDED |
| * @see #EVENT_FLAG_DISPLAY_CHANGED |
| * @see #EVENT_FLAG_DISPLAY_REMOVED |
| * @see #EVENT_FLAG_DISPLAY_BRIGHTNESS |
| * @see #registerDisplayListener(DisplayListener, Handler) |
| * @see #unregisterDisplayListener |
| * |
| * @hide |
| */ |
| public void registerDisplayListener(@NonNull DisplayListener listener, |
| @Nullable Handler handler, @EventsMask long eventsMask) { |
| mGlobal.registerDisplayListener(listener, handler, eventsMask); |
| } |
| |
| /** |
| * Unregisters a display listener. |
| * |
| * @param listener The listener to unregister. |
| * |
| * @see #registerDisplayListener |
| */ |
| public void unregisterDisplayListener(DisplayListener listener) { |
| mGlobal.unregisterDisplayListener(listener); |
| } |
| |
| /** |
| * Starts scanning for available Wifi displays. |
| * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. |
| * <p> |
| * Calls to this method nest and must be matched by an equal number of calls to |
| * {@link #stopWifiDisplayScan()}. |
| * </p><p> |
| * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. |
| * </p> |
| * |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public void startWifiDisplayScan() { |
| mGlobal.startWifiDisplayScan(); |
| } |
| |
| /** |
| * Stops scanning for available Wifi displays. |
| * <p> |
| * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. |
| * </p> |
| * |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public void stopWifiDisplayScan() { |
| mGlobal.stopWifiDisplayScan(); |
| } |
| |
| /** |
| * Connects to a Wifi display. |
| * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. |
| * <p> |
| * Automatically remembers the display after a successful connection, if not |
| * already remembered. |
| * </p><p> |
| * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. |
| * </p> |
| * |
| * @param deviceAddress The MAC address of the device to which we should connect. |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public void connectWifiDisplay(String deviceAddress) { |
| mGlobal.connectWifiDisplay(deviceAddress); |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void pauseWifiDisplay() { |
| mGlobal.pauseWifiDisplay(); |
| } |
| |
| /** @hide */ |
| @UnsupportedAppUsage |
| public void resumeWifiDisplay() { |
| mGlobal.resumeWifiDisplay(); |
| } |
| |
| /** |
| * Disconnects from the current Wifi display. |
| * The results are sent as a {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED} broadcast. |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public void disconnectWifiDisplay() { |
| mGlobal.disconnectWifiDisplay(); |
| } |
| |
| /** |
| * Renames a Wifi display. |
| * <p> |
| * The display must already be remembered for this call to succeed. In other words, |
| * we must already have successfully connected to the display at least once and then |
| * not forgotten it. |
| * </p><p> |
| * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. |
| * </p> |
| * |
| * @param deviceAddress The MAC address of the device to rename. |
| * @param alias The alias name by which to remember the device, or null |
| * or empty if no alias should be used. |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public void renameWifiDisplay(String deviceAddress, String alias) { |
| mGlobal.renameWifiDisplay(deviceAddress, alias); |
| } |
| |
| /** |
| * Forgets a previously remembered Wifi display. |
| * <p> |
| * Automatically disconnects from the display if currently connected to it. |
| * </p><p> |
| * Requires {@link android.Manifest.permission#CONFIGURE_WIFI_DISPLAY}. |
| * </p> |
| * |
| * @param deviceAddress The MAC address of the device to forget. |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public void forgetWifiDisplay(String deviceAddress) { |
| mGlobal.forgetWifiDisplay(deviceAddress); |
| } |
| |
| /** |
| * Gets the current Wifi display status. |
| * Watch for changes in the status by registering a broadcast receiver for |
| * {@link #ACTION_WIFI_DISPLAY_STATUS_CHANGED}. |
| * |
| * @return The current Wifi display status. |
| * @hide |
| */ |
| @UnsupportedAppUsage |
| public WifiDisplayStatus getWifiDisplayStatus() { |
| return mGlobal.getWifiDisplayStatus(); |
| } |
| |
| /** |
| * Set the level of color saturation to apply to the display. |
| * @param level The amount of saturation to apply, between 0 and 1 inclusive. |
| * 0 produces a grayscale image, 1 is normal. |
| * |
| * @hide |
| * @deprecated use {@link ColorDisplayManager#setSaturationLevel(int)} instead. The level passed |
| * as a parameter here will be rounded to the nearest hundredth. |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_SATURATION) |
| public void setSaturationLevel(float level) { |
| if (level < 0f || level > 1f) { |
| throw new IllegalArgumentException("Saturation level must be between 0 and 1"); |
| } |
| final ColorDisplayManager cdm = mContext.getSystemService(ColorDisplayManager.class); |
| cdm.setSaturationLevel(Math.round(level * 100f)); |
| } |
| |
| /** |
| * Sets the HDR types that have been disabled by user. |
| * @param userDisabledTypes the HDR types to disable. |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) |
| public void setUserDisabledHdrTypes(@NonNull @HdrType int[] userDisabledTypes) { |
| mGlobal.setUserDisabledHdrTypes(userDisabledTypes); |
| } |
| |
| /** |
| * Sets whether or not the user disabled HDR types are returned from |
| * {@link Display#getHdrCapabilities}. |
| * |
| * @param areUserDisabledHdrTypesAllowed If true, the user-disabled types |
| * are ignored and returned, if the display supports them. If false, the |
| * user-disabled types are taken into consideration and are never returned, |
| * even if the display supports them. |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.WRITE_SECURE_SETTINGS) |
| public void setAreUserDisabledHdrTypesAllowed(boolean areUserDisabledHdrTypesAllowed) { |
| mGlobal.setAreUserDisabledHdrTypesAllowed(areUserDisabledHdrTypesAllowed); |
| } |
| |
| /** |
| * Returns whether or not the user-disabled HDR types are returned from |
| * {@link Display#getHdrCapabilities}. |
| * |
| * @hide |
| */ |
| @TestApi |
| public boolean areUserDisabledHdrTypesAllowed() { |
| return mGlobal.areUserDisabledHdrTypesAllowed(); |
| } |
| |
| /** |
| * Returns the HDR formats disabled by the user. |
| * |
| * @hide |
| */ |
| @TestApi |
| public @NonNull int[] getUserDisabledHdrTypes() { |
| return mGlobal.getUserDisabledHdrTypes(); |
| } |
| |
| |
| /** |
| * Creates a virtual display. |
| * |
| * @see #createVirtualDisplay(String, int, int, int, Surface, int, |
| * VirtualDisplay.Callback, Handler) |
| */ |
| public VirtualDisplay createVirtualDisplay(@NonNull String name, |
| @IntRange(from = 1) int width, |
| @IntRange(from = 1) int height, |
| @IntRange(from = 1) int densityDpi, |
| @Nullable Surface surface, |
| @VirtualDisplayFlag int flags) { |
| return createVirtualDisplay(name, width, height, densityDpi, surface, flags, null, null); |
| } |
| |
| /** |
| * Creates a virtual display. |
| * <p> |
| * The content of a virtual display is rendered to a {@link Surface} provided |
| * by the application. |
| * </p><p> |
| * The virtual display should be {@link VirtualDisplay#release released} |
| * when no longer needed. Because a virtual display renders to a surface |
| * provided by the application, it will be released automatically when the |
| * process terminates and all remaining windows on it will be forcibly removed. |
| * </p><p> |
| * The behavior of the virtual display depends on the flags that are provided |
| * to this method. By default, virtual displays are created to be private, |
| * non-presentation and unsecure. Permissions may be required to use certain flags. |
| * </p><p> |
| * As of {@link android.os.Build.VERSION_CODES#KITKAT_WATCH}, the surface may |
| * be attached or detached dynamically using {@link VirtualDisplay#setSurface}. |
| * Previously, the surface had to be non-null when {@link #createVirtualDisplay} |
| * was called and could not be changed for the lifetime of the display. |
| * </p><p> |
| * Detaching the surface that backs a virtual display has a similar effect to |
| * turning off the screen. |
| * </p> |
| * |
| * @param name The name of the virtual display, must be non-empty. |
| * @param width The width of the virtual display in pixels, must be greater than 0. |
| * @param height The height of the virtual display in pixels, must be greater than 0. |
| * @param densityDpi The density of the virtual display in dpi, must be greater than 0. |
| * @param surface The surface to which the content of the virtual display should |
| * be rendered, or null if there is none initially. |
| * @param flags A combination of virtual display flags: |
| * {@link #VIRTUAL_DISPLAY_FLAG_PUBLIC}, {@link #VIRTUAL_DISPLAY_FLAG_PRESENTATION}, |
| * {@link #VIRTUAL_DISPLAY_FLAG_SECURE}, {@link #VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY}, |
| * or {@link #VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR}. |
| * @param callback Callback to call when the state of the {@link VirtualDisplay} changes |
| * @param handler The handler on which the listener should be invoked, or null |
| * if the listener should be invoked on the calling thread's looper. |
| * @return The newly created virtual display, or null if the application could |
| * not create the virtual display. |
| * |
| * @throws SecurityException if the caller does not have permission to create |
| * a virtual display with the specified flags. |
| */ |
| public VirtualDisplay createVirtualDisplay(@NonNull String name, |
| @IntRange(from = 1) int width, |
| @IntRange(from = 1) int height, |
| @IntRange(from = 1) int densityDpi, |
| @Nullable Surface surface, |
| @VirtualDisplayFlag int flags, |
| @Nullable VirtualDisplay.Callback callback, |
| @Nullable Handler handler) { |
| final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, |
| height, densityDpi); |
| builder.setFlags(flags); |
| if (surface != null) { |
| builder.setSurface(surface); |
| } |
| return createVirtualDisplay(null /* projection */, builder.build(), callback, handler, |
| null /* windowContext */); |
| } |
| |
| // TODO : Remove this hidden API after remove all callers. (Refer to MultiDisplayService) |
| /** @hide */ |
| public VirtualDisplay createVirtualDisplay( |
| @Nullable MediaProjection projection, |
| @NonNull String name, |
| @IntRange(from = 1) int width, |
| @IntRange(from = 1) int height, |
| @IntRange(from = 1) int densityDpi, |
| @Nullable Surface surface, |
| @VirtualDisplayFlag int flags, |
| @Nullable VirtualDisplay.Callback callback, |
| @Nullable Handler handler, |
| @Nullable String uniqueId) { |
| final VirtualDisplayConfig.Builder builder = new VirtualDisplayConfig.Builder(name, width, |
| height, densityDpi); |
| builder.setFlags(flags); |
| if (uniqueId != null) { |
| builder.setUniqueId(uniqueId); |
| } |
| if (surface != null) { |
| builder.setSurface(surface); |
| } |
| return createVirtualDisplay(projection, builder.build(), callback, handler, |
| null /* windowContext */); |
| } |
| |
| /** @hide */ |
| public VirtualDisplay createVirtualDisplay(@Nullable MediaProjection projection, |
| @NonNull VirtualDisplayConfig virtualDisplayConfig, |
| @Nullable VirtualDisplay.Callback callback, @Nullable Handler handler, |
| @Nullable Context windowContext) { |
| Executor executor = null; |
| // If callback is null, the executor will not be used. Avoid creating the handler and the |
| // handler executor. |
| if (callback != null) { |
| executor = new HandlerExecutor( |
| Handler.createAsync(handler != null ? handler.getLooper() : Looper.myLooper())); |
| } |
| return mGlobal.createVirtualDisplay(mContext, projection, virtualDisplayConfig, callback, |
| executor, windowContext); |
| } |
| |
| /** |
| * Gets the stable device display size, in pixels. |
| * |
| * This should really only be used for things like server-side filtering of available |
| * applications. Most applications don't need the level of stability guaranteed by this and |
| * should instead query either the size of the display they're currently running on or the |
| * size of the default display. |
| * @hide |
| */ |
| @SystemApi |
| public Point getStableDisplaySize() { |
| return mGlobal.getStableDisplaySize(); |
| } |
| |
| /** |
| * Fetch {@link BrightnessChangeEvent}s. |
| * @hide until we make it a system api. |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.BRIGHTNESS_SLIDER_USAGE) |
| public List<BrightnessChangeEvent> getBrightnessEvents() { |
| return mGlobal.getBrightnessEvents(mContext.getOpPackageName()); |
| } |
| |
| /** |
| * Fetch {@link AmbientBrightnessDayStats}s. |
| * |
| * @hide until we make it a system api |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.ACCESS_AMBIENT_LIGHT_STATS) |
| public List<AmbientBrightnessDayStats> getAmbientBrightnessStats() { |
| return mGlobal.getAmbientBrightnessStats(); |
| } |
| |
| /** |
| * Sets the global display brightness configuration. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) |
| public void setBrightnessConfiguration(BrightnessConfiguration c) { |
| setBrightnessConfigurationForUser(c, mContext.getUserId(), mContext.getPackageName()); |
| } |
| |
| /** |
| * Sets the brightness configuration for the specified display. |
| * If the specified display doesn't exist, then this will return and do nothing. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) |
| public void setBrightnessConfigurationForDisplay(@NonNull BrightnessConfiguration c, |
| @NonNull String uniqueId) { |
| mGlobal.setBrightnessConfigurationForDisplay(c, uniqueId, mContext.getUserId(), |
| mContext.getPackageName()); |
| } |
| |
| /** |
| * Gets the brightness configuration for the specified display and default user. |
| * Returns the default configuration if unset or display is invalid. |
| * |
| * @hide |
| */ |
| @Nullable |
| @SystemApi |
| @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) |
| public BrightnessConfiguration getBrightnessConfigurationForDisplay( |
| @NonNull String uniqueId) { |
| return mGlobal.getBrightnessConfigurationForDisplay(uniqueId, mContext.getUserId()); |
| } |
| |
| /** |
| * Sets the global display brightness configuration for a specific user. |
| * |
| * Note this requires the INTERACT_ACROSS_USERS permission if setting the configuration for a |
| * user other than the one you're currently running as. |
| * |
| * @hide |
| */ |
| public void setBrightnessConfigurationForUser(BrightnessConfiguration c, int userId, |
| String packageName) { |
| mGlobal.setBrightnessConfigurationForUser(c, userId, packageName); |
| } |
| |
| /** |
| * Gets the global display brightness configuration or the default curve if one hasn't been set. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) |
| public BrightnessConfiguration getBrightnessConfiguration() { |
| return getBrightnessConfigurationForUser(mContext.getUserId()); |
| } |
| |
| /** |
| * Gets the global display brightness configuration or the default curve if one hasn't been set |
| * for a specific user. |
| * |
| * Note this requires the INTERACT_ACROSS_USERS permission if getting the configuration for a |
| * user other than the one you're currently running as. |
| * |
| * @hide |
| */ |
| public BrightnessConfiguration getBrightnessConfigurationForUser(int userId) { |
| return mGlobal.getBrightnessConfigurationForUser(userId); |
| } |
| |
| /** |
| * Gets the default global display brightness configuration or null one hasn't |
| * been configured. |
| * |
| * @hide |
| */ |
| @SystemApi |
| @RequiresPermission(Manifest.permission.CONFIGURE_DISPLAY_BRIGHTNESS) |
| @Nullable |
| public BrightnessConfiguration getDefaultBrightnessConfiguration() { |
| return mGlobal.getDefaultBrightnessConfiguration(); |
| } |
| |
| |
| /** |
| * Gets the last requested minimal post processing setting for the display with displayId. |
| * |
| * @hide |
| */ |
| @TestApi |
| public boolean isMinimalPostProcessingRequested(int displayId) { |
| return mGlobal.isMinimalPostProcessingRequested(displayId); |
| } |
| |
| /** |
| * Temporarily sets the brightness of the display. |
| * <p> |
| * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. |
| * </p> |
| * |
| * @param brightness The brightness value from 0.0f to 1.0f. |
| * |
| * @hide Requires signature permission. |
| */ |
| public void setTemporaryBrightness(int displayId, float brightness) { |
| mGlobal.setTemporaryBrightness(displayId, brightness); |
| } |
| |
| |
| /** |
| * Sets the brightness of the specified display. |
| * <p> |
| * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} |
| * permission. |
| * </p> |
| * |
| * @param displayId the logical display id |
| * @param brightness The brightness value from 0.0f to 1.0f. |
| * |
| * @hide |
| */ |
| @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) |
| public void setBrightness(int displayId, @FloatRange(from = 0f, to = 1f) float brightness) { |
| mGlobal.setBrightness(displayId, brightness); |
| } |
| |
| |
| /** |
| * Gets the brightness of the specified display. |
| * <p> |
| * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} |
| * permission. |
| * </p> |
| * |
| * @param displayId The display of which brightness value to get from. |
| * |
| * @hide |
| */ |
| @RequiresPermission(Manifest.permission.CONTROL_DISPLAY_BRIGHTNESS) |
| @FloatRange(from = 0f, to = 1f) |
| public float getBrightness(int displayId) { |
| return mGlobal.getBrightness(displayId); |
| } |
| |
| |
| /** |
| * Temporarily sets the auto brightness adjustment factor. |
| * <p> |
| * Requires the {@link android.Manifest.permission#CONTROL_DISPLAY_BRIGHTNESS} permission. |
| * </p> |
| * |
| * @param adjustment The adjustment factor from -1.0 to 1.0. |
| * |
| * @hide Requires signature permission. |
| */ |
| public void setTemporaryAutoBrightnessAdjustment(float adjustment) { |
| mGlobal.setTemporaryAutoBrightnessAdjustment(adjustment); |
| } |
| |
| /** |
| * Returns the minimum brightness curve, which guarantess that any brightness curve that dips |
| * below it is rejected by the system. |
| * This prevent auto-brightness from setting the screen so dark as to prevent the user from |
| * resetting or disabling it, and maps lux to the absolute minimum nits that are still readable |
| * in that ambient brightness. |
| * |
| * @return The minimum brightness curve (as lux values and their corresponding nits values). |
| * |
| * @hide |
| */ |
| @SystemApi |
| public Pair<float[], float[]> getMinimumBrightnessCurve() { |
| return mGlobal.getMinimumBrightnessCurve(); |
| } |
| |
| /** |
| * Sets the global default {@link Display.Mode}. The display mode includes preference for |
| * resolution and refresh rate. The mode change is applied globally, i.e. to all the connected |
| * displays. If the mode specified is not supported by a connected display, then no mode change |
| * occurs for that display. |
| * |
| * @param mode The {@link Display.Mode} to set, which can include resolution and/or |
| * refresh-rate. It is created using {@link Display.Mode.Builder}. |
| *` |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) |
| public void setGlobalUserPreferredDisplayMode(@NonNull Display.Mode mode) { |
| // Create a new object containing default values for the unused fields like mode ID and |
| // alternative refresh rates. |
| Display.Mode preferredMode = new Display.Mode(mode.getPhysicalWidth(), |
| mode.getPhysicalHeight(), mode.getRefreshRate()); |
| mGlobal.setUserPreferredDisplayMode(Display.INVALID_DISPLAY, preferredMode); |
| } |
| |
| /** |
| * Removes the global user preferred display mode. |
| * User preferred display mode is cleared for all the connected displays. |
| * |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.MODIFY_USER_PREFERRED_DISPLAY_MODE) |
| public void clearGlobalUserPreferredDisplayMode() { |
| mGlobal.setUserPreferredDisplayMode(Display.INVALID_DISPLAY, null); |
| } |
| |
| /** |
| * Returns the global user preferred display mode. |
| * If no user preferred mode has been set, or it has been cleared, this method returns null. |
| * |
| * @hide |
| */ |
| @TestApi |
| @Nullable |
| public Display.Mode getGlobalUserPreferredDisplayMode() { |
| return mGlobal.getUserPreferredDisplayMode(Display.INVALID_DISPLAY); |
| } |
| |
| /** |
| * When enabled the app requested mode is always selected regardless of user settings and |
| * policies for low brightness, low battery, etc. |
| * |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) |
| public void setShouldAlwaysRespectAppRequestedMode(boolean enabled) { |
| mGlobal.setShouldAlwaysRespectAppRequestedMode(enabled); |
| } |
| |
| /** |
| * Returns whether we are running in a mode which always selects the app requested display mode |
| * and ignores user settings and policies for low brightness, low battery etc. |
| * |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.OVERRIDE_DISPLAY_MODE_REQUESTS) |
| public boolean shouldAlwaysRespectAppRequestedMode() { |
| return mGlobal.shouldAlwaysRespectAppRequestedMode(); |
| } |
| |
| /** |
| * Sets the refresh rate switching type. |
| * This matches {@link android.provider.Settings.Secure.MATCH_CONTENT_FRAME_RATE} |
| * |
| * @hide |
| */ |
| @TestApi |
| @RequiresPermission(Manifest.permission.MODIFY_REFRESH_RATE_SWITCHING_TYPE) |
| public void setRefreshRateSwitchingType(@SwitchingType int newValue) { |
| mGlobal.setRefreshRateSwitchingType(newValue); |
| } |
| |
| /** |
| * Returns the user preference for "Match content frame rate". |
| * <p> |
| * Never: Even if the app requests it, the device will never try to match its output to the |
| * original frame rate of the content. |
| * </p><p> |
| * Seamless: If the app requests it, the device will match its output to the original frame |
| * rate of the content, ONLY if the display can transition seamlessly. |
| * </p><p> |
| * Always: If the app requests it, the device will match its output to the original |
| * frame rate of the content. This may cause the screen to go blank for a |
| * second when exiting or entering a video playback. |
| * </p> |
| */ |
| @MatchContentFrameRateType public int getMatchContentFrameRateUserPreference() { |
| return toMatchContentFrameRateSetting(mGlobal.getRefreshRateSwitchingType()); |
| } |
| |
| @MatchContentFrameRateType |
| private int toMatchContentFrameRateSetting(@SwitchingType int switchingType) { |
| switch (switchingType) { |
| case SWITCHING_TYPE_NONE: |
| return MATCH_CONTENT_FRAMERATE_NEVER; |
| case SWITCHING_TYPE_WITHIN_GROUPS: |
| return MATCH_CONTENT_FRAMERATE_SEAMLESSS_ONLY; |
| case SWITCHING_TYPE_ACROSS_AND_WITHIN_GROUPS: |
| return MATCH_CONTENT_FRAMERATE_ALWAYS; |
| default: |
| Slog.e(TAG, switchingType + " is not a valid value of switching type."); |
| return MATCH_CONTENT_FRAMERATE_UNKNOWN; |
| } |
| } |
| |
| /** |
| * Listens for changes in available display devices. |
| */ |
| public interface DisplayListener { |
| /** |
| * Called whenever a logical display has been added to the system. |
| * Use {@link DisplayManager#getDisplay} to get more information about |
| * the display. |
| * |
| * @param displayId The id of the logical display that was added. |
| */ |
| void onDisplayAdded(int displayId); |
| |
| /** |
| * Called whenever a logical display has been removed from the system. |
| * |
| * @param displayId The id of the logical display that was removed. |
| */ |
| void onDisplayRemoved(int displayId); |
| |
| /** |
| * Called whenever the properties of a logical {@link android.view.Display}, |
| * such as size and density, have changed. |
| * |
| * @param displayId The id of the logical display that changed. |
| */ |
| void onDisplayChanged(int displayId); |
| } |
| |
| /** |
| * Interface for accessing keys belonging to {@link |
| * android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER}. |
| * @hide |
| */ |
| public interface DeviceConfig { |
| |
| /** |
| * Key for refresh rate in the low zone defined by thresholds. |
| * |
| * Note that the name and value don't match because they were added before we had a high |
| * zone to consider. |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.integer#config_defaultZoneBehavior |
| */ |
| String KEY_REFRESH_RATE_IN_LOW_ZONE = "refresh_rate_in_zone"; |
| |
| /** |
| * Key for accessing the low display brightness thresholds for the configured refresh |
| * rate zone. |
| * The value will be a pair of comma separated integers representing the minimum and maximum |
| * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). |
| * |
| * Note that the name and value don't match because they were added before we had a high |
| * zone to consider. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate |
| * @hide |
| */ |
| String KEY_FIXED_REFRESH_RATE_LOW_DISPLAY_BRIGHTNESS_THRESHOLDS = |
| "peak_refresh_rate_brightness_thresholds"; |
| |
| /** |
| * Key for accessing the low ambient brightness thresholds for the configured refresh |
| * rate zone. The value will be a pair of comma separated integers representing the minimum |
| * and maximum thresholds of the zone, respectively, in lux. |
| * |
| * Note that the name and value don't match because they were added before we had a high |
| * zone to consider. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate |
| * @hide |
| */ |
| String KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS = |
| "peak_refresh_rate_ambient_thresholds"; |
| /** |
| * Key for refresh rate in the high zone defined by thresholds. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.integer#config_fixedRefreshRateInHighZone |
| */ |
| String KEY_REFRESH_RATE_IN_HIGH_ZONE = "refresh_rate_in_high_zone"; |
| |
| /** |
| * Key for accessing the display brightness thresholds for the configured refresh rate zone. |
| * The value will be a pair of comma separated integers representing the minimum and maximum |
| * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]). |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.array#config_brightnessHighThresholdsOfFixedRefreshRate |
| * @hide |
| */ |
| String KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS = |
| "fixed_refresh_rate_high_display_brightness_thresholds"; |
| |
| /** |
| * Key for accessing the ambient brightness thresholds for the configured refresh rate zone. |
| * The value will be a pair of comma separated integers representing the minimum and maximum |
| * thresholds of the zone, respectively, in lux. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.array#config_ambientHighThresholdsOfFixedRefreshRate |
| * @hide |
| */ |
| String KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS = |
| "fixed_refresh_rate_high_ambient_brightness_thresholds"; |
| |
| /** |
| * Key for refresh rate when the device is in high brightness mode for sunlight visility. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.integer#config_defaultRefreshRateInHbmSunlight |
| */ |
| String KEY_REFRESH_RATE_IN_HBM_SUNLIGHT = "refresh_rate_in_hbm_sunlight"; |
| |
| /** |
| * Key for refresh rate when the device is in high brightness mode for HDR. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.integer#config_defaultRefreshRateInHbmHdr |
| */ |
| String KEY_REFRESH_RATE_IN_HBM_HDR = "refresh_rate_in_hbm_hdr"; |
| |
| /** |
| * Key for default peak refresh rate |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.integer#config_defaultPeakRefreshRate |
| * @hide |
| */ |
| String KEY_PEAK_REFRESH_RATE_DEFAULT = "peak_refresh_rate_default"; |
| |
| // TODO(b/162536543): rename it once it is proved not harmful for users. |
| /** |
| * Key for controlling which packages are explicitly blocked from running at refresh rates |
| * higher than 60hz. An app may be added to this list if they exhibit performance issues at |
| * higher refresh rates. |
| * |
| * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER |
| * @see android.R.array#config_highRefreshRateBlacklist |
| * @hide |
| */ |
| String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist"; |
| |
| /** |
| * Key for the brightness throttling data as a String formatted: |
| * <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>] |
| * Where the latter part is repeated for each throttling level, and the entirety is repeated |
| * for each display, separated by a semicolon. |
| * For example: |
| * 123,1,critical,0.8;456,2,moderate,0.9,critical,0.7 |
| */ |
| String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data"; |
| } |
| } |