Loading core/java/android/hardware/display/DisplayManager.java +4 −2 Original line number Diff line number Diff line Loading @@ -1758,10 +1758,12 @@ public final class DisplayManager { /** * 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. * [,<throttlingId>]? * Where [<severity as string>,<brightness cap>] is repeated for each throttling level. * The entirety is repeated for each display and throttling id, separated by a semicolon. * For example: * 123,1,critical,0.8;456,2,moderate,0.9,critical,0.7 * 123,1,critical,0.8,default;123,1,moderate,0.6,id_2;456,2,moderate,0.9,critical,0.7 */ String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data"; } Loading services/core/java/com/android/server/display/BrightnessThrottler.java +121 −50 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package com.android.server.display; import static com.android.server.display.DisplayDeviceConfig.DEFAULT_ID; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.display.BrightnessInfo; import android.hardware.display.DisplayManager; Loading Loading @@ -63,8 +66,16 @@ class BrightnessThrottler { private final DeviceConfigInterface mDeviceConfig; private int mThrottlingStatus; // Maps the throttling ID to the data. Sourced from DisplayDeviceConfig. @NonNull private HashMap<String, BrightnessThrottlingData> mDdcThrottlingDataMap; // Current throttling data being used. // Null if we do not support throttling. @Nullable private BrightnessThrottlingData mThrottlingData; private BrightnessThrottlingData mDdcThrottlingData; private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX; private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; Loading @@ -73,35 +84,45 @@ class BrightnessThrottler { // The most recent string that has been set from DeviceConfig private String mBrightnessThrottlingDataString; // The brightness throttling configuration that should be used. private String mBrightnessThrottlingDataId; // 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); // We need to store the data for every display device, so we do not need to update this each // time the underlying display device changes. // This map is indexed by uniqueDisplayId, to provide maps for throttlingId -> throttlingData. // HashMap< uniqueDisplayId, HashMap< throttlingDataId, BrightnessThrottlingData >> private final HashMap<String, HashMap<String, BrightnessThrottlingData>> mBrightnessThrottlingDataOverride = new HashMap<>(1); BrightnessThrottler(Handler handler, BrightnessThrottlingData throttlingData, Runnable throttlingChangeCallback, String uniqueDisplayId) { this(new Injector(), handler, handler, throttlingData, throttlingChangeCallback, uniqueDisplayId); BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, @NonNull HashMap<String, BrightnessThrottlingData> brightnessThrottlingDataMap) { this(new Injector(), handler, handler, throttlingChangeCallback, uniqueDisplayId, throttlingDataId, brightnessThrottlingDataMap); } @VisibleForTesting BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler, BrightnessThrottlingData throttlingData, Runnable throttlingChangeCallback, String uniqueDisplayId) { Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, @NonNull HashMap<String, BrightnessThrottlingData> brightnessThrottlingDataMap) { mInjector = injector; mHandler = handler; mDeviceConfigHandler = deviceConfigHandler; mThrottlingData = throttlingData; mDdcThrottlingData = throttlingData; mDdcThrottlingDataMap = brightnessThrottlingDataMap; mThrottlingChangeCallback = throttlingChangeCallback; mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler); mUniqueDisplayId = uniqueDisplayId; mDeviceConfig = injector.getDeviceConfig(); mDeviceConfigListener = new DeviceConfigListener(); resetThrottlingData(mThrottlingData, mUniqueDisplayId); mBrightnessThrottlingDataId = throttlingDataId; mDdcThrottlingDataMap = brightnessThrottlingDataMap; loadBrightnessThrottlingDataFromDeviceConfig(); loadBrightnessThrottlingDataFromDisplayDeviceConfig(mDdcThrottlingDataMap, mBrightnessThrottlingDataId, mUniqueDisplayId); } boolean deviceSupportsThrottling() { Loading Loading @@ -133,23 +154,14 @@ class BrightnessThrottler { mThrottlingStatus = THROTTLING_INVALID; } private void resetThrottlingData() { resetThrottlingData(mDdcThrottlingData, mUniqueDisplayId); } void resetThrottlingData(BrightnessThrottlingData throttlingData, String displayId) { stop(); mUniqueDisplayId = displayId; mDdcThrottlingData = throttlingData; mDeviceConfigListener.startListening(); reloadBrightnessThrottlingDataOverride(); mThrottlingData = mBrightnessThrottlingDataOverride.getOrDefault(mUniqueDisplayId, throttlingData); if (deviceSupportsThrottling()) { mSkinThermalStatusObserver.startObserving(); } void loadBrightnessThrottlingDataFromDisplayDeviceConfig( HashMap<String, BrightnessThrottlingData> ddcThrottlingDataMap, String brightnessThrottlingDataId, String uniqueDisplayId) { mDdcThrottlingDataMap = ddcThrottlingDataMap; mBrightnessThrottlingDataId = brightnessThrottlingDataId; mUniqueDisplayId = uniqueDisplayId; resetThrottlingData(); } private float verifyAndConstrainBrightnessCap(float brightness) { Loading Loading @@ -183,7 +195,7 @@ class BrightnessThrottler { float brightnessCap = PowerManager.BRIGHTNESS_MAX; int brightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; if (mThrottlingStatus != THROTTLING_INVALID) { if (mThrottlingStatus != THROTTLING_INVALID && mThrottlingData != null) { // Throttling levels are sorted by increasing severity for (ThrottlingLevel level : mThrottlingData.throttlingLevels) { if (level.thermalStatus <= mThrottlingStatus) { Loading Loading @@ -218,13 +230,14 @@ class BrightnessThrottler { private void dumpLocal(PrintWriter pw) { pw.println("BrightnessThrottler:"); pw.println(" mBrightnessThrottlingDataId=" + mBrightnessThrottlingDataId); 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(" mDdcThrottlingDataMap=" + mDdcThrottlingDataMap); pw.println(" mBrightnessThrottlingDataOverride=" + mBrightnessThrottlingDataOverride); pw.println(" mBrightnessThrottlingDataString=" + mBrightnessThrottlingDataString); Loading @@ -237,8 +250,18 @@ class BrightnessThrottler { /* defaultValue= */ null); } private boolean parseAndSaveData(@NonNull String strArray, @NonNull HashMap<String, BrightnessThrottlingData> tempBrightnessThrottlingData) { // The brightness throttling data id may or may not be specified in the string that is passed // in, if there is none specified, we assume it is for the default case. Each string passed in // here must be for one display and one throttling id. // 123,1,critical,0.8 // 456,2,moderate,0.9,critical,0.7 // 456,2,moderate,0.9,critical,0.7,default // 456,2,moderate,0.9,critical,0.7,id_2 // displayId, number, <state, val> * number // displayId, <number, <state, val> * number>, throttlingId private boolean parseAndAddData(@NonNull String strArray, @NonNull HashMap<String, HashMap<String, BrightnessThrottlingData>> displayIdToThrottlingIdToBtd) { boolean validConfig = true; String[] items = strArray.split(","); int i = 0; Loading @@ -254,29 +277,42 @@ class BrightnessThrottler { 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 = String throttlingDataId = (i < items.length) ? items[i++] : DEFAULT_ID; BrightnessThrottlingData throttlingLevelsData = DisplayDeviceConfig.BrightnessThrottlingData.create(throttlingLevels); tempBrightnessThrottlingData.put(uniqueDisplayId, toSave); // Add throttlingLevelsData to inner map where necessary. HashMap<String, BrightnessThrottlingData> throttlingMapForDisplay = displayIdToThrottlingIdToBtd.get(uniqueDisplayId); if (throttlingMapForDisplay == null) { throttlingMapForDisplay = new HashMap<>(); throttlingMapForDisplay.put(throttlingDataId, throttlingLevelsData); displayIdToThrottlingIdToBtd.put(uniqueDisplayId, throttlingMapForDisplay); } else if (throttlingMapForDisplay.containsKey(throttlingDataId)) { Slog.e(TAG, "Throttling data for display " + uniqueDisplayId + "contains duplicate throttling ids: '" + throttlingDataId + "'"); return false; } else { throttlingMapForDisplay.put(throttlingDataId, throttlingLevelsData); } } catch (NumberFormatException | IndexOutOfBoundsException | UnknownThermalStatusException e) { validConfig = false; Slog.e(TAG, "Throttling data is invalid array: '" + strArray + "'", e); validConfig = false; } if (i != items.length) { validConfig = false; } return validConfig; } public void reloadBrightnessThrottlingDataOverride() { HashMap<String, BrightnessThrottlingData> tempBrightnessThrottlingData = private void loadBrightnessThrottlingDataFromDeviceConfig() { HashMap<String, HashMap<String, BrightnessThrottlingData>> tempThrottlingData = new HashMap<>(1); mBrightnessThrottlingDataString = getBrightnessThrottlingDataString(); boolean validConfig = true; Loading @@ -284,15 +320,15 @@ class BrightnessThrottler { if (mBrightnessThrottlingDataString != null) { String[] throttlingDataSplits = mBrightnessThrottlingDataString.split(";"); for (String s : throttlingDataSplits) { if (!parseAndSaveData(s, tempBrightnessThrottlingData)) { if (!parseAndAddData(s, tempThrottlingData)) { validConfig = false; break; } } if (validConfig) { mBrightnessThrottlingDataOverride.putAll(tempBrightnessThrottlingData); tempBrightnessThrottlingData.clear(); mBrightnessThrottlingDataOverride.putAll(tempThrottlingData); tempThrottlingData.clear(); } } else { Loading @@ -300,15 +336,50 @@ class BrightnessThrottler { } } private void resetThrottlingData() { stop(); mDeviceConfigListener.startListening(); // Get throttling data for this id, if it exists mThrottlingData = getConfigFromId(mBrightnessThrottlingDataId); // Fallback to default id otherwise. if (!DEFAULT_ID.equals(mBrightnessThrottlingDataId) && mThrottlingData == null) { mThrottlingData = getConfigFromId(DEFAULT_ID); Slog.d(TAG, "Falling back to default throttling Id"); } if (deviceSupportsThrottling()) { mSkinThermalStatusObserver.startObserving(); } } private BrightnessThrottlingData getConfigFromId(String id) { BrightnessThrottlingData returnValue; // Fallback pattern for fetching correct throttling data for this display and id. // 1) throttling data from device config for this throttling data id returnValue = mBrightnessThrottlingDataOverride.get(mUniqueDisplayId) == null ? null : mBrightnessThrottlingDataOverride.get(mUniqueDisplayId).get(id); // 2) throttling data from ddc for this throttling data id returnValue = returnValue == null ? mDdcThrottlingDataMap.get(id) : returnValue; return returnValue; } /** * 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. * <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>][,throttlingId]? * Where [<severity as string>,<brightness cap>] is repeated for each throttling level, and the * entirety is repeated for each display & throttling data id, separated by a semicolon. */ public class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { public Executor mExecutor = new HandlerExecutor(mDeviceConfigHandler); Loading @@ -320,7 +391,7 @@ class BrightnessThrottler { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { reloadBrightnessThrottlingDataOverride(); loadBrightnessThrottlingDataFromDeviceConfig(); resetThrottlingData(); } } Loading services/core/java/com/android/server/display/DisplayDeviceConfig.java +24 −32 Original line number Diff line number Diff line Loading @@ -143,17 +143,17 @@ import javax.xml.datatype.DatatypeConfigurationException; * <brightness>0.01</brightness> * </brightnessThrottlingPoint> * </brightnessThrottlingMap> * <concurrentDisplaysBrightnessThrottlingMap> * <brightnessThrottlingMap id="id_2"> // optional attribute, leave blank for default * <brightnessThrottlingPoint> * <thermalStatus>severe</thermalStatus> * <brightness>0.07</brightness> * <thermalStatus>moderate</thermalStatus> * <brightness>0.2</brightness> * </brightnessThrottlingPoint> * <brightnessThrottlingPoint> * <thermalStatus>critical</thermalStatus> * <brightness>0.005</brightness> * <thermalStatus>severe</thermalStatus> * <brightness>0.1</brightness> * </brightnessThrottlingPoint> * </concurrentDisplaysBrightnessThrottlingMap> * <refreshRateThrottlingMap> * </brightnessThrottlingMap> <refreshRateThrottlingMap> * <refreshRateThrottlingPoint> * <thermalStatus>critical</thermalStatus> * <refreshRateRange> Loading Loading @@ -687,8 +687,8 @@ public class DisplayDeviceConfig { private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; private final Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap = new HashMap<>(); private final HashMap<String, BrightnessThrottlingData> mBrightnessThrottlingDataMapByThrottlingId = new HashMap<>(); private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>> mRefreshRateThrottlingMap = new HashMap<>(); Loading Loading @@ -1346,11 +1346,11 @@ public class DisplayDeviceConfig { } /** * @param id The ID of the throttling data * @return brightness throttling configuration data for the display. * @return brightness throttling configuration data for this display, for each throttling id. */ public BrightnessThrottlingData getBrightnessThrottlingData(String id) { return BrightnessThrottlingData.create(mBrightnessThrottlingDataMap.get(id)); public HashMap<String, BrightnessThrottlingData> getBrightnessThrottlingDataMapByThrottlingId() { return mBrightnessThrottlingDataMapByThrottlingId; } /** Loading Loading @@ -1525,7 +1525,8 @@ public class DisplayDeviceConfig { + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled + ", mHbmData=" + mHbmData + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline + ", mBrightnessThrottlingData=" + mBrightnessThrottlingDataMap + ", mBrightnessThrottlingDataMapByThrottlingId=" + mBrightnessThrottlingDataMapByThrottlingId + "\n" + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease Loading Loading @@ -1918,11 +1919,11 @@ public class DisplayDeviceConfig { if (!badConfig) { String id = map.getId() == null ? DEFAULT_ID : map.getId(); if (mBrightnessThrottlingDataMap.containsKey(id)) { if (mBrightnessThrottlingDataMapByThrottlingId.containsKey(id)) { throw new RuntimeException("Brightness throttling data with ID " + id + " already exists"); } mBrightnessThrottlingDataMap.put(id, mBrightnessThrottlingDataMapByThrottlingId.put(id, BrightnessThrottlingData.create(throttlingLevels)); } } Loading Loading @@ -1971,8 +1972,8 @@ public class DisplayDeviceConfig { )); } if (refreshRates.size() == 0) { Slog.w(TAG, "RefreshRateThrottling: no valid throttling points fond for map, mapId=" + id); Slog.w(TAG, "RefreshRateThrottling: no valid throttling points found for map, " + "mapId=" + id); continue; } mRefreshRateThrottlingMap.put(id, refreshRates); Loading Loading @@ -3077,7 +3078,7 @@ public class DisplayDeviceConfig { /** * Creates multiple teperature based throttling levels of brightness * Creates multiple temperature based throttling levels of brightness */ public static BrightnessThrottlingData create(List<ThrottlingLevel> throttlingLevels) { if (throttlingLevels == null || throttlingLevels.size() == 0) { Loading Loading @@ -3120,15 +3121,6 @@ public class DisplayDeviceConfig { return new BrightnessThrottlingData(throttlingLevels); } static public BrightnessThrottlingData create(BrightnessThrottlingData other) { if (other == null) { return null; } return BrightnessThrottlingData.create(other.throttlingLevels); } @Override public String toString() { return "BrightnessThrottlingData{" Loading services/core/java/com/android/server/display/DisplayPowerController.java +11 −9 Original line number Diff line number Diff line Loading @@ -505,7 +505,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private DisplayDeviceConfig mDisplayDeviceConfig; // Identifiers for suspend blocker acuisition requests // Identifiers for suspend blocker acquisition requests private final String mSuspendBlockerIdUnfinishedBusiness; private final String mSuspendBlockerIdOnStateChanged; private final String mSuspendBlockerIdProxPositive; Loading @@ -515,6 +515,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private boolean mIsEnabled; private boolean mIsInTransition; // The id of the brightness throttling policy that should be used. private String mBrightnessThrottlingDataId; // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there Loading Loading @@ -905,14 +906,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadNitBasedBrightnessSetting(); /// Since the underlying display-device changed, we really don't know the // last command that was sent to change it's state. Lets assume it is unknown so // last command that was sent to change it's state. Let's assume it is unknown so // that we trigger a change immediately. mPowerState.resetScreenState(); } else if (!mBrightnessThrottlingDataId.equals(brightnessThrottlingDataId)) { changed = true; mBrightnessThrottlingDataId = brightnessThrottlingDataId; mBrightnessThrottler.resetThrottlingData( config.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( config.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) { Loading Loading @@ -981,9 +983,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call sdrBrightness, maxDesiredHdrSdrRatio); } }); mBrightnessThrottler.resetThrottlingData( mDisplayDeviceConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mUniqueDisplayId); mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } private void sendUpdatePowerState() { Loading Loading @@ -2116,11 +2118,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); return new BrightnessThrottler(mHandler, ddConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), () -> { sendUpdatePowerState(); postBrightnessChangeRunnable(); }, mUniqueDisplayId); }, mUniqueDisplayId, mLogicalDisplay.getBrightnessThrottlingDataIdLocked(), ddConfig.getBrightnessThrottlingDataMapByThrottlingId()); } private void blockScreenOn() { Loading services/core/java/com/android/server/display/DisplayPowerController2.java +10 −8 Original line number Diff line number Diff line Loading @@ -400,6 +400,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal private boolean mIsEnabled; private boolean mIsInTransition; // The id of the brightness throttling policy that should be used. private String mBrightnessThrottlingDataId; // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there Loading Loading @@ -722,14 +723,15 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config); // Since the underlying display-device changed, we really don't know the // last command that was sent to change it's state. Lets assume it is unknown so // last command that was sent to change it's state. Let's assume it is unknown so // that we trigger a change immediately. mPowerState.resetScreenState(); } else if (!mBrightnessThrottlingDataId.equals(brightnessThrottlingDataId)) { changed = true; mBrightnessThrottlingDataId = brightnessThrottlingDataId; mBrightnessThrottler.resetThrottlingData( config.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( config.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) { Loading Loading @@ -795,9 +797,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal sdrBrightness, maxDesiredHdrSdrRatio); } }); mBrightnessThrottler.resetThrottlingData( mDisplayDeviceConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mUniqueDisplayId); mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } private void sendUpdatePowerState() { Loading Loading @@ -1757,11 +1759,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); return new BrightnessThrottler(mHandler, ddConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), () -> { sendUpdatePowerState(); postBrightnessChangeRunnable(); }, mUniqueDisplayId); }, mUniqueDisplayId, mLogicalDisplay.getBrightnessThrottlingDataIdLocked(), ddConfig.getBrightnessThrottlingDataMapByThrottlingId()); } private void blockScreenOn() { Loading Loading
core/java/android/hardware/display/DisplayManager.java +4 −2 Original line number Diff line number Diff line Loading @@ -1758,10 +1758,12 @@ public final class DisplayManager { /** * 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. * [,<throttlingId>]? * Where [<severity as string>,<brightness cap>] is repeated for each throttling level. * The entirety is repeated for each display and throttling id, separated by a semicolon. * For example: * 123,1,critical,0.8;456,2,moderate,0.9,critical,0.7 * 123,1,critical,0.8,default;123,1,moderate,0.6,id_2;456,2,moderate,0.9,critical,0.7 */ String KEY_BRIGHTNESS_THROTTLING_DATA = "brightness_throttling_data"; } Loading
services/core/java/com/android/server/display/BrightnessThrottler.java +121 −50 Original line number Diff line number Diff line Loading @@ -16,7 +16,10 @@ package com.android.server.display; import static com.android.server.display.DisplayDeviceConfig.DEFAULT_ID; import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.hardware.display.BrightnessInfo; import android.hardware.display.DisplayManager; Loading Loading @@ -63,8 +66,16 @@ class BrightnessThrottler { private final DeviceConfigInterface mDeviceConfig; private int mThrottlingStatus; // Maps the throttling ID to the data. Sourced from DisplayDeviceConfig. @NonNull private HashMap<String, BrightnessThrottlingData> mDdcThrottlingDataMap; // Current throttling data being used. // Null if we do not support throttling. @Nullable private BrightnessThrottlingData mThrottlingData; private BrightnessThrottlingData mDdcThrottlingData; private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX; private @BrightnessInfo.BrightnessMaxReason int mBrightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; Loading @@ -73,35 +84,45 @@ class BrightnessThrottler { // The most recent string that has been set from DeviceConfig private String mBrightnessThrottlingDataString; // The brightness throttling configuration that should be used. private String mBrightnessThrottlingDataId; // 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); // We need to store the data for every display device, so we do not need to update this each // time the underlying display device changes. // This map is indexed by uniqueDisplayId, to provide maps for throttlingId -> throttlingData. // HashMap< uniqueDisplayId, HashMap< throttlingDataId, BrightnessThrottlingData >> private final HashMap<String, HashMap<String, BrightnessThrottlingData>> mBrightnessThrottlingDataOverride = new HashMap<>(1); BrightnessThrottler(Handler handler, BrightnessThrottlingData throttlingData, Runnable throttlingChangeCallback, String uniqueDisplayId) { this(new Injector(), handler, handler, throttlingData, throttlingChangeCallback, uniqueDisplayId); BrightnessThrottler(Handler handler, Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, @NonNull HashMap<String, BrightnessThrottlingData> brightnessThrottlingDataMap) { this(new Injector(), handler, handler, throttlingChangeCallback, uniqueDisplayId, throttlingDataId, brightnessThrottlingDataMap); } @VisibleForTesting BrightnessThrottler(Injector injector, Handler handler, Handler deviceConfigHandler, BrightnessThrottlingData throttlingData, Runnable throttlingChangeCallback, String uniqueDisplayId) { Runnable throttlingChangeCallback, String uniqueDisplayId, String throttlingDataId, @NonNull HashMap<String, BrightnessThrottlingData> brightnessThrottlingDataMap) { mInjector = injector; mHandler = handler; mDeviceConfigHandler = deviceConfigHandler; mThrottlingData = throttlingData; mDdcThrottlingData = throttlingData; mDdcThrottlingDataMap = brightnessThrottlingDataMap; mThrottlingChangeCallback = throttlingChangeCallback; mSkinThermalStatusObserver = new SkinThermalStatusObserver(mInjector, mHandler); mUniqueDisplayId = uniqueDisplayId; mDeviceConfig = injector.getDeviceConfig(); mDeviceConfigListener = new DeviceConfigListener(); resetThrottlingData(mThrottlingData, mUniqueDisplayId); mBrightnessThrottlingDataId = throttlingDataId; mDdcThrottlingDataMap = brightnessThrottlingDataMap; loadBrightnessThrottlingDataFromDeviceConfig(); loadBrightnessThrottlingDataFromDisplayDeviceConfig(mDdcThrottlingDataMap, mBrightnessThrottlingDataId, mUniqueDisplayId); } boolean deviceSupportsThrottling() { Loading Loading @@ -133,23 +154,14 @@ class BrightnessThrottler { mThrottlingStatus = THROTTLING_INVALID; } private void resetThrottlingData() { resetThrottlingData(mDdcThrottlingData, mUniqueDisplayId); } void resetThrottlingData(BrightnessThrottlingData throttlingData, String displayId) { stop(); mUniqueDisplayId = displayId; mDdcThrottlingData = throttlingData; mDeviceConfigListener.startListening(); reloadBrightnessThrottlingDataOverride(); mThrottlingData = mBrightnessThrottlingDataOverride.getOrDefault(mUniqueDisplayId, throttlingData); if (deviceSupportsThrottling()) { mSkinThermalStatusObserver.startObserving(); } void loadBrightnessThrottlingDataFromDisplayDeviceConfig( HashMap<String, BrightnessThrottlingData> ddcThrottlingDataMap, String brightnessThrottlingDataId, String uniqueDisplayId) { mDdcThrottlingDataMap = ddcThrottlingDataMap; mBrightnessThrottlingDataId = brightnessThrottlingDataId; mUniqueDisplayId = uniqueDisplayId; resetThrottlingData(); } private float verifyAndConstrainBrightnessCap(float brightness) { Loading Loading @@ -183,7 +195,7 @@ class BrightnessThrottler { float brightnessCap = PowerManager.BRIGHTNESS_MAX; int brightnessMaxReason = BrightnessInfo.BRIGHTNESS_MAX_REASON_NONE; if (mThrottlingStatus != THROTTLING_INVALID) { if (mThrottlingStatus != THROTTLING_INVALID && mThrottlingData != null) { // Throttling levels are sorted by increasing severity for (ThrottlingLevel level : mThrottlingData.throttlingLevels) { if (level.thermalStatus <= mThrottlingStatus) { Loading Loading @@ -218,13 +230,14 @@ class BrightnessThrottler { private void dumpLocal(PrintWriter pw) { pw.println("BrightnessThrottler:"); pw.println(" mBrightnessThrottlingDataId=" + mBrightnessThrottlingDataId); 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(" mDdcThrottlingDataMap=" + mDdcThrottlingDataMap); pw.println(" mBrightnessThrottlingDataOverride=" + mBrightnessThrottlingDataOverride); pw.println(" mBrightnessThrottlingDataString=" + mBrightnessThrottlingDataString); Loading @@ -237,8 +250,18 @@ class BrightnessThrottler { /* defaultValue= */ null); } private boolean parseAndSaveData(@NonNull String strArray, @NonNull HashMap<String, BrightnessThrottlingData> tempBrightnessThrottlingData) { // The brightness throttling data id may or may not be specified in the string that is passed // in, if there is none specified, we assume it is for the default case. Each string passed in // here must be for one display and one throttling id. // 123,1,critical,0.8 // 456,2,moderate,0.9,critical,0.7 // 456,2,moderate,0.9,critical,0.7,default // 456,2,moderate,0.9,critical,0.7,id_2 // displayId, number, <state, val> * number // displayId, <number, <state, val> * number>, throttlingId private boolean parseAndAddData(@NonNull String strArray, @NonNull HashMap<String, HashMap<String, BrightnessThrottlingData>> displayIdToThrottlingIdToBtd) { boolean validConfig = true; String[] items = strArray.split(","); int i = 0; Loading @@ -254,29 +277,42 @@ class BrightnessThrottler { 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 = String throttlingDataId = (i < items.length) ? items[i++] : DEFAULT_ID; BrightnessThrottlingData throttlingLevelsData = DisplayDeviceConfig.BrightnessThrottlingData.create(throttlingLevels); tempBrightnessThrottlingData.put(uniqueDisplayId, toSave); // Add throttlingLevelsData to inner map where necessary. HashMap<String, BrightnessThrottlingData> throttlingMapForDisplay = displayIdToThrottlingIdToBtd.get(uniqueDisplayId); if (throttlingMapForDisplay == null) { throttlingMapForDisplay = new HashMap<>(); throttlingMapForDisplay.put(throttlingDataId, throttlingLevelsData); displayIdToThrottlingIdToBtd.put(uniqueDisplayId, throttlingMapForDisplay); } else if (throttlingMapForDisplay.containsKey(throttlingDataId)) { Slog.e(TAG, "Throttling data for display " + uniqueDisplayId + "contains duplicate throttling ids: '" + throttlingDataId + "'"); return false; } else { throttlingMapForDisplay.put(throttlingDataId, throttlingLevelsData); } } catch (NumberFormatException | IndexOutOfBoundsException | UnknownThermalStatusException e) { validConfig = false; Slog.e(TAG, "Throttling data is invalid array: '" + strArray + "'", e); validConfig = false; } if (i != items.length) { validConfig = false; } return validConfig; } public void reloadBrightnessThrottlingDataOverride() { HashMap<String, BrightnessThrottlingData> tempBrightnessThrottlingData = private void loadBrightnessThrottlingDataFromDeviceConfig() { HashMap<String, HashMap<String, BrightnessThrottlingData>> tempThrottlingData = new HashMap<>(1); mBrightnessThrottlingDataString = getBrightnessThrottlingDataString(); boolean validConfig = true; Loading @@ -284,15 +320,15 @@ class BrightnessThrottler { if (mBrightnessThrottlingDataString != null) { String[] throttlingDataSplits = mBrightnessThrottlingDataString.split(";"); for (String s : throttlingDataSplits) { if (!parseAndSaveData(s, tempBrightnessThrottlingData)) { if (!parseAndAddData(s, tempThrottlingData)) { validConfig = false; break; } } if (validConfig) { mBrightnessThrottlingDataOverride.putAll(tempBrightnessThrottlingData); tempBrightnessThrottlingData.clear(); mBrightnessThrottlingDataOverride.putAll(tempThrottlingData); tempThrottlingData.clear(); } } else { Loading @@ -300,15 +336,50 @@ class BrightnessThrottler { } } private void resetThrottlingData() { stop(); mDeviceConfigListener.startListening(); // Get throttling data for this id, if it exists mThrottlingData = getConfigFromId(mBrightnessThrottlingDataId); // Fallback to default id otherwise. if (!DEFAULT_ID.equals(mBrightnessThrottlingDataId) && mThrottlingData == null) { mThrottlingData = getConfigFromId(DEFAULT_ID); Slog.d(TAG, "Falling back to default throttling Id"); } if (deviceSupportsThrottling()) { mSkinThermalStatusObserver.startObserving(); } } private BrightnessThrottlingData getConfigFromId(String id) { BrightnessThrottlingData returnValue; // Fallback pattern for fetching correct throttling data for this display and id. // 1) throttling data from device config for this throttling data id returnValue = mBrightnessThrottlingDataOverride.get(mUniqueDisplayId) == null ? null : mBrightnessThrottlingDataOverride.get(mUniqueDisplayId).get(id); // 2) throttling data from ddc for this throttling data id returnValue = returnValue == null ? mDdcThrottlingDataMap.get(id) : returnValue; return returnValue; } /** * 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. * <displayId>,<no of throttling levels>,[<severity as string>,<brightness cap>][,throttlingId]? * Where [<severity as string>,<brightness cap>] is repeated for each throttling level, and the * entirety is repeated for each display & throttling data id, separated by a semicolon. */ public class DeviceConfigListener implements DeviceConfig.OnPropertiesChangedListener { public Executor mExecutor = new HandlerExecutor(mDeviceConfigHandler); Loading @@ -320,7 +391,7 @@ class BrightnessThrottler { @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { reloadBrightnessThrottlingDataOverride(); loadBrightnessThrottlingDataFromDeviceConfig(); resetThrottlingData(); } } Loading
services/core/java/com/android/server/display/DisplayDeviceConfig.java +24 −32 Original line number Diff line number Diff line Loading @@ -143,17 +143,17 @@ import javax.xml.datatype.DatatypeConfigurationException; * <brightness>0.01</brightness> * </brightnessThrottlingPoint> * </brightnessThrottlingMap> * <concurrentDisplaysBrightnessThrottlingMap> * <brightnessThrottlingMap id="id_2"> // optional attribute, leave blank for default * <brightnessThrottlingPoint> * <thermalStatus>severe</thermalStatus> * <brightness>0.07</brightness> * <thermalStatus>moderate</thermalStatus> * <brightness>0.2</brightness> * </brightnessThrottlingPoint> * <brightnessThrottlingPoint> * <thermalStatus>critical</thermalStatus> * <brightness>0.005</brightness> * <thermalStatus>severe</thermalStatus> * <brightness>0.1</brightness> * </brightnessThrottlingPoint> * </concurrentDisplaysBrightnessThrottlingMap> * <refreshRateThrottlingMap> * </brightnessThrottlingMap> <refreshRateThrottlingMap> * <refreshRateThrottlingPoint> * <thermalStatus>critical</thermalStatus> * <refreshRateRange> Loading Loading @@ -687,8 +687,8 @@ public class DisplayDeviceConfig { private int[] mHighDisplayBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; private int[] mHighAmbientBrightnessThresholds = DEFAULT_BRIGHTNESS_THRESHOLDS; private final Map<String, BrightnessThrottlingData> mBrightnessThrottlingDataMap = new HashMap<>(); private final HashMap<String, BrightnessThrottlingData> mBrightnessThrottlingDataMapByThrottlingId = new HashMap<>(); private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>> mRefreshRateThrottlingMap = new HashMap<>(); Loading Loading @@ -1346,11 +1346,11 @@ public class DisplayDeviceConfig { } /** * @param id The ID of the throttling data * @return brightness throttling configuration data for the display. * @return brightness throttling configuration data for this display, for each throttling id. */ public BrightnessThrottlingData getBrightnessThrottlingData(String id) { return BrightnessThrottlingData.create(mBrightnessThrottlingDataMap.get(id)); public HashMap<String, BrightnessThrottlingData> getBrightnessThrottlingDataMapByThrottlingId() { return mBrightnessThrottlingDataMapByThrottlingId; } /** Loading Loading @@ -1525,7 +1525,8 @@ public class DisplayDeviceConfig { + ", isHbmEnabled=" + mIsHighBrightnessModeEnabled + ", mHbmData=" + mHbmData + ", mSdrToHdrRatioSpline=" + mSdrToHdrRatioSpline + ", mBrightnessThrottlingData=" + mBrightnessThrottlingDataMap + ", mBrightnessThrottlingDataMapByThrottlingId=" + mBrightnessThrottlingDataMapByThrottlingId + "\n" + ", mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease Loading Loading @@ -1918,11 +1919,11 @@ public class DisplayDeviceConfig { if (!badConfig) { String id = map.getId() == null ? DEFAULT_ID : map.getId(); if (mBrightnessThrottlingDataMap.containsKey(id)) { if (mBrightnessThrottlingDataMapByThrottlingId.containsKey(id)) { throw new RuntimeException("Brightness throttling data with ID " + id + " already exists"); } mBrightnessThrottlingDataMap.put(id, mBrightnessThrottlingDataMapByThrottlingId.put(id, BrightnessThrottlingData.create(throttlingLevels)); } } Loading Loading @@ -1971,8 +1972,8 @@ public class DisplayDeviceConfig { )); } if (refreshRates.size() == 0) { Slog.w(TAG, "RefreshRateThrottling: no valid throttling points fond for map, mapId=" + id); Slog.w(TAG, "RefreshRateThrottling: no valid throttling points found for map, " + "mapId=" + id); continue; } mRefreshRateThrottlingMap.put(id, refreshRates); Loading Loading @@ -3077,7 +3078,7 @@ public class DisplayDeviceConfig { /** * Creates multiple teperature based throttling levels of brightness * Creates multiple temperature based throttling levels of brightness */ public static BrightnessThrottlingData create(List<ThrottlingLevel> throttlingLevels) { if (throttlingLevels == null || throttlingLevels.size() == 0) { Loading Loading @@ -3120,15 +3121,6 @@ public class DisplayDeviceConfig { return new BrightnessThrottlingData(throttlingLevels); } static public BrightnessThrottlingData create(BrightnessThrottlingData other) { if (other == null) { return null; } return BrightnessThrottlingData.create(other.throttlingLevels); } @Override public String toString() { return "BrightnessThrottlingData{" Loading
services/core/java/com/android/server/display/DisplayPowerController.java +11 −9 Original line number Diff line number Diff line Loading @@ -505,7 +505,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private DisplayDeviceConfig mDisplayDeviceConfig; // Identifiers for suspend blocker acuisition requests // Identifiers for suspend blocker acquisition requests private final String mSuspendBlockerIdUnfinishedBusiness; private final String mSuspendBlockerIdOnStateChanged; private final String mSuspendBlockerIdProxPositive; Loading @@ -515,6 +515,7 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call private boolean mIsEnabled; private boolean mIsInTransition; // The id of the brightness throttling policy that should be used. private String mBrightnessThrottlingDataId; // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there Loading Loading @@ -905,14 +906,15 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call loadNitBasedBrightnessSetting(); /// Since the underlying display-device changed, we really don't know the // last command that was sent to change it's state. Lets assume it is unknown so // last command that was sent to change it's state. Let's assume it is unknown so // that we trigger a change immediately. mPowerState.resetScreenState(); } else if (!mBrightnessThrottlingDataId.equals(brightnessThrottlingDataId)) { changed = true; mBrightnessThrottlingDataId = brightnessThrottlingDataId; mBrightnessThrottler.resetThrottlingData( config.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( config.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) { Loading Loading @@ -981,9 +983,9 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call sdrBrightness, maxDesiredHdrSdrRatio); } }); mBrightnessThrottler.resetThrottlingData( mDisplayDeviceConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mUniqueDisplayId); mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } private void sendUpdatePowerState() { Loading Loading @@ -2116,11 +2118,11 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); return new BrightnessThrottler(mHandler, ddConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), () -> { sendUpdatePowerState(); postBrightnessChangeRunnable(); }, mUniqueDisplayId); }, mUniqueDisplayId, mLogicalDisplay.getBrightnessThrottlingDataIdLocked(), ddConfig.getBrightnessThrottlingDataMapByThrottlingId()); } private void blockScreenOn() { Loading
services/core/java/com/android/server/display/DisplayPowerController2.java +10 −8 Original line number Diff line number Diff line Loading @@ -400,6 +400,7 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal private boolean mIsEnabled; private boolean mIsInTransition; // The id of the brightness throttling policy that should be used. private String mBrightnessThrottlingDataId; // DPCs following the brightness of this DPC. This is used in concurrent displays mode - there Loading Loading @@ -722,14 +723,15 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal mDisplayPowerProximityStateController.notifyDisplayDeviceChanged(config); // Since the underlying display-device changed, we really don't know the // last command that was sent to change it's state. Lets assume it is unknown so // last command that was sent to change it's state. Let's assume it is unknown so // that we trigger a change immediately. mPowerState.resetScreenState(); } else if (!mBrightnessThrottlingDataId.equals(brightnessThrottlingDataId)) { changed = true; mBrightnessThrottlingDataId = brightnessThrottlingDataId; mBrightnessThrottler.resetThrottlingData( config.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( config.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } if (mIsEnabled != isEnabled || mIsInTransition != isInTransition) { Loading Loading @@ -795,9 +797,9 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal sdrBrightness, maxDesiredHdrSdrRatio); } }); mBrightnessThrottler.resetThrottlingData( mDisplayDeviceConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), mUniqueDisplayId); mBrightnessThrottler.loadBrightnessThrottlingDataFromDisplayDeviceConfig( mDisplayDeviceConfig.getBrightnessThrottlingDataMapByThrottlingId(), mBrightnessThrottlingDataId, mUniqueDisplayId); } private void sendUpdatePowerState() { Loading Loading @@ -1757,11 +1759,11 @@ final class DisplayPowerController2 implements AutomaticBrightnessController.Cal final DisplayDevice device = mLogicalDisplay.getPrimaryDisplayDeviceLocked(); final DisplayDeviceConfig ddConfig = device.getDisplayDeviceConfig(); return new BrightnessThrottler(mHandler, ddConfig.getBrightnessThrottlingData(mBrightnessThrottlingDataId), () -> { sendUpdatePowerState(); postBrightnessChangeRunnable(); }, mUniqueDisplayId); }, mUniqueDisplayId, mLogicalDisplay.getBrightnessThrottlingDataIdLocked(), ddConfig.getBrightnessThrottlingDataMapByThrottlingId()); } private void blockScreenOn() { Loading