blob: 90d312e47bdc32d0bd991ecdb106ace9a104327f [file] [log] [blame]
/*
* Copyright (C) 2018 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 android.Manifest;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.ContentResolver;
import android.content.Context;
import android.metrics.LogMaker;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.ServiceManager.ServiceNotFoundException;
import android.provider.Settings.Secure;
import com.android.internal.R;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.time.LocalTime;
/**
* Manages the display's color transforms and modes.
*
* @hide
*/
@SystemApi
@SystemService(Context.COLOR_DISPLAY_SERVICE)
public final class ColorDisplayManager {
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({CAPABILITY_NONE, CAPABILITY_PROTECTED_CONTENT, CAPABILITY_HARDWARE_ACCELERATION_GLOBAL,
CAPABILITY_HARDWARE_ACCELERATION_PER_APP})
public @interface CapabilityType {}
/**
* The device does not support color transforms.
*
* @hide
*/
@SystemApi
public static final int CAPABILITY_NONE = 0x0;
/**
* The device can use GPU composition on protected content (layers whose buffers are protected
* in the trusted memory zone).
*
* @hide
*/
@SystemApi
public static final int CAPABILITY_PROTECTED_CONTENT = 0x1;
/**
* The device's hardware can efficiently apply transforms to the entire display.
*
* @hide
*/
@SystemApi
public static final int CAPABILITY_HARDWARE_ACCELERATION_GLOBAL = 0x2;
/**
* The device's hardware can efficiently apply transforms to a specific Surface (window) so
* that apps can be transformed independently of one another.
*
* @hide
*/
@SystemApi
public static final int CAPABILITY_HARDWARE_ACCELERATION_PER_APP = 0x4;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM_TIME, AUTO_MODE_TWILIGHT })
public @interface AutoMode {}
/**
* Auto mode value to prevent Night display from being automatically activated. It can still
* be activated manually via {@link #setNightDisplayActivated(boolean)}.
*
* @see #setNightDisplayAutoMode(int)
*
* @hide
*/
@SystemApi
public static final int AUTO_MODE_DISABLED = 0;
/**
* Auto mode value to automatically activate Night display at a specific start and end time.
*
* @see #setNightDisplayAutoMode(int)
* @see #setNightDisplayCustomStartTime(LocalTime)
* @see #setNightDisplayCustomEndTime(LocalTime)
*
* @hide
*/
@SystemApi
public static final int AUTO_MODE_CUSTOM_TIME = 1;
/**
* Auto mode value to automatically activate Night display from sunset to sunrise.
*
* @see #setNightDisplayAutoMode(int)
*
* @hide
*/
@SystemApi
public static final int AUTO_MODE_TWILIGHT = 2;
/**
* @hide
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({COLOR_MODE_NATURAL, COLOR_MODE_BOOSTED, COLOR_MODE_SATURATED, COLOR_MODE_AUTOMATIC})
public @interface ColorMode {}
/**
* Color mode with natural colors.
*
* @hide
* @see #setColorMode(int)
*/
public static final int COLOR_MODE_NATURAL = 0;
/**
* Color mode with boosted colors.
*
* @hide
* @see #setColorMode(int)
*/
public static final int COLOR_MODE_BOOSTED = 1;
/**
* Color mode with saturated colors.
*
* @hide
* @see #setColorMode(int)
*/
public static final int COLOR_MODE_SATURATED = 2;
/**
* Color mode with automatic colors.
*
* @hide
* @see #setColorMode(int)
*/
public static final int COLOR_MODE_AUTOMATIC = 3;
/**
* Display color mode range reserved for vendor customizations by the RenderIntent definition in
* hardware/interfaces/graphics/common/1.1/types.hal. These are NOT directly related to (but ARE
* mutually exclusive with) the {@link ColorMode} constants, but ARE directly related (and ARE
* mutually exclusive with) the DISPLAY_COLOR_* constants in DisplayTransformManager.
*
* @hide
*/
public static final int VENDOR_COLOR_MODE_RANGE_MIN = 256; // 0x100
/**
* @hide
*/
public static final int VENDOR_COLOR_MODE_RANGE_MAX = 511; // 0x1ff
private final ColorDisplayManagerInternal mManager;
private MetricsLogger mMetricsLogger;
/**
* @hide
*/
public ColorDisplayManager() {
mManager = ColorDisplayManagerInternal.getInstance();
}
/**
* (De)activates the night display transform.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setNightDisplayActivated(boolean activated) {
return mManager.setNightDisplayActivated(activated);
}
/**
* Returns whether the night display transform is currently active.
*
* @hide
*/
public boolean isNightDisplayActivated() {
return mManager.isNightDisplayActivated();
}
/**
* Sets the color temperature of the night display transform.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setNightDisplayColorTemperature(int temperature) {
return mManager.setNightDisplayColorTemperature(temperature);
}
/**
* Gets the color temperature of the night display transform.
*
* @hide
*/
public int getNightDisplayColorTemperature() {
return mManager.getNightDisplayColorTemperature();
}
/**
* Returns the current auto mode value controlling when Night display will be automatically
* activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM_TIME}, or
* {@link #AUTO_MODE_TWILIGHT}.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public @AutoMode int getNightDisplayAutoMode() {
return mManager.getNightDisplayAutoMode();
}
/**
* Returns the current auto mode value, without validation, or {@code 1} if the auto mode has
* never been set.
*
* @hide
*/
public int getNightDisplayAutoModeRaw() {
return mManager.getNightDisplayAutoModeRaw();
}
/**
* Sets the current auto mode value controlling when Night display will be automatically
* activated. One of {@link #AUTO_MODE_DISABLED}, {@link #AUTO_MODE_CUSTOM_TIME}, or
* {@link #AUTO_MODE_TWILIGHT}.
*
* @param autoMode the new auto mode to use
* @return {@code true} if new auto mode was set successfully
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setNightDisplayAutoMode(@AutoMode int autoMode) {
if (autoMode != AUTO_MODE_DISABLED
&& autoMode != AUTO_MODE_CUSTOM_TIME
&& autoMode != AUTO_MODE_TWILIGHT) {
throw new IllegalArgumentException("Invalid autoMode: " + autoMode);
}
if (mManager.getNightDisplayAutoMode() != autoMode) {
getMetricsLogger().write(new LogMaker(
MetricsEvent.ACTION_NIGHT_DISPLAY_AUTO_MODE_CHANGED)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(autoMode));
}
return mManager.setNightDisplayAutoMode(autoMode);
}
/**
* Returns the local time when Night display will be automatically activated when using
* {@link ColorDisplayManager#AUTO_MODE_CUSTOM_TIME}.
*
* @hide
*/
public @NonNull LocalTime getNightDisplayCustomStartTime() {
return mManager.getNightDisplayCustomStartTime().getLocalTime();
}
/**
* Sets the local time when Night display will be automatically activated when using
* {@link ColorDisplayManager#AUTO_MODE_CUSTOM_TIME}.
*
* @param startTime the local time to automatically activate Night display
* @return {@code true} if the new custom start time was set successfully
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setNightDisplayCustomStartTime(@NonNull LocalTime startTime) {
if (startTime == null) {
throw new IllegalArgumentException("startTime cannot be null");
}
getMetricsLogger().write(new LogMaker(
MetricsEvent.ACTION_NIGHT_DISPLAY_AUTO_MODE_CUSTOM_TIME_CHANGED)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(0));
return mManager.setNightDisplayCustomStartTime(new Time(startTime));
}
/**
* Returns the local time when Night display will be automatically deactivated when using
* {@link #AUTO_MODE_CUSTOM_TIME}.
*
* @hide
*/
public @NonNull LocalTime getNightDisplayCustomEndTime() {
return mManager.getNightDisplayCustomEndTime().getLocalTime();
}
/**
* Sets the local time when Night display will be automatically deactivated when using
* {@link #AUTO_MODE_CUSTOM_TIME}.
*
* @param endTime the local time to automatically deactivate Night display
* @return {@code true} if the new custom end time was set successfully
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setNightDisplayCustomEndTime(@NonNull LocalTime endTime) {
if (endTime == null) {
throw new IllegalArgumentException("endTime cannot be null");
}
getMetricsLogger().write(new LogMaker(
MetricsEvent.ACTION_NIGHT_DISPLAY_AUTO_MODE_CUSTOM_TIME_CHANGED)
.setType(MetricsEvent.TYPE_ACTION)
.setSubtype(1));
return mManager.setNightDisplayCustomEndTime(new Time(endTime));
}
/**
* Sets the current display color mode.
*
* @hide
*/
public void setColorMode(int colorMode) {
mManager.setColorMode(colorMode);
}
/**
* Gets the current display color mode.
*
* @hide
*/
public int getColorMode() {
return mManager.getColorMode();
}
/**
* Returns whether the device has a wide color gamut display.
*
* @hide
*/
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean isDeviceColorManaged() {
return mManager.isDeviceColorManaged();
}
/**
* Set the level of color saturation to apply to the display.
*
* @param saturationLevel 0-100 (inclusive), where 100 is full saturation
* @return whether the saturation level change was applied successfully
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setSaturationLevel(@IntRange(from = 0, to = 100) int saturationLevel) {
return mManager.setSaturationLevel(saturationLevel);
}
/**
* Gets whether or not a non-default saturation level is currently applied to the display.
*
* @return {@code true} if the display is not at full saturation
* @hide
*/
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean isSaturationActivated() {
return mManager.isSaturationActivated();
}
/**
* Set the level of color saturation to apply to a specific app.
*
* @param packageName the package name of the app whose windows should be desaturated
* @param saturationLevel 0-100 (inclusive), where 100 is full saturation
* @return whether the saturation level change was applied successfully
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setAppSaturationLevel(@NonNull String packageName,
@IntRange(from = 0, to = 100) int saturationLevel) {
return mManager.setAppSaturationLevel(packageName, saturationLevel);
}
/**
* Enables or disables display white balance.
*
* @hide
*/
@RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
return mManager.setDisplayWhiteBalanceEnabled(enabled);
}
/**
* Returns whether display white balance is currently enabled. Even if enabled, it may or may
* not be active, if another transform with higher priority is active.
*
* @hide
*/
public boolean isDisplayWhiteBalanceEnabled() {
return mManager.isDisplayWhiteBalanceEnabled();
}
/**
* Returns {@code true} if Night Display is supported by the device.
*
* @hide
*/
public static boolean isNightDisplayAvailable(Context context) {
return context.getResources().getBoolean(R.bool.config_nightDisplayAvailable);
}
/**
* Returns the minimum allowed color temperature (in Kelvin) to tint the display when
* activated.
*
* @hide
*/
public static int getMinimumColorTemperature(Context context) {
return context.getResources()
.getInteger(R.integer.config_nightDisplayColorTemperatureMin);
}
/**
* Returns the maximum allowed color temperature (in Kelvin) to tint the display when
* activated.
*
* @hide
*/
public static int getMaximumColorTemperature(Context context) {
return context.getResources()
.getInteger(R.integer.config_nightDisplayColorTemperatureMax);
}
/**
* Returns {@code true} if display white balance is supported by the device.
*
* @hide
*/
public static boolean isDisplayWhiteBalanceAvailable(Context context) {
return context.getResources().getBoolean(R.bool.config_displayWhiteBalanceAvailable);
}
/**
* Check if the color transforms are color accelerated. Some transforms are experimental only
* on non-accelerated platforms due to the performance implications.
*
* @hide
*/
public static boolean isColorTransformAccelerated(Context context) {
return context.getResources().getBoolean(R.bool.config_setColorTransformAccelerated);
}
/**
* Returns the available software and hardware color transform capabilities of this device.
*
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
public @CapabilityType int getTransformCapabilities() {
return mManager.getTransformCapabilities();
}
/**
* Returns whether accessibility transforms are currently enabled, which determines whether
* color modes are currently configurable for this device.
*
* @hide
*/
public static boolean areAccessibilityTransformsEnabled(Context context) {
final ContentResolver cr = context.getContentResolver();
return Secure.getInt(cr, Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0) == 1
|| Secure.getInt(cr, Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0) == 1;
}
private MetricsLogger getMetricsLogger() {
if (mMetricsLogger == null) {
mMetricsLogger = new MetricsLogger();
}
return mMetricsLogger;
}
private static class ColorDisplayManagerInternal {
private static ColorDisplayManagerInternal sInstance;
private final IColorDisplayManager mCdm;
private ColorDisplayManagerInternal(IColorDisplayManager colorDisplayManager) {
mCdm = colorDisplayManager;
}
public static ColorDisplayManagerInternal getInstance() {
synchronized (ColorDisplayManagerInternal.class) {
if (sInstance == null) {
try {
IBinder b = ServiceManager.getServiceOrThrow(Context.COLOR_DISPLAY_SERVICE);
sInstance = new ColorDisplayManagerInternal(
IColorDisplayManager.Stub.asInterface(b));
} catch (ServiceNotFoundException e) {
throw new IllegalStateException(e);
}
}
return sInstance;
}
}
boolean isNightDisplayActivated() {
try {
return mCdm.isNightDisplayActivated();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setNightDisplayActivated(boolean activated) {
try {
return mCdm.setNightDisplayActivated(activated);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
int getNightDisplayColorTemperature() {
try {
return mCdm.getNightDisplayColorTemperature();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setNightDisplayColorTemperature(int temperature) {
try {
return mCdm.setNightDisplayColorTemperature(temperature);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
int getNightDisplayAutoMode() {
try {
return mCdm.getNightDisplayAutoMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
int getNightDisplayAutoModeRaw() {
try {
return mCdm.getNightDisplayAutoModeRaw();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setNightDisplayAutoMode(int autoMode) {
try {
return mCdm.setNightDisplayAutoMode(autoMode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Time getNightDisplayCustomStartTime() {
try {
return mCdm.getNightDisplayCustomStartTime();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setNightDisplayCustomStartTime(Time startTime) {
try {
return mCdm.setNightDisplayCustomStartTime(startTime);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
Time getNightDisplayCustomEndTime() {
try {
return mCdm.getNightDisplayCustomEndTime();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setNightDisplayCustomEndTime(Time endTime) {
try {
return mCdm.setNightDisplayCustomEndTime(endTime);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean isDeviceColorManaged() {
try {
return mCdm.isDeviceColorManaged();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setSaturationLevel(int saturationLevel) {
try {
return mCdm.setSaturationLevel(saturationLevel);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean isSaturationActivated() {
try {
return mCdm.isSaturationActivated();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setAppSaturationLevel(String packageName, int saturationLevel) {
try {
return mCdm.setAppSaturationLevel(packageName, saturationLevel);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean isDisplayWhiteBalanceEnabled() {
try {
return mCdm.isDisplayWhiteBalanceEnabled();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
try {
return mCdm.setDisplayWhiteBalanceEnabled(enabled);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
int getColorMode() {
try {
return mCdm.getColorMode();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
void setColorMode(int colorMode) {
try {
mCdm.setColorMode(colorMode);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
int getTransformCapabilities() {
try {
return mCdm.getTransformCapabilities();
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
}