Update PowerProfile to support multidisplay devices
Replaced the display related power constants with new ones that support multidisply. The legacy constants are marked as UnsupportedAppUsage, so they have not been removed yet and they attempting to read them will return the power constant values for the first display. Fixes: 200226329 Test: atest com.android.internal.os.PowerProfileTest#testPowerProfile Test: atest FrameworksCoreTests:com.android.internal.os.BatteryStatsTests Change-Id: Id181443bd6f553ee37fc4a1647d31644fcad7912
This commit is contained in:
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_AMBIENT;
|
||||
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryUsageStats;
|
||||
@@ -32,8 +34,9 @@ public class AmbientDisplayPowerCalculator extends PowerCalculator {
|
||||
private final UsageBasedPowerEstimator mPowerEstimator;
|
||||
|
||||
public AmbientDisplayPowerCalculator(PowerProfile powerProfile) {
|
||||
// TODO(b/200239964): update to support multidisplay.
|
||||
mPowerEstimator = new UsageBasedPowerEstimator(
|
||||
powerProfile.getAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY));
|
||||
powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 0));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,10 +17,12 @@
|
||||
package com.android.internal.os;
|
||||
|
||||
|
||||
import android.annotation.StringDef;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.XmlResourceParser;
|
||||
import android.util.Slog;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -30,6 +32,8 @@ import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
||||
@@ -40,6 +44,8 @@ import java.util.HashMap;
|
||||
*/
|
||||
public class PowerProfile {
|
||||
|
||||
public static final String TAG = "PowerProfile";
|
||||
|
||||
/*
|
||||
* POWER_CPU_SUSPEND: Power consumption when CPU is in power collapse mode.
|
||||
* POWER_CPU_IDLE: Power consumption when CPU is awake (when a wake lock is held). This should
|
||||
@@ -145,12 +151,18 @@ public class PowerProfile {
|
||||
|
||||
/**
|
||||
* Power consumption when screen is in doze/ambient/always-on mode, including backlight power.
|
||||
*
|
||||
* @deprecated Use {@link #POWER_GROUP_DISPLAY_AMBIENT} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public static final String POWER_AMBIENT_DISPLAY = "ambient.on";
|
||||
|
||||
/**
|
||||
* Power consumption when screen is on, not including the backlight power.
|
||||
*
|
||||
* @deprecated Use {@link #POWER_GROUP_DISPLAY_SCREEN_ON} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage
|
||||
public static final String POWER_SCREEN_ON = "screen.on";
|
||||
|
||||
@@ -175,7 +187,10 @@ public class PowerProfile {
|
||||
/**
|
||||
* Power consumption at full backlight brightness. If the backlight is at
|
||||
* 50% brightness, then this should be multiplied by 0.5
|
||||
*
|
||||
* @deprecated Use {@link #POWER_GROUP_DISPLAY_SCREEN_FULL} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
@UnsupportedAppUsage
|
||||
public static final String POWER_SCREEN_FULL = "screen.full";
|
||||
|
||||
@@ -220,6 +235,29 @@ public class PowerProfile {
|
||||
*/
|
||||
public static final String POWER_BATTERY_CAPACITY = "battery.capacity";
|
||||
|
||||
/**
|
||||
* Power consumption when a screen is in doze/ambient/always-on mode, including backlight power.
|
||||
*/
|
||||
public static final String POWER_GROUP_DISPLAY_AMBIENT = "ambient.on.display";
|
||||
|
||||
/**
|
||||
* Power consumption when a screen is on, not including the backlight power.
|
||||
*/
|
||||
public static final String POWER_GROUP_DISPLAY_SCREEN_ON = "screen.on.display";
|
||||
|
||||
/**
|
||||
* Power consumption of a screen at full backlight brightness.
|
||||
*/
|
||||
public static final String POWER_GROUP_DISPLAY_SCREEN_FULL = "screen.full.display";
|
||||
|
||||
@StringDef(prefix = { "POWER_GROUP_" }, value = {
|
||||
POWER_GROUP_DISPLAY_AMBIENT,
|
||||
POWER_GROUP_DISPLAY_SCREEN_ON,
|
||||
POWER_GROUP_DISPLAY_SCREEN_FULL,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface PowerGroup {}
|
||||
|
||||
/**
|
||||
* A map from Power Use Item to its power consumption.
|
||||
*/
|
||||
@@ -255,6 +293,7 @@ public class PowerProfile {
|
||||
readPowerValuesFromXml(context, forTest);
|
||||
}
|
||||
initCpuClusters();
|
||||
initDisplays();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +463,58 @@ public class PowerProfile {
|
||||
return 0;
|
||||
}
|
||||
|
||||
private int mNumDisplays;
|
||||
|
||||
private void initDisplays() {
|
||||
// Figure out how many displays are listed in the power profile.
|
||||
mNumDisplays = 0;
|
||||
while (!Double.isNaN(
|
||||
getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, mNumDisplays, Double.NaN))
|
||||
|| !Double.isNaN(
|
||||
getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, mNumDisplays, Double.NaN))
|
||||
|| !Double.isNaN(
|
||||
getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, mNumDisplays,
|
||||
Double.NaN))) {
|
||||
mNumDisplays++;
|
||||
}
|
||||
|
||||
// Handle legacy display power constants.
|
||||
final Double deprecatedAmbientDisplay = sPowerItemMap.get(POWER_AMBIENT_DISPLAY);
|
||||
boolean legacy = false;
|
||||
if (deprecatedAmbientDisplay != null && mNumDisplays == 0) {
|
||||
final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_AMBIENT, 0);
|
||||
Slog.w(TAG, POWER_AMBIENT_DISPLAY + " is deprecated! Use " + key + " instead.");
|
||||
sPowerItemMap.put(key, deprecatedAmbientDisplay);
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
final Double deprecatedScreenOn = sPowerItemMap.get(POWER_SCREEN_ON);
|
||||
if (deprecatedScreenOn != null && mNumDisplays == 0) {
|
||||
final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_SCREEN_ON, 0);
|
||||
Slog.w(TAG, POWER_SCREEN_ON + " is deprecated! Use " + key + " instead.");
|
||||
sPowerItemMap.put(key, deprecatedScreenOn);
|
||||
legacy = true;
|
||||
}
|
||||
|
||||
final Double deprecatedScreenFull = sPowerItemMap.get(POWER_SCREEN_FULL);
|
||||
if (deprecatedScreenFull != null && mNumDisplays == 0) {
|
||||
final String key = getOrdinalPowerType(POWER_GROUP_DISPLAY_SCREEN_FULL, 0);
|
||||
Slog.w(TAG, POWER_SCREEN_FULL + " is deprecated! Use " + key + " instead.");
|
||||
sPowerItemMap.put(key, deprecatedScreenFull);
|
||||
legacy = true;
|
||||
}
|
||||
if (legacy) {
|
||||
mNumDisplays = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number built in displays on the device as defined in the power_profile.xml.
|
||||
*/
|
||||
public int getNumDisplays() {
|
||||
return mNumDisplays;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of memory bandwidth buckets defined in power_profile.xml, or a
|
||||
* default value if the subsystem has no recorded value.
|
||||
@@ -495,6 +586,32 @@ public class PowerProfile {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average current in mA consumed by an ordinaled subsystem, or the given
|
||||
* default value if the subsystem has no recorded value.
|
||||
*
|
||||
* @param group the subsystem {@link PowerGroup}.
|
||||
* @param ordinal which entity in the {@link PowerGroup}.
|
||||
* @param defaultValue the value to return if the subsystem has no recorded value.
|
||||
* @return the average current in milliAmps.
|
||||
*/
|
||||
public double getAveragePowerForOrdinal(@PowerGroup String group, int ordinal,
|
||||
double defaultValue) {
|
||||
final String type = getOrdinalPowerType(group, ordinal);
|
||||
return getAveragePowerOrDefault(type, defaultValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average current in mA consumed by an ordinaled subsystem.
|
||||
*
|
||||
* @param group the subsystem {@link PowerGroup}.
|
||||
* @param ordinal which entity in the {@link PowerGroup}.
|
||||
* @return the average current in milliAmps.
|
||||
*/
|
||||
public double getAveragePowerForOrdinal(@PowerGroup String group, int ordinal) {
|
||||
return getAveragePowerForOrdinal(group, ordinal, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the battery capacity, if available, in milli Amp Hours. If not available,
|
||||
* it returns zero.
|
||||
@@ -682,4 +799,9 @@ public class PowerProfile {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Creates the key for an ordinaled power constant from the group and ordinal.
|
||||
private static String getOrdinalPowerType(@PowerGroup String group, int ordinal) {
|
||||
return group + ordinal;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;
|
||||
|
||||
import android.os.BatteryConsumer;
|
||||
import android.os.BatteryStats;
|
||||
import android.os.BatteryUsageStats;
|
||||
@@ -50,10 +53,11 @@ public class ScreenPowerCalculator extends PowerCalculator {
|
||||
}
|
||||
|
||||
public ScreenPowerCalculator(PowerProfile powerProfile) {
|
||||
// TODO(b/200239964): update to support multidisplay.
|
||||
mScreenOnPowerEstimator = new UsageBasedPowerEstimator(
|
||||
powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON));
|
||||
powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 0));
|
||||
mScreenFullPowerEstimator = new UsageBasedPowerEstimator(
|
||||
powerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL));
|
||||
powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 0));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,9 +27,33 @@
|
||||
are totally dependent on the platform and can vary
|
||||
significantly, so should be measured on the shipping platform
|
||||
with a power meter. -->
|
||||
<item name="ambient.on">0.1</item> <!-- ~100mA -->
|
||||
<item name="screen.on">0.1</item> <!-- ~100mA -->
|
||||
<item name="screen.full">0.1</item> <!-- ~100mA -->
|
||||
|
||||
<!-- Display related values. -->
|
||||
<!-- Average battery current draw of display0 while in ambient mode, including backlight.
|
||||
There must be one of these for each display, labeled:
|
||||
ambient.on.display0, ambient.on.display1, etc...
|
||||
|
||||
Each display suffix number should match it's ordinal in its display device config.
|
||||
-->
|
||||
<item name="ambient.on.display0">0.1</item> <!-- ~100mA -->
|
||||
<!-- Average battery current draw of display0 while on without backlight.
|
||||
There must be one of these for each display, labeled:
|
||||
screen.on.display0, screen.on.display1, etc...
|
||||
|
||||
Each display suffix number should match it's ordinal in its display device config.
|
||||
-->
|
||||
<item name="screen.on.display0">0.1</item> <!-- ~100mA -->
|
||||
<!-- Average battery current draw of the backlight at full brightness.
|
||||
The full current draw of display N at full brightness should be the sum of screen.on.displayN
|
||||
and screen.full.displayN
|
||||
|
||||
There must be one of these for each display, labeled:
|
||||
screen.full.display0, screen.full.display1, etc...
|
||||
|
||||
Each display suffix number should match it's ordinal in its display device config.
|
||||
-->
|
||||
<item name="screen.full.display0">0.1</item> <!-- ~100mA -->
|
||||
|
||||
<item name="bluetooth.active">0.1</item> <!-- Bluetooth data transfer, ~10mA -->
|
||||
<item name="bluetooth.on">0.1</item> <!-- Bluetooth on & connectable, but not connected, ~0.1mA -->
|
||||
<item name="wifi.on">0.1</item> <!-- ~3mA -->
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_AMBIENT;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.os.BatteryConsumer;
|
||||
@@ -36,7 +38,7 @@ public class AmbientDisplayPowerCalculatorTest {
|
||||
|
||||
@Rule
|
||||
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
|
||||
.setAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY, 10.0);
|
||||
.setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 0, 10.0);
|
||||
|
||||
@Test
|
||||
public void testMeasuredEnergyBasedModel() {
|
||||
|
||||
@@ -110,6 +110,14 @@ public class BatteryUsageStatsRule implements TestRule {
|
||||
return this;
|
||||
}
|
||||
|
||||
public BatteryUsageStatsRule setAveragePowerForOrdinal(String group, int ordinal,
|
||||
double value) {
|
||||
when(mPowerProfile.getAveragePowerForOrdinal(group, ordinal)).thenReturn(value);
|
||||
when(mPowerProfile.getAveragePowerForOrdinal(eq(group), eq(ordinal),
|
||||
anyDouble())).thenReturn(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/** Call only after setting the power profile information. */
|
||||
public BatteryUsageStatsRule initMeasuredEnergyStatsLocked() {
|
||||
return initMeasuredEnergyStatsLocked(new String[0]);
|
||||
|
||||
@@ -17,6 +17,10 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_AMBIENT;
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
@@ -53,7 +57,12 @@ public class PowerProfileTest extends TestCase {
|
||||
assertEquals(4, mProfile.getNumSpeedStepsInCpuCluster(1));
|
||||
assertEquals(60.0, mProfile.getAveragePowerForCpuCore(1, 3));
|
||||
assertEquals(3000.0, mProfile.getBatteryCapacity());
|
||||
assertEquals(0.5, mProfile.getAveragePower(PowerProfile.POWER_AMBIENT_DISPLAY));
|
||||
assertEquals(0.5,
|
||||
mProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 0));
|
||||
assertEquals(100.0,
|
||||
mProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 0));
|
||||
assertEquals(800.0,
|
||||
mProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 0));
|
||||
assertEquals(100.0, mProfile.getAveragePower(PowerProfile.POWER_AUDIO));
|
||||
assertEquals(150.0, mProfile.getAveragePower(PowerProfile.POWER_VIDEO));
|
||||
}
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
package com.android.internal.os;
|
||||
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_FULL;
|
||||
import static com.android.internal.os.PowerProfile.POWER_GROUP_DISPLAY_SCREEN_ON;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
@@ -42,8 +45,8 @@ public class ScreenPowerCalculatorTest {
|
||||
|
||||
@Rule
|
||||
public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
|
||||
.setAveragePower(PowerProfile.POWER_SCREEN_ON, 36.0)
|
||||
.setAveragePower(PowerProfile.POWER_SCREEN_FULL, 48.0);
|
||||
.setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 0, 36.0)
|
||||
.setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 0, 48.0);
|
||||
|
||||
@Test
|
||||
public void testMeasuredEnergyBasedModel() {
|
||||
|
||||
Reference in New Issue
Block a user