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
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index b505395..8bc11cb 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -1448,5 +1448,15 @@
* @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";
}
}
diff --git a/services/core/java/com/android/server/display/BrightnessThrottler.java b/services/core/java/com/android/server/display/BrightnessThrottler.java
index 767b2d1..eccee52 100644
--- a/services/core/java/com/android/server/display/BrightnessThrottler.java
+++ b/services/core/java/com/android/server/display/BrightnessThrottler.java
@@ -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 @@
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 @@
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 @@
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 @@
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 @@
return IThermalService.Stub.asInterface(
ServiceManager.getService(Context.THERMAL_SERVICE));
}
+
+ @NonNull
+ public DeviceConfigInterface getDeviceConfig() {
+ return DeviceConfigInterface.REAL;
+ }
}
}
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index a25ac21..2322280d 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -279,10 +279,14 @@
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 @@
return config;
}
+ void setBrightnessThrottlingData(BrightnessThrottlingData brightnessThrottlingData) {
+ mBrightnessThrottlingData = brightnessThrottlingData;
+ }
+
/**
* Return the brightness mapping nits array.
*
@@ -637,6 +645,7 @@
+ ", mHbmData=" + mHbmData
+ ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline
+ ", mBrightnessThrottlingData=" + mBrightnessThrottlingData
+ + ", mOriginalBrightnessThrottlingData=" + mOriginalBrightnessThrottlingData
+ ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -932,6 +941,7 @@
if (!badConfig) {
mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels);
+ mOriginalBrightnessThrottlingData = mBrightnessThrottlingData;
}
}
@@ -1407,7 +1417,9 @@
/**
* 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 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 @@
+ "} ";
}
+ @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));
}
}
-
}
}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index d05a902..f9ee7f7 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -861,7 +861,7 @@
}
});
mBrightnessThrottler.resetThrottlingData(
- mDisplayDeviceConfig.getBrightnessThrottlingData());
+ mDisplayDeviceConfig.getBrightnessThrottlingData(), mUniqueDisplayId);
}
private void sendUpdatePowerState() {
@@ -1816,7 +1816,7 @@
() -> {
sendUpdatePowerStateLocked();
postBrightnessChangeRunnable();
- });
+ }, mUniqueDisplayId);
}
private void blockScreenOn() {
diff --git a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
index 0ed90d2..6a6cd6c 100644
--- a/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/BrightnessThrottlerTest.java
@@ -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.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.MockitoAnnotations;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
@SmallTest
@@ -70,6 +68,8 @@
@Mock IThermalService mThermalServiceMock;
@Mock Injector mInjectorMock;
+ DisplayModeDirectorTest.FakeDeviceConfig mDeviceConfigFake;
+
@Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
@Before
@@ -83,6 +83,8 @@
return true;
}
});
+ mDeviceConfigFake = new DisplayModeDirectorTest.FakeDeviceConfig();
+ when(mInjectorMock.getDeviceConfig()).thenReturn(mDeviceConfigFake);
}
@@ -292,6 +294,170 @@
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 @@
}
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) {
diff --git a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
index 864f315..968e1d8 100644
--- a/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/DisplayModeDirectorTest.java
@@ -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 @@
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);