am 4718afcd: am 14b57010: Merge "BatteryStats: Record cpu power usage from /proc/uid_cputime" into mnc-dev

* commit '4718afcd2e5d52638ba1c4f58b2db6aea01171de':
  BatteryStats: Record cpu power usage from /proc/uid_cputime
This commit is contained in:
Adam Lesinski
2015-07-01 01:06:31 +00:00
committed by Android Git Automerger
3 changed files with 73 additions and 19 deletions

View File

@@ -184,6 +184,7 @@ public abstract class BatteryStats implements Parcelable {
private static final String UID_DATA = "uid";
private static final String APK_DATA = "apk";
private static final String PROCESS_DATA = "pr";
private static final String CPU_DATA = "cpu";
private static final String SENSOR_DATA = "sr";
private static final String VIBRATOR_DATA = "vib";
private static final String FOREGROUND_DATA = "fg";
@@ -456,9 +457,14 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getSystemCpuTimeUs(int which);
/**
* Get the total cpu power consumed (in milli-ampere-microseconds).
*/
public abstract long getCpuPowerMaUs(int which);
/**
* Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
* @param speedStep the index of the CPU speed. This is not the actual speed of the CPU.
* @param step the index of the CPU speed. This is not the actual speed of the CPU.
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
* @see BatteryStats#getCpuSpeedSteps()
*/
@@ -2905,6 +2911,14 @@ public abstract class BatteryStats implements Parcelable {
dumpLine(pw, uid, category, STATE_TIME_DATA, stateTimes);
}
final long userCpuTimeUs = u.getUserCpuTimeUs(which);
final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
final long powerCpuMaUs = u.getCpuPowerMaUs(which);
if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
dumpLine(pw, uid, category, CPU_DATA, userCpuTimeUs / 1000, systemCpuTimeUs / 1000,
powerCpuMaUs / 1000);
}
final ArrayMap<String, ? extends BatteryStats.Uid.Proc> processStats
= u.getProcessStats();
for (int ipr=processStats.size()-1; ipr>=0; ipr--) {
@@ -2970,6 +2984,10 @@ public abstract class BatteryStats implements Parcelable {
printer.print(BatteryStatsHelper.makemAh(power));
}
private void printmAh(StringBuilder sb, double power) {
sb.append(BatteryStatsHelper.makemAh(power));
}
/**
* Temporary for settings.
*/
@@ -4028,13 +4046,17 @@ public abstract class BatteryStats implements Parcelable {
final long userCpuTimeUs = u.getUserCpuTimeUs(which);
final long systemCpuTimeUs = u.getSystemCpuTimeUs(which);
if (userCpuTimeUs > 0 || systemCpuTimeUs > 0) {
final long powerCpuMaUs = u.getCpuPowerMaUs(which);
if (userCpuTimeUs > 0 || systemCpuTimeUs > 0 || powerCpuMaUs > 0) {
sb.setLength(0);
sb.append(prefix);
sb.append(" Total cpu time: u=");
formatTimeMs(sb, userCpuTimeUs / 1000);
sb.append("s=");
formatTimeMs(sb, systemCpuTimeUs / 1000);
sb.append("p=");
printmAh(sb, powerCpuMaUs / (1000.0 * 1000.0 * 60.0 * 60.0));
sb.append("mAh");
pw.println(sb.toString());
}

View File

@@ -106,7 +106,7 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
// Current on-disk Parcel version
private static final int VERSION = 129 + (USE_OLD_HISTORY ? 1000 : 0);
private static final int VERSION = 130 + (USE_OLD_HISTORY ? 1000 : 0);
// Maximum number of items we will record in the history.
private static final int MAX_HISTORY_ITEMS = 2000;
@@ -4386,6 +4386,7 @@ public final class BatteryStatsImpl extends BatteryStats {
LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
LongSamplingCounter[] mSpeedBins;
/**
@@ -4977,6 +4978,11 @@ public final class BatteryStatsImpl extends BatteryStats {
return mSystemCpuTime.getCountLocked(which);
}
@Override
public long getCpuPowerMaUs(int which) {
return mCpuPower.getCountLocked(which);
}
@Override
public long getTimeAtCpuSpeed(int step, int which) {
if (step >= 0 && step < mSpeedBins.length) {
@@ -5097,6 +5103,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUserCpuTime.reset(false);
mSystemCpuTime.reset(false);
mCpuPower.reset(false);
for (int i = 0; i < mSpeedBins.length; i++) {
LongSamplingCounter c = mSpeedBins[i];
if (c != null) {
@@ -5248,6 +5255,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUserCpuTime.detach();
mSystemCpuTime.detach();
mCpuPower.detach();
for (int i = 0; i < mSpeedBins.length; i++) {
LongSamplingCounter c = mSpeedBins[i];
if (c != null) {
@@ -5427,6 +5435,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUserCpuTime.writeToParcel(out);
mSystemCpuTime.writeToParcel(out);
mCpuPower.writeToParcel(out);
out.writeInt(mSpeedBins.length);
for (int i = 0; i < mSpeedBins.length; i++) {
@@ -5618,6 +5627,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
int bins = in.readInt();
int steps = getCpuSpeedSteps();
@@ -7964,7 +7974,8 @@ public final class BatteryStatsImpl extends BatteryStats {
mKernelUidCpuTimeReader.readDelta(!mOnBatteryInternal ? null :
new KernelUidCpuTimeReader.Callback() {
@Override
public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs) {
public void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs,
long powerMaUs) {
final Uid u = getUidStatsLocked(mapUid(uid));
// Accumulate the total system and user time.
@@ -7978,7 +7989,7 @@ public final class BatteryStatsImpl extends BatteryStats {
TimeUtils.formatDuration(userTimeUs / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(systemTimeUs / 1000, sb);
sb.append("\n");
sb.append(" p=").append(powerMaUs / 1000).append("mAms\n");
}
if (numWakelocksF > 0) {
@@ -7994,11 +8005,13 @@ public final class BatteryStatsImpl extends BatteryStats {
TimeUtils.formatDuration(userTimeUs / 1000, sb);
sb.append(" s=");
TimeUtils.formatDuration(systemTimeUs / 1000, sb);
sb.append(" p=").append(powerMaUs / 1000).append("mAms");
Slog.d(TAG, sb.toString());
}
u.mUserCpuTime.addCountLocked(userTimeUs);
u.mSystemCpuTime.addCountLocked(systemTimeUs);
u.mCpuPower.addCountLocked(powerMaUs);
// Add the cpu speeds to this UID. These are used as a ratio
// for computing the power this UID used.
@@ -9229,6 +9242,7 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mUserCpuTime.readSummaryFromParcelLocked(in);
u.mSystemCpuTime.readSummaryFromParcelLocked(in);
u.mCpuPower.readSummaryFromParcelLocked(in);
int NSB = in.readInt();
if (NSB > 100) {
@@ -9575,6 +9589,7 @@ public final class BatteryStatsImpl extends BatteryStats {
u.mUserCpuTime.writeSummaryFromParcelLocked(out);
u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
u.mCpuPower.writeSummaryFromParcelLocked(out);
out.writeInt(u.mSpeedBins.length);
for (int i = 0; i < u.mSpeedBins.length; i++) {

View File

@@ -30,7 +30,7 @@ import java.io.IOException;
/**
* Reads /proc/uid_cputime/show_uid_stat which has the line format:
*
* uid: user_time_micro_seconds system_time_micro_seconds
* uid: user_time_micro_seconds system_time_micro_seconds power_in_milli-amp-micro_seconds
*
* This provides the time a UID's processes spent executing in user-space and kernel-space.
* The file contains a monotonically increasing count of time for a single boot. This class
@@ -46,11 +46,18 @@ public class KernelUidCpuTimeReader {
* Callback interface for processing each line of the proc file.
*/
public interface Callback {
void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs);
/**
* @param uid UID of the app
* @param userTimeUs time spent executing in user space in microseconds
* @param systemTimeUs time spent executing in kernel space in microseconds
* @param powerMaUs power consumed executing, in milli-ampere microseconds
*/
void onUidCpuTime(int uid, long userTimeUs, long systemTimeUs, long powerMaUs);
}
private SparseLongArray mLastUserTimeUs = new SparseLongArray();
private SparseLongArray mLastSystemTimeUs = new SparseLongArray();
private SparseLongArray mLastPowerMaUs = new SparseLongArray();
private long mLastTimeReadUs = 0;
/**
@@ -70,50 +77,60 @@ public class KernelUidCpuTimeReader {
final int uid = Integer.parseInt(uidStr.substring(0, uidStr.length() - 1), 10);
final long userTimeUs = Long.parseLong(splitter.next(), 10);
final long systemTimeUs = Long.parseLong(splitter.next(), 10);
final long powerMaUs = Long.parseLong(splitter.next(), 10) / 1000;
if (callback != null) {
long userTimeDeltaUs = userTimeUs;
long systemTimeDeltaUs = systemTimeUs;
long powerDeltaMaUs = powerMaUs;
int index = mLastUserTimeUs.indexOfKey(uid);
if (index >= 0) {
userTimeDeltaUs -= mLastUserTimeUs.valueAt(index);
systemTimeDeltaUs -= mLastSystemTimeUs.valueAt(index);
powerDeltaMaUs -= mLastPowerMaUs.valueAt(index);
final long timeDiffUs = nowUs - mLastTimeReadUs;
if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 ||
if (userTimeDeltaUs < 0 || systemTimeDeltaUs < 0 || powerDeltaMaUs < 0 ||
userTimeDeltaUs > timeDiffUs || systemTimeDeltaUs > timeDiffUs) {
StringBuilder sb = new StringBuilder("Malformed cpu data!\n");
StringBuilder sb = new StringBuilder("Malformed cpu data for UID=");
sb.append(uid).append("!\n");
sb.append("Time between reads: ");
TimeUtils.formatDuration(timeDiffUs / 1000, sb);
sb.append("ms\n");
sb.append("\n");
sb.append("Previous times: u=");
TimeUtils.formatDuration(mLastUserTimeUs.valueAt(index) / 1000, sb);
sb.append("ms s=");
sb.append(" s=");
TimeUtils.formatDuration(mLastSystemTimeUs.valueAt(index) / 1000, sb);
sb.append("ms\n");
sb.append(" p=").append(mLastPowerMaUs.valueAt(index) / 1000);
sb.append("mAms\n");
sb.append("Current times: u=");
TimeUtils.formatDuration(userTimeUs / 1000, sb);
sb.append("ms s=");
sb.append(" s=");
TimeUtils.formatDuration(systemTimeUs / 1000, sb);
sb.append("ms\n");
sb.append("Delta for UID=").append(uid).append(": u=");
sb.append(" p=").append(powerMaUs / 1000);
sb.append("mAms\n");
sb.append("Delta: u=");
TimeUtils.formatDuration(userTimeDeltaUs / 1000, sb);
sb.append("ms s=");
sb.append(" s=");
TimeUtils.formatDuration(systemTimeDeltaUs / 1000, sb);
sb.append("ms");
sb.append(" p=").append(powerDeltaMaUs / 1000).append("mAms");
Slog.wtf(TAG, sb.toString());
userTimeDeltaUs = 0;
systemTimeDeltaUs = 0;
powerDeltaMaUs = 0;
}
}
if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0) {
callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs);
if (userTimeDeltaUs != 0 || systemTimeDeltaUs != 0 || powerDeltaMaUs != 0) {
callback.onUidCpuTime(uid, userTimeDeltaUs, systemTimeDeltaUs,
powerDeltaMaUs);
}
}
mLastUserTimeUs.put(uid, userTimeUs);
mLastSystemTimeUs.put(uid, systemTimeUs);
mLastPowerMaUs.put(uid, powerMaUs);
}
} catch (IOException e) {
Slog.e(TAG, "Failed to read uid_cputime", e);