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",