[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
diff --git a/services/core/java/com/android/server/display/DisplayDeviceConfig.java b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
index 9e92c8d..cfbe0c6 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceConfig.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceConfig.java
@@ -60,6 +60,9 @@
 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 @@
  *      </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 @@
     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 @@
     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 @@
         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;
@@ -1491,6 +1531,14 @@
     }
 
     /**
+     * @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
      */
     public long getAutoBrightnessDarkeningLightDebounce() {
@@ -1702,6 +1750,9 @@
                 + ", mThermalBrightnessThrottlingDataMapByThrottlingId="
                 + mThermalBrightnessThrottlingDataMapByThrottlingId
                 + "\n"
+                + ", mPowerThrottlingDataMapByThrottlingId="
+                + mPowerThrottlingDataMapByThrottlingId
+                + "\n"
                 + "mBrightnessRampFastDecrease=" + mBrightnessRampFastDecrease
                 + ", mBrightnessRampFastIncrease=" + mBrightnessRampFastIncrease
                 + ", mBrightnessRampSlowDecrease=" + mBrightnessRampSlowDecrease
@@ -1853,6 +1904,7 @@
                 loadBrightnessConstraintsFromConfigXml();
                 loadBrightnessMap(config);
                 loadThermalThrottlingConfig(config);
+                loadPowerThrottlingConfigData(config);
                 loadHighBrightnessModeData(config);
                 loadLuxThrottling(config);
                 loadQuirks(config);
@@ -2171,6 +2223,59 @@
         }
     }
 
+    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();
@@ -3379,6 +3484,148 @@
     }
 
     /**
+     * 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.
      */
     public static class ThermalBrightnessThrottlingData {
diff --git a/services/core/xsd/display-device-config/display-device-config.xsd b/services/core/xsd/display-device-config/display-device-config.xsd
index d0a9c45..debd891 100644
--- a/services/core/xsd/display-device-config/display-device-config.xsd
+++ b/services/core/xsd/display-device-config/display-device-config.xsd
@@ -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">
diff --git a/services/core/xsd/display-device-config/schema/current.txt b/services/core/xsd/display-device-config/schema/current.txt
index 949b1f2..2d27f0c 100644
--- a/services/core/xsd/display-device-config/schema/current.txt
+++ b/services/core/xsd/display-device-config/schema/current.txt
@@ -106,6 +106,7 @@
     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 @@
     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 @@
     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;
diff --git a/services/core/xsd/display-layout-config/display-layout-config.xsd b/services/core/xsd/display-layout-config/display-layout-config.xsd
index 57b5d00..4e95465 100644
--- a/services/core/xsd/display-layout-config/display-layout-config.xsd
+++ b/services/core/xsd/display-layout-config/display-layout-config.xsd
@@ -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>
diff --git a/services/core/xsd/display-layout-config/schema/current.txt b/services/core/xsd/display-layout-config/schema/current.txt
index 2d4f7a4..195cae5 100644
--- a/services/core/xsd/display-layout-config/schema/current.txt
+++ b/services/core/xsd/display-layout-config/schema/current.txt
@@ -8,6 +8,7 @@
     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 @@
     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);
   }
diff --git a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
index 6ef150c..c37d21a 100644
--- a/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
+++ b/services/tests/displayservicetests/src/com/android/server/display/DisplayDeviceConfigTest.java
@@ -179,6 +179,89 @@
     }
 
     @Test
+    public void testPowerThrottlingConfigFromDisplayConfig() throws IOException {
+        setupDisplayDeviceConfigFromDisplayConfigFile();
+
+        DisplayDeviceConfig.PowerThrottlingConfigData powerThrottlingConfigData =
+                mDisplayDeviceConfig.getPowerThrottlingConfigData();
+        assertNotNull(powerThrottlingConfigData);
+        assertEquals(0.1f, powerThrottlingConfigData.brightnessLowestCapAllowed, SMALL_DELTA);
+        assertEquals(10, powerThrottlingConfigData.pollingWindowMillis);
+    }
+
+    @Test
+    public void testPowerThrottlingDataFromDisplayConfig() throws IOException {
+        setupDisplayDeviceConfigFromDisplayConfigFile();
+
+        List<DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel>
+                defaultThrottlingLevels = new ArrayList<>();
+        defaultThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.light), 800f
+                ));
+        defaultThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.moderate), 600f
+                ));
+        defaultThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.severe), 400f
+                ));
+        defaultThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.critical), 200f
+                ));
+        defaultThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.emergency), 100f
+                ));
+        defaultThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 50f
+                ));
+
+        DisplayDeviceConfig.PowerThrottlingData defaultThrottlingData =
+                new DisplayDeviceConfig.PowerThrottlingData(defaultThrottlingLevels);
+
+        List<DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel>
+                concurrentThrottlingLevels = new ArrayList<>();
+        concurrentThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.light), 800f
+                ));
+        concurrentThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.moderate), 600f
+                ));
+        concurrentThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.severe), 400f
+                ));
+        concurrentThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.critical), 200f
+                ));
+        concurrentThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.emergency), 100f
+                ));
+        concurrentThrottlingLevels.add(
+                new DisplayDeviceConfig.PowerThrottlingData.ThrottlingLevel(
+                        DisplayDeviceConfig.convertThermalStatus(ThermalStatus.shutdown), 50f
+                ));
+        DisplayDeviceConfig.PowerThrottlingData concurrentThrottlingData =
+                new DisplayDeviceConfig.PowerThrottlingData(concurrentThrottlingLevels);
+
+        HashMap<String, DisplayDeviceConfig.PowerThrottlingData> throttlingDataMap =
+                new HashMap<>(2);
+        throttlingDataMap.put("default", defaultThrottlingData);
+        throttlingDataMap.put("concurrent", concurrentThrottlingData);
+
+        assertEquals(throttlingDataMap,
+                mDisplayDeviceConfig.getPowerThrottlingDataMapByThrottlingId());
+    }
+
+    @Test
     public void testConfigValuesFromConfigResource() {
         setupDisplayDeviceConfigFromConfigResourceFile();
         verifyConfigValuesFromConfigResource();
@@ -845,6 +928,64 @@
                 +   "</screenBrightnessRampSlowIncreaseIdle>\n";
     }
 
+    private String getPowerThrottlingConfig() {
+        return  "<powerThrottlingConfig >\n"
+                +       "<brightnessLowestCapAllowed>0.1</brightnessLowestCapAllowed>\n"
+                +       "<pollingWindowMillis>10</pollingWindowMillis>\n"
+                +       "<powerThrottlingMap>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>light</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>800</powerQuotaMilliWatts>\n"
+                +        "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>moderate</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>600</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>severe</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>400</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>critical</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>200</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>emergency</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>100</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>shutdown</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>50</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +       "</powerThrottlingMap>\n"
+                +       "<powerThrottlingMap id=\"concurrent\">\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>light</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>800</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>moderate</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>600</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>severe</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>400</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>critical</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>200</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>emergency</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>100</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +           "<powerThrottlingPoint>\n"
+                +               "<thermalStatus>shutdown</thermalStatus>\n"
+                +               "<powerQuotaMilliWatts>50</powerQuotaMilliWatts>\n"
+                +           "</powerThrottlingPoint>\n"
+                +       "</powerThrottlingMap>\n"
+                +   "</powerThrottlingConfig>\n";
+    }
     private String getScreenBrightnessRampCapsIdle() {
         return "<screenBrightnessRampIncreaseMaxIdleMillis>"
                 +       "4000"
@@ -915,6 +1056,7 @@
                 +            "</displayBrightnessPoint>\n"
                 +       "</displayBrightnessMapping>\n"
                 +   "</autoBrightness>\n"
+                +  getPowerThrottlingConfig()
                 +   "<highBrightnessMode enabled=\"true\">\n"
                 +       "<transitionPoint>" + BRIGHTNESS[1] + "</transitionPoint>\n"
                 +       "<minimumLux>10000</minimumLux>\n"