Brightnessthrottler updateable through DeviceConfig

Add listener and methods to allow BrightnessThrottler to be updated
though DeviceConfig.

Bug: 224567082
Test: atest com.android.server.display
Test: adb shell device_config put display_manager
brightness_throttling_data
"local:4619827677550801152,3,moderate,0.5,severe,0.379518072,emergency,0.248995984;local:4619827677550801151,1,moderate,0.75;local:4619827677550801150,0"
adb shell dumpsys display | grep -A20 BrightnessThrottler

Change-Id: If4fe4875d6a05cb03fbf69abb8a62a645098b3a0
This commit is contained in:
Fiona Campbell
2022-04-22 12:22:17 +00:00
committed by Michael Wright
parent 8a1e0cf16e
commit 265f9a6c9c
6 changed files with 439 additions and 25 deletions

View File

@@ -1448,5 +1448,15 @@ public final class DisplayManager {
* @hide
*/
String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
/**
* Key for the brightness throttling data as a String formatted:
* <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>]
* Where the latter part is repeated for each throttling level, and the entirety is repeated
* for each display, separated by a semicolon.
* For example:
* 123,1,critical,0.8;456,2,moderate,0.9,critical,0.7
*/
String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data";
}
}

View File

@@ -16,21 +16,31 @@
package com.android.server.display;
import android.annotation.NonNull;
import android.content.Context;
import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.Temperature;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.util.Slog;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import com.android.internal.annotations.VisibleForTesting;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.Executor;
/**
* This class monitors various conditions, such as skin temperature throttling status, and limits
@@ -44,28 +54,54 @@ class BrightnessThrottler {
private final Injector mInjector;
private final Handler mHandler;
private BrightnessThrottlingData mThrottlingData;
// We need a separate handler for unit testing. These two handlers are the same throughout the
// non-test code.
private final Handler mDeviceConfigHandler;
private final Runnable mThrottlingChangeCallback;
private final SkinThermalStatusObserver mSkinThermalStatusObserver;
private final DeviceConfigListener mDeviceConfigListener;
private final DeviceConfigInterface mDeviceConfig;
private int mThrottlingStatus;
private BrightnessThrottlingData mThrottlingData;
private BrightnessThrottlingData mDdcThrottlingData;
private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason =
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
private String mUniqueDisplayId;
// The most recent string that has been set from DeviceConfig
private String mBrightnessThrottlingDataString;
// This is a collection of brightness throttling data that has been written as overrides from
// the DeviceConfig. This will always take priority over the display device config data.
private HashMap<String, BrightnessThrottlingData> mBrightnessThrottlingDataOverride =
new HashMap<>(1);
BrightnessThrottler(Handler handler, BrightnessThrottlingData throttlingData,
Runnable throttlingChangeCallback) {
this(new Injector(), handler, throttlingData, throttlingChangeCallback);
Runnable throttlingChangeCallback, String uniqueDisplayId) {
this(new Injector(), handler, handler, throttlingData, throttlingChangeCallback,
uniqueDisplayId);
}
BrightnessThrottler(Injector injector, Handler handler, BrightnessThrottlingData throttlingData,
Runnable throttlingChangeCallback) {
@VisibleForTesting
BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler,
BrightnessThrottlingData throttlingData, Runnable throttlingChangeCallback,
String uniqueDisplayId) {
mInjector = injector;
mHandler = handler;
mDeviceConfigHandler = deviceConfigHandler;
mThrottlingData = throttlingData;
mDdcThrottlingData = throttlingData;
mThrottlingChangeCallback = throttlingChangeCallback;
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
resetThrottlingData(mThrottlingData);
mUniqueDisplayId = uniqueDisplayId;
mDeviceConfig = injector.getDeviceConfig();
mDeviceConfigListener = new DeviceConfigListener();
resetThrottlingData(mThrottlingData, mUniqueDisplayId);
}
boolean deviceSupportsThrottling() {
@@ -86,7 +122,7 @@ class BrightnessThrottler {
void stop() {
mSkinThermalStatusObserver.stopObserving();
mDeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener);
// We're asked to stop throttling, so reset brightness restrictions.
mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
@@ -97,9 +133,19 @@ class BrightnessThrottler {
mThrottlingStatus = THROTTLING_INVALID;
}
void resetThrottlingData(BrightnessThrottlingData throttlingData) {
private void resetThrottlingData() {
resetThrottlingData(mDdcThrottlingData, mUniqueDisplayId);
}
void resetThrottlingData(BrightnessThrottlingData throttlingData, String displayId) {
stop();
mThrottlingData = throttlingData;
mUniqueDisplayId = displayId;
mDdcThrottlingData = throttlingData;
mDeviceConfigListener.startListening();
reloadBrightnessThrottlingDataOverride();
mThrottlingData = mBrightnessThrottlingDataOverride.getOrDefault(mUniqueDisplayId,
throttlingData);
if (deviceSupportsThrottling()) {
mSkinThermalStatusObserver.startObserving();
@@ -173,14 +219,148 @@ class BrightnessThrottler {
private void dumpLocal(PrintWriter pw) {
pw.println("BrightnessThrottler:");
pw.println(" mThrottlingData=" + mThrottlingData);
pw.println(" mDdcThrottlingData=" + mDdcThrottlingData);
pw.println(" mUniqueDisplayId=" + mUniqueDisplayId);
pw.println(" mThrottlingStatus=" + mThrottlingStatus);
pw.println(" mBrightnessCap=" + mBrightnessCap);
pw.println(" mBrightnessMaxReason=" +
BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason));
pw.println(" mBrightnessThrottlingDataOverride=" + mBrightnessThrottlingDataOverride);
pw.println(" mBrightnessThrottlingDataString=" + mBrightnessThrottlingDataString);
mSkinThermalStatusObserver.dump(pw);
}
private String getBrightnessThrottlingDataString() {
return mDeviceConfig.getString(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA,
/* defaultValue= */ null);
}
private boolean parseAndSaveData(@NonNull String strArray,
@NonNull HashMap<String, BrightnessThrottlingData> tempBrightnessThrottlingData) {
boolean validConfig = true;
String[] items = strArray.split(",");
int i = 0;
try {
String uniqueDisplayId = items[i++];
// number of throttling points
int noOfThrottlingPoints = Integer.parseInt(items[i++]);
List<ThrottlingLevel> throttlingLevels = new ArrayList<>(noOfThrottlingPoints);
// throttling level and point
for (int j = 0; j < noOfThrottlingPoints; j++) {
String severity = items[i++];
int status = parseThermalStatus(severity);
float brightnessPoint = parseBrightness(items[i++]);
throttlingLevels.add(new ThrottlingLevel(status, brightnessPoint));
}
BrightnessThrottlingData toSave =
DisplayDeviceConfig.BrightnessThrottlingData.create(throttlingLevels);
tempBrightnessThrottlingData.put(uniqueDisplayId, toSave);
} catch (NumberFormatException | IndexOutOfBoundsException
| UnknownThermalStatusException e) {
validConfig = false;
Slog.e(TAG, "Throttling data is invalid array: '" + strArray + "'", e);
}
if (i != items.length) {
validConfig = false;
}
return validConfig;
}
public void reloadBrightnessThrottlingDataOverride() {
HashMap<String, BrightnessThrottlingData> tempBrightnessThrottlingData =
new HashMap<>(1);
mBrightnessThrottlingDataString = getBrightnessThrottlingDataString();
boolean validConfig = true;
mBrightnessThrottlingDataOverride.clear();
if (mBrightnessThrottlingDataString != null) {
String[] throttlingDataSplits = mBrightnessThrottlingDataString.split(";");
for (String s : throttlingDataSplits) {
if (!parseAndSaveData(s, tempBrightnessThrottlingData)) {
validConfig = false;
break;
}
}
if (validConfig) {
mBrightnessThrottlingDataOverride.putAll(tempBrightnessThrottlingData);
tempBrightnessThrottlingData.clear();
}
} else {
Slog.w(TAG, "DeviceConfig BrightnessThrottlingData is null");
}
}
/**
* Listens to config data change and updates the brightness throttling data using
* DisplayManager#KEY_BRIGHTNESS_THROTTLING_DATA.
* The format should be a string similar to: "local:4619827677550801152,2,moderate,0.5,severe,
* 0.379518072;local:4619827677550801151,1,moderate,0.75"
* In this order:
* <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>]
* Where the latter part is repeated for each throttling level, and the entirety is repeated
* for each display, separated by a semicolon.
*/
public class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener {
public Executor mExecutor = new HandlerExecutor(mDeviceConfigHandler);
public void startListening() {
mDeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
mExecutor, this);
}
@Override
public void onPropertiesChanged(DeviceConfig.Properties properties) {
reloadBrightnessThrottlingDataOverride();
resetThrottlingData();
}
}
private float parseBrightness(String intVal) throws NumberFormatException {
float value = Float.parseFloat(intVal);
if (value < PowerManager.BRIGHTNESS_MIN || value > PowerManager.BRIGHTNESS_MAX) {
throw new NumberFormatException("Brightness constraint value out of bounds.");
}
return value;
}
@PowerManager.ThermalStatus private int parseThermalStatus(@NonNull String value)
throws UnknownThermalStatusException {
switch (value) {
case "none":
return PowerManager.THERMAL_STATUS_NONE;
case "light":
return PowerManager.THERMAL_STATUS_LIGHT;
case "moderate":
return PowerManager.THERMAL_STATUS_MODERATE;
case "severe":
return PowerManager.THERMAL_STATUS_SEVERE;
case "critical":
return PowerManager.THERMAL_STATUS_CRITICAL;
case "emergency":
return PowerManager.THERMAL_STATUS_EMERGENCY;
case "shutdown":
return PowerManager.THERMAL_STATUS_SHUTDOWN;
default:
throw new UnknownThermalStatusException("Invalid Thermal Status: " + value);
}
}
private static class UnknownThermalStatusException extends Exception {
UnknownThermalStatusException(String message) {
super(message);
}
}
private final class SkinThermalStatusObserver extends IThermalEventListener.Stub {
private final Injector mInjector;
private final Handler mHandler;
@@ -258,5 +438,10 @@ class BrightnessThrottler {
return IThermalService.Stub.asInterface(
ServiceManager.getService(Context.THERMAL_SERVICE));
}
@NonNull
public DeviceConfigInterface getDeviceConfig() {
return DeviceConfigInterface.REAL;
}
}
}

View File

@@ -279,10 +279,14 @@ public class DisplayDeviceConfig {
private HighBrightnessModeData mHbmData;
private DensityMapping mDensityMapping;
private String mLoadedFrom = null;
private BrightnessThrottlingData mBrightnessThrottlingData;
private Spline mSdrToHdrRatioSpline;
// Brightness Throttling data may be updated via the DeviceConfig. Here we store the original
// data, which comes from the ddc, and the current one, which may be the DeviceConfig
// overwritten value.
private BrightnessThrottlingData mBrightnessThrottlingData;
private BrightnessThrottlingData mOriginalBrightnessThrottlingData;
private DisplayDeviceConfig(Context context) {
mContext = context;
}
@@ -422,6 +426,10 @@ public class DisplayDeviceConfig {
return config;
}
void setBrightnessThrottlingData(BrightnessThrottlingData brightnessThrottlingData) {
mBrightnessThrottlingData = brightnessThrottlingData;
}
/**
* Return the brightness mapping nits array.
*
@@ -637,6 +645,7 @@ public class DisplayDeviceConfig {
+ ", mHbmData=" + mHbmData
+ ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline
+ ", mBrightnessThrottlingData=" + mBrightnessThrottlingData
+ ", mOriginalBrightnessThrottlingData=" + mOriginalBrightnessThrottlingData
+ ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -932,6 +941,7 @@ public class DisplayDeviceConfig {
if (!badConfig) {
mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels);
mOriginalBrightnessThrottlingData = mBrightnessThrottlingData;
}
}
@@ -1407,7 +1417,9 @@ public class DisplayDeviceConfig {
/**
* Container for brightness throttling data.
*/
static class BrightnessThrottlingData {
public static class BrightnessThrottlingData {
public List<ThrottlingLevel> throttlingLevels;
static class ThrottlingLevel {
public @PowerManager.ThermalStatus int thermalStatus;
public float brightness;
@@ -1421,9 +1433,25 @@ public class DisplayDeviceConfig {
public String toString() {
return "[" + thermalStatus + "," + brightness + "]";
}
}
public List<ThrottlingLevel> throttlingLevels;
@Override
public boolean equals(Object obj) {
if (!(obj instanceof ThrottlingLevel)) {
return false;
}
ThrottlingLevel otherThrottlingLevel = (ThrottlingLevel) obj;
return otherThrottlingLevel.thermalStatus == this.thermalStatus
&& otherThrottlingLevel.brightness == this.brightness;
}
@Override
public int hashCode() {
int result = 1;
result = 31 * result + thermalStatus;
result = 31 * result + Float.hashCode(brightness);
return result;
}
}
static public BrightnessThrottlingData create(List<ThrottlingLevel> throttlingLevels)
{
@@ -1482,12 +1510,30 @@ public class DisplayDeviceConfig {
+ "} ";
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!(obj instanceof BrightnessThrottlingData)) {
return false;
}
BrightnessThrottlingData otherBrightnessThrottlingData = (BrightnessThrottlingData) obj;
return throttlingLevels.equals(otherBrightnessThrottlingData.throttlingLevels);
}
@Override
public int hashCode() {
return throttlingLevels.hashCode();
}
private BrightnessThrottlingData(List<ThrottlingLevel> inLevels) {
throttlingLevels = new ArrayList<>(inLevels.size());
for (ThrottlingLevel level : inLevels) {
throttlingLevels.add(new ThrottlingLevel(level.thermalStatus, level.brightness));
}
}
}
}

View File

@@ -861,7 +861,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
}
});
mBrightnessThrottler.resetThrottlingData(
mDisplayDeviceConfig.getBrightnessThrottlingData());
mDisplayDeviceConfig.getBrightnessThrottlingData(), mUniqueDisplayId);
}
private void sendUpdatePowerState() {
@@ -1816,7 +1816,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call
() -> {
sendUpdatePowerStateLocked();
postBrightnessChangeRunnable();
});
}, mUniqueDisplayId);
}
private void blockScreenOn() {

View File

@@ -16,13 +16,11 @@
package com.android.server.display;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -34,17 +32,18 @@ import android.os.IThermalEventListener;
import android.os.IThermalService;
import android.os.Message;
import android.os.PowerManager;
import android.os.Temperature.ThrottlingStatus;
import android.os.Temperature;
import android.os.Temperature.ThrottlingStatus;
import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BackgroundThread;
import com.android.server.display.BrightnessThrottler.Injector;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import org.junit.Before;
import org.junit.Test;
@@ -55,7 +54,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@SmallTest
@@ -70,6 +68,8 @@ public class BrightnessThrottlerTest {
@Mock IThermalService mThermalServiceMock;
@Mock Injector mInjectorMock;
DisplayModeDirectorTest.FakeDeviceConfig mDeviceConfigFake;
@Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
@Before
@@ -83,6 +83,8 @@ public class BrightnessThrottlerTest {
return true;
}
});
mDeviceConfigFake = new DisplayModeDirectorTest.FakeDeviceConfig();
when(mInjectorMock.getDeviceConfig()).thenReturn(mDeviceConfigFake);
}
@@ -292,6 +294,170 @@ public class BrightnessThrottlerTest {
assertEquals(BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE, throttler.getBrightnessMaxReason());
}
@Test public void testUpdateThrottlingData() throws Exception {
// Initialise brightness throttling levels
// Ensure that they are overridden by setting the data through device config.
final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
0.25f);
List<ThrottlingLevel> levels = new ArrayList<>();
levels.add(level);
final BrightnessThrottlingData data = BrightnessThrottlingData.create(levels);
mDeviceConfigFake.setBrightnessThrottlingData("123,1,critical,0.4");
final BrightnessThrottler throttler = createThrottlerSupported(data);
verify(mThermalServiceMock).registerThermalEventListenerWithType(
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
// Set status too low to trigger throttling
listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1));
mTestLooper.dispatchAll();
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
assertFalse(throttler.isThrottled());
// Set status high enough to trigger throttling
listener.notifyThrottling(getSkinTemp(level.thermalStatus));
mTestLooper.dispatchAll();
assertEquals(0.4f, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
// Update thresholds
// This data is equivalent to the string "123,1,critical,0.8", passed below
final ThrottlingLevel newLevel = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
0.8f);
// Set new (valid) data from device config
mDeviceConfigFake.setBrightnessThrottlingData("123,1,critical,0.8");
// Set status too low to trigger throttling
listener.notifyThrottling(getSkinTemp(newLevel.thermalStatus - 1));
mTestLooper.dispatchAll();
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
assertFalse(throttler.isThrottled());
// Set status high enough to trigger throttling
listener.notifyThrottling(getSkinTemp(newLevel.thermalStatus));
mTestLooper.dispatchAll();
assertEquals(newLevel.brightness, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
}
@Test public void testInvalidThrottlingStrings() throws Exception {
// Initialise brightness throttling levels
// Ensure that they are not overridden by invalid data through device config.
final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
0.25f);
List<ThrottlingLevel> levels = new ArrayList<>();
levels.add(level);
final BrightnessThrottlingData data = BrightnessThrottlingData.create(levels);
final BrightnessThrottler throttler = createThrottlerSupported(data);
verify(mThermalServiceMock).registerThermalEventListenerWithType(
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
// None of these are valid so shouldn't override the original data
mDeviceConfigFake.setBrightnessThrottlingData("321,1,critical,0.4"); // Not the current id
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData("123,0,critical,0.4"); // Incorrect number
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData("123,2,critical,0.4"); // Incorrect number
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData("123,1,invalid,0.4"); // Invalid level
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData("123,1,critical,none"); // Invalid brightness
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData("123,1,critical,-3"); // Invalid brightness
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData("invalid string"); // Invalid format
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
mDeviceConfigFake.setBrightnessThrottlingData(""); // Invalid format
testThrottling(throttler, listener, PowerManager.BRIGHTNESS_MAX, 0.25f);
}
private void testThrottling(BrightnessThrottler throttler, IThermalEventListener listener,
float tooLowCap, float tooHighCap) throws Exception {
final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
tooHighCap);
// Set status too low to trigger throttling
listener.notifyThrottling(getSkinTemp(level.thermalStatus - 1));
mTestLooper.dispatchAll();
assertEquals(tooLowCap, throttler.getBrightnessCap(), 0f);
assertFalse(throttler.isThrottled());
// Set status high enough to trigger throttling
listener.notifyThrottling(getSkinTemp(level.thermalStatus));
mTestLooper.dispatchAll();
assertEquals(tooHighCap, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
}
@Test public void testMultipleConfigPoints() throws Exception {
// Initialise brightness throttling levels
final ThrottlingLevel level = new ThrottlingLevel(PowerManager.THERMAL_STATUS_CRITICAL,
0.25f);
List<ThrottlingLevel> levels = new ArrayList<>();
levels.add(level);
final BrightnessThrottlingData data = BrightnessThrottlingData.create(levels);
// These are identical to the string set below
final ThrottlingLevel levelSevere = new ThrottlingLevel(PowerManager.THERMAL_STATUS_SEVERE,
0.9f);
final ThrottlingLevel levelCritical = new ThrottlingLevel(
PowerManager.THERMAL_STATUS_CRITICAL, 0.5f);
final ThrottlingLevel levelEmergency = new ThrottlingLevel(
PowerManager.THERMAL_STATUS_EMERGENCY, 0.1f);
mDeviceConfigFake.setBrightnessThrottlingData(
"123,3,severe,0.9,critical,0.5,emergency,0.1");
final BrightnessThrottler throttler = createThrottlerSupported(data);
verify(mThermalServiceMock).registerThermalEventListenerWithType(
mThermalEventListenerCaptor.capture(), eq(Temperature.TYPE_SKIN));
final IThermalEventListener listener = mThermalEventListenerCaptor.getValue();
// Ensure that the multiple levels set via the string through the device config correctly
// override the original display device config ones.
// levelSevere
// Set status too low to trigger throttling
listener.notifyThrottling(getSkinTemp(levelSevere.thermalStatus - 1));
mTestLooper.dispatchAll();
assertEquals(PowerManager.BRIGHTNESS_MAX, throttler.getBrightnessCap(), 0f);
assertFalse(throttler.isThrottled());
// Set status high enough to trigger throttling
listener.notifyThrottling(getSkinTemp(levelSevere.thermalStatus));
mTestLooper.dispatchAll();
assertEquals(0.9f, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
// levelCritical
// Set status too low to trigger throttling
listener.notifyThrottling(getSkinTemp(levelCritical.thermalStatus - 1));
mTestLooper.dispatchAll();
assertEquals(0.9f, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
// Set status high enough to trigger throttling
listener.notifyThrottling(getSkinTemp(levelCritical.thermalStatus));
mTestLooper.dispatchAll();
assertEquals(0.5f, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
//levelEmergency
// Set status too low to trigger throttling
listener.notifyThrottling(getSkinTemp(levelEmergency.thermalStatus - 1));
mTestLooper.dispatchAll();
assertEquals(0.5f, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
// Set status high enough to trigger throttling
listener.notifyThrottling(getSkinTemp(levelEmergency.thermalStatus));
mTestLooper.dispatchAll();
assertEquals(0.1f, throttler.getBrightnessCap(), 0f);
assertTrue(throttler.isThrottled());
}
private void assertThrottlingLevelsEquals(
List<ThrottlingLevel> expected,
List<ThrottlingLevel> actual) {
@@ -307,12 +473,13 @@ public class BrightnessThrottlerTest {
}
private BrightnessThrottler createThrottlerUnsupported() {
return new BrightnessThrottler(mInjectorMock, mHandler, null, () -> {});
return new BrightnessThrottler(mInjectorMock, mHandler, mHandler, null, () -> {}, null);
}
private BrightnessThrottler createThrottlerSupported(BrightnessThrottlingData data) {
assertNotNull(data);
return new BrightnessThrottler(mInjectorMock, mHandler, data, () -> {});
return new BrightnessThrottler(mInjectorMock, mHandler, BackgroundThread.getHandler(),
data, () -> {}, "123");
}
private Temperature getSkinTemp(@ThrottlingStatus int status) {

View File

@@ -16,6 +16,7 @@
package com.android.server.display;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_BRIGHTNESS_THROTTLING_DATA;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_AMBIENT_BRIGHTNESS_THRESHOLDS;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_BRIGHTNESS_THRESHOLDS;
@@ -1902,6 +1903,11 @@ public class DisplayModeDirectorTest {
KEY_REFRESH_RATE_IN_HBM_HDR, String.valueOf(fps));
}
void setBrightnessThrottlingData(String brightnessThrottlingData) {
putPropertyAndNotify(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
KEY_BRIGHTNESS_THROTTLING_DATA, brightnessThrottlingData);
}
void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
String thresholds = toPropertyValue(brightnessThresholds);