Merge "Brightnessthrottler updateable through DeviceConfig" into tm-qpr-dev

This commit is contained in:
Michael Wright
2022-06-24 20:10:06 +00:00
committed by Android (Google) Code Review
6 changed files with 439 additions and 25 deletions

View File

@@ -1448,5 +1448,15 @@ public final class DisplayManager {
* @hide * @hide
*/ */
String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist"; 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; package com.android.server.display;
import android.annotation.NonNull;
import android.content.Context; import android.content.Context;
import android.hardware.display.BrightnessInfo; import android.hardware.display.BrightnessInfo;
import android.hardware.display.DisplayManager;
import android.os.Handler; import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.IThermalEventListener; import android.os.IThermalEventListener;
import android.os.IThermalService; import android.os.IThermalService;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.RemoteException; import android.os.RemoteException;
import android.os.ServiceManager; import android.os.ServiceManager;
import android.os.Temperature; import android.os.Temperature;
import android.provider.DeviceConfig;
import android.provider.DeviceConfigInterface;
import android.util.Slog; 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;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import java.io.PrintWriter; 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 * 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 Injector mInjector;
private final Handler mHandler; 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 Runnable mThrottlingChangeCallback;
private final SkinThermalStatusObserver mSkinThermalStatusObserver; private final SkinThermalStatusObserver mSkinThermalStatusObserver;
private final DeviceConfigListener mDeviceConfigListener;
private final DeviceConfigInterface mDeviceConfig;
private int mThrottlingStatus; private int mThrottlingStatus;
private BrightnessThrottlingData mThrottlingData;
private BrightnessThrottlingData mDdcThrottlingData;
private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX; private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason = private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason =
BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; 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, BrightnessThrottler(Handler handler, BrightnessThrottlingData throttlingData,
Runnable throttlingChangeCallback) { Runnable throttlingChangeCallback, String uniqueDisplayId) {
this(new Injector(), handler, throttlingData, throttlingChangeCallback); this(new Injector(), handler, handler, throttlingData, throttlingChangeCallback,
uniqueDisplayId);
} }
BrightnessThrottler(Injector injector, Handler handler, BrightnessThrottlingData throttlingData, @VisibleForTesting
Runnable throttlingChangeCallback) { BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler,
BrightnessThrottlingData throttlingData, Runnable throttlingChangeCallback,
String uniqueDisplayId) {
mInjector = injector; mInjector = injector;
mHandler = handler; mHandler = handler;
mDeviceConfigHandler = deviceConfigHandler;
mThrottlingData = throttlingData; mThrottlingData = throttlingData;
mDdcThrottlingData = throttlingData;
mThrottlingChangeCallback = throttlingChangeCallback; mThrottlingChangeCallback = throttlingChangeCallback;
mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler); mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler);
resetThrottlingData(mThrottlingData); mUniqueDisplayId = uniqueDisplayId;
mDeviceConfig = injector.getDeviceConfig();
mDeviceConfigListener = new DeviceConfigListener();
resetThrottlingData(mThrottlingData, mUniqueDisplayId);
} }
boolean deviceSupportsThrottling() { boolean deviceSupportsThrottling() {
@@ -86,7 +122,7 @@ class BrightnessThrottler {
void stop() { void stop() {
mSkinThermalStatusObserver.stopObserving(); mSkinThermalStatusObserver.stopObserving();
mDeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigListener);
// We're asked to stop throttling, so reset brightness restrictions. // We're asked to stop throttling, so reset brightness restrictions.
mBrightnessCap = PowerManager.BRIGHTNESS_MAX; mBrightnessCap = PowerManager.BRIGHTNESS_MAX;
mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE;
@@ -97,9 +133,19 @@ class BrightnessThrottler {
mThrottlingStatus = THROTTLING_INVALID; mThrottlingStatus = THROTTLING_INVALID;
} }
void resetThrottlingData(BrightnessThrottlingData throttlingData) { private void resetThrottlingData() {
resetThrottlingData(mDdcThrottlingData, mUniqueDisplayId);
}
void resetThrottlingData(BrightnessThrottlingData throttlingData, String displayId) {
stop(); stop();
mThrottlingData = throttlingData;
mUniqueDisplayId = displayId;
mDdcThrottlingData = throttlingData;
mDeviceConfigListener.startListening();
reloadBrightnessThrottlingDataOverride();
mThrottlingData = mBrightnessThrottlingDataOverride.getOrDefault(mUniqueDisplayId,
throttlingData);
if (deviceSupportsThrottling()) { if (deviceSupportsThrottling()) {
mSkinThermalStatusObserver.startObserving(); mSkinThermalStatusObserver.startObserving();
@@ -173,14 +219,148 @@ class BrightnessThrottler {
private void dumpLocal(PrintWriter pw) { private void dumpLocal(PrintWriter pw) {
pw.println("BrightnessThrottler:"); pw.println("BrightnessThrottler:");
pw.println(" mThrottlingData=" + mThrottlingData); pw.println(" mThrottlingData=" + mThrottlingData);
pw.println(" mDdcThrottlingData=" + mDdcThrottlingData);
pw.println(" mUniqueDisplayId=" + mUniqueDisplayId);
pw.println(" mThrottlingStatus=" + mThrottlingStatus); pw.println(" mThrottlingStatus=" + mThrottlingStatus);
pw.println(" mBrightnessCap=" + mBrightnessCap); pw.println(" mBrightnessCap=" + mBrightnessCap);
pw.println(" mBrightnessMaxReason=" + pw.println(" mBrightnessMaxReason=" +
BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason)); BrightnessInfo.briMaxReasonToString(mBrightnessMaxReason));
pw.println(" mBrightnessThrottlingDataOverride=" + mBrightnessThrottlingDataOverride);
pw.println(" mBrightnessThrottlingDataString=" + mBrightnessThrottlingDataString);
mSkinThermalStatusObserver.dump(pw); 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 class SkinThermalStatusObserver extends IThermalEventListener.Stub {
private final Injector mInjector; private final Injector mInjector;
private final Handler mHandler; private final Handler mHandler;
@@ -258,5 +438,10 @@ class BrightnessThrottler {
return IThermalService.Stub.asInterface( return IThermalService.Stub.asInterface(
ServiceManager.getService(Context.THERMAL_SERVICE)); 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 HighBrightnessModeData mHbmData;
private DensityMapping mDensityMapping; private DensityMapping mDensityMapping;
private String mLoadedFrom = null; private String mLoadedFrom = null;
private BrightnessThrottlingData mBrightnessThrottlingData;
private Spline mSdrToHdrRatioSpline; 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) { private DisplayDeviceConfig(Context context) {
mContext = context; mContext = context;
} }
@@ -422,6 +426,10 @@ public class DisplayDeviceConfig {
return config; return config;
} }
void setBrightnessThrottlingData(BrightnessThrottlingData brightnessThrottlingData) {
mBrightnessThrottlingData = brightnessThrottlingData;
}
/** /**
* Return the brightness mapping nits array. * Return the brightness mapping nits array.
* *
@@ -637,6 +645,7 @@ public class DisplayDeviceConfig {
+ ", mHbmData=" + mHbmData + ", mHbmData=" + mHbmData
+ ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline
+ ", mBrightnessThrottlingData=" + mBrightnessThrottlingData + ", mBrightnessThrottlingData=" + mBrightnessThrottlingData
+ ", mOriginalBrightnessThrottlingData=" + mOriginalBrightnessThrottlingData
+ ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
+ ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
+ ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -932,6 +941,7 @@ public class DisplayDeviceConfig {
if (!badConfig) { if (!badConfig) {
mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels); mBrightnessThrottlingData = BrightnessThrottlingData.create(throttlingLevels);
mOriginalBrightnessThrottlingData = mBrightnessThrottlingData;
} }
} }
@@ -1407,7 +1417,9 @@ public class DisplayDeviceConfig {
/** /**
* Container for brightness throttling data. * Container for brightness throttling data.
*/ */
static class BrightnessThrottlingData { public static class BrightnessThrottlingData {
public List<ThrottlingLevel> throttlingLevels;
static class ThrottlingLevel { static class ThrottlingLevel {
public @PowerManager.ThermalStatus int thermalStatus; public @PowerManager.ThermalStatus int thermalStatus;
public float brightness; public float brightness;
@@ -1421,9 +1433,25 @@ public class DisplayDeviceConfig {
public String toString() { public String toString() {
return "[" + thermalStatus + "," + brightness + "]"; 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) 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) { private BrightnessThrottlingData(List<ThrottlingLevel> inLevels) {
throttlingLevels = new ArrayList<>(inLevels.size()); throttlingLevels = new ArrayList<>(inLevels.size());
for (ThrottlingLevel level : inLevels) { for (ThrottlingLevel level : inLevels) {
throttlingLevels.add(new ThrottlingLevel(level.thermalStatus, level.brightness)); throttlingLevels.add(new ThrottlingLevel(level.thermalStatus, level.brightness));
} }
} }
} }
} }

View File

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

View File

@@ -16,13 +16,11 @@
package com.android.server.display; package com.android.server.display;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.eq; import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.never; import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verify;
@@ -34,17 +32,18 @@ import android.os.IThermalEventListener;
import android.os.IThermalService; import android.os.IThermalService;
import android.os.Message; import android.os.Message;
import android.os.PowerManager; import android.os.PowerManager;
import android.os.Temperature.ThrottlingStatus;
import android.os.Temperature; import android.os.Temperature;
import android.os.Temperature.ThrottlingStatus;
import android.os.test.TestLooper; import android.os.test.TestLooper;
import android.platform.test.annotations.Presubmit; import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.internal.os.BackgroundThread;
import com.android.server.display.BrightnessThrottler.Injector; 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;
import com.android.server.display.DisplayDeviceConfig.BrightnessThrottlingData.ThrottlingLevel;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -55,7 +54,6 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; import java.util.List;
@SmallTest @SmallTest
@@ -70,6 +68,8 @@ public class BrightnessThrottlerTest {
@Mock IThermalService mThermalServiceMock; @Mock IThermalService mThermalServiceMock;
@Mock Injector mInjectorMock; @Mock Injector mInjectorMock;
DisplayModeDirectorTest.FakeDeviceConfig mDeviceConfigFake;
@Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor; @Captor ArgumentCaptor<IThermalEventListener> mThermalEventListenerCaptor;
@Before @Before
@@ -83,6 +83,8 @@ public class BrightnessThrottlerTest {
return true; 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()); 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( private void assertThrottlingLevelsEquals(
List<ThrottlingLevel> expected, List<ThrottlingLevel> expected,
List<ThrottlingLevel> actual) { List<ThrottlingLevel> actual) {
@@ -307,12 +473,13 @@ public class BrightnessThrottlerTest {
} }
private BrightnessThrottler createThrottlerUnsupported() { private BrightnessThrottler createThrottlerUnsupported() {
return new BrightnessThrottler(mInjectorMock, mHandler, null, () -> {}); return new BrightnessThrottler(mInjectorMock, mHandler, mHandler, null, () -> {}, null);
} }
private BrightnessThrottler createThrottlerSupported(BrightnessThrottlingData data) { private BrightnessThrottler createThrottlerSupported(BrightnessThrottlingData data) {
assertNotNull(data); assertNotNull(data);
return new BrightnessThrottler(mInjectorMock, mHandler, data, () -> {}); return new BrightnessThrottler(mInjectorMock, mHandler, BackgroundThread.getHandler(),
data, () -> {}, "123");
} }
private Temperature getSkinTemp(@ThrottlingStatus int status) { private Temperature getSkinTemp(@ThrottlingStatus int status) {

View File

@@ -16,6 +16,7 @@
package com.android.server.display; 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_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_HIGH_DISPLAY_BRIGHTNESS_THRESHOLDS;
import static android.hardware.display.DisplayManager.DeviceConfig.KEY_FIXED_REFRESH_RATE_LOW_AMBIENT_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)); 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) { void setLowDisplayBrightnessThresholds(int[] brightnessThresholds) {
String thresholds = toPropertyValue(brightnessThresholds); String thresholds = toPropertyValue(brightnessThresholds);