Loading services/core/java/com/android/server/display/DisplayDeviceConfig.java +23 −8 Original line number Diff line number Diff line Loading @@ -150,7 +150,9 @@ import javax.xml.datatype.DatatypeConfigurationException; * <screenBrightnessDefault>0.65</screenBrightnessDefault> * <powerThrottlingConfig> * <brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed> * <pollingWindowMillis>15</pollingWindowMillis> * <customAnimationRateSec>0.004</customAnimationRateSec> * <pollingWindowMaxMillis>30000</pollingWindowMaxMillis> * <pollingWindowMinMillis>10000</pollingWindowMinMillis> * <powerThrottlingMap> * <powerThrottlingPoint> * <thermalStatus>severe</thermalStatus> Loading Loading @@ -2184,9 +2186,13 @@ public class DisplayDeviceConfig { return; } float lowestBrightnessCap = powerThrottlingCfg.getBrightnessLowestCapAllowed().floatValue(); int pollingWindowMillis = powerThrottlingCfg.getPollingWindowMillis().intValue(); float customAnimationRateSec = powerThrottlingCfg.getCustomAnimationRateSec().floatValue(); int pollingWindowMaxMillis = powerThrottlingCfg.getPollingWindowMaxMillis().intValue(); int pollingWindowMinMillis = powerThrottlingCfg.getPollingWindowMinMillis().intValue(); mPowerThrottlingConfigData = new PowerThrottlingConfigData(lowestBrightnessCap, pollingWindowMillis); customAnimationRateSec, pollingWindowMaxMillis, pollingWindowMinMillis); } private void loadRefreshRateSetting(DisplayConfiguration config) { Loading Loading @@ -2980,12 +2986,19 @@ public class DisplayDeviceConfig { public static class PowerThrottlingConfigData { /** Lowest brightness cap allowed for this device. */ public final float brightnessLowestCapAllowed; /** Time window for polling power in seconds. */ public final int pollingWindowMillis; /** Time take to animate brightness in seconds. */ public final float customAnimationRateSec; /** Time window for maximum polling power in milliseconds. */ public final int pollingWindowMaxMillis; /** Time window for minimum polling power in milliseconds. */ public final int pollingWindowMinMillis; public PowerThrottlingConfigData(float brightnessLowestCapAllowed, int pollingWindowMillis) { float customAnimationRateSec, int pollingWindowMaxMillis, int pollingWindowMinMillis) { this.brightnessLowestCapAllowed = brightnessLowestCapAllowed; this.pollingWindowMillis = pollingWindowMillis; this.customAnimationRateSec = customAnimationRateSec; this.pollingWindowMaxMillis = pollingWindowMaxMillis; this.pollingWindowMinMillis = pollingWindowMinMillis; } @Override Loading @@ -2993,7 +3006,9 @@ public class DisplayDeviceConfig { return "PowerThrottlingConfigData{" + "brightnessLowestCapAllowed: " + brightnessLowestCapAllowed + ", pollingWindowMillis: " + pollingWindowMillis + ", customAnimationRateSec: " + customAnimationRateSec + ", pollingWindowMaxMillis: " + pollingWindowMaxMillis + ", pollingWindowMinMillis: " + pollingWindowMinMillis + "} "; } } Loading services/core/java/com/android/server/display/DisplayPowerController.java +4 −3 Original line number Diff line number Diff line Loading @@ -591,7 +591,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mThermalBrightnessThrottlingDataId, logicalDisplay.getPowerThrottlingDataIdLocked(), mDisplayDeviceConfig, displayDeviceInfo.width, displayDeviceInfo.height, displayToken, mDisplayId), mContext, flags, mSensorManager); displayToken, mDisplayId), mContext, flags, mSensorManager, mDisplayBrightnessController.getCurrentBrightness()); // Seed the cached brightness saveBrightnessInfo(getScreenBrightnessSetting()); mAutomaticBrightnessStrategy = Loading Loading @@ -3305,10 +3306,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call BrightnessClamperController getBrightnessClamperController(Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { return new BrightnessClamperController(handler, clamperChangeListener, data, context, flags, sensorManager); flags, sensorManager, currentBrightness); } DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler, Loading services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +30 −7 Original line number Diff line number Diff line Loading @@ -75,10 +75,13 @@ public class BrightnessClamperController { private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState(); private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener; private final DisplayManagerFlags mDisplayManagerFlags; private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX; private float mCustomAnimationRate = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; @Nullable private BrightnessPowerClamper mPowerClamper; @Nullable private Type mClamperType = null; private boolean mClamperApplied = false; Loading @@ -93,16 +96,18 @@ public class BrightnessClamperController { public BrightnessClamperController(Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager); DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager, currentBrightness); } @VisibleForTesting BrightnessClamperController(Injector injector, Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler = handler; mDisplayManagerFlags = flags; mLightSensorController = injector.getLightSensorController(sensorManager, context, mLightSensorListener, mHandler); Loading @@ -117,7 +122,15 @@ public class BrightnessClamperController { }; mClampers = injector.getClampers(handler, clamperChangeListenerInternal, data, flags, context); context, currentBrightness); if (mDisplayManagerFlags.isPowerThrottlingClamperEnabled()) { for (BrightnessClamper clamper: mClampers) { if (clamper.getType() == Type.POWER) { mPowerClamper = (BrightnessPowerClamper) clamper; break; } } } mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListener, data); Loading Loading @@ -183,6 +196,12 @@ public class BrightnessClamperController { mModifiers.get(i).apply(request, builder); } if (mDisplayManagerFlags.isPowerThrottlingClamperEnabled()) { if (mPowerClamper != null) { mPowerClamper.updateCurrentBrightness(cappedBrightness); } } return builder.build(); } Loading Loading @@ -312,13 +331,17 @@ public class BrightnessClamperController { List<BrightnessClamper<? super DisplayDeviceData>> getClampers(Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, DisplayManagerFlags flags, Context context) { DisplayManagerFlags flags, Context context, float currentBrightness) { List<BrightnessClamper<? super DisplayDeviceData>> clampers = new ArrayList<>(); clampers.add( new BrightnessThermalClamper(handler, clamperChangeListener, data)); if (flags.isPowerThrottlingClamperEnabled()) { // Check if power-throttling config is present. PowerThrottlingConfigData configData = data.getPowerThrottlingConfigData(); if (configData != null) { clampers.add(new BrightnessPowerClamper(handler, clamperChangeListener, data)); data, currentBrightness)); } } if (flags.isBrightnessWearBedtimeModeClamperEnabled()) { clampers.add(new BrightnessWearBedtimeModeClamper(handler, context, Loading services/core/java/com/android/server/display/brightness/clamper/BrightnessPowerClamper.java +209 −28 Original line number Diff line number Diff line Loading @@ -21,16 +21,23 @@ import static com.android.server.display.brightness.clamper.BrightnessClamperCon import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.Handler; import android.os.IThermalEventListener; import android.os.IThermalService; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.Temperature; import android.provider.DeviceConfigInterface; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.DisplayBrightnessState; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingConfigData; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingData; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel; import com.android.server.display.brightness.BrightnessUtils; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.utils.DeviceConfigParsingUtils; Loading Loading @@ -65,14 +72,21 @@ class BrightnessPowerClamper extends private PowerThrottlingData mPowerThrottlingDataActive = null; @Nullable private PowerThrottlingConfigData mPowerThrottlingConfigData = null; @NonNull private final ThermalLevelListener mThermalLevelListener; @NonNull private final PowerChangeListener mPowerChangeListener; private @Temperature.ThrottlingStatus int mCurrentThermalLevel = Temperature.THROTTLING_NONE; private boolean mCurrentThermalLevelChanged = false; private float mCurrentAvgPowerConsumed = 0; @Nullable private String mUniqueDisplayId = null; @Nullable private String mDataId = null; private float mCurrentBrightness = PowerManager.BRIGHTNESS_INVALID; private float mCustomAnimationRateSec = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; private float mCustomAnimationRateSecDeviceConfig = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> { try { int status = DeviceConfigParsingUtils.parseThermalStatus(key); Loading @@ -88,23 +102,41 @@ class BrightnessPowerClamper extends BrightnessPowerClamper(Handler handler, ClamperChangeListener listener, PowerData powerData) { this(new Injector(), handler, listener, powerData); PowerData powerData, float currentBrightness) { this(new Injector(), handler, listener, powerData, currentBrightness); } @VisibleForTesting BrightnessPowerClamper(Injector injector, Handler handler, ClamperChangeListener listener, PowerData powerData) { PowerData powerData, float currentBrightness) { super(handler, listener); mInjector = injector; mConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mCurrentBrightness = currentBrightness; mPowerChangeListener = (powerConsumed, thermalStatus) -> { recalculatePowerQuotaChange(powerConsumed, thermalStatus); }; mPowerThrottlingConfigData = powerData.getPowerThrottlingConfigData(); if (mPowerThrottlingConfigData != null) { mCustomAnimationRateSecDeviceConfig = mPowerThrottlingConfigData.customAnimationRateSec; } mThermalLevelListener = new ThermalLevelListener(handler); mPmicMonitor = mInjector.getPmicMonitor(mPowerChangeListener, mThermalLevelListener.getThermalService(), mPowerThrottlingConfigData.pollingWindowMaxMillis, mPowerThrottlingConfigData.pollingWindowMinMillis); mConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler.post(() -> { setDisplayData(powerData); loadOverrideData(); start(); }); } @VisibleForTesting PowerChangeListener getPowerChangeListener() { return mPowerChangeListener; } @Override Loading @@ -113,6 +145,11 @@ class BrightnessPowerClamper extends return Type.POWER; } @Override float getCustomAnimationRate() { return mCustomAnimationRateSec; } @Override void onDeviceConfigChanged() { mHandler.post(() -> { Loading @@ -134,6 +171,9 @@ class BrightnessPowerClamper extends if (mPmicMonitor != null) { mPmicMonitor.shutdown(); } if (mThermalLevelListener != null) { mThermalLevelListener.stop(); } } /** Loading @@ -144,11 +184,20 @@ class BrightnessPowerClamper extends pw.println(" mCurrentAvgPowerConsumed=" + mCurrentAvgPowerConsumed); pw.println(" mUniqueDisplayId=" + mUniqueDisplayId); pw.println(" mCurrentThermalLevel=" + mCurrentThermalLevel); pw.println(" mCurrentThermalLevelChanged=" + mCurrentThermalLevelChanged); pw.println(" mPowerThrottlingDataFromDDC=" + (mPowerThrottlingDataFromDDC == null ? "null" : mPowerThrottlingDataFromDDC.toString())); mThermalLevelListener.dump(pw); super.dump(pw); } /** * Updates current brightness, for power calculations. */ public void updateCurrentBrightness(float currentBrightness) { mCurrentBrightness = currentBrightness; } private void recalculateActiveData() { if (mUniqueDisplayId == null || mDataId == null) { return; Loading @@ -156,17 +205,11 @@ class BrightnessPowerClamper extends mPowerThrottlingDataActive = mPowerThrottlingDataOverride .getOrDefault(mUniqueDisplayId, Map.of()).getOrDefault(mDataId, mPowerThrottlingDataFromDDC); if (mPowerThrottlingDataActive != null) { if (mPmicMonitor != null) { mPmicMonitor.stop(); mPmicMonitor.start(); } } else { if (mPowerThrottlingDataActive == null) { if (mPmicMonitor != null) { mPmicMonitor.stop(); } } recalculateBrightnessCap(); } private void loadOverrideData() { Loading Loading @@ -198,21 +241,57 @@ class BrightnessPowerClamper extends if (mPowerThrottlingDataActive == null) { return; } if (powerQuota > 0 && mCurrentAvgPowerConsumed > powerQuota) { if (powerQuota > 0) { if (BrightnessUtils.isValidBrightnessValue(mCurrentBrightness) && (mCurrentAvgPowerConsumed > powerQuota)) { isActive = true; // calculate new brightness Cap. // Brightness has a linear relation to power-consumed. targetBrightnessCap = (powerQuota / mCurrentAvgPowerConsumed) * PowerManager.BRIGHTNESS_MAX; (powerQuota / mCurrentAvgPowerConsumed) * mCurrentBrightness; } else if (mCurrentThermalLevelChanged) { if (mCurrentThermalLevel == Temperature.THROTTLING_NONE) { // reset pmic and remove the power-throttling cap. isActive = true; targetBrightnessCap = PowerManager.BRIGHTNESS_MAX; mPmicMonitor.stop(); } else { isActive = true; // Since the thermal status has changed, we need to remove power-throttling cap. // Instead of recalculating and changing brightness again, adding flicker, // we will wait for the next pmic cycle to re-evaluate this value // make act on it, if needed. targetBrightnessCap = PowerManager.BRIGHTNESS_MAX; if (mPmicMonitor.isStopped()) { mPmicMonitor.start(); } } } else { // Current power consumed is under the quota. isActive = true; targetBrightnessCap = PowerManager.BRIGHTNESS_MAX; } } // Cap to lowest allowed brightness on device. if (mPowerThrottlingConfigData != null) { targetBrightnessCap = Math.max(targetBrightnessCap, mPowerThrottlingConfigData.brightnessLowestCapAllowed); } if (mBrightnessCap != targetBrightnessCap || mIsActive != isActive) { mIsActive = isActive; Slog.i(TAG, "Power clamper changing current brightness cap mBrightnessCap: " + mBrightnessCap + " to target brightness cap:" + targetBrightnessCap + " for current screen brightness: " + mCurrentBrightness); mBrightnessCap = targetBrightnessCap; Slog.i(TAG, "Power clamper changed state: thermalStatus:" + mCurrentThermalLevel + " mCurrentThermalLevelChanged:" + mCurrentThermalLevelChanged + " mCurrentAvgPowerConsumed:" + mCurrentAvgPowerConsumed + " mCustomAnimationRateSec:" + mCustomAnimationRateSecDeviceConfig); mCustomAnimationRateSec = mCustomAnimationRateSecDeviceConfig; mChangeListener.onChanged(); } else { mCustomAnimationRateSec = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; } } Loading @@ -234,6 +313,11 @@ class BrightnessPowerClamper extends private void recalculatePowerQuotaChange(float avgPowerConsumed, int thermalStatus) { mHandler.post(() -> { if (mCurrentThermalLevel != thermalStatus) { mCurrentThermalLevelChanged = true; } else { mCurrentThermalLevelChanged = false; } mCurrentThermalLevel = thermalStatus; mCurrentAvgPowerConsumed = avgPowerConsumed; recalculateBrightnessCap(); Loading @@ -244,14 +328,107 @@ class BrightnessPowerClamper extends if (mPowerThrottlingConfigData == null) { return; } PowerChangeListener listener = (powerConsumed, thermalStatus) -> { recalculatePowerQuotaChange(powerConsumed, thermalStatus); }; mPmicMonitor = mInjector.getPmicMonitor(listener, mPowerThrottlingConfigData.pollingWindowMillis); if (mPowerThrottlingConfigData.pollingWindowMaxMillis <= mPowerThrottlingConfigData.pollingWindowMinMillis) { Slog.e(TAG, "Brightness power max polling window:" + mPowerThrottlingConfigData.pollingWindowMaxMillis + " msec, should be greater than brightness min polling window:" + mPowerThrottlingConfigData.pollingWindowMinMillis + " msec."); return; } if ((mPowerThrottlingConfigData.pollingWindowMaxMillis % mPowerThrottlingConfigData.pollingWindowMinMillis) != 0) { Slog.e(TAG, "Brightness power max polling window:" + mPowerThrottlingConfigData.pollingWindowMaxMillis + " msec, is not divisible by brightness min polling window:" + mPowerThrottlingConfigData.pollingWindowMinMillis + " msec."); return; } mCustomAnimationRateSecDeviceConfig = mPowerThrottlingConfigData.customAnimationRateSec; mThermalLevelListener.start(); } private void activatePmicMonitor() { if (!mPmicMonitor.isStopped()) { return; } mPmicMonitor.start(); } private void deactivatePmicMonitor(@Temperature.ThrottlingStatus int status) { if (status != Temperature.THROTTLING_NONE) { return; } if (mPmicMonitor.isStopped()) { return; } mPmicMonitor.stop(); } private final class ThermalLevelListener extends IThermalEventListener.Stub { private final Handler mHandler; private IThermalService mThermalService; private boolean mStarted; ThermalLevelListener(Handler handler) { mHandler = handler; mStarted = false; mThermalService = IThermalService.Stub.asInterface( ServiceManager.getService(Context.THERMAL_SERVICE)); } IThermalService getThermalService() { return mThermalService; } void start() { if (mStarted) { return; } if (mThermalService == null) { return; } try { // TODO b/279114539 Try DISPLAY first and then fallback to SKIN. mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN); mStarted = true; } catch (RemoteException e) { Slog.e(TAG, "Failed to register thermal status listener", e); } } @Override public void notifyThrottling(Temperature temp) { @Temperature.ThrottlingStatus int status = temp.getStatus(); if (status >= Temperature.THROTTLING_LIGHT) { Slog.d(TAG, "Activating pmic monitor due to thermal state:" + status); mHandler.post(() -> activatePmicMonitor()); } else { if (!mPmicMonitor.isStopped()) { mHandler.post(() -> deactivatePmicMonitor(status)); } } } void stop() { if (!mStarted) { return; } try { mThermalService.unregisterThermalEventListener(this); mStarted = false; } catch (RemoteException e) { Slog.e(TAG, "Failed to unregister thermal status listener", e); } mThermalService = null; } void dump(PrintWriter writer) { writer.println(" ThermalLevelObserver:"); writer.println(" mStarted: " + mStarted); } } public interface PowerData { @NonNull String getUniqueDisplayId(); Loading Loading @@ -279,8 +456,12 @@ class BrightnessPowerClamper extends @VisibleForTesting static class Injector { PmicMonitor getPmicMonitor(PowerChangeListener listener, int pollingTime) { return new PmicMonitor(listener, pollingTime); PmicMonitor getPmicMonitor(PowerChangeListener powerChangeListener, IThermalService thermalService, int pollingMaxTimeMillis, int pollingMinTimeMillis) { return new PmicMonitor(powerChangeListener, thermalService, pollingMaxTimeMillis, pollingMinTimeMillis); } DeviceConfigParameterProvider getDeviceConfigParameterProvider() { Loading services/core/java/com/android/server/display/brightness/clamper/PmicMonitor.java +54 −19 File changed.Preview size limit exceeded, changes collapsed. Show changes Loading
services/core/java/com/android/server/display/DisplayDeviceConfig.java +23 −8 Original line number Diff line number Diff line Loading @@ -150,7 +150,9 @@ import javax.xml.datatype.DatatypeConfigurationException; * <screenBrightnessDefault>0.65</screenBrightnessDefault> * <powerThrottlingConfig> * <brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed> * <pollingWindowMillis>15</pollingWindowMillis> * <customAnimationRateSec>0.004</customAnimationRateSec> * <pollingWindowMaxMillis>30000</pollingWindowMaxMillis> * <pollingWindowMinMillis>10000</pollingWindowMinMillis> * <powerThrottlingMap> * <powerThrottlingPoint> * <thermalStatus>severe</thermalStatus> Loading Loading @@ -2184,9 +2186,13 @@ public class DisplayDeviceConfig { return; } float lowestBrightnessCap = powerThrottlingCfg.getBrightnessLowestCapAllowed().floatValue(); int pollingWindowMillis = powerThrottlingCfg.getPollingWindowMillis().intValue(); float customAnimationRateSec = powerThrottlingCfg.getCustomAnimationRateSec().floatValue(); int pollingWindowMaxMillis = powerThrottlingCfg.getPollingWindowMaxMillis().intValue(); int pollingWindowMinMillis = powerThrottlingCfg.getPollingWindowMinMillis().intValue(); mPowerThrottlingConfigData = new PowerThrottlingConfigData(lowestBrightnessCap, pollingWindowMillis); customAnimationRateSec, pollingWindowMaxMillis, pollingWindowMinMillis); } private void loadRefreshRateSetting(DisplayConfiguration config) { Loading Loading @@ -2980,12 +2986,19 @@ public class DisplayDeviceConfig { public static class PowerThrottlingConfigData { /** Lowest brightness cap allowed for this device. */ public final float brightnessLowestCapAllowed; /** Time window for polling power in seconds. */ public final int pollingWindowMillis; /** Time take to animate brightness in seconds. */ public final float customAnimationRateSec; /** Time window for maximum polling power in milliseconds. */ public final int pollingWindowMaxMillis; /** Time window for minimum polling power in milliseconds. */ public final int pollingWindowMinMillis; public PowerThrottlingConfigData(float brightnessLowestCapAllowed, int pollingWindowMillis) { float customAnimationRateSec, int pollingWindowMaxMillis, int pollingWindowMinMillis) { this.brightnessLowestCapAllowed = brightnessLowestCapAllowed; this.pollingWindowMillis = pollingWindowMillis; this.customAnimationRateSec = customAnimationRateSec; this.pollingWindowMaxMillis = pollingWindowMaxMillis; this.pollingWindowMinMillis = pollingWindowMinMillis; } @Override Loading @@ -2993,7 +3006,9 @@ public class DisplayDeviceConfig { return "PowerThrottlingConfigData{" + "brightnessLowestCapAllowed: " + brightnessLowestCapAllowed + ", pollingWindowMillis: " + pollingWindowMillis + ", customAnimationRateSec: " + customAnimationRateSec + ", pollingWindowMaxMillis: " + pollingWindowMaxMillis + ", pollingWindowMinMillis: " + pollingWindowMinMillis + "} "; } } Loading
services/core/java/com/android/server/display/DisplayPowerController.java +4 −3 Original line number Diff line number Diff line Loading @@ -591,7 +591,8 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call mThermalBrightnessThrottlingDataId, logicalDisplay.getPowerThrottlingDataIdLocked(), mDisplayDeviceConfig, displayDeviceInfo.width, displayDeviceInfo.height, displayToken, mDisplayId), mContext, flags, mSensorManager); displayToken, mDisplayId), mContext, flags, mSensorManager, mDisplayBrightnessController.getCurrentBrightness()); // Seed the cached brightness saveBrightnessInfo(getScreenBrightnessSetting()); mAutomaticBrightnessStrategy = Loading Loading @@ -3305,10 +3306,10 @@ final class DisplayPowerController implements AutomaticBrightnessController.Call BrightnessClamperController getBrightnessClamperController(Handler handler, BrightnessClamperController.ClamperChangeListener clamperChangeListener, BrightnessClamperController.DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { return new BrightnessClamperController(handler, clamperChangeListener, data, context, flags, sensorManager); flags, sensorManager, currentBrightness); } DisplayWhiteBalanceController getDisplayWhiteBalanceController(Handler handler, Loading
services/core/java/com/android/server/display/brightness/clamper/BrightnessClamperController.java +30 −7 Original line number Diff line number Diff line Loading @@ -75,10 +75,13 @@ public class BrightnessClamperController { private ModifiersAggregatedState mModifiersAggregatedState = new ModifiersAggregatedState(); private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener; private final DisplayManagerFlags mDisplayManagerFlags; private float mBrightnessCap = PowerManager.BRIGHTNESS_MAX; private float mCustomAnimationRate = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; @Nullable private BrightnessPowerClamper mPowerClamper; @Nullable private Type mClamperType = null; private boolean mClamperApplied = false; Loading @@ -93,16 +96,18 @@ public class BrightnessClamperController { public BrightnessClamperController(Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager); DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { this(new Injector(), handler, clamperChangeListener, data, context, flags, sensorManager, currentBrightness); } @VisibleForTesting BrightnessClamperController(Injector injector, Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, Context context, DisplayManagerFlags flags, SensorManager sensorManager) { DisplayManagerFlags flags, SensorManager sensorManager, float currentBrightness) { mDeviceConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler = handler; mDisplayManagerFlags = flags; mLightSensorController = injector.getLightSensorController(sensorManager, context, mLightSensorListener, mHandler); Loading @@ -117,7 +122,15 @@ public class BrightnessClamperController { }; mClampers = injector.getClampers(handler, clamperChangeListenerInternal, data, flags, context); context, currentBrightness); if (mDisplayManagerFlags.isPowerThrottlingClamperEnabled()) { for (BrightnessClamper clamper: mClampers) { if (clamper.getType() == Type.POWER) { mPowerClamper = (BrightnessPowerClamper) clamper; break; } } } mModifiers = injector.getModifiers(flags, context, handler, clamperChangeListener, data); Loading Loading @@ -183,6 +196,12 @@ public class BrightnessClamperController { mModifiers.get(i).apply(request, builder); } if (mDisplayManagerFlags.isPowerThrottlingClamperEnabled()) { if (mPowerClamper != null) { mPowerClamper.updateCurrentBrightness(cappedBrightness); } } return builder.build(); } Loading Loading @@ -312,13 +331,17 @@ public class BrightnessClamperController { List<BrightnessClamper<? super DisplayDeviceData>> getClampers(Handler handler, ClamperChangeListener clamperChangeListener, DisplayDeviceData data, DisplayManagerFlags flags, Context context) { DisplayManagerFlags flags, Context context, float currentBrightness) { List<BrightnessClamper<? super DisplayDeviceData>> clampers = new ArrayList<>(); clampers.add( new BrightnessThermalClamper(handler, clamperChangeListener, data)); if (flags.isPowerThrottlingClamperEnabled()) { // Check if power-throttling config is present. PowerThrottlingConfigData configData = data.getPowerThrottlingConfigData(); if (configData != null) { clampers.add(new BrightnessPowerClamper(handler, clamperChangeListener, data)); data, currentBrightness)); } } if (flags.isBrightnessWearBedtimeModeClamperEnabled()) { clampers.add(new BrightnessWearBedtimeModeClamper(handler, context, Loading
services/core/java/com/android/server/display/brightness/clamper/BrightnessPowerClamper.java +209 −28 Original line number Diff line number Diff line Loading @@ -21,16 +21,23 @@ import static com.android.server.display.brightness.clamper.BrightnessClamperCon import android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.Handler; import android.os.IThermalEventListener; import android.os.IThermalService; import android.os.PowerManager; import android.os.RemoteException; import android.os.ServiceManager; import android.os.Temperature; import android.provider.DeviceConfigInterface; import android.util.Slog; import com.android.internal.annotations.VisibleForTesting; import com.android.server.display.DisplayBrightnessState; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingConfigData; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingData; import com.android.server.display.DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel; import com.android.server.display.brightness.BrightnessUtils; import com.android.server.display.feature.DeviceConfigParameterProvider; import com.android.server.display.utils.DeviceConfigParsingUtils; Loading Loading @@ -65,14 +72,21 @@ class BrightnessPowerClamper extends private PowerThrottlingData mPowerThrottlingDataActive = null; @Nullable private PowerThrottlingConfigData mPowerThrottlingConfigData = null; @NonNull private final ThermalLevelListener mThermalLevelListener; @NonNull private final PowerChangeListener mPowerChangeListener; private @Temperature.ThrottlingStatus int mCurrentThermalLevel = Temperature.THROTTLING_NONE; private boolean mCurrentThermalLevelChanged = false; private float mCurrentAvgPowerConsumed = 0; @Nullable private String mUniqueDisplayId = null; @Nullable private String mDataId = null; private float mCurrentBrightness = PowerManager.BRIGHTNESS_INVALID; private float mCustomAnimationRateSec = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; private float mCustomAnimationRateSecDeviceConfig = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; private final BiFunction<String, String, ThrottlingLevel> mDataPointMapper = (key, value) -> { try { int status = DeviceConfigParsingUtils.parseThermalStatus(key); Loading @@ -88,23 +102,41 @@ class BrightnessPowerClamper extends BrightnessPowerClamper(Handler handler, ClamperChangeListener listener, PowerData powerData) { this(new Injector(), handler, listener, powerData); PowerData powerData, float currentBrightness) { this(new Injector(), handler, listener, powerData, currentBrightness); } @VisibleForTesting BrightnessPowerClamper(Injector injector, Handler handler, ClamperChangeListener listener, PowerData powerData) { PowerData powerData, float currentBrightness) { super(handler, listener); mInjector = injector; mConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mCurrentBrightness = currentBrightness; mPowerChangeListener = (powerConsumed, thermalStatus) -> { recalculatePowerQuotaChange(powerConsumed, thermalStatus); }; mPowerThrottlingConfigData = powerData.getPowerThrottlingConfigData(); if (mPowerThrottlingConfigData != null) { mCustomAnimationRateSecDeviceConfig = mPowerThrottlingConfigData.customAnimationRateSec; } mThermalLevelListener = new ThermalLevelListener(handler); mPmicMonitor = mInjector.getPmicMonitor(mPowerChangeListener, mThermalLevelListener.getThermalService(), mPowerThrottlingConfigData.pollingWindowMaxMillis, mPowerThrottlingConfigData.pollingWindowMinMillis); mConfigParameterProvider = injector.getDeviceConfigParameterProvider(); mHandler.post(() -> { setDisplayData(powerData); loadOverrideData(); start(); }); } @VisibleForTesting PowerChangeListener getPowerChangeListener() { return mPowerChangeListener; } @Override Loading @@ -113,6 +145,11 @@ class BrightnessPowerClamper extends return Type.POWER; } @Override float getCustomAnimationRate() { return mCustomAnimationRateSec; } @Override void onDeviceConfigChanged() { mHandler.post(() -> { Loading @@ -134,6 +171,9 @@ class BrightnessPowerClamper extends if (mPmicMonitor != null) { mPmicMonitor.shutdown(); } if (mThermalLevelListener != null) { mThermalLevelListener.stop(); } } /** Loading @@ -144,11 +184,20 @@ class BrightnessPowerClamper extends pw.println(" mCurrentAvgPowerConsumed=" + mCurrentAvgPowerConsumed); pw.println(" mUniqueDisplayId=" + mUniqueDisplayId); pw.println(" mCurrentThermalLevel=" + mCurrentThermalLevel); pw.println(" mCurrentThermalLevelChanged=" + mCurrentThermalLevelChanged); pw.println(" mPowerThrottlingDataFromDDC=" + (mPowerThrottlingDataFromDDC == null ? "null" : mPowerThrottlingDataFromDDC.toString())); mThermalLevelListener.dump(pw); super.dump(pw); } /** * Updates current brightness, for power calculations. */ public void updateCurrentBrightness(float currentBrightness) { mCurrentBrightness = currentBrightness; } private void recalculateActiveData() { if (mUniqueDisplayId == null || mDataId == null) { return; Loading @@ -156,17 +205,11 @@ class BrightnessPowerClamper extends mPowerThrottlingDataActive = mPowerThrottlingDataOverride .getOrDefault(mUniqueDisplayId, Map.of()).getOrDefault(mDataId, mPowerThrottlingDataFromDDC); if (mPowerThrottlingDataActive != null) { if (mPmicMonitor != null) { mPmicMonitor.stop(); mPmicMonitor.start(); } } else { if (mPowerThrottlingDataActive == null) { if (mPmicMonitor != null) { mPmicMonitor.stop(); } } recalculateBrightnessCap(); } private void loadOverrideData() { Loading Loading @@ -198,21 +241,57 @@ class BrightnessPowerClamper extends if (mPowerThrottlingDataActive == null) { return; } if (powerQuota > 0 && mCurrentAvgPowerConsumed > powerQuota) { if (powerQuota > 0) { if (BrightnessUtils.isValidBrightnessValue(mCurrentBrightness) && (mCurrentAvgPowerConsumed > powerQuota)) { isActive = true; // calculate new brightness Cap. // Brightness has a linear relation to power-consumed. targetBrightnessCap = (powerQuota / mCurrentAvgPowerConsumed) * PowerManager.BRIGHTNESS_MAX; (powerQuota / mCurrentAvgPowerConsumed) * mCurrentBrightness; } else if (mCurrentThermalLevelChanged) { if (mCurrentThermalLevel == Temperature.THROTTLING_NONE) { // reset pmic and remove the power-throttling cap. isActive = true; targetBrightnessCap = PowerManager.BRIGHTNESS_MAX; mPmicMonitor.stop(); } else { isActive = true; // Since the thermal status has changed, we need to remove power-throttling cap. // Instead of recalculating and changing brightness again, adding flicker, // we will wait for the next pmic cycle to re-evaluate this value // make act on it, if needed. targetBrightnessCap = PowerManager.BRIGHTNESS_MAX; if (mPmicMonitor.isStopped()) { mPmicMonitor.start(); } } } else { // Current power consumed is under the quota. isActive = true; targetBrightnessCap = PowerManager.BRIGHTNESS_MAX; } } // Cap to lowest allowed brightness on device. if (mPowerThrottlingConfigData != null) { targetBrightnessCap = Math.max(targetBrightnessCap, mPowerThrottlingConfigData.brightnessLowestCapAllowed); } if (mBrightnessCap != targetBrightnessCap || mIsActive != isActive) { mIsActive = isActive; Slog.i(TAG, "Power clamper changing current brightness cap mBrightnessCap: " + mBrightnessCap + " to target brightness cap:" + targetBrightnessCap + " for current screen brightness: " + mCurrentBrightness); mBrightnessCap = targetBrightnessCap; Slog.i(TAG, "Power clamper changed state: thermalStatus:" + mCurrentThermalLevel + " mCurrentThermalLevelChanged:" + mCurrentThermalLevelChanged + " mCurrentAvgPowerConsumed:" + mCurrentAvgPowerConsumed + " mCustomAnimationRateSec:" + mCustomAnimationRateSecDeviceConfig); mCustomAnimationRateSec = mCustomAnimationRateSecDeviceConfig; mChangeListener.onChanged(); } else { mCustomAnimationRateSec = DisplayBrightnessState.CUSTOM_ANIMATION_RATE_NOT_SET; } } Loading @@ -234,6 +313,11 @@ class BrightnessPowerClamper extends private void recalculatePowerQuotaChange(float avgPowerConsumed, int thermalStatus) { mHandler.post(() -> { if (mCurrentThermalLevel != thermalStatus) { mCurrentThermalLevelChanged = true; } else { mCurrentThermalLevelChanged = false; } mCurrentThermalLevel = thermalStatus; mCurrentAvgPowerConsumed = avgPowerConsumed; recalculateBrightnessCap(); Loading @@ -244,14 +328,107 @@ class BrightnessPowerClamper extends if (mPowerThrottlingConfigData == null) { return; } PowerChangeListener listener = (powerConsumed, thermalStatus) -> { recalculatePowerQuotaChange(powerConsumed, thermalStatus); }; mPmicMonitor = mInjector.getPmicMonitor(listener, mPowerThrottlingConfigData.pollingWindowMillis); if (mPowerThrottlingConfigData.pollingWindowMaxMillis <= mPowerThrottlingConfigData.pollingWindowMinMillis) { Slog.e(TAG, "Brightness power max polling window:" + mPowerThrottlingConfigData.pollingWindowMaxMillis + " msec, should be greater than brightness min polling window:" + mPowerThrottlingConfigData.pollingWindowMinMillis + " msec."); return; } if ((mPowerThrottlingConfigData.pollingWindowMaxMillis % mPowerThrottlingConfigData.pollingWindowMinMillis) != 0) { Slog.e(TAG, "Brightness power max polling window:" + mPowerThrottlingConfigData.pollingWindowMaxMillis + " msec, is not divisible by brightness min polling window:" + mPowerThrottlingConfigData.pollingWindowMinMillis + " msec."); return; } mCustomAnimationRateSecDeviceConfig = mPowerThrottlingConfigData.customAnimationRateSec; mThermalLevelListener.start(); } private void activatePmicMonitor() { if (!mPmicMonitor.isStopped()) { return; } mPmicMonitor.start(); } private void deactivatePmicMonitor(@Temperature.ThrottlingStatus int status) { if (status != Temperature.THROTTLING_NONE) { return; } if (mPmicMonitor.isStopped()) { return; } mPmicMonitor.stop(); } private final class ThermalLevelListener extends IThermalEventListener.Stub { private final Handler mHandler; private IThermalService mThermalService; private boolean mStarted; ThermalLevelListener(Handler handler) { mHandler = handler; mStarted = false; mThermalService = IThermalService.Stub.asInterface( ServiceManager.getService(Context.THERMAL_SERVICE)); } IThermalService getThermalService() { return mThermalService; } void start() { if (mStarted) { return; } if (mThermalService == null) { return; } try { // TODO b/279114539 Try DISPLAY first and then fallback to SKIN. mThermalService.registerThermalEventListenerWithType(this, Temperature.TYPE_SKIN); mStarted = true; } catch (RemoteException e) { Slog.e(TAG, "Failed to register thermal status listener", e); } } @Override public void notifyThrottling(Temperature temp) { @Temperature.ThrottlingStatus int status = temp.getStatus(); if (status >= Temperature.THROTTLING_LIGHT) { Slog.d(TAG, "Activating pmic monitor due to thermal state:" + status); mHandler.post(() -> activatePmicMonitor()); } else { if (!mPmicMonitor.isStopped()) { mHandler.post(() -> deactivatePmicMonitor(status)); } } } void stop() { if (!mStarted) { return; } try { mThermalService.unregisterThermalEventListener(this); mStarted = false; } catch (RemoteException e) { Slog.e(TAG, "Failed to unregister thermal status listener", e); } mThermalService = null; } void dump(PrintWriter writer) { writer.println(" ThermalLevelObserver:"); writer.println(" mStarted: " + mStarted); } } public interface PowerData { @NonNull String getUniqueDisplayId(); Loading Loading @@ -279,8 +456,12 @@ class BrightnessPowerClamper extends @VisibleForTesting static class Injector { PmicMonitor getPmicMonitor(PowerChangeListener listener, int pollingTime) { return new PmicMonitor(listener, pollingTime); PmicMonitor getPmicMonitor(PowerChangeListener powerChangeListener, IThermalService thermalService, int pollingMaxTimeMillis, int pollingMinTimeMillis) { return new PmicMonitor(powerChangeListener, thermalService, pollingMaxTimeMillis, pollingMinTimeMillis); } DeviceConfigParameterProvider getDeviceConfigParameterProvider() { Loading
services/core/java/com/android/server/display/brightness/clamper/PmicMonitor.java +54 −19 File changed.Preview size limit exceeded, changes collapsed. Show changes