From cf74d28888d8016051402ad7a6335de5c2b27b2f Mon Sep 17 00:00:00 2001 From: Christine Franks Date: Tue, 24 Oct 2017 19:04:22 -0700 Subject: Support native and srgb for night display Bug: 68159303 Test: make -j100 Merged-In: Iea4b38bd8c9037f50b7ffa6e3c4f12b0e536a8ce Change-Id: Iea4b38bd8c9037f50b7ffa6e3c4f12b0e536a8ce --- core/java/android/provider/Settings.java | 6 ++ .../internal/app/NightDisplayController.java | 64 ++++++++++++++- core/res/res/values/config.xml | 24 ++++++ core/res/res/values/symbols.xml | 2 + .../server/display/DisplayTransformManager.java | 92 ++++++++++++++++++++++ .../server/display/NightDisplayService.java | 50 +++++++----- 6 files changed, 219 insertions(+), 19 deletions(-) diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java index aad8bc725e6f..7b847ae45df8 100755 --- a/core/java/android/provider/Settings.java +++ b/core/java/android/provider/Settings.java @@ -3046,6 +3046,12 @@ public final class Settings { private static final Validator DIM_SCREEN_VALIDATOR = sBooleanValidator; + /** + * The display color mode. + * @hide + */ + public static final String DISPLAY_COLOR_MODE = "display_color_mode"; + /** * The amount of time in milliseconds before the device goes to sleep or begins * to dream after a period of inactivity. This value is also known as the diff --git a/core/java/com/android/internal/app/NightDisplayController.java b/core/java/com/android/internal/app/NightDisplayController.java index 860c5c4c3d3b..78a8b17ee5fa 100644 --- a/core/java/com/android/internal/app/NightDisplayController.java +++ b/core/java/com/android/internal/app/NightDisplayController.java @@ -26,6 +26,7 @@ import android.net.Uri; import android.os.Handler; import android.os.Looper; import android.provider.Settings.Secure; +import android.provider.Settings.System; import android.util.Slog; import com.android.internal.R; @@ -50,6 +51,10 @@ public final class NightDisplayController { @IntDef({ AUTO_MODE_DISABLED, AUTO_MODE_CUSTOM, AUTO_MODE_TWILIGHT }) public @interface AutoMode {} + @Retention(RetentionPolicy.SOURCE) + @IntDef({ COLOR_MODE_NATURAL, COLOR_MODE_BOOSTED, COLOR_MODE_SATURATED }) + public @interface ColorMode {} + /** * Auto mode value to prevent Night display from being automatically activated. It can still * be activated manually via {@link #setActivated(boolean)}. @@ -72,6 +77,25 @@ public final class NightDisplayController { */ public static final int AUTO_MODE_TWILIGHT = 2; + /** + * Color mode with natural colors. + * + * @see #setColorMode(int) + */ + public static final int COLOR_MODE_NATURAL = 0; + /** + * Color mode with boosted colors. + * + * @see #setColorMode(int) + */ + public static final int COLOR_MODE_BOOSTED = 1; + /** + * Color mode with saturated colors. + * + * @see #setColorMode(int) + */ + public static final int COLOR_MODE_SATURATED = 2; + private final Context mContext; private final int mUserId; @@ -117,7 +141,8 @@ public final class NightDisplayController { public boolean setActivated(boolean activated) { if (isActivated() != activated) { Secure.putLongForUser(mContext.getContentResolver(), - Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, System.currentTimeMillis(), + Secure.NIGHT_DISPLAY_LAST_ACTIVATED_TIME, + java.lang.System.currentTimeMillis(), mUserId); } return Secure.putIntForUser(mContext.getContentResolver(), @@ -293,6 +318,31 @@ public final class NightDisplayController { Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE, colorTemperature, mUserId); } + /** + * Get the current color mode. + */ + public int getColorMode() { + final int colorMode = System.getIntForUser(mContext.getContentResolver(), + System.DISPLAY_COLOR_MODE, COLOR_MODE_BOOSTED, mUserId); + if (colorMode < COLOR_MODE_NATURAL || colorMode > COLOR_MODE_SATURATED) { + return COLOR_MODE_BOOSTED; + } + return colorMode; + } + + /** + * Set the current color mode. + * + * @param colorMode the color mode + */ + public void setColorMode(@ColorMode int colorMode) { + if (colorMode < COLOR_MODE_NATURAL || colorMode > COLOR_MODE_SATURATED) { + return; + } + System.putIntForUser(mContext.getContentResolver(), System.DISPLAY_COLOR_MODE, colorMode, + mUserId); + } + /** * Returns the minimum allowed color temperature (in Kelvin) to tint the display when activated. */ @@ -339,6 +389,9 @@ public final class NightDisplayController { case Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE: mCallback.onColorTemperatureChanged(getColorTemperature()); break; + case System.DISPLAY_COLOR_MODE: + mCallback.onDisplayColorModeChanged(getColorMode()); + break; } } } @@ -367,6 +420,8 @@ public final class NightDisplayController { false /* notifyForDescendants */, mContentObserver, mUserId); cr.registerContentObserver(Secure.getUriFor(Secure.NIGHT_DISPLAY_COLOR_TEMPERATURE), false /* notifyForDescendants */, mContentObserver, mUserId); + cr.registerContentObserver(System.getUriFor(System.DISPLAY_COLOR_MODE), + false /* notifyForDecendants */, mContentObserver, mUserId); } } } @@ -513,5 +568,12 @@ public final class NightDisplayController { * @param colorTemperature the color temperature to tint the screen */ default void onColorTemperatureChanged(int colorTemperature) {} + + /** + * Callback invoked when the color mode changes. + * + * @param displayColorMode the color mode + */ + default void onDisplayColorModeChanged(int displayColorMode) {} } } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index d1b3fec451db..bffab8bf2ca2 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -844,6 +844,30 @@ 4082 + + 0.0 + 0.0 + 1.0 + -0.00000000962353339 + 0.000153045476 + 0.390782778 + -0.0000000189359041 + 0.000302412211 + -0.198650895 + + + + 0.0 + 0.0 + 1.0 + -0.00000000962353339 + 0.000153045476 + 0.390782778 + -0.0000000189359041 + 0.000302412211 + -0.198650895 + + diff --git a/services/core/java/com/android/server/display/DisplayTransformManager.java b/services/core/java/com/android/server/display/DisplayTransformManager.java index dbbb318db63b..2aba871f521e 100644 --- a/services/core/java/com/android/server/display/DisplayTransformManager.java +++ b/services/core/java/com/android/server/display/DisplayTransformManager.java @@ -16,15 +16,20 @@ package com.android.server.display; +import android.app.ActivityManager; +import android.app.IActivityManager; import android.opengl.Matrix; import android.os.IBinder; import android.os.Parcel; import android.os.RemoteException; import android.os.ServiceManager; +import android.os.SystemProperties; +import android.util.Log; import android.util.Slog; import android.util.SparseArray; import com.android.internal.annotations.GuardedBy; +import com.android.internal.app.NightDisplayController; import java.util.Arrays; /** @@ -50,6 +55,17 @@ public class DisplayTransformManager { private static final int SURFACE_FLINGER_TRANSACTION_COLOR_MATRIX = 1015; private static final int SURFACE_FLINGER_TRANSACTION_DALTONIZER = 1014; + static final String PERSISTENT_PROPERTY_SATURATION = "persist.sys.sf.color_saturation"; + + static final String PERSISTENT_PROPERTY_NATIVE_MODE = "persist.sys.sf.native_mode"; + + private static final int SURFACE_FLINGER_TRANSACTION_SATURATION = 1022; + private static final int SURFACE_FLINGER_TRANSACTION_NATIVE_MODE = 1023; + + static final float COLOR_SATURATION_NATURAL = 1.0f; + + static final float COLOR_SATURATION_BOOSTED = 1.1f; + /** * Map of level -> color transformation matrix. */ @@ -68,9 +84,18 @@ public class DisplayTransformManager { @GuardedBy("mDaltonizerModeLock") private int mDaltonizerMode = -1; + private IBinder mSurfaceFlinger; + /* package */ DisplayTransformManager() { } + public IBinder getSurfaceFlinger() { + if (mSurfaceFlinger == null) { + mSurfaceFlinger = ServiceManager.getService("SurfaceFlinger"); + } + return mSurfaceFlinger; + } + /** * Returns a copy of the color transform matrix set for a given level. */ @@ -201,4 +226,71 @@ public class DisplayTransformManager { } } } + + public static boolean isNativeModeEnabled() { + return SystemProperties.getBoolean(PERSISTENT_PROPERTY_NATIVE_MODE, false); + } + + public boolean setColorMode(int colorMode) { + if (colorMode == NightDisplayController.COLOR_MODE_NATURAL) { + applySaturation(COLOR_SATURATION_NATURAL); + setNativeMode(false); + } else if (colorMode == NightDisplayController.COLOR_MODE_BOOSTED) { + applySaturation(COLOR_SATURATION_BOOSTED); + setNativeMode(false); + } else if (colorMode == NightDisplayController.COLOR_MODE_SATURATED) { + applySaturation(COLOR_SATURATION_NATURAL); + setNativeMode(true); + } + + updateConfiguration(); + + return true; + } + + /** + * Propagates the provided saturation to the SurfaceFlinger. + */ + private void applySaturation(float saturation) { + SystemProperties.set(PERSISTENT_PROPERTY_SATURATION, Float.toString(saturation)); + if (getSurfaceFlinger() != null) { + final Parcel data = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + data.writeFloat(saturation); + try { + getSurfaceFlinger().transact(SURFACE_FLINGER_TRANSACTION_SATURATION, data, null, 0); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to set saturation", ex); + } finally { + data.recycle(); + } + } + } + + /** + * Toggles native mode on/off in SurfaceFlinger. + */ + private void setNativeMode(boolean enabled) { + SystemProperties.set(PERSISTENT_PROPERTY_NATIVE_MODE, enabled ? "1" : "0"); + if (getSurfaceFlinger() != null) { + final Parcel data = Parcel.obtain(); + data.writeInterfaceToken("android.ui.ISurfaceComposer"); + data.writeInt(enabled ? 1 : 0); + try { + getSurfaceFlinger().transact(SURFACE_FLINGER_TRANSACTION_NATIVE_MODE, data, null, 0); + } catch (RemoteException ex) { + Log.e(TAG, "Failed to set native mode", ex); + } finally { + data.recycle(); + } + } + } + + void updateConfiguration() { + try { + ActivityManager.getService().updateConfiguration(null); + } catch (RemoteException e) { + Log.e(TAG, "Could not update configuration", e); + } + } } diff --git a/services/core/java/com/android/server/display/NightDisplayService.java b/services/core/java/com/android/server/display/NightDisplayService.java index 026921deea55..eeee76863003 100644 --- a/services/core/java/com/android/server/display/NightDisplayService.java +++ b/services/core/java/com/android/server/display/NightDisplayService.java @@ -52,6 +52,8 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.Calendar; import java.util.TimeZone; +import com.android.internal.R; + import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY; /** @@ -110,19 +112,7 @@ public final class NightDisplayService extends SystemService private float[] mMatrixNight = new float[16]; - /** - * The 3x3 color transformation matrix is formatted like so: - * - * - * - * - *
R: a coefficientG: a coefficientB: a coefficient
R: b coefficientG: b coefficientB: b coefficient
R: y-interceptG: y-interceptB: y-intercept
- */ - private static final float[] mColorTempCoefficients = new float[] { - 0.0f, -0.000000014365268757f, -0.000000000910931179f, - 0.0f, 0.000255092801250106f, 0.000207598323269139f, - 1.0f, -0.064156942434907716f, -0.349361641294833436f - }; + private final float[] mColorTempCoefficients = new float[9]; private int mCurrentUser = UserHandle.USER_NULL; private ContentObserver mUserSetupObserver; @@ -240,6 +230,8 @@ public final class NightDisplayService extends SystemService mController = new NightDisplayController(getContext(), mCurrentUser); mController.setListener(this); + setCoefficientMatrix(getContext()); + // Prepare color transformation matrix. setMatrix(mController.getColorTemperature(), mMatrixNight); @@ -335,6 +327,28 @@ public final class NightDisplayService extends SystemService applyTint(true); } + @Override + public void onDisplayColorModeChanged(int colorMode) { + final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class); + dtm.setColorMode(colorMode); + + setCoefficientMatrix(getContext()); + setMatrix(mController.getColorTemperature(), mMatrixNight); + if (mController.isActivated()) { + applyTint(true); + } + } + + private void setCoefficientMatrix(Context context) { + final boolean isNative = DisplayTransformManager.isNativeModeEnabled(); + final String[] coefficients = context.getResources().getStringArray(isNative ? + R.array.config_nightDisplayColorTemperatureCoefficientsNative + : R.array.config_nightDisplayColorTemperatureCoefficients); + for (int i = 0; i < 9 && i < coefficients.length; i++) { + mColorTempCoefficients[i] = Float.parseFloat(coefficients[i]); + } + } + /** * Applies current color temperature matrix, or removes it if deactivated. * @@ -410,11 +424,11 @@ public final class NightDisplayService extends SystemService final float squareTemperature = colorTemperature * colorTemperature; final float red = squareTemperature * mColorTempCoefficients[0] - + colorTemperature * mColorTempCoefficients[3] + mColorTempCoefficients[6]; - final float green = squareTemperature * mColorTempCoefficients[1] - + colorTemperature * mColorTempCoefficients[4] + mColorTempCoefficients[7]; - final float blue = squareTemperature * mColorTempCoefficients[2] - + colorTemperature * mColorTempCoefficients[5] + mColorTempCoefficients[8]; + + colorTemperature * mColorTempCoefficients[1] + mColorTempCoefficients[2]; + final float green = squareTemperature * mColorTempCoefficients[3] + + colorTemperature * mColorTempCoefficients[4] + mColorTempCoefficients[5]; + final float blue = squareTemperature * mColorTempCoefficients[6] + + colorTemperature * mColorTempCoefficients[7] + mColorTempCoefficients[8]; outTemp[0] = red; outTemp[5] = green; outTemp[10] = blue; -- cgit v1.2.3-59-g8ed1b