Merge "Brightnessthrottler updateable through DeviceConfig" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
c5f1c156ba
@@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user