Make brightness per-user in PersistentDataStore

Bug: 275503471
Test: atest PersistentDataStoreTest
Change-Id: I934ae2c453f47cfe9fccbedebb00e86cd6070c38
This commit is contained in:
Kriti Dang
2023-04-03 11:49:14 +02:00
parent 6bcaace5d2
commit 963c80fb07
9 changed files with 233 additions and 33 deletions

View File

@@ -40,6 +40,7 @@ public class BrightnessSetting {
private final LogicalDisplay mLogicalDisplay;
private int mUserSerial;
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -56,13 +57,15 @@ public class BrightnessSetting {
@GuardedBy("mSyncRoot")
private float mBrightness;
BrightnessSetting(@NonNull PersistentDataStore persistentDataStore,
BrightnessSetting(int userSerial,
@NonNull PersistentDataStore persistentDataStore,
@NonNull LogicalDisplay logicalDisplay,
DisplayManagerService.SyncRoot syncRoot) {
mPersistentDataStore = persistentDataStore;
mLogicalDisplay = logicalDisplay;
mUserSerial = userSerial;
mBrightness = mPersistentDataStore.getBrightness(
mLogicalDisplay.getPrimaryDisplayDeviceLocked());
mLogicalDisplay.getPrimaryDisplayDeviceLocked(), userSerial);
mSyncRoot = syncRoot;
}
@@ -96,8 +99,13 @@ public class BrightnessSetting {
mListeners.remove(l);
}
/** Sets the user serial for the brightness setting */
public void setUserSerial(int userSerial) {
mUserSerial = userSerial;
}
/**
* Sets the brigtness and broadcasts the change to the listeners.
* Sets the brightness and broadcasts the change to the listeners.
* @param brightness The value to which the brightness is to be set.
*/
public void setBrightness(float brightness) {
@@ -112,7 +120,8 @@ public class BrightnessSetting {
// changed.
if (brightness != mBrightness) {
mPersistentDataStore.setBrightness(mLogicalDisplay.getPrimaryDisplayDeviceLocked(),
brightness);
brightness, mUserSerial
);
}
mBrightness = brightness;
int toSend = Float.floatToIntBits(mBrightness);

View File

@@ -652,6 +652,12 @@ public final class DisplayManagerService extends SystemService {
logicalDisplay.getPrimaryDisplayDeviceLocked().getUniqueId(),
userSerial);
dpc.setBrightnessConfiguration(config, /* shouldResetShortTermModel= */ true);
// change the brightness value according to the selected user.
final DisplayDevice device = logicalDisplay.getPrimaryDisplayDeviceLocked();
if (device != null) {
dpc.setBrightness(
mPersistentDataStore.getBrightness(device, userSerial), userSerial);
}
}
dpc.onSwitchUser(newUserId);
});
@@ -3134,8 +3140,9 @@ public final class DisplayManagerService extends SystemService {
mBrightnessTracker = new BrightnessTracker(mContext, null);
}
final BrightnessSetting brightnessSetting = new BrightnessSetting(mPersistentDataStore,
display, mSyncRoot);
final int userSerial = getUserManager().getUserSerialNumber(mContext.getUserId());
final BrightnessSetting brightnessSetting = new BrightnessSetting(userSerial,
mPersistentDataStore, display, mSyncRoot);
final DisplayPowerControllerInterface displayPowerController;
// If display is internal and has a HighBrightnessModeMetadata mapping, use that.

View File

@@ -2664,9 +2664,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
@Override
public void setBrightness(float brightnessValue) {
public void setBrightness(float brightnessValue, int userSerial) {
// Update the setting, which will eventually call back into DPC to have us actually update
// the display with the new value.
mBrightnessSetting.setUserSerial(userSerial);
mBrightnessSetting.setBrightness(brightnessValue);
if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
float nits = convertToNits(brightnessValue);

View File

@@ -2172,8 +2172,8 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal
}
@Override
public void setBrightness(float brightnessValue) {
mDisplayBrightnessController.setBrightness(brightnessValue);
public void setBrightness(float brightnessValue, int userSerial) {
mDisplayBrightnessController.setBrightness(brightnessValue, userSerial);
}
@Override

View File

@@ -29,7 +29,7 @@ import java.io.PrintWriter;
* An interface to manage the display's power state and brightness
*/
public interface DisplayPowerControllerInterface {
int DEFAULT_USER_SERIAL = -1;
/**
* Notified when the display is changed.
*
@@ -98,7 +98,17 @@ public interface DisplayPowerControllerInterface {
* Set the screen brightness of the associated display
* @param brightness The value to which the brightness is to be set
*/
void setBrightness(float brightness);
default void setBrightness(float brightness) {
setBrightness(brightness, DEFAULT_USER_SERIAL);
}
/**
* Set the screen brightness of the associated display
* @param brightness The value to which the brightness is to be set
* @param userSerial The user for which the brightness value is to be set. Use userSerial = -1,
* if brightness needs to be updated for the current user.
*/
void setBrightness(float brightness, int userSerial);
/**
* Checks if the proximity sensor is available

View File

@@ -133,6 +133,7 @@ final class PersistentDataStore {
private static final String TAG_BRIGHTNESS_NITS_FOR_DEFAULT_DISPLAY =
"brightness-nits-for-default-display";
public static final int DEFAULT_USER_ID = -1;
// Remembered Wifi display devices.
private ArrayList<WifiDisplay> mRememberedWifiDisplays = new ArrayList<WifiDisplay>();
@@ -294,7 +295,7 @@ final class PersistentDataStore {
return false;
}
public float getBrightness(DisplayDevice device) {
public float getBrightness(DisplayDevice device, int userSerial) {
if (device == null || !device.hasStableUniqueId()) {
return Float.NaN;
}
@@ -302,10 +303,10 @@ final class PersistentDataStore {
if (state == null) {
return Float.NaN;
}
return state.getBrightness();
return state.getBrightness(userSerial);
}
public boolean setBrightness(DisplayDevice displayDevice, float brightness) {
public boolean setBrightness(DisplayDevice displayDevice, float brightness, int userSerial) {
if (displayDevice == null || !displayDevice.hasStableUniqueId()) {
return false;
}
@@ -314,7 +315,7 @@ final class PersistentDataStore {
return false;
}
final DisplayState state = getDisplayState(displayDeviceUniqueId, true);
if (state.setBrightness(brightness)) {
if (state.setBrightness(brightness, userSerial)) {
setDirty();
return true;
}
@@ -611,6 +612,7 @@ final class PersistentDataStore {
state.saveToXml(serializer);
serializer.endTag(null, TAG_DISPLAY);
}
serializer.endTag(null, TAG_DISPLAY_STATES);
serializer.startTag(null, TAG_STABLE_DEVICE_VALUES);
mStableDeviceValues.saveToXml(serializer);
@@ -649,7 +651,8 @@ final class PersistentDataStore {
private static final class DisplayState {
private int mColorMode;
private float mBrightness = Float.NaN;
private SparseArray<Float> mPerUserBrightness = new SparseArray<>();
private int mWidth;
private int mHeight;
private float mRefreshRate;
@@ -670,16 +673,25 @@ final class PersistentDataStore {
return mColorMode;
}
public boolean setBrightness(float brightness) {
if (brightness == mBrightness) {
public boolean setBrightness(float brightness, int userSerial) {
// Remove the default user brightness, before setting a new user-specific value.
// This is a one-time operation, required to restructure the config after user-specific
// brightness was introduced.
mPerUserBrightness.remove(DEFAULT_USER_ID);
if (getBrightness(userSerial) == brightness) {
return false;
}
mBrightness = brightness;
mPerUserBrightness.set(userSerial, brightness);
return true;
}
public float getBrightness() {
return mBrightness;
public float getBrightness(int userSerial) {
float brightness = mPerUserBrightness.get(userSerial, Float.NaN);
if (Float.isNaN(brightness)) {
brightness = mPerUserBrightness.get(DEFAULT_USER_ID, Float.NaN);
}
return brightness;
}
public boolean setBrightnessConfiguration(BrightnessConfiguration configuration,
@@ -729,12 +741,7 @@ final class PersistentDataStore {
mColorMode = Integer.parseInt(value);
break;
case TAG_BRIGHTNESS_VALUE:
String brightness = parser.nextText();
try {
mBrightness = Float.parseFloat(brightness);
} catch (NumberFormatException e) {
mBrightness = Float.NaN;
}
loadBrightnessFromXml(parser);
break;
case TAG_BRIGHTNESS_CONFIGURATIONS:
mDisplayBrightnessConfigurations.loadFromXml(parser);
@@ -760,11 +767,12 @@ final class PersistentDataStore {
serializer.text(Integer.toString(mColorMode));
serializer.endTag(null, TAG_COLOR_MODE);
serializer.startTag(null, TAG_BRIGHTNESS_VALUE);
if (!Float.isNaN(mBrightness)) {
serializer.text(Float.toString(mBrightness));
for (int i = 0; i < mPerUserBrightness.size(); i++) {
serializer.startTag(null, TAG_BRIGHTNESS_VALUE);
serializer.attributeInt(null, ATTR_USER_SERIAL, mPerUserBrightness.keyAt(i));
serializer.text(Float.toString(mPerUserBrightness.valueAt(i)));
serializer.endTag(null, TAG_BRIGHTNESS_VALUE);
}
serializer.endTag(null, TAG_BRIGHTNESS_VALUE);
serializer.startTag(null, TAG_BRIGHTNESS_CONFIGURATIONS);
mDisplayBrightnessConfigurations.saveToXml(serializer);
@@ -785,12 +793,33 @@ final class PersistentDataStore {
public void dump(final PrintWriter pw, final String prefix) {
pw.println(prefix + "ColorMode=" + mColorMode);
pw.println(prefix + "BrightnessValue=" + mBrightness);
pw.println(prefix + "BrightnessValues: ");
for (int i = 0; i < mPerUserBrightness.size(); i++) {
pw.println("User: " + mPerUserBrightness.keyAt(i)
+ " Value: " + mPerUserBrightness.valueAt(i));
}
pw.println(prefix + "DisplayBrightnessConfigurations: ");
mDisplayBrightnessConfigurations.dump(pw, prefix);
pw.println(prefix + "Resolution=" + mWidth + " " + mHeight);
pw.println(prefix + "RefreshRate=" + mRefreshRate);
}
private void loadBrightnessFromXml(TypedXmlPullParser parser)
throws IOException, XmlPullParserException {
int userSerial;
try {
userSerial = parser.getAttributeInt(null, ATTR_USER_SERIAL);
} catch (NumberFormatException | XmlPullParserException e) {
userSerial = DEFAULT_USER_ID;
Slog.e(TAG, "Failed to read user serial", e);
}
String brightness = parser.nextText();
try {
mPerUserBrightness.set(userSerial, Float.parseFloat(brightness));
} catch (NumberFormatException nfe) {
Slog.e(TAG, "Failed to read brightness", nfe);
}
}
}
private static final class StableDeviceValues {

View File

@@ -38,6 +38,8 @@ import java.io.PrintWriter;
* display. Applies the chosen brightness.
*/
public final class DisplayBrightnessController {
private static final int DEFAULT_USER_SERIAL = -1;
// The ID of the display tied to this DisplayBrightnessController
private final int mDisplayId;
@@ -274,8 +276,16 @@ public final class DisplayBrightnessController {
* Notifies the brightnessSetting to persist the supplied brightness value.
*/
public void setBrightness(float brightnessValue) {
setBrightness(brightnessValue, DEFAULT_USER_SERIAL);
}
/**
* Notifies the brightnessSetting to persist the supplied brightness value for a user.
*/
public void setBrightness(float brightnessValue, int userSerial) {
// Update the setting, which will eventually call back into DPC to have us actually
// update the display with the new value.
mBrightnessSetting.setUserSerial(userSerial);
mBrightnessSetting.setBrightness(brightnessValue);
if (mDisplayId == Display.DEFAULT_DISPLAY && mPersistBrightnessNitsForDefaultDisplay) {
float nits = convertToNits(brightnessValue);

View File

@@ -59,6 +59,114 @@ public class PersistentDataStoreTest {
mDataStore = new PersistentDataStore(mInjector, handler);
}
@Test
public void testLoadBrightness() {
final String uniqueDisplayId = "test:123";
final DisplayDevice testDisplayDevice = new DisplayDevice(
null, null, uniqueDisplayId, null) {
@Override
public boolean hasStableUniqueId() {
return true;
}
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
return null;
}
};
String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<display-manager-state>\n"
+ " <display-states>\n"
+ " <display unique-id=\"test:123\">\n"
+ " <brightness-value user-serial=\"1\">0.1</brightness-value>\n"
+ " <brightness-value user-serial=\"2\">0.2</brightness-value>\n"
+ " </display>\n"
+ " </display-states>\n"
+ "</display-manager-state>\n";
InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8));
mInjector.setReadStream(is);
mDataStore.loadIfNeeded();
float brightness = mDataStore.getBrightness(testDisplayDevice, 1);
assertEquals(0.1, brightness, 0.01);
brightness = mDataStore.getBrightness(testDisplayDevice, 2);
assertEquals(0.2, brightness, 0.01);
}
@Test
public void testSetBrightness_brightnessTagWithNoUserId_updatesToBrightnessTagWithUserId() {
final String uniqueDisplayId = "test:123";
final DisplayDevice testDisplayDevice =
new DisplayDevice(null, null, uniqueDisplayId, null) {
@Override
public boolean hasStableUniqueId() {
return true;
}
@Override
public DisplayDeviceInfo getDisplayDeviceInfoLocked() {
return null;
}
};
String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
+ "<display-manager-state>\n"
+ " <display-states>\n"
+ " <color-mode>0</color-mode>\n"
+ " <display unique-id=\"test:123\">\n"
+ " <brightness-value>0.5</brightness-value>\n"
+ " </display>\n"
+ " </display-states>\n"
+ "</display-manager-state>\n";
InputStream is = new ByteArrayInputStream(contents.getBytes(StandardCharsets.UTF_8));
mInjector.setReadStream(is);
mDataStore.loadIfNeeded();
float user1Brightness = mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
float user2Brightness = mDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
assertEquals(0.5, user1Brightness, 0.01);
assertEquals(0.5, user2Brightness, 0.01);
// Override the value for user 2. Default user must have been removed.
mDataStore.setBrightness(testDisplayDevice, 0.2f, 2 /* userSerial */ /* brightness*/);
user1Brightness = mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
user2Brightness = mDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
assertTrue(Float.isNaN(user1Brightness));
assertEquals(0.2f, user2Brightness, 0.01);
// Override the value for user 1. User-specific brightness values should co-exist.
mDataStore.setBrightness(testDisplayDevice, 0.1f, 1 /* userSerial */ /* brightness*/);
user1Brightness = mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
user2Brightness = mDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
assertEquals(0.1f, user1Brightness, 0.01);
assertEquals(0.2f, user2Brightness, 0.01);
// Validate saveIfNeeded writes user-specific brightnes.
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
mInjector.setWriteStream(baos);
mDataStore.saveIfNeeded();
mTestLooper.dispatchAll();
assertTrue(mInjector.wasWriteSuccessful());
TestInjector newInjector = new TestInjector();
PersistentDataStore newDataStore = new PersistentDataStore(newInjector);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
newInjector.setReadStream(bais);
newDataStore.loadIfNeeded();
user1Brightness = newDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */);
user2Brightness = newDataStore.getBrightness(testDisplayDevice, 2 /* userSerial */);
float unknownUserBrightness =
newDataStore.getBrightness(testDisplayDevice, 999 /* userSerial */);
assertEquals(0.1f, user1Brightness, 0.01);
assertEquals(0.2f, user2Brightness, 0.01);
assertTrue(Float.isNaN(unknownUserBrightness));
}
@Test
public void testLoadingBrightnessConfigurations() {
String contents = "<?xml version='1.0' encoding='utf-8' standalone='yes' ?>\n"
@@ -374,7 +482,7 @@ public class PersistentDataStoreTest {
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
newInjector.setReadStream(bais);
newDataStore.loadIfNeeded();
assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice)));
assertTrue(Float.isNaN(mDataStore.getBrightness(testDisplayDevice, 1 /* userSerial */)));
}
@Test

View File

@@ -19,6 +19,7 @@ package com.android.server.display.brightness;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.clearInvocations;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -247,6 +248,7 @@ public final class DisplayBrightnessControllerTest {
0.0f);
verify(mBrightnessChangeExecutor).execute(mOnBrightnessChangeRunnable);
verify(mBrightnessSetting).setBrightness(brightnessValue);
verify(mBrightnessSetting).setUserSerial(anyInt());
// Does nothing if the value is invalid
mDisplayBrightnessController.updateScreenBrightnessSetting(Float.NaN);
@@ -358,4 +360,28 @@ public final class DisplayBrightnessControllerTest {
verify(mBrightnessSetting, never()).getBrightnessNitsForDefaultDisplay();
verify(mBrightnessSetting, never()).setBrightness(brightness);
}
@Test
public void testChangeBrightnessNitsWhenUserChanges() {
float brightnessValue1 = 0.3f;
float nits1 = 200f;
float brightnessValue2 = 0.5f;
float nits2 = 300f;
AutomaticBrightnessController automaticBrightnessController =
mock(AutomaticBrightnessController.class);
when(automaticBrightnessController.convertToNits(brightnessValue1)).thenReturn(nits1);
when(automaticBrightnessController.convertToNits(brightnessValue2)).thenReturn(nits2);
mDisplayBrightnessController.setAutomaticBrightnessController(
automaticBrightnessController);
mDisplayBrightnessController.setBrightness(brightnessValue1, 1 /* user-serial */);
verify(mBrightnessSetting).setUserSerial(1);
verify(mBrightnessSetting).setBrightness(brightnessValue1);
verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(nits1);
mDisplayBrightnessController.setBrightness(brightnessValue2, 2 /* user-serial */);
verify(mBrightnessSetting).setUserSerial(2);
verify(mBrightnessSetting).setBrightness(brightnessValue2);
verify(mBrightnessSetting).setBrightnessNitsForDefaultDisplay(nits2);
}
}