Merge "Differentiate per-layer saturation levels" into rvc-dev

This commit is contained in:
Christine Franks
2020-04-08 17:16:00 +00:00
committed by Android (Google) Code Review
3 changed files with 115 additions and 25 deletions

View File

@@ -17,6 +17,7 @@
package com.android.server.display.color; package com.android.server.display.color;
import android.annotation.UserIdInt; import android.annotation.UserIdInt;
import android.util.ArrayMap;
import android.util.SparseArray; import android.util.SparseArray;
import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy;
@@ -61,11 +62,12 @@ class AppSaturationController {
* Set the saturation level ({@code ColorDisplayManager#SaturationLevel} constant for a given * Set the saturation level ({@code ColorDisplayManager#SaturationLevel} constant for a given
* package name and userId. * package name and userId.
*/ */
public boolean setSaturationLevel(String packageName, @UserIdInt int userId, public boolean setSaturationLevel(String callingPackageName, String affectedPackageName,
@UserIdInt int userId,
int saturationLevel) { int saturationLevel) {
synchronized (mLock) { synchronized (mLock) {
return getSaturationControllerLocked(packageName, userId) return getSaturationControllerLocked(affectedPackageName, userId)
.setSaturationLevel(saturationLevel); .setSaturationLevel(callingPackageName, saturationLevel);
} }
} }
@@ -148,13 +150,19 @@ class AppSaturationController {
private static class SaturationController { private static class SaturationController {
private static final int FULL_SATURATION = 100;
private final List<WeakReference<ColorTransformController>> mControllerRefs = private final List<WeakReference<ColorTransformController>> mControllerRefs =
new ArrayList<>(); new ArrayList<>();
private int mSaturationLevel = 100; private final ArrayMap<String, Integer> mSaturationLevels = new ArrayMap<>();
private float[] mTransformMatrix = new float[9]; private float[] mTransformMatrix = new float[9];
private boolean setSaturationLevel(int saturationLevel) { private boolean setSaturationLevel(String callingPackageName, int saturationLevel) {
mSaturationLevel = saturationLevel; if (saturationLevel == FULL_SATURATION) {
mSaturationLevels.remove(callingPackageName);
} else {
mSaturationLevels.put(callingPackageName, saturationLevel);
}
if (!mControllerRefs.isEmpty()) { if (!mControllerRefs.isEmpty()) {
return updateState(); return updateState();
} }
@@ -163,17 +171,27 @@ class AppSaturationController {
private boolean addColorTransformController( private boolean addColorTransformController(
WeakReference<ColorTransformController> controller) { WeakReference<ColorTransformController> controller) {
mControllerRefs.add(controller);
if (mSaturationLevel != 100) {
return updateState();
} else {
clearExpiredReferences(); clearExpiredReferences();
mControllerRefs.add(controller);
if (!mSaturationLevels.isEmpty()) {
return updateState();
} }
return false; return false;
} }
private int calculateSaturationLevel() {
int saturationLevel = FULL_SATURATION;
for (int i = 0; i < mSaturationLevels.size(); i++) {
final int level = mSaturationLevels.valueAt(i);
if (level < saturationLevel) {
saturationLevel = level;
}
}
return saturationLevel;
}
private boolean updateState() { private boolean updateState() {
computeGrayscaleTransformMatrix(mSaturationLevel / 100f, mTransformMatrix); computeGrayscaleTransformMatrix(calculateSaturationLevel() / 100f, mTransformMatrix);
boolean updated = false; boolean updated = false;
final Iterator<WeakReference<ColorTransformController>> iterator = mControllerRefs final Iterator<WeakReference<ColorTransformController>> iterator = mControllerRefs
@@ -190,7 +208,6 @@ class AppSaturationController {
} }
} }
return updated; return updated;
} }
private void clearExpiredReferences() { private void clearExpiredReferences() {
@@ -206,7 +223,7 @@ class AppSaturationController {
} }
private void dump(PrintWriter pw) { private void dump(PrintWriter pw) {
pw.println(" mSaturationLevel: " + mSaturationLevel); pw.println(" mSaturationLevels: " + mSaturationLevels);
pw.println(" mControllerRefs count: " + mControllerRefs.size()); pw.println(" mControllerRefs count: " + mControllerRefs.size());
} }
} }

View File

@@ -44,6 +44,7 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.res.Resources; import android.content.res.Resources;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.hardware.display.ColorDisplayManager; import android.hardware.display.ColorDisplayManager;
@@ -73,6 +74,7 @@ import com.android.internal.R;
import com.android.internal.annotations.VisibleForTesting; import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.DumpUtils; import com.android.internal.util.DumpUtils;
import com.android.server.DisplayThread; import com.android.server.DisplayThread;
import com.android.server.LocalServices;
import com.android.server.SystemService; import com.android.server.SystemService;
import com.android.server.twilight.TwilightListener; import com.android.server.twilight.TwilightListener;
import com.android.server.twilight.TwilightManager; import com.android.server.twilight.TwilightManager;
@@ -817,9 +819,11 @@ public final class ColorDisplayService extends SystemService {
return LocalDateTime.MIN; return LocalDateTime.MIN;
} }
private boolean setAppSaturationLevelInternal(String packageName, int saturationLevel) { private boolean setAppSaturationLevelInternal(String callingPackageName,
String affectedPackageName, int saturationLevel) {
return mAppSaturationController return mAppSaturationController
.setSaturationLevel(packageName, mCurrentUser, saturationLevel); .setSaturationLevel(callingPackageName, affectedPackageName, mCurrentUser,
saturationLevel);
} }
private void setColorModeInternal(@ColorMode int colorMode) { private void setColorModeInternal(@ColorMode int colorMode) {
@@ -1533,9 +1537,11 @@ public final class ColorDisplayService extends SystemService {
getContext().enforceCallingPermission( getContext().enforceCallingPermission(
Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS, Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
"Permission required to set display saturation level"); "Permission required to set display saturation level");
final String callingPackageName = LocalServices.getService(PackageManagerInternal.class)
.getNameForUid(Binder.getCallingUid());
final long token = Binder.clearCallingIdentity(); final long token = Binder.clearCallingIdentity();
try { try {
return setAppSaturationLevelInternal(packageName, level); return setAppSaturationLevelInternal(callingPackageName, packageName, level);
} finally { } finally {
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
} }

View File

@@ -43,7 +43,9 @@ import java.lang.ref.WeakReference;
@RunWith(AndroidJUnit4.class) @RunWith(AndroidJUnit4.class)
public class AppSaturationControllerTest { public class AppSaturationControllerTest {
private static final String TEST_PACKAGE_NAME = "com.android.test"; private static final String TEST_CALLER_PACKAGE_NAME = "com.android.test.caller";
private static final String TEST_CALLER_PACKAGE_NAME_TWO = "com.android.test.caller.two";
private static final String TEST_AFFECTED_PACKAGE_NAME = "com.android.test.affected";
private int mUserId; private int mUserId;
private AppSaturationController mAppSaturationController; private AppSaturationController mAppSaturationController;
@@ -70,8 +72,11 @@ public class AppSaturationControllerTest {
public void addColorTransformController_appliesExistingSaturation() { public void addColorTransformController_appliesExistingSaturation() {
final WeakReference<ColorTransformController> ref = new WeakReference<>( final WeakReference<ColorTransformController> ref = new WeakReference<>(
mColorTransformController); mColorTransformController);
mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); mAppSaturationController
mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); .setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
30);
mAppSaturationController
.addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix);
verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
} }
@@ -80,14 +85,19 @@ public class AppSaturationControllerTest {
public void setSaturationLevel_resetToDefault() { public void setSaturationLevel_resetToDefault() {
final WeakReference<ColorTransformController> ref = new WeakReference<>( final WeakReference<ColorTransformController> ref = new WeakReference<>(
mColorTransformController); mColorTransformController);
mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); mAppSaturationController
.addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
verify(mColorTransformController, never()) verify(mColorTransformController, never())
.applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); .applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
30);
AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix);
verify(mColorTransformController, times(1)) verify(mColorTransformController, times(1))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100); mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
100);
AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix); AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix);
verify(mColorTransformController, times(2)) verify(mColorTransformController, times(2))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
@@ -97,19 +107,76 @@ public class AppSaturationControllerTest {
public void setSaturationLevel_updateLevel() { public void setSaturationLevel_updateLevel() {
final WeakReference<ColorTransformController> ref = new WeakReference<>( final WeakReference<ColorTransformController> ref = new WeakReference<>(
mColorTransformController); mColorTransformController);
mAppSaturationController.addColorTransformController(TEST_PACKAGE_NAME, mUserId, ref); mAppSaturationController
.addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
verify(mColorTransformController, never()) verify(mColorTransformController, never())
.applyAppSaturation(any(), eq(TRANSLATION_VECTOR)); .applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 30); mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
30);
AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix); AppSaturationController.computeGrayscaleTransformMatrix(.3f, mMatrix);
verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); verify(mColorTransformController).applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 70); mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
70);
AppSaturationController.computeGrayscaleTransformMatrix(.7f, mMatrix); AppSaturationController.computeGrayscaleTransformMatrix(.7f, mMatrix);
verify(mColorTransformController, times(2)) verify(mColorTransformController, times(2))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
mAppSaturationController.setSaturationLevel(TEST_PACKAGE_NAME, mUserId, 100); mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
100);
AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix); AppSaturationController.computeGrayscaleTransformMatrix(1.0f, mMatrix);
verify(mColorTransformController, times(3)) verify(mColorTransformController, times(3))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR)); .applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
} }
@Test
public void setSaturationLevel_multipleCallers_appliesStrongest() {
final WeakReference<ColorTransformController> ref = new WeakReference<>(
mColorTransformController);
mAppSaturationController
.addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
verify(mColorTransformController, never())
.applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
30);
AppSaturationController.computeGrayscaleTransformMatrix(0.3f, mMatrix);
verify(mColorTransformController, times(1))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME,
mUserId,
70);
verify(mColorTransformController, times(2))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
}
@Test
public void setSaturationLevel_multipleCallers_removingOneDoesNotAffectTheOther() {
final WeakReference<ColorTransformController> ref = new WeakReference<>(
mColorTransformController);
mAppSaturationController
.addColorTransformController(TEST_AFFECTED_PACKAGE_NAME, mUserId, ref);
verify(mColorTransformController, never())
.applyAppSaturation(any(), eq(TRANSLATION_VECTOR));
mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME, TEST_AFFECTED_PACKAGE_NAME, mUserId,
70);
AppSaturationController.computeGrayscaleTransformMatrix(0.7f, mMatrix);
verify(mColorTransformController, times(1))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME,
mUserId,
30);
AppSaturationController.computeGrayscaleTransformMatrix(0.3f, mMatrix);
verify(mColorTransformController, times(2))
.applyAppSaturation(eq(mMatrix), eq(TRANSLATION_VECTOR));
mAppSaturationController
.setSaturationLevel(TEST_CALLER_PACKAGE_NAME_TWO, TEST_AFFECTED_PACKAGE_NAME,
mUserId,
100);
AppSaturationController.computeGrayscaleTransformMatrix(0.7f, mMatrix);
}
} }