summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author TreeHugger Robot <treehugger-gerrit@google.com> 2023-03-21 16:37:45 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2023-03-21 16:37:45 +0000
commit3a32c2285e44e60cc297ccbe5bb2629a1a845ce3 (patch)
tree888e289930c89796cd4ba7c295f305cab4080303
parenta76b11622aa5e50cf08bbb5bf391a94b65788174 (diff)
parent33d9beaf2d0b6ea0c073ec22824bedc2e4fb81f0 (diff)
Merge "Proportionally attribute Mobile Radio Energy Consumption to Phone usage." into tm-qpr-dev
-rw-r--r--core/java/android/os/BatteryStats.java9
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java55
-rw-r--r--core/java/com/android/internal/os/PhonePowerCalculator.java25
-rw-r--r--core/java/com/android/internal/power/MeasuredEnergyStats.java4
-rw-r--r--core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java20
-rw-r--r--services/core/java/com/android/server/am/BatteryExternalStatsWorker.java1
6 files changed, 91 insertions, 23 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 76475f2142c0..4f49f12691d0 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -2808,6 +2808,15 @@ public abstract class BatteryStats implements Parcelable {
public abstract long getMobileRadioMeasuredBatteryConsumptionUC();
/**
+ * Returns the battery consumption (in microcoulombs) of the phone calls, derived from on device
+ * power measurement data.
+ * Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
+ *
+ * {@hide}
+ */
+ public abstract long getPhoneEnergyConsumptionUC();
+
+ /**
* Returns the battery consumption (in microcoulombs) of the screen while on, derived from on
* device power measurement data.
* Will return {@link #POWER_DATA_UNAVAILABLE} if data is unavailable.
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 6fed26c4a81d..e1e57de15346 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -166,8 +166,8 @@ public class BatteryStatsImpl extends BatteryStats {
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
- // Current on-disk Parcel version
- static final int VERSION = 210;
+ // Current on-disk Parcel version. Must be updated when the format of the parcelable changes
+ public static final int VERSION = 211;
// The maximum number of names wakelocks we will keep track of
// per uid; once the limit is reached, we batch the remaining wakelocks
@@ -6491,6 +6491,9 @@ public class BatteryStatsImpl extends BatteryStats {
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mPhoneOn = true;
mPhoneOnTimer.startRunningLocked(elapsedRealtimeMs);
+ if (mConstants.PHONE_ON_EXTERNAL_STATS_COLLECTION) {
+ scheduleSyncExternalStatsLocked("phone-on", ExternalStatsSync.UPDATE_RADIO);
+ }
}
}
@@ -6509,6 +6512,7 @@ public class BatteryStatsImpl extends BatteryStats {
addHistoryRecordLocked(elapsedRealtimeMs, uptimeMs);
mPhoneOn = false;
mPhoneOnTimer.stopRunningLocked(elapsedRealtimeMs);
+ scheduleSyncExternalStatsLocked("phone-off", ExternalStatsSync.UPDATE_RADIO);
}
}
@@ -8475,6 +8479,12 @@ public class BatteryStatsImpl extends BatteryStats {
@GuardedBy("this")
@Override
+ public long getPhoneEnergyConsumptionUC() {
+ return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_PHONE);
+ }
+
+ @GuardedBy("this")
+ @Override
public long getScreenOnMeasuredBatteryConsumptionUC() {
return getPowerBucketConsumptionUC(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON);
}
@@ -13717,18 +13727,36 @@ public class BatteryStatsImpl extends BatteryStats {
}
synchronized (this) {
+ final long totalRadioDurationMs =
+ mMobileRadioActiveTimer.getTimeSinceMarkLocked(
+ elapsedRealtimeMs * 1000) / 1000;
+ mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
+ final long phoneOnDurationMs = Math.min(totalRadioDurationMs,
+ mPhoneOnTimer.getTimeSinceMarkLocked(elapsedRealtimeMs * 1000) / 1000);
+ mPhoneOnTimer.setMark(elapsedRealtimeMs);
+
if (!mOnBatteryInternal || mIgnoreNextExternalStats) {
return;
}
final SparseDoubleArray uidEstimatedConsumptionMah;
+ final long dataConsumedChargeUC;
if (consumedChargeUC > 0 && mMobileRadioPowerCalculator != null
&& mGlobalMeasuredEnergyStats != null) {
+ // Crudely attribute power consumption. Added (totalRadioDurationMs / 2) to the
+ // numerator for long rounding.
+ final long phoneConsumedChargeUC =
+ (consumedChargeUC * phoneOnDurationMs + totalRadioDurationMs / 2)
+ / totalRadioDurationMs;
+ dataConsumedChargeUC = consumedChargeUC - phoneConsumedChargeUC;
mGlobalMeasuredEnergyStats.updateStandardBucket(
- MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, consumedChargeUC);
+ MeasuredEnergyStats.POWER_BUCKET_PHONE, phoneConsumedChargeUC);
+ mGlobalMeasuredEnergyStats.updateStandardBucket(
+ MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO, dataConsumedChargeUC);
uidEstimatedConsumptionMah = new SparseDoubleArray();
} else {
uidEstimatedConsumptionMah = null;
+ dataConsumedChargeUC = POWER_DATA_UNAVAILABLE;
}
if (deltaInfo != null) {
@@ -13888,14 +13916,9 @@ public class BatteryStatsImpl extends BatteryStats {
// Update the MeasuredEnergyStats information.
if (uidEstimatedConsumptionMah != null) {
double totalEstimatedConsumptionMah = 0.0;
-
- // Estimate total active radio power consumption since last mark.
- final long totalRadioTimeMs = mMobileRadioActiveTimer.getTimeSinceMarkLocked(
- elapsedRealtimeMs * 1000) / 1000;
- mMobileRadioActiveTimer.setMark(elapsedRealtimeMs);
totalEstimatedConsumptionMah +=
mMobileRadioPowerCalculator.calcPowerFromRadioActiveDurationMah(
- totalRadioTimeMs);
+ totalRadioDurationMs);
// Estimate idle power consumption at each signal strength level
final int numSignalStrengthLevels = mPhoneSignalStrengthsTimer.length;
@@ -13919,7 +13942,7 @@ public class BatteryStatsImpl extends BatteryStats {
mMobileRadioPowerCalculator.calcScanTimePowerMah(scanTimeMs);
distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO,
- consumedChargeUC, uidEstimatedConsumptionMah,
+ dataConsumedChargeUC, uidEstimatedConsumptionMah,
totalEstimatedConsumptionMah, elapsedRealtimeMs);
}
@@ -16651,6 +16674,8 @@ public class BatteryStatsImpl extends BatteryStats {
public static final String KEY_MAX_HISTORY_BUFFER_KB = "max_history_buffer_kb";
public static final String KEY_BATTERY_CHARGED_DELAY_MS =
"battery_charged_delay_ms";
+ public static final String KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION =
+ "phone_on_external_stats_collection";
private static final boolean DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME = true;
private static final long DEFAULT_KERNEL_UID_READERS_THROTTLE_TIME = 1_000;
@@ -16663,6 +16688,7 @@ public class BatteryStatsImpl extends BatteryStats {
private static final int DEFAULT_MAX_HISTORY_FILES_LOW_RAM_DEVICE = 64;
private static final int DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB = 64; /*Kilo Bytes*/
private static final int DEFAULT_BATTERY_CHARGED_DELAY_MS = 900000; /* 15 min */
+ private static final boolean DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION = true;
public boolean TRACK_CPU_ACTIVE_CLUSTER_TIME = DEFAULT_TRACK_CPU_ACTIVE_CLUSTER_TIME;
/* Do not set default value for KERNEL_UID_READERS_THROTTLE_TIME. Need to trigger an
@@ -16678,6 +16704,8 @@ public class BatteryStatsImpl extends BatteryStats {
public int MAX_HISTORY_FILES;
public int MAX_HISTORY_BUFFER; /*Bytes*/
public int BATTERY_CHARGED_DELAY_MS = DEFAULT_BATTERY_CHARGED_DELAY_MS;
+ public boolean PHONE_ON_EXTERNAL_STATS_COLLECTION =
+ DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION;
private ContentResolver mResolver;
private final KeyValueListParser mParser = new KeyValueListParser(',');
@@ -16754,6 +16782,11 @@ public class BatteryStatsImpl extends BatteryStats {
DEFAULT_MAX_HISTORY_BUFFER_LOW_RAM_DEVICE_KB
: DEFAULT_MAX_HISTORY_BUFFER_KB)
* 1024;
+
+ PHONE_ON_EXTERNAL_STATS_COLLECTION = mParser.getBoolean(
+ KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION,
+ DEFAULT_PHONE_ON_EXTERNAL_STATS_COLLECTION);
+
updateBatteryChargedDelayMsLocked();
}
}
@@ -16808,6 +16841,8 @@ public class BatteryStatsImpl extends BatteryStats {
pw.println(MAX_HISTORY_BUFFER/1024);
pw.print(KEY_BATTERY_CHARGED_DELAY_MS); pw.print("=");
pw.println(BATTERY_CHARGED_DELAY_MS);
+ pw.print(KEY_PHONE_ON_EXTERNAL_STATS_COLLECTION); pw.print("=");
+ pw.println(PHONE_ON_EXTERNAL_STATS_COLLECTION);
}
}
diff --git a/core/java/com/android/internal/os/PhonePowerCalculator.java b/core/java/com/android/internal/os/PhonePowerCalculator.java
index cb893defab14..f1c4ffe07788 100644
--- a/core/java/com/android/internal/os/PhonePowerCalculator.java
+++ b/core/java/com/android/internal/os/PhonePowerCalculator.java
@@ -40,14 +40,27 @@ public class PhonePowerCalculator extends PowerCalculator {
@Override
public void calculate(BatteryUsageStats.Builder builder, BatteryStats batteryStats,
long rawRealtimeUs, long rawUptimeUs, BatteryUsageStatsQuery query) {
+ final long energyConsumerUC = batteryStats.getPhoneEnergyConsumptionUC();
+ final int powerModel = getPowerModel(energyConsumerUC, query);
+
final long phoneOnTimeMs = batteryStats.getPhoneOnTime(rawRealtimeUs,
BatteryStats.STATS_SINCE_CHARGED) / 1000;
- final double phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);
- if (phoneOnPower != 0) {
- builder.getAggregateBatteryConsumerBuilder(
- BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
- .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower)
- .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs);
+ final double phoneOnPower;
+ switch (powerModel) {
+ case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+ phoneOnPower = uCtoMah(energyConsumerUC);
+ break;
+ case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+ default:
+ phoneOnPower = mPowerEstimator.calculatePower(phoneOnTimeMs);
}
+
+ if (phoneOnPower == 0.0) return;
+
+ builder.getAggregateBatteryConsumerBuilder(
+ BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
+ .setConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnPower, powerModel)
+ .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_PHONE, phoneOnTimeMs);
+
}
}
diff --git a/core/java/com/android/internal/power/MeasuredEnergyStats.java b/core/java/com/android/internal/power/MeasuredEnergyStats.java
index 7fb8696a217d..5bfdd62592c8 100644
--- a/core/java/com/android/internal/power/MeasuredEnergyStats.java
+++ b/core/java/com/android/internal/power/MeasuredEnergyStats.java
@@ -59,7 +59,9 @@ public class MeasuredEnergyStats {
public static final int POWER_BUCKET_BLUETOOTH = 5;
public static final int POWER_BUCKET_GNSS = 6;
public static final int POWER_BUCKET_MOBILE_RADIO = 7;
- public static final int NUMBER_STANDARD_POWER_BUCKETS = 8; // Buckets above this are custom.
+ public static final int POWER_BUCKET_CAMERA = 8;
+ public static final int POWER_BUCKET_PHONE = 9;
+ public static final int NUMBER_STANDARD_POWER_BUCKETS = 10; // Buckets above this are custom.
@IntDef(prefix = {"POWER_BUCKET_"}, value = {
POWER_BUCKET_UNKNOWN,
diff --git a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
index 00ac1985f897..0bdf491e6377 100644
--- a/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/MobileRadioPowerCalculatorTest.java
@@ -245,6 +245,8 @@ public class MobileRadioPowerCalculatorTest {
stats.noteNetworkInterfaceForTransports("cellular",
new int[]{NetworkCapabilities.TRANSPORT_CELLULAR});
+ stats.notePhoneOnLocked(9800, 9800);
+
// Note application network activity
NetworkStats networkStats = new NetworkStats(10000, 1)
.addEntry(new NetworkStats.Entry("cellular", APP_UID, 0, 0,
@@ -257,27 +259,33 @@ public class MobileRadioPowerCalculatorTest {
mStatsRule.setTime(12_000, 12_000);
- MobileRadioPowerCalculator calculator =
+ MobileRadioPowerCalculator mobileRadioPowerCalculator =
new MobileRadioPowerCalculator(mStatsRule.getPowerProfile());
-
- mStatsRule.apply(calculator);
+ PhonePowerCalculator phonePowerCalculator =
+ new PhonePowerCalculator(mStatsRule.getPowerProfile());
+ mStatsRule.apply(mobileRadioPowerCalculator, phonePowerCalculator);
UidBatteryConsumer uidConsumer = mStatsRule.getUidBatteryConsumer(APP_UID);
assertThat(uidConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(1.53934);
+ .isWithin(PRECISION).of(1.38541);
assertThat(uidConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
// 10_000_000 micro-Coulomb * 1/1000 milli/micro * 1/3600 hour/second = 2.77778 mAh
assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(2.77778);
+ .isWithin(PRECISION).of(2.5);
assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+ assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isWithin(PRECISION).of(0.27778);
+ assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_PHONE))
+ .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+
BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
- .isWithin(PRECISION).of(1.53934);
+ .isWithin(PRECISION).of(1.38541);
assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_MOBILE_RADIO))
.isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
}
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 702526a4beab..dc1ef7eee0b6 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -891,6 +891,7 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync {
break;
case EnergyConsumerType.MOBILE_RADIO:
buckets[MeasuredEnergyStats.POWER_BUCKET_MOBILE_RADIO] = true;
+ buckets[MeasuredEnergyStats.POWER_BUCKET_PHONE] = true;
break;
case EnergyConsumerType.DISPLAY:
buckets[MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON] = true;