Move global grayscale to ColorDisplayService
Bug: 111215474
Test: atest FrameworksServicesTests:ColorDisplayServiceTest
Change-Id: I9b72d53b2614f225422f15f3b4018383d75071cd
diff --git a/api/system-current.txt b/api/system-current.txt
index cb1e96a..bf367cb 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -1541,6 +1541,10 @@
field public static final android.os.Parcelable.Creator<android.hardware.display.BrightnessCorrection> CREATOR;
}
+ public final class ColorDisplayManager {
+ method public boolean setSaturationLevel(int);
+ }
+
public final class DisplayManager {
method public java.util.List<android.hardware.display.AmbientBrightnessDayStats> getAmbientBrightnessStats();
method public android.hardware.display.BrightnessConfiguration getBrightnessConfiguration();
@@ -1549,7 +1553,7 @@
method public android.util.Pair<float[], float[]> getMinimumBrightnessCurve();
method public android.graphics.Point getStableDisplaySize();
method public void setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration);
- method public void setSaturationLevel(float);
+ method public deprecated void setSaturationLevel(float);
}
}
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index dd782ec..0cf2d18 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -16,7 +16,9 @@
package android.hardware.display;
+import android.Manifest;
import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
import android.annotation.SystemService;
import android.content.Context;
import android.os.IBinder;
@@ -31,6 +33,7 @@
*
* @hide
*/
+@SystemApi
@SystemService(Context.COLOR_DISPLAY_SERVICE)
public final class ColorDisplayManager {
@@ -48,13 +51,29 @@
*
* @hide
*/
- @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+ @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(int saturationLevel) {
+ return mManager.setSaturationLevel(saturationLevel);
+ }
+
+ /**
* 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);
@@ -62,6 +81,8 @@
/**
* 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);
@@ -99,5 +120,13 @@
throw e.rethrowFromSystemServer();
}
}
+
+ boolean setSaturationLevel(int saturationLevel) {
+ try {
+ return mCdm.setSaturationLevel(saturationLevel);
+ } catch (RemoteException e) {
+ throw e.rethrowFromSystemServer();
+ }
+ }
}
}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 82e765d..44b653c 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -563,11 +563,16 @@
* 0 produces a grayscale image, 1 is normal.
*
* @hide
+ * @deprecated use {@link ColorDisplayManager#setSaturationLevel(int)}.
*/
@SystemApi
@RequiresPermission(Manifest.permission.CONTROL_DISPLAY_SATURATION)
public void setSaturationLevel(float level) {
- mGlobal.setSaturationLevel(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));
}
/**
diff --git a/core/java/android/hardware/display/DisplayManagerGlobal.java b/core/java/android/hardware/display/DisplayManagerGlobal.java
index 7304ab4..cda8498 100644
--- a/core/java/android/hardware/display/DisplayManagerGlobal.java
+++ b/core/java/android/hardware/display/DisplayManagerGlobal.java
@@ -394,17 +394,6 @@
}
}
- /**
- * Set the level of color saturation to apply to the display.
- */
- public void setSaturationLevel(float level) {
- try {
- mDm.setSaturationLevel(level);
- } catch (RemoteException ex) {
- throw ex.rethrowFromSystemServer();
- }
- }
-
public VirtualDisplay createVirtualDisplay(Context context, MediaProjection projection,
String name, int width, int height, int densityDpi, Surface surface, int flags,
VirtualDisplay.Callback callback, Handler handler, String uniqueId) {
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index f786589..81b82c6 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -19,4 +19,6 @@
/** @hide */
interface IColorDisplayManager {
boolean isDeviceColorManaged();
+
+ boolean setSaturationLevel(int saturationLevel);
}
\ No newline at end of file
diff --git a/core/java/android/hardware/display/IDisplayManager.aidl b/core/java/android/hardware/display/IDisplayManager.aidl
index b575997..2d81cdf 100644
--- a/core/java/android/hardware/display/IDisplayManager.aidl
+++ b/core/java/android/hardware/display/IDisplayManager.aidl
@@ -66,9 +66,6 @@
// Requires CONFIGURE_DISPLAY_COLOR_MODE
void requestColorMode(int displayId, int colorMode);
- // Requires CONTROL_DISPLAY_SATURATION
- void setSaturationLevel(float level);
-
// Requires CAPTURE_VIDEO_OUTPUT, CAPTURE_SECURE_VIDEO_OUTPUT, or an appropriate
// MediaProjection token for certain combinations of flags.
int createVirtualDisplay(in IVirtualDisplayCallback callback,
diff --git a/services/core/java/com/android/server/display/ColorDisplayService.java b/services/core/java/com/android/server/display/ColorDisplayService.java
index 73d3d95..b332c47 100644
--- a/services/core/java/com/android/server/display/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/ColorDisplayService.java
@@ -18,7 +18,9 @@
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_DISPLAY_WHITE_BALANCE;
import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_NIGHT_DISPLAY;
+import static com.android.server.display.DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION;
+import android.Manifest;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.animation.TypeEvaluator;
@@ -31,6 +33,7 @@
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
+import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager;
import android.hardware.display.IColorDisplayManager;
@@ -39,6 +42,7 @@
import android.os.Binder;
import android.os.Handler;
import android.os.Looper;
+import android.os.Message;
import android.os.UserHandle;
import android.provider.Settings.Secure;
import android.provider.Settings.System;
@@ -61,6 +65,7 @@
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeParseException;
+import java.util.Arrays;
/**
* Controls the display's color transforms.
@@ -83,6 +88,10 @@
Matrix.setIdentityM(MATRIX_IDENTITY, 0);
}
+ private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 0;
+ private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 1;
+ private static final int MSG_APPLY_GLOBAL_SATURATION = 2;
+
/**
* Evaluator used to animate color matrix transitions.
*/
@@ -161,6 +170,53 @@
}
};
+ private final TintController mGlobalSaturationTintController = new TintController() {
+
+ private float[] mMatrixGlobalSaturation = new float[16];
+
+ @Override
+ public void setUp(Context context, boolean needsLinear) {
+ }
+
+ @Override
+ public float[] getMatrix() {
+ return Arrays.copyOf(mMatrixGlobalSaturation, mMatrixGlobalSaturation.length);
+ }
+
+ @Override
+ public void setMatrix(int saturationLevel) {
+ if (saturationLevel < 0) {
+ saturationLevel = 0;
+ } else if (saturationLevel > 100) {
+ saturationLevel = 100;
+ }
+ Slog.d(TAG, "Setting saturation level: " + saturationLevel);
+
+ if (saturationLevel == 100) {
+ Matrix.setIdentityM(mMatrixGlobalSaturation, 0);
+ } else {
+ float saturation = saturationLevel * 0.1f;
+ float desaturation = 1.0f - saturation;
+ float[] luminance = {0.231f * desaturation, 0.715f * desaturation,
+ 0.072f * desaturation};
+ mMatrixGlobalSaturation[0] = luminance[0] + saturation;
+ mMatrixGlobalSaturation[1] = luminance[0];
+ mMatrixGlobalSaturation[2] = luminance[0];
+ mMatrixGlobalSaturation[4] = luminance[1];
+ mMatrixGlobalSaturation[5] = luminance[1] + saturation;
+ mMatrixGlobalSaturation[6] = luminance[1];
+ mMatrixGlobalSaturation[8] = luminance[2];
+ mMatrixGlobalSaturation[9] = luminance[2];
+ mMatrixGlobalSaturation[10] = luminance[2] + saturation;
+ }
+ }
+
+ @Override
+ public int getLevel() {
+ return LEVEL_COLOR_MATRIX_SATURATION;
+ }
+ };
+
private final Handler mHandler;
private int mCurrentUser = UserHandle.USER_NULL;
@@ -178,7 +234,7 @@
public ColorDisplayService(Context context) {
super(context);
- mHandler = new Handler(Looper.getMainLooper());
+ mHandler = new TintHandler(Looper.getMainLooper());
}
@Override
@@ -904,6 +960,23 @@
void onDisplayWhiteBalanceStatusChanged(boolean enabled);
}
+ private final class TintHandler extends Handler {
+
+ TintHandler(Looper looper) {
+ super(looper, null, true /* async */);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_APPLY_GLOBAL_SATURATION:
+ mGlobalSaturationTintController.setMatrix(msg.arg1);
+ applyTint(mGlobalSaturationTintController, false);
+ break;
+ }
+ }
+ }
+
private final class BinderService extends IColorDisplayManager.Stub {
@Override
@@ -915,5 +988,27 @@
Binder.restoreCallingIdentity(token);
}
}
+
+ @Override
+ public boolean setSaturationLevel(int level) {
+ final boolean hasTransformsPermission = getContext()
+ .checkCallingPermission(Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+ == PackageManager.PERMISSION_GRANTED;
+ final boolean hasLegacyPermission = getContext()
+ .checkCallingPermission(Manifest.permission.CONTROL_DISPLAY_SATURATION)
+ == PackageManager.PERMISSION_GRANTED;
+ if (!hasTransformsPermission && !hasLegacyPermission) {
+ throw new SecurityException("Permission required to set display saturation level");
+ }
+ final long token = Binder.clearCallingIdentity();
+ try {
+ final Message message = mHandler.obtainMessage(MSG_APPLY_GLOBAL_SATURATION);
+ message.arg1 = level;
+ mHandler.sendMessage(message);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+ return true;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index b1ba05c..4a17c65 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -724,27 +724,6 @@
}
}
- private void setSaturationLevelInternal(float level) {
- if (level < 0 || level > 1) {
- throw new IllegalArgumentException("Saturation level must be between 0 and 1");
- }
- float[] matrix = (level == 1.0f ? null : computeSaturationMatrix(level));
- DisplayTransformManager dtm = LocalServices.getService(DisplayTransformManager.class);
- dtm.setColorMatrix(DisplayTransformManager.LEVEL_COLOR_MATRIX_SATURATION, matrix);
- }
-
- private static float[] computeSaturationMatrix(float saturation) {
- float desaturation = 1.0f - saturation;
- float[] luminance = {0.231f * desaturation, 0.715f * desaturation, 0.072f * desaturation};
- float[] matrix = {
- luminance[0] + saturation, luminance[0], luminance[0], 0,
- luminance[1], luminance[1] + saturation, luminance[1], 0,
- luminance[2], luminance[2], luminance[2] + saturation, 0,
- 0, 0, 0, 1
- };
- return matrix;
- }
-
private int createVirtualDisplayInternal(IVirtualDisplayCallback callback,
IMediaProjection projection, int callingUid, String packageName, String name, int width,
int height, int densityDpi, Surface surface, int flags, String uniqueId) {
@@ -1836,19 +1815,6 @@
}
@Override // Binder call
- public void setSaturationLevel(float level) {
- mContext.enforceCallingOrSelfPermission(
- Manifest.permission.CONTROL_DISPLAY_SATURATION,
- "Permission required to set display saturation level");
- final long token = Binder.clearCallingIdentity();
- try {
- setSaturationLevelInternal(level);
- } finally {
- Binder.restoreCallingIdentity(token);
- }
- }
-
- @Override // Binder call
public int createVirtualDisplay(IVirtualDisplayCallback callback,
IMediaProjection projection, String packageName, String name,
int width, int height, int densityDpi, Surface surface, int flags,