From cb308d9c61feaf44975025db84522b234f690258 Mon Sep 17 00:00:00 2001 From: Blake Kragten Date: Mon, 28 Jan 2019 10:54:13 -0800 Subject: [PATCH] Power Monitor Addition framworks base: Frameworks Base section of power monitor addition. Since IPowerStats does not have a java interface, we needed to make a native interface into the code. I followed how the LowPowerStats collection is being done. Native code is located in com_android_server_am_BatteryStatsService.cpp. We are calling the getEnergyData to get all rails energy data that has been collecting from boot. This energy data is collected in uWs (microWatt seconds). After the rail data is collected at each update in the RailStats class, the wifi and cellular total energy values will contain the energy that all rails associated with the specific subsystem will have. We update and collect the energy data using battery stats and propagate it to telephony metrics. When we collect the total energy for an update we need to zero out the energy data so it can be accumulated correctly. 1/31: Added modemRailEnergy and wifiRailEnergy to Volta historian. Bug: 115929961 Test: adb shell dumpsys activity service TelephonyDebugService --metrics Results Examples: Energy consumed by modem (mAh): 2.41 Energy Rails consumed by modem (mAh): 2.76 Dumpsys historian results: +4m23s712ms (2) 100 cc511a18 modemRailChargemAh=0.34 wifiRailChargemAh=1.17 +wifi_scan stats=0:"dump" +10m24s089ms (2) 100 c4511a18 modemRailChargemAh=0.71 wifiRailChargemAh=1.77 stats=0:"write" +11m24s228ms (3) 100 c4511a19 volt=4315 charge=3988 modemRailChargemAh=0.77 wifiRailChargemAh=1.94 wifi_signal_strength=2 stats=0:"battery-state" Change-Id: I97521a03204968079e61f3de86640d4f1a580255 --- core/java/android/os/BatteryStats.java | 65 +++++- .../os/connectivity/WifiBatteryStats.java | 13 ++ .../android/internal/os/BatteryStatsImpl.java | 185 +++++++++++++----- .../com/android/internal/os/RailStats.java | 147 ++++++++++++++ core/proto/android/os/batterystats.proto | 4 + .../server/am/BatteryExternalStatsWorker.java | 4 + .../server/am/BatteryStatsService.java | 24 ++- ..._android_server_am_BatteryStatsService.cpp | 119 ++++++++++- 8 files changed, 499 insertions(+), 62 deletions(-) create mode 100644 core/java/com/android/internal/os/RailStats.java diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java index ab6dd7c07b420..b7e65b9151b97 100644 --- a/core/java/android/os/BatteryStats.java +++ b/core/java/android/os/BatteryStats.java @@ -46,6 +46,7 @@ import com.android.internal.os.BatteryStatsHelper; import java.io.FileDescriptor; import java.io.PrintWriter; +import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; @@ -262,6 +263,7 @@ public abstract class BatteryStats implements Parcelable { private static final long BYTES_PER_KB = 1024; private static final long BYTES_PER_MB = 1048576; // 1024^2 private static final long BYTES_PER_GB = 1073741824; //1024^3 + public static final double MILLISECONDS_IN_HOUR = 3600 * 1000; private static final String VERSION_DATA = "vers"; private static final String UID_DATA = "uid"; @@ -482,6 +484,13 @@ public abstract class BatteryStats implements Parcelable { * yield a value of 0 if the device doesn't support power calculations. */ public abstract LongCounter getPowerCounter(); + + /** + * @return a non-null {@link LongCounter} representing total power monitored on the rails + * in mAms (miliamps-milliseconds). The counter may always yield a value of 0 if the device + * doesn't support power rail monitoring. + */ + public abstract LongCounter getMonitoredRailChargeConsumedMaMs(); } /** @@ -1526,6 +1535,9 @@ public abstract class BatteryStats implements Parcelable { // The charge of the battery in micro-Ampere-hours. public int batteryChargeUAh; + public double modemRailChargeMah; + public double wifiRailChargeMah; + // Constants from SCREEN_BRIGHTNESS_* public static final int STATE_BRIGHTNESS_SHIFT = 0; public static final int STATE_BRIGHTNESS_MASK = 0x7; @@ -1738,6 +1750,8 @@ public abstract class BatteryStats implements Parcelable { | ((((int)batteryVoltage)<<16)&0xffff0000); dest.writeInt(bat); dest.writeInt(batteryChargeUAh); + dest.writeDouble(modemRailChargeMah); + dest.writeDouble(wifiRailChargeMah); dest.writeInt(states); dest.writeInt(states2); if (wakelockTag != null) { @@ -1767,6 +1781,8 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = (short)(bat2&0xffff); batteryVoltage = (char)((bat2>>16)&0xffff); batteryChargeUAh = src.readInt(); + modemRailChargeMah = src.readDouble(); + wifiRailChargeMah = src.readDouble(); states = src.readInt(); states2 = src.readInt(); if ((bat&0x10000000) != 0) { @@ -1807,6 +1823,8 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = 0; batteryVoltage = 0; batteryChargeUAh = 0; + modemRailChargeMah = 0; + wifiRailChargeMah = 0; states = 0; states2 = 0; wakelockTag = null; @@ -1835,6 +1853,8 @@ public abstract class BatteryStats implements Parcelable { batteryTemperature = o.batteryTemperature; batteryVoltage = o.batteryVoltage; batteryChargeUAh = o.batteryChargeUAh; + modemRailChargeMah = o.modemRailChargeMah; + wifiRailChargeMah = o.wifiRailChargeMah; states = o.states; states2 = o.states2; if (o.wakelockTag != null) { @@ -1867,6 +1887,8 @@ public abstract class BatteryStats implements Parcelable { && batteryTemperature == o.batteryTemperature && batteryVoltage == o.batteryVoltage && batteryChargeUAh == o.batteryChargeUAh + && modemRailChargeMah == o.modemRailChargeMah + && wifiRailChargeMah == o.wifiRailChargeMah && states == o.states && states2 == o.states2 && currentTime == o.currentTime; @@ -3311,7 +3333,8 @@ public abstract class BatteryStats implements Parcelable { if (counter.getIdleTimeCounter().getCountLocked(which) != 0 || counter.getRxTimeCounter().getCountLocked(which) != 0 - || counter.getPowerCounter().getCountLocked(which) != 0) { + || counter.getPowerCounter().getCountLocked(which) != 0 + || counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which) != 0) { return true; } @@ -3345,7 +3368,10 @@ public abstract class BatteryStats implements Parcelable { pw.print(","); pw.print(counter.getRxTimeCounter().getCountLocked(which)); pw.print(","); - pw.print(counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60)); + pw.print(counter.getPowerCounter().getCountLocked(which) / (MILLISECONDS_IN_HOUR)); + pw.print(","); + pw.print(counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which) + / (MILLISECONDS_IN_HOUR)); for (LongCounter c : counter.getTxTimeCounters()) { pw.print(","); pw.print(c.getCountLocked(which)); @@ -3370,7 +3396,10 @@ public abstract class BatteryStats implements Parcelable { proto.write(ControllerActivityProto.RX_DURATION_MS, counter.getRxTimeCounter().getCountLocked(which)); proto.write(ControllerActivityProto.POWER_MAH, - counter.getPowerCounter().getCountLocked(which) / (1000 * 60 * 60)); + counter.getPowerCounter().getCountLocked(which) / (MILLISECONDS_IN_HOUR)); + proto.write(ControllerActivityProto.MONITORED_RAIL_CHARGE_MAH, + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which) + / (MILLISECONDS_IN_HOUR)); long tToken; LongCounter[] txCounters = counter.getTxTimeCounters(); @@ -3400,6 +3429,8 @@ public abstract class BatteryStats implements Parcelable { final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); final long powerDrainMaMs = counter.getPowerCounter().getCountLocked(which); + final long monitoredRailChargeConsumedMaMs = + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which); // Battery real time final long totalControllerActivityTimeMs = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000; @@ -3522,10 +3553,22 @@ public abstract class BatteryStats implements Parcelable { sb.append(" "); sb.append(controllerName); sb.append(" Battery drain: ").append( - BatteryStatsHelper.makemAh(powerDrainMaMs / (double) (1000*60*60))); + BatteryStatsHelper.makemAh(powerDrainMaMs / MILLISECONDS_IN_HOUR)); sb.append("mAh"); pw.println(sb.toString()); } + + if (monitoredRailChargeConsumedMaMs > 0) { + sb.setLength(0); + sb.append(prefix); + sb.append(" "); + sb.append(controllerName); + sb.append(" Monitored rail energy drain: ").append( + new DecimalFormat("#.##").format( + monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR)); + sb.append(" mAh"); + pw.println(sb.toString()); + } } /** @@ -6103,6 +6146,8 @@ public abstract class BatteryStats implements Parcelable { int oldTemp = -1; int oldVolt = -1; int oldChargeMAh = -1; + double oldModemRailChargeMah = -1; + double oldWifiRailChargeMah = -1; long lastTime = -1; void reset() { @@ -6114,6 +6159,8 @@ public abstract class BatteryStats implements Parcelable { oldTemp = -1; oldVolt = -1; oldChargeMAh = -1; + oldModemRailChargeMah = -1; + oldWifiRailChargeMah = -1; } public void printNextItem(PrintWriter pw, HistoryItem rec, long baseTime, boolean checkin, @@ -6299,6 +6346,16 @@ public abstract class BatteryStats implements Parcelable { item.append(checkin ? ",Bcc=" : " charge="); item.append(oldChargeMAh); } + if (oldModemRailChargeMah != rec.modemRailChargeMah) { + oldModemRailChargeMah = rec.modemRailChargeMah; + item.append(checkin ? ",Mrc=" : " modemRailChargemAh="); + item.append(new DecimalFormat("#.##").format(oldModemRailChargeMah)); + } + if (oldWifiRailChargeMah != rec.wifiRailChargeMah) { + oldWifiRailChargeMah = rec.wifiRailChargeMah; + item.append(checkin ? ",Wrc=" : " wifiRailChargemAh="); + item.append(new DecimalFormat("#.##").format(oldWifiRailChargeMah)); + } printBitDescriptions(item, oldState, rec.states, rec.wakelockTag, HISTORY_STATE_DESCRIPTIONS, !checkin); printBitDescriptions(item, oldState2, rec.states2, null, diff --git a/core/java/android/os/connectivity/WifiBatteryStats.java b/core/java/android/os/connectivity/WifiBatteryStats.java index e5341eeeb17be..3639c71ae3b50 100644 --- a/core/java/android/os/connectivity/WifiBatteryStats.java +++ b/core/java/android/os/connectivity/WifiBatteryStats.java @@ -44,6 +44,7 @@ public final class WifiBatteryStats implements Parcelable { private long[] mTimeInStateMs; private long[] mTimeInSupplicantStateMs; private long[] mTimeInRxSignalStrengthLevelMs; + private long mMonitoredRailChargeConsumedMaMs; public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -77,6 +78,7 @@ public final class WifiBatteryStats implements Parcelable { out.writeLongArray(mTimeInStateMs); out.writeLongArray(mTimeInRxSignalStrengthLevelMs); out.writeLongArray(mTimeInSupplicantStateMs); + out.writeLong(mMonitoredRailChargeConsumedMaMs); } public void readFromParcel(Parcel in) { @@ -96,6 +98,7 @@ public final class WifiBatteryStats implements Parcelable { in.readLongArray(mTimeInStateMs); in.readLongArray(mTimeInRxSignalStrengthLevelMs); in.readLongArray(mTimeInSupplicantStateMs); + mMonitoredRailChargeConsumedMaMs = in.readLong(); } public long getLoggingDurationMs() { @@ -162,6 +165,10 @@ public final class WifiBatteryStats implements Parcelable { return mTimeInSupplicantStateMs; } + public long getMonitoredRailChargeConsumedMaMs() { + return mMonitoredRailChargeConsumedMaMs; + } + public void setLoggingDurationMs(long t) { mLoggingDurationMs = t; return; @@ -245,6 +252,11 @@ public final class WifiBatteryStats implements Parcelable { return; } + public void setMonitoredRailChargeConsumedMaMs(long monitoredRailEnergyConsumedMaMs) { + mMonitoredRailChargeConsumedMaMs = monitoredRailEnergyConsumedMaMs; + return; + } + public int describeContents() { return 0; } @@ -274,6 +286,7 @@ public final class WifiBatteryStats implements Parcelable { Arrays.fill(mTimeInRxSignalStrengthLevelMs, 0); mTimeInSupplicantStateMs = new long[BatteryStats.NUM_WIFI_SUPPL_STATES]; Arrays.fill(mTimeInSupplicantStateMs, 0); + mMonitoredRailChargeConsumedMaMs = 0; return; } } \ No newline at end of file diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java index 52e1748c621c6..4ff99482feff7 100644 --- a/core/java/com/android/internal/os/BatteryStatsImpl.java +++ b/core/java/com/android/internal/os/BatteryStatsImpl.java @@ -187,6 +187,8 @@ public class BatteryStatsImpl extends BatteryStats { static final int MSG_REPORT_RESET_STATS = 4; static final long DELAY_UPDATE_WAKELOCKS = 5*1000; + private static final double MILLISECONDS_IN_HOUR = 3600 * 1000; + private final KernelWakelockReader mKernelWakelockReader = new KernelWakelockReader(); private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats(); @@ -252,6 +254,9 @@ public class BatteryStatsImpl extends BatteryStats { private static final long RPM_STATS_UPDATE_FREQ_MS = 1000; /** Last time that RPM stats were updated by updateRpmStatsLocked. */ private long mLastRpmStatsUpdateTimeMs = -RPM_STATS_UPDATE_FREQ_MS; + + /** Container for Rail Energy Data stats. */ + private final RailStats mTmpRailStats = new RailStats(); /** * Use a queue to delay removing UIDs from {@link KernelCpuUidUserSysTimeReader}, * {@link KernelCpuUidActiveTimeReader}, {@link KernelCpuUidClusterTimeReader}, @@ -327,6 +332,15 @@ public class BatteryStatsImpl extends BatteryStats { public String getSubsystemLowPowerStats(); } + /** interface to update rail information for power monitor */ + public interface RailEnergyDataCallback { + /** Function to fill the map for the rail data stats + * Used for power monitoring feature + * @param railStats + */ + void fillRailDataStats(RailStats railStats); + } + public static abstract class UserInfoProvider { private int[] userIds; protected abstract @Nullable int[] getUserIds(); @@ -361,6 +375,8 @@ public class BatteryStatsImpl extends BatteryStats { } }; + public final RailEnergyDataCallback mRailEnergyDataCallback; + /** * This handler is running on {@link BackgroundThread}. */ @@ -593,7 +609,9 @@ public class BatteryStatsImpl extends BatteryStats { int UPDATE_RADIO = 0x04; int UPDATE_BT = 0x08; int UPDATE_RPM = 0x10; // 16 - int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM; + int UPDATE_RAIL = 0x20; // 32 + int UPDATE_ALL = UPDATE_CPU | UPDATE_WIFI | UPDATE_RADIO | UPDATE_BT | UPDATE_RPM + | UPDATE_RAIL; Future scheduleSync(String reason, int flags); Future scheduleCpuSyncDueToRemovedUid(int uid); @@ -1078,6 +1096,7 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryStatsHistory = null; mHandler = null; mPlatformIdleStateCallback = null; + mRailEnergyDataCallback = null; mUserInfoProvider = null; mConstants = new Constants(mHandler); clearHistoryLocked(); @@ -3005,6 +3024,7 @@ public class BatteryStatsImpl extends BatteryStats { private final LongSamplingCounter mRxTimeMillis; private final LongSamplingCounter[] mTxTimeMillis; private final LongSamplingCounter mPowerDrainMaMs; + private final LongSamplingCounter mMonitoredRailChargeConsumedMaMs; public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates) { mIdleTimeMillis = new LongSamplingCounter(timeBase); @@ -3016,6 +3036,7 @@ public class BatteryStatsImpl extends BatteryStats { mTxTimeMillis[i] = new LongSamplingCounter(timeBase); } mPowerDrainMaMs = new LongSamplingCounter(timeBase); + mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase); } public ControllerActivityCounterImpl(TimeBase timeBase, int numTxStates, Parcel in) { @@ -3033,6 +3054,7 @@ public class BatteryStatsImpl extends BatteryStats { mTxTimeMillis[i] = new LongSamplingCounter(timeBase, in); } mPowerDrainMaMs = new LongSamplingCounter(timeBase, in); + mMonitoredRailChargeConsumedMaMs = new LongSamplingCounter(timeBase, in); } public void readSummaryFromParcel(Parcel in) { @@ -3048,6 +3070,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.readSummaryFromParcelLocked(in); } mPowerDrainMaMs.readSummaryFromParcelLocked(in); + mMonitoredRailChargeConsumedMaMs.readSummaryFromParcelLocked(in); } @Override @@ -3065,6 +3088,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.writeSummaryFromParcelLocked(dest); } mPowerDrainMaMs.writeSummaryFromParcelLocked(dest); + mMonitoredRailChargeConsumedMaMs.writeSummaryFromParcelLocked(dest); } @Override @@ -3078,6 +3102,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.writeToParcel(dest); } mPowerDrainMaMs.writeToParcel(dest); + mMonitoredRailChargeConsumedMaMs.writeToParcel(dest); } public void reset(boolean detachIfReset) { @@ -3089,6 +3114,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.reset(detachIfReset); } mPowerDrainMaMs.reset(detachIfReset); + mMonitoredRailChargeConsumedMaMs.reset(detachIfReset); } public void detach() { @@ -3100,6 +3126,7 @@ public class BatteryStatsImpl extends BatteryStats { counter.detach(); } mPowerDrainMaMs.detach(); + mMonitoredRailChargeConsumedMaMs.detach(); } /** @@ -3154,6 +3181,15 @@ public class BatteryStatsImpl extends BatteryStats { public LongSamplingCounter getPowerCounter() { return mPowerDrainMaMs; } + + /** + * @return a LongSamplingCounter, measuring actual monitored rail energy consumed + * milli-ampere milli-seconds (mAmS). + */ + @Override + public LongSamplingCounter getMonitoredRailChargeConsumedMaMs() { + return mMonitoredRailChargeConsumedMaMs; + } } /** Get Resource Power Manager stats. Create a new one if it doesn't already exist. */ @@ -3497,6 +3533,8 @@ public class BatteryStatsImpl extends BatteryStats { if (DEBUG) Slog.i(TAG, "WRITE DELTA: batteryChargeUAh=" + cur.batteryChargeUAh); dest.writeInt(cur.batteryChargeUAh); } + dest.writeDouble(cur.modemRailChargeMah); + dest.writeDouble(cur.wifiRailChargeMah); } private int buildBatteryLevelInt(HistoryItem h) { @@ -3747,6 +3785,8 @@ public class BatteryStatsImpl extends BatteryStats { if ((firstToken&DELTA_BATTERY_CHARGE_FLAG) != 0) { cur.batteryChargeUAh = src.readInt(); } + cur.modemRailChargeMah = src.readDouble(); + cur.wifiRailChargeMah = src.readDouble(); } @Override @@ -10111,12 +10151,12 @@ public class BatteryStatsImpl extends BatteryStats { } public BatteryStatsImpl(File systemDir, Handler handler, PlatformIdleStateCallback cb, - UserInfoProvider userInfoProvider) { - this(new SystemClocks(), systemDir, handler, cb, userInfoProvider); + RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) { + this(new SystemClocks(), systemDir, handler, cb, railStatsCb, userInfoProvider); } private BatteryStatsImpl(Clocks clocks, File systemDir, Handler handler, - PlatformIdleStateCallback cb, + PlatformIdleStateCallback cb, RailEnergyDataCallback railStatsCb, UserInfoProvider userInfoProvider) { init(clocks); @@ -10218,6 +10258,7 @@ public class BatteryStatsImpl extends BatteryStats { clearHistoryLocked(); updateDailyDeadlineLocked(); mPlatformIdleStateCallback = cb; + mRailEnergyDataCallback = railStatsCb; mUserInfoProvider = userInfoProvider; } @@ -10238,6 +10279,7 @@ public class BatteryStatsImpl extends BatteryStats { mBatteryStatsHistory = new BatteryStatsHistory(this, mHistoryBuffer); readFromParcel(p); mPlatformIdleStateCallback = null; + mRailEnergyDataCallback = null; } public void setPowerProfileLocked(PowerProfile profile) { @@ -10934,6 +10976,8 @@ public class BatteryStatsImpl extends BatteryStats { mWakeupReasonStats.clear(); } + mTmpRailStats.reset(); + mLastHistoryStepDetails = null; mLastStepCpuUserTime = mLastStepCpuSystemTime = 0; mCurStepCpuUserTime = mCurStepCpuSystemTime = 0; @@ -11321,6 +11365,16 @@ public class BatteryStatsImpl extends BatteryStats { mWifiActivity.getPowerCounter().addCountLocked( (long) (info.getControllerEnergyUsed() / opVolt)); } + // Converting uWs to mAms. + // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms + long monitoredRailChargeConsumedMaMs = + (long) (mTmpRailStats.getWifiTotalEnergyUseduWs() / opVolt); + mWifiActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked( + monitoredRailChargeConsumedMaMs); + mHistoryCur.wifiRailChargeMah += + (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); + addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + mTmpRailStats.resetWifiTotalEnergyUsed(); } } } @@ -11411,9 +11465,18 @@ public class BatteryStatsImpl extends BatteryStats { // We store the power drain as mAms. mModemActivity.getPowerCounter().addCountLocked((long) energyUsed); + // Converting uWs to mAms. + // Conversion: (uWs * (1000ms / 1s) * (1mW / 1000uW)) / mV = mAms + long monitoredRailChargeConsumedMaMs = + (long) (mTmpRailStats.getCellularTotalEnergyUseduWs() / opVolt); + mModemActivity.getMonitoredRailChargeConsumedMaMs().addCountLocked( + monitoredRailChargeConsumedMaMs); + mHistoryCur.modemRailChargeMah += + (monitoredRailChargeConsumedMaMs / MILLISECONDS_IN_HOUR); + addHistoryRecordLocked(mClocks.elapsedRealtime(), mClocks.uptimeMillis()); + mTmpRailStats.resetCellularTotalEnergyUsed(); } } - final long elapsedRealtimeMs = mClocks.elapsedRealtime(); long radioTime = mMobileRadioActivePerAppTimer.getTimeSinceMarkLocked( elapsedRealtimeMs * 1000); @@ -11811,6 +11874,16 @@ public class BatteryStatsImpl extends BatteryStats { } } + /** + * Read and record Rail Energy data. + */ + public void updateRailStatsLocked() { + if (mRailEnergyDataCallback == null || !mTmpRailStats.isRailStatsAvailable()) { + return; + } + mRailEnergyDataCallback.fillRailDataStats(mTmpRailStats); + } + /** * Read and distribute kernel wake lock use across apps. */ @@ -12950,6 +13023,8 @@ public class BatteryStatsImpl extends BatteryStats { final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which); + final long monitoredRailChargeConsumedMaMs = + counter.getMonitoredRailChargeConsumedMaMs().getCountLocked(which); long[] timeInRatMs = new long[BatteryStats.NUM_DATA_CONNECTION_TYPES]; for (int i = 0; i < timeInRatMs.length; i++) { timeInRatMs[i] = getPhoneDataConnectionTime(i, rawRealTime, which) / 1000; @@ -12979,58 +13054,62 @@ public class BatteryStatsImpl extends BatteryStats { s.setTimeInRatMs(timeInRatMs); s.setTimeInRxSignalStrengthLevelMs(timeInRxSignalStrengthLevelMs); s.setTxTimeMs(txTimeMs); + s.setMonitoredRailChargeConsumedMaMs(monitoredRailChargeConsumedMaMs); return s; } - /*@hide */ - public WifiBatteryStats getWifiBatteryStats() { - WifiBatteryStats s = new WifiBatteryStats(); - final int which = STATS_SINCE_CHARGED; - final long rawRealTime = SystemClock.elapsedRealtime() * 1000; - final ControllerActivityCounter counter = getWifiControllerActivity(); - final long idleTimeMs = counter.getIdleTimeCounter().getCountLocked(which); - final long scanTimeMs = counter.getScanTimeCounter().getCountLocked(which); - final long rxTimeMs = counter.getRxTimeCounter().getCountLocked(which); - final long txTimeMs = counter.getTxTimeCounters()[0].getCountLocked(which); - final long totalControllerActivityTimeMs - = computeBatteryRealtime(SystemClock.elapsedRealtime() * 1000, which) / 1000; - final long sleepTimeMs - = totalControllerActivityTimeMs - (idleTimeMs + rxTimeMs + txTimeMs); - final long energyConsumedMaMs = counter.getPowerCounter().getCountLocked(which); - long numAppScanRequest = 0; - for (int i = 0; i < mUidStats.size(); i++) { - numAppScanRequest += mUidStats.valueAt(i).mWifiScanTimer.getCountLocked(which); - } - long[] timeInStateMs = new long[NUM_WIFI_STATES]; - for (int i=0; i mRailInfoData = new ArrayMap<>(); + + private long mCellularTotalEnergyUseduWs = 0; + private long mWifiTotalEnergyUseduWs = 0; + private boolean mRailStatsAvailability = true; + + /** Updates the rail data map of all power monitor rails being monitored + * Function is called from native side + * @param index + * @param railName + * @param subSystemName + * @param timestampSinceBootMs + * @param energyUsedSinceBootuWs + */ + public void updateRailData(long index, String railName, String subSystemName, + long timestampSinceBootMs, long energyUsedSinceBootuWs) { + if (!(subSystemName.equals(WIFI_SUBSYSTEM) || subSystemName.equals(CELLULAR_SUBSYSTEM))) { + return; + } + RailInfoData node = mRailInfoData.get(index); + if (node == null) { + mRailInfoData.put(index, new RailInfoData(index, railName, subSystemName, + timestampSinceBootMs, energyUsedSinceBootuWs)); + if (subSystemName.equals(WIFI_SUBSYSTEM)) { + mWifiTotalEnergyUseduWs += energyUsedSinceBootuWs; + return; + } + if (subSystemName.equals(CELLULAR_SUBSYSTEM)) { + mCellularTotalEnergyUseduWs += energyUsedSinceBootuWs; + } + return; + } + long timeSinceLastLogMs = timestampSinceBootMs - node.timestampSinceBootMs; + long energyUsedSinceLastLoguWs = energyUsedSinceBootuWs - node.energyUsedSinceBootuWs; + if (timeSinceLastLogMs < 0 || energyUsedSinceLastLoguWs < 0) { + energyUsedSinceLastLoguWs = node.energyUsedSinceBootuWs; + } + node.timestampSinceBootMs = timestampSinceBootMs; + node.energyUsedSinceBootuWs = energyUsedSinceBootuWs; + if (subSystemName.equals(WIFI_SUBSYSTEM)) { + mWifiTotalEnergyUseduWs += energyUsedSinceLastLoguWs; + return; + } + if (subSystemName.equals(CELLULAR_SUBSYSTEM)) { + mCellularTotalEnergyUseduWs += energyUsedSinceLastLoguWs; + } + } + + /** resets the cellular total energy used aspect. + */ + public void resetCellularTotalEnergyUsed() { + mCellularTotalEnergyUseduWs = 0; + } + + /** resets the wifi total energy used aspect. + */ + public void resetWifiTotalEnergyUsed() { + mWifiTotalEnergyUseduWs = 0; + } + + public long getCellularTotalEnergyUseduWs() { + return mCellularTotalEnergyUseduWs; + } + + public long getWifiTotalEnergyUseduWs() { + return mWifiTotalEnergyUseduWs; + } + + /** reset the total energy subsystems + * + */ + public void reset() { + mCellularTotalEnergyUseduWs = 0; + mWifiTotalEnergyUseduWs = 0; + } + + public RailStats getRailStats() { + return this; + } + + public void setRailStatsAvailability(boolean railStatsAvailability) { + mRailStatsAvailability = railStatsAvailability; + } + + public boolean isRailStatsAvailable() { + return mRailStatsAvailability; + } + + /** Container class to contain rail data information */ + public static class RailInfoData { + private static final String TAG = "RailInfoData"; + public long index; + public String railName; + public String subSystemName; + public long timestampSinceBootMs; + public long energyUsedSinceBootuWs; + + private RailInfoData(long index, String railName, String subSystemName, + long timestampSinceBootMs, long energyUsedSinceBoot) { + this.index = index; + this.railName = railName; + this.subSystemName = subSystemName; + this.timestampSinceBootMs = timestampSinceBootMs; + this.energyUsedSinceBootuWs = energyUsedSinceBoot; + } + + /** print the rail data + * + */ + public void printData() { + Slog.d(TAG, "Index = " + index); + Slog.d(TAG, "RailName = " + railName); + Slog.d(TAG, "SubSystemName = " + subSystemName); + Slog.d(TAG, "TimestampSinceBootMs = " + timestampSinceBootMs); + Slog.d(TAG, "EnergyUsedSinceBootuWs = " + energyUsedSinceBootuWs); + } + } +} diff --git a/core/proto/android/os/batterystats.proto b/core/proto/android/os/batterystats.proto index a4167c1871947..516fa7b9336bc 100644 --- a/core/proto/android/os/batterystats.proto +++ b/core/proto/android/os/batterystats.proto @@ -58,6 +58,10 @@ message ControllerActivityProto { optional int64 duration_ms = 2; } repeated TxLevel tx = 4; + + // Total rail charge consumed by the monitored rails by the controller. The value may + // always be 0 if the device doesn't support monitored rail calculations. + optional double monitored_rail_charge_mah = 5; } message SystemProto { diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java index 24543b7974dfa..236797b575567 100644 --- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java +++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java @@ -477,6 +477,10 @@ class BatteryExternalStatsWorker implements BatteryStatsImpl.ExternalStatsSync { mStats.updateRpmStatsLocked(); } + if ((updateFlags & UPDATE_RAIL) != 0) { + mStats.updateRailStatsLocked(); + } + if (bluetoothInfo != null) { if (bluetoothInfo.isValid()) { mStats.updateBluetoothStateLocked(bluetoothInfo); diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java index 08900328a200f..4d5cb8cb44738 100644 --- a/services/core/java/com/android/server/am/BatteryStatsService.java +++ b/services/core/java/com/android/server/am/BatteryStatsService.java @@ -59,6 +59,7 @@ import com.android.internal.app.IBatteryStats; import com.android.internal.os.BatteryStatsHelper; import com.android.internal.os.BatteryStatsImpl; import com.android.internal.os.PowerProfile; +import com.android.internal.os.RailStats; import com.android.internal.os.RpmStats; import com.android.internal.util.DumpUtils; import com.android.internal.util.ParseUtils; @@ -84,7 +85,8 @@ import java.util.concurrent.Future; */ public final class BatteryStatsService extends IBatteryStats.Stub implements PowerManagerInternal.LowPowerModeListener, - BatteryStatsImpl.PlatformIdleStateCallback { + BatteryStatsImpl.PlatformIdleStateCallback, + BatteryStatsImpl.RailEnergyDataCallback { static final String TAG = "BatteryStatsService"; static final boolean DBG = false; @@ -98,6 +100,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub private native void getLowPowerStats(RpmStats rpmStats); private native int getPlatformLowPowerStats(ByteBuffer outBuffer); private native int getSubsystemLowPowerStats(ByteBuffer outBuffer); + private native void getRailEnergyPowerStats(RailStats railStats); private CharsetDecoder mDecoderStat = StandardCharsets.UTF_8 .newDecoder() .onMalformedInput(CodingErrorAction.REPLACE) @@ -120,6 +123,16 @@ public final class BatteryStatsService extends IBatteryStats.Stub } } + @Override + public void fillRailDataStats(RailStats railStats) { + if (DBG) Slog.d(TAG, "begin getRailEnergyPowerStats"); + try { + getRailEnergyPowerStats(railStats); + } finally { + if (DBG) Slog.d(TAG, "end getRailEnergyPowerStats"); + } + } + @Override public String getPlatformLowPowerStats() { if (DBG) Slog.d(TAG, "begin getPlatformLowPowerStats"); @@ -177,7 +190,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub return (umi != null) ? umi.getUserIds() : null; } }; - mStats = new BatteryStatsImpl(systemDir, handler, this, mUserManagerUserInfoProvider); + mStats = new BatteryStatsImpl(systemDir, handler, this, + this, mUserManagerUserInfoProvider); mWorker = new BatteryExternalStatsWorker(context, mStats); mStats.setExternalStatsSyncLocked(mWorker); mStats.setRadioScanningTimeoutLocked(mContext.getResources().getInteger( @@ -1460,7 +1474,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub in.unmarshall(raw, 0, raw.length); in.setDataPosition(0); BatteryStatsImpl checkinStats = new BatteryStatsImpl( - null, mStats.mHandler, null, mUserManagerUserInfoProvider); + null, mStats.mHandler, null, null, + mUserManagerUserInfoProvider); checkinStats.readSummaryFromParcel(in); in.recycle(); checkinStats.dumpProtoLocked( @@ -1498,7 +1513,8 @@ public final class BatteryStatsService extends IBatteryStats.Stub in.unmarshall(raw, 0, raw.length); in.setDataPosition(0); BatteryStatsImpl checkinStats = new BatteryStatsImpl( - null, mStats.mHandler, null, mUserManagerUserInfoProvider); + null, mStats.mHandler, null, null, + mUserManagerUserInfoProvider); checkinStats.readSummaryFromParcel(in); in.recycle(); checkinStats.dumpCheckinLocked(mContext, pw, apps, flags, diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp index 5c19ad33617c5..9cbb58d35b9f0 100644 --- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp +++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp @@ -17,6 +17,7 @@ #define LOG_TAG "BatteryStatsService" //#define LOG_NDEBUG 0 +#include #include #include #include @@ -28,6 +29,7 @@ #include #include #include +#include #include #include @@ -87,6 +89,15 @@ std::function gGetLowPowerStatsImpl = {}; std::function gGetPlatformLowPowerStatsImpl = {}; std::function gGetSubsystemLowPowerStatsImpl = {}; +// Cellular/Wifi power monitor rail information +static jmethodID jupdateRailData = NULL; +static jmethodID jsetRailStatsAvailability = NULL; + +std::function gGetRailEnergyPowerStatsImpl = {}; + +std::unordered_map> gPowerStatsHalRailNames = {}; +static bool power_monitor_available = false; + // The caller must be holding gPowerHalMutex. static void deinitPowerStatsLocked() { gPowerStatsHalV1_0 = nullptr; @@ -258,6 +269,7 @@ static bool initializePowerStats() { gPowerStatsHalStateNames.clear(); gPowerStatsHalPlatformIds.clear(); gPowerStatsHalSubsystemIds.clear(); + gPowerStatsHalRailNames.clear(); Return ret; ret = gPowerStatsHalV1_0->getPowerEntityInfo([](auto infos, auto status) { @@ -301,6 +313,27 @@ static bool initializePowerStats() { return false; } + // Get Power monitor rails available + ret = gPowerStatsHalV1_0->getRailInfo([](auto rails, auto status) { + if (status != Status::SUCCESS) { + ALOGW("Rail information is not available"); + power_monitor_available = false; + return; + } + + // Fill out rail names/subsystems into gPowerStatsHalRailNames + for (auto rail : rails) { + gPowerStatsHalRailNames.emplace(rail.index, + std::make_pair(rail.railName, rail.subsysName)); + } + if (!gPowerStatsHalRailNames.empty()) { + power_monitor_available = true; + } + }); + if (!checkResultLocked(ret, __func__)) { + return false; + } + return (!gPowerStatsHalEntityNames.empty()) && (!gPowerStatsHalStateNames.empty()); } @@ -517,6 +550,50 @@ static jint getPowerStatsHalSubsystemData(JNIEnv* env, jobject outBuf) { return total_added; } +static void getPowerStatsHalRailEnergyData(JNIEnv* env, jobject jrailStats) { + using android::hardware::power::stats::V1_0::Status; + using android::hardware::power::stats::V1_0::EnergyData; + + if (!getPowerStatsHalLocked()) { + ALOGE("failed to get power stats"); + return; + } + + if (!power_monitor_available) { + env->CallVoidMethod(jrailStats, jsetRailStatsAvailability, false); + ALOGW("Rail energy data is not available"); + return; + } + + // Get power rail energySinceBoot data + Return ret = gPowerStatsHalV1_0->getEnergyData({}, + [&env, &jrailStats](auto energyData, auto status) { + if (status == Status::NOT_SUPPORTED) { + ALOGW("getEnergyData is not supported"); + return; + } + + for (auto data : energyData) { + if (!(data.timestamp > LLONG_MAX || data.energy > LLONG_MAX)) { + env->CallVoidMethod(jrailStats, + jupdateRailData, + data.index, + env->NewStringUTF( + gPowerStatsHalRailNames.at(data.index).first.c_str()), + env->NewStringUTF( + gPowerStatsHalRailNames.at(data.index).second.c_str()), + data.timestamp, + data.energy); + } else { + ALOGE("Java long overflow seen. Rail index %d not updated", data.index); + } + } + }); + if (!checkResultLocked(ret, __func__)) { + ALOGE("getEnergyData failed"); + } +} + // The caller must be holding powerHalMutex. static void getPowerHalLowPowerData(JNIEnv* env, jobject jrpmStats) { sp powerHalV1_0 = getPowerHalV1_0(); @@ -761,11 +838,13 @@ static void setUpPowerStatsLocked() { gGetLowPowerStatsImpl = getPowerStatsHalLowPowerData; gGetPlatformLowPowerStatsImpl = getPowerStatsHalPlatformData; gGetSubsystemLowPowerStatsImpl = getPowerStatsHalSubsystemData; + gGetRailEnergyPowerStatsImpl = getPowerStatsHalRailEnergyData; } else if (android::hardware::power::V1_0::IPower::getService() != nullptr) { ALOGI("Using power HAL"); gGetLowPowerStatsImpl = getPowerHalLowPowerData; gGetPlatformLowPowerStatsImpl = getPowerHalPlatformData; gGetSubsystemLowPowerStatsImpl = getPowerHalSubsystemData; + gGetRailEnergyPowerStatsImpl = NULL; } } @@ -835,11 +914,44 @@ static jint getSubsystemLowPowerStats(JNIEnv* env, jobject /* clazz */, jobject return -1; } +static void getRailEnergyPowerStats(JNIEnv* env, jobject /* clazz */, jobject jrailStats) { + if (jrailStats == NULL) { + jniThrowException(env, "java/lang/NullPointerException", + "The railstats jni input jobject jrailStats is null."); + return; + } + if (jupdateRailData == NULL) { + ALOGE("A railstats jni jmethodID is null."); + return; + } + + std::lock_guard lock(gPowerHalMutex); + + if (!gGetRailEnergyPowerStatsImpl) { + setUpPowerStatsLocked(); + } + + if (gGetRailEnergyPowerStatsImpl) { + gGetRailEnergyPowerStatsImpl(env, jrailStats); + return; + } + + if (jsetRailStatsAvailability == NULL) { + ALOGE("setRailStatsAvailability jni jmethodID is null."); + return; + } + env->CallVoidMethod(jrailStats, jsetRailStatsAvailability, false); + ALOGE("Unable to load Power.Stats.HAL. Setting rail availability to false"); + return; +} + static const JNINativeMethod method_table[] = { { "nativeWaitWakeup", "(Ljava/nio/ByteBuffer;)I", (void*)nativeWaitWakeup }, { "getLowPowerStats", "(Lcom/android/internal/os/RpmStats;)V", (void*)getLowPowerStats }, { "getPlatformLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getPlatformLowPowerStats }, { "getSubsystemLowPowerStats", "(Ljava/nio/ByteBuffer;)I", (void*)getSubsystemLowPowerStats }, + { "getRailEnergyPowerStats", "(Lcom/android/internal/os/RailStats;)V", + (void*)getRailEnergyPowerStats }, }; int register_android_server_BatteryStatsService(JNIEnv *env) @@ -850,8 +962,9 @@ int register_android_server_BatteryStatsService(JNIEnv *env) env->FindClass("com/android/internal/os/RpmStats$PowerStatePlatformSleepState"); jclass clsPowerStateSubsystem = env->FindClass("com/android/internal/os/RpmStats$PowerStateSubsystem"); + jclass clsRailStats = env->FindClass("com/android/internal/os/RailStats"); if (clsRpmStats == NULL || clsPowerStatePlatformSleepState == NULL - || clsPowerStateSubsystem == NULL) { + || clsPowerStateSubsystem == NULL || clsRailStats == NULL) { ALOGE("A rpmstats jni jclass is null."); } else { jgetAndUpdatePlatformState = env->GetMethodID(clsRpmStats, "getAndUpdatePlatformState", @@ -862,6 +975,10 @@ int register_android_server_BatteryStatsService(JNIEnv *env) "(Ljava/lang/String;JI)V"); jputState = env->GetMethodID(clsPowerStateSubsystem, "putState", "(Ljava/lang/String;JI)V"); + jupdateRailData = env->GetMethodID(clsRailStats, "updateRailData", + "(JLjava/lang/String;Ljava/lang/String;JJ)V"); + jsetRailStatsAvailability = env->GetMethodID(clsRailStats, "setRailStatsAvailability", + "(Z)V"); } return jniRegisterNativeMethods(env, "com/android/server/am/BatteryStatsService",