Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3da7ebe5 authored by Manali Bhutiyani's avatar Manali Bhutiyani
Browse files

[power-based-throttling] device config changes.

This change adds the new device config changes needed
for supporting power-based throttling.

This mainly consists of
1. A new map from thermal status -> power quota for display.
2. Power based throttling parameters for finetuning.

Bug: 261221454
Test: Added new tests in DisplayDeviceConfigTest
Change-Id: Ic3c57159f1d99ea91b4061af21dd4f9f6db9b11e
parent 6e2cdc93
Loading
Loading
Loading
Loading
+247 −0
Original line number Diff line number Diff line
@@ -60,6 +60,9 @@ import com.android.server.display.config.LuxThrottling;
import com.android.server.display.config.NitsMap;
import com.android.server.display.config.NonNegativeFloatToFloatPoint;
import com.android.server.display.config.Point;
import com.android.server.display.config.PowerThrottlingConfig;
import com.android.server.display.config.PowerThrottlingMap;
import com.android.server.display.config.PowerThrottlingPoint;
import com.android.server.display.config.PredefinedBrightnessLimitNames;
import com.android.server.display.config.RefreshRateConfigs;
import com.android.server.display.config.RefreshRateRange;
@@ -139,6 +142,30 @@ import javax.xml.datatype.DatatypeConfigurationException;
 *      </screenBrightnessMap>
 *
 *      <screenBrightnessDefault>0.65</screenBrightnessDefault>
 *      <powerThrottlingConfig>
 *        <brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed>
 *        <pollingWindowMillis>15</pollingWindowMillis>
 *          <powerThrottlingMap>
 *              <powerThrottlingPoint>
 *                  <thermalStatus>severe</thermalStatus>
 *                  <powerQuotaMilliWatts>200.6</powerQuotaMilliWatts>
 *              </powerThrottlingPoint>
 *              <powerThrottlingPoint>
 *                  <thermalStatus>critical</thermalStatus>
 *                  <powerQuotaMilliWatts>300</powerQuotaMilliWatts>
 *              </powerThrottlingPoint>
 *          </powerThrottlingMap>
 *          <powerThrottlingMap id="id_2"> // optional attribute, leave blank for default
 *             <powerThrottlingPoint>
 *                 <thermalStatus>moderate</thermalStatus>
 *                 <powerQuotaMilliWatts>400</powerQuotaMilliWatts>
 *             </powerThrottlingPoint>
 *             <powerThrottlingPoint>
 *                 <thermalStatus>severe</thermalStatus>
 *                 <powerQuotaMilliWatts>250</powerQuotaMilliWatts>
 *            </powerThrottlingPoint>
 *          </powerThrottlingMap>
 *      </powerThrottlingConfig>
 *
 *      <thermalThrottling>
 *        <brightnessThrottlingMap>
@@ -669,6 +696,8 @@ public class DisplayDeviceConfig {
    private List<String> mQuirks;
    private boolean mIsHighBrightnessModeEnabled = false;
    private HighBrightnessModeData mHbmData;
    @Nullable
    private PowerThrottlingConfigData mPowerThrottlingConfigData;
    private DensityMapping mDensityMapping;
    private String mLoadedFrom = null;
    private Spline mSdrToHdrRatioSpline;
@@ -781,6 +810,9 @@ public class DisplayDeviceConfig {
    private final HashMap<String, ThermalBrightnessThrottlingData>
            mThermalBrightnessThrottlingDataMapByThrottlingId = new HashMap<>();

    private final HashMap<String, PowerThrottlingData>
            mPowerThrottlingDataMapByThrottlingId = new HashMap<>();

    private final Map<String, SparseArray<SurfaceControl.RefreshRateRange>>
            mRefreshRateThrottlingMap = new HashMap<>();

@@ -1458,6 +1490,14 @@ public class DisplayDeviceConfig {
        return hbmData;
    }

    /**
     * @return Power throttling configuration data for the display.
     */
    @Nullable
    public PowerThrottlingConfigData getPowerThrottlingConfigData() {
        return mPowerThrottlingConfigData;
    }

    @NonNull
    public Map<BrightnessLimitMapType, Map<Float, Float>> getLuxThrottlingData() {
        return mLuxThrottlingData;
@@ -1490,6 +1530,14 @@ public class DisplayDeviceConfig {
        return mRefreshRateThrottlingMap.get(key);
    }

    /**
     * @return power throttling configuration data for this display, for each throttling id.
     **/
    public HashMap<String, PowerThrottlingData>
            getPowerThrottlingDataMapByThrottlingId() {
        return mPowerThrottlingDataMapByThrottlingId;
    }

    /**
     * @return Auto brightness darkening light debounce
     */
@@ -1702,6 +1750,9 @@ public class DisplayDeviceConfig {
                + ", mThermalBrightnessThrottlingDataMapByThrottlingId="
                + mThermalBrightnessThrottlingDataMapByThrottlingId
                + "\n"
                + ", mPowerThrottlingDataMapByThrottlingId="
                + mPowerThrottlingDataMapByThrottlingId
                + "\n"
                + "mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
                + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
                + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -1853,6 +1904,7 @@ public class DisplayDeviceConfig {
                loadBrightnessConstraintsFromConfigXml();
                loadBrightnessMap(config);
                loadThermalThrottlingConfig(config);
                loadPowerThrottlingConfigData(config);
                loadHighBrightnessModeData(config);
                loadLuxThrottling(config);
                loadQuirks(config);
@@ -2171,6 +2223,59 @@ public class DisplayDeviceConfig {
        }
    }

    private boolean loadPowerThrottlingMaps(PowerThrottlingConfig throttlingConfig) {
        final List<PowerThrottlingMap> maps = throttlingConfig.getPowerThrottlingMap();
        if (maps == null || maps.isEmpty()) {
            Slog.i(TAG, "No power throttling map found");
            return false;
        }

        for (PowerThrottlingMap map : maps) {
            final List<PowerThrottlingPoint> points = map.getPowerThrottlingPoint();
            // At least 1 point is guaranteed by the display device config schema
            List<PowerThrottlingData.ThrottlingLevel> throttlingLevels =
                    new ArrayList<>(points.size());

            boolean badConfig = false;
            for (PowerThrottlingPoint point : points) {
                ThermalStatus status = point.getThermalStatus();
                if (!thermalStatusIsValid(status)) {
                    badConfig = true;
                    break;
                }

                throttlingLevels.add(new PowerThrottlingData.ThrottlingLevel(
                        convertThermalStatus(status),
                            point.getPowerQuotaMilliWatts().floatValue()));
            }

            if (!badConfig) {
                String id = map.getId() == null ? DEFAULT_ID : map.getId();
                if (mPowerThrottlingDataMapByThrottlingId.containsKey(id)) {
                    throw new RuntimeException("Power throttling data with ID " + id
                            + " already exists");
                }
                mPowerThrottlingDataMapByThrottlingId.put(id,
                        PowerThrottlingData.create(throttlingLevels));
            }
        }
        return true;
    }

    private void loadPowerThrottlingConfigData(DisplayConfiguration config) {
        final PowerThrottlingConfig powerThrottlingCfg = config.getPowerThrottlingConfig();
        if (powerThrottlingCfg == null) {
            return;
        }
        if (!loadPowerThrottlingMaps(powerThrottlingCfg)) {
            return;
        }
        float lowestBrightnessCap = powerThrottlingCfg.getBrightnessLowestCapAllowed().floatValue();
        int pollingWindowMillis = powerThrottlingCfg.getPollingWindowMillis().intValue();
        mPowerThrottlingConfigData = new PowerThrottlingConfigData(lowestBrightnessCap,
                                                                   pollingWindowMillis);
    }

    private void loadRefreshRateSetting(DisplayConfiguration config) {
        final RefreshRateConfigs refreshRateConfigs =
                (config == null) ? null : config.getRefreshRate();
@@ -3378,6 +3483,148 @@ public class DisplayDeviceConfig {
        }
    }

    /**
     * Container for Power throttling configuration data.
     * TODO(b/302814899): extract to separate class.
     */
    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;
        public PowerThrottlingConfigData(float brightnessLowestCapAllowed,
                int pollingWindowMillis) {
            this.brightnessLowestCapAllowed = brightnessLowestCapAllowed;
            this.pollingWindowMillis = pollingWindowMillis;
        }

        @Override
        public String toString() {
            return "PowerThrottlingConfigData{"
                    + "brightnessLowestCapAllowed: "
                    + brightnessLowestCapAllowed
                    + ", pollingWindowMillis: " + pollingWindowMillis
                    + "} ";
        }
    }

    /**
     * Container for power throttling data.
     * TODO(b/302814899): extract to separate class and unify with ThermalBrightnessThrottlingData.
     */
    public static class PowerThrottlingData {
        public List<ThrottlingLevel> throttlingLevels;

        /**
         * thermal status to power quota mapping.
         */
        public static class ThrottlingLevel {
            public @PowerManager.ThermalStatus int thermalStatus;
            public float powerQuotaMilliWatts;

            public ThrottlingLevel(
                    @PowerManager.ThermalStatus int thermalStatus, float powerQuotaMilliWatts) {
                this.thermalStatus = thermalStatus;
                this.powerQuotaMilliWatts = powerQuotaMilliWatts;
            }

            @Override
            public String toString() {
                return "[" + thermalStatus + "," + powerQuotaMilliWatts + "]";
            }

            @Override
            public boolean equals(Object obj) {
                if (!(obj instanceof ThrottlingLevel)) {
                    return false;
                }
                ThrottlingLevel otherThrottlingLevel = (ThrottlingLevel) obj;

                return otherThrottlingLevel.thermalStatus == this.thermalStatus
                        && otherThrottlingLevel.powerQuotaMilliWatts == this.powerQuotaMilliWatts;
            }

            @Override
            public int hashCode() {
                int result = 1;
                result = 31 * result + thermalStatus;
                result = 31 * result + Float.hashCode(powerQuotaMilliWatts);
                return result;
            }
        }


        /**
         * Creates multiple temperature based throttling levels of power quota.
         */
        public static PowerThrottlingData create(
                List<ThrottlingLevel> throttlingLevels) {
            if (throttlingLevels == null || throttlingLevels.size() == 0) {
                Slog.e(TAG, "PowerThrottlingData received null or empty throttling levels");
                return null;
            }

            ThrottlingLevel prevLevel = throttlingLevels.get(0);
            final int numLevels = throttlingLevels.size();
            for (int i = 1; i < numLevels; i++) {
                ThrottlingLevel thisLevel = throttlingLevels.get(i);

                if (thisLevel.thermalStatus <= prevLevel.thermalStatus) {
                    Slog.e(TAG, "powerThrottlingMap must be strictly increasing, ignoring "
                            + "configuration. ThermalStatus " + thisLevel.thermalStatus + " <= "
                            + prevLevel.thermalStatus);
                    return null;
                }

                if (thisLevel.powerQuotaMilliWatts >= prevLevel.powerQuotaMilliWatts) {
                    Slog.e(TAG, "powerThrottlingMap must be strictly decreasing, ignoring "
                            + "configuration. powerQuotaMilliWatts "
                            + thisLevel.powerQuotaMilliWatts + " >= "
                            + prevLevel.powerQuotaMilliWatts);
                    return null;
                }

                prevLevel = thisLevel;
            }
            return new PowerThrottlingData(throttlingLevels);
        }

        @Override
        public String toString() {
            return "PowerThrottlingData{"
                    + "throttlingLevels:" + throttlingLevels
                    + "} ";
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }

            if (!(obj instanceof PowerThrottlingData)) {
                return false;
            }

            PowerThrottlingData otherData = (PowerThrottlingData) obj;
            return throttlingLevels.equals(otherData.throttlingLevels);
        }

        @Override
        public int hashCode() {
            return throttlingLevels.hashCode();
        }

        @VisibleForTesting
        PowerThrottlingData(List<ThrottlingLevel> inLevels) {
            throttlingLevels = new ArrayList<>(inLevels.size());
            for (ThrottlingLevel level : inLevels) {
                throttlingLevels.add(new ThrottlingLevel(level.thermalStatus,
                        level.powerQuotaMilliWatts));
            }
        }
    }

    /**
     * Container for brightness throttling data.
     */
+39 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@
                    <xs:annotation name="nonnull"/>
                    <xs:annotation name="final"/>
                </xs:element>
                <xs:element type="powerThrottlingConfig" name="powerThrottlingConfig" minOccurs="0"
                            maxOccurs="1"/>
                <xs:element type="luxThrottling" name="luxThrottling" minOccurs="0"
                            maxOccurs="1"/>
                <xs:element type="highBrightnessMode" name="highBrightnessMode" minOccurs="0"
@@ -350,6 +352,43 @@
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="powerThrottlingMap">
        <xs:sequence>
            <xs:element name="powerThrottlingPoint" type="powerThrottlingPoint" maxOccurs="unbounded" minOccurs="1">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
        </xs:sequence>
        <xs:attribute name="id" type="xs:string"/>
    </xs:complexType>

    <xs:complexType name="powerThrottlingPoint">
        <xs:sequence>
            <xs:element type="thermalStatus" name="thermalStatus">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
            <xs:element type="nonNegativeDecimal" name="powerQuotaMilliWatts">
                <xs:annotation name="nonnull"/>
                <xs:annotation name="final"/>
            </xs:element>
        </xs:sequence>
    </xs:complexType>

    <xs:complexType name="powerThrottlingConfig">
        <xs:element type="nonNegativeDecimal" name="brightnessLowestCapAllowed">
            <xs:annotation name="nonnull"/>
            <xs:annotation name="final"/>
        </xs:element>
        <xs:element name="pollingWindowMillis" type="xs:nonNegativeInteger">
            <xs:annotation name="nonnull"/>
            <xs:annotation name="final"/>
        </xs:element>
        <xs:element type="powerThrottlingMap" name="powerThrottlingMap" maxOccurs="unbounded">
                <xs:annotation name="final"/>
        </xs:element>
    </xs:complexType>

    <xs:complexType name="nitsMap">
        <xs:sequence>
            <xs:element name="point" type="point" maxOccurs="unbounded" minOccurs="2">
+26 −0
Original line number Diff line number Diff line
@@ -106,6 +106,7 @@ package com.android.server.display.config {
    method public final com.android.server.display.config.SensorDetails getLightSensor();
    method public com.android.server.display.config.LuxThrottling getLuxThrottling();
    method @Nullable public final String getName();
    method public com.android.server.display.config.PowerThrottlingConfig getPowerThrottlingConfig();
    method public final com.android.server.display.config.SensorDetails getProxSensor();
    method public com.android.server.display.config.DisplayQuirks getQuirks();
    method public com.android.server.display.config.RefreshRateConfigs getRefreshRate();
@@ -138,6 +139,7 @@ package com.android.server.display.config {
    method public final void setLightSensor(com.android.server.display.config.SensorDetails);
    method public void setLuxThrottling(com.android.server.display.config.LuxThrottling);
    method public final void setName(@Nullable String);
    method public void setPowerThrottlingConfig(com.android.server.display.config.PowerThrottlingConfig);
    method public final void setProxSensor(com.android.server.display.config.SensorDetails);
    method public void setQuirks(com.android.server.display.config.DisplayQuirks);
    method public void setRefreshRate(com.android.server.display.config.RefreshRateConfigs);
@@ -246,6 +248,30 @@ package com.android.server.display.config {
    method public final void setValue(@NonNull java.math.BigDecimal);
  }

  public class PowerThrottlingConfig {
    ctor public PowerThrottlingConfig();
    method @NonNull public final java.math.BigDecimal getBrightnessLowestCapAllowed();
    method @NonNull public final java.math.BigInteger getPollingWindowMillis();
    method public final java.util.List<com.android.server.display.config.PowerThrottlingMap> getPowerThrottlingMap();
    method public final void setBrightnessLowestCapAllowed(@NonNull java.math.BigDecimal);
    method public final void setPollingWindowMillis(@NonNull java.math.BigInteger);
  }

  public class PowerThrottlingMap {
    ctor public PowerThrottlingMap();
    method public String getId();
    method @NonNull public final java.util.List<com.android.server.display.config.PowerThrottlingPoint> getPowerThrottlingPoint();
    method public void setId(String);
  }

  public class PowerThrottlingPoint {
    ctor public PowerThrottlingPoint();
    method @NonNull public final java.math.BigDecimal getPowerQuotaMilliWatts();
    method @NonNull public final com.android.server.display.config.ThermalStatus getThermalStatus();
    method public final void setPowerQuotaMilliWatts(@NonNull java.math.BigDecimal);
    method public final void setThermalStatus(@NonNull com.android.server.display.config.ThermalStatus);
  }

  public enum PredefinedBrightnessLimitNames {
    method public String getRawName();
    enum_constant public static final com.android.server.display.config.PredefinedBrightnessLimitNames _default;
+1 −0
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@
            <xs:element name="address" type="xs:nonNegativeInteger"/>
            <xs:element name="position" type="xs:string" minOccurs="0" maxOccurs="1" />
            <xs:element name="brightnessThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
            <xs:element name="powerThrottlingMapId" type="xs:string" minOccurs="0" maxOccurs="1" />
            <xs:element name="refreshRateThermalThrottlingMapId" type="xs:string" minOccurs="0" />
            <xs:element name="leadDisplayAddress" type="xs:nonNegativeInteger" minOccurs="0" maxOccurs="1" />
        </xs:sequence>
+2 −0
Original line number Diff line number Diff line
@@ -8,6 +8,7 @@ package com.android.server.display.config.layout {
    method public String getDisplayGroup();
    method public java.math.BigInteger getLeadDisplayAddress();
    method public String getPosition();
    method public String getPowerThrottlingMapId();
    method public String getRefreshRateThermalThrottlingMapId();
    method public String getRefreshRateZoneId();
    method public boolean isDefaultDisplay();
@@ -19,6 +20,7 @@ package com.android.server.display.config.layout {
    method public void setEnabled(boolean);
    method public void setLeadDisplayAddress(java.math.BigInteger);
    method public void setPosition(String);
    method public void setPowerThrottlingMapId(String);
    method public void setRefreshRateThermalThrottlingMapId(String);
    method public void setRefreshRateZoneId(String);
  }
Loading