Merge "BatteryStats: Better big-little CPU accounting" into mnc-dr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
680553957e
@@ -463,13 +463,15 @@ public abstract class BatteryStats implements Parcelable {
|
|||||||
public abstract long getCpuPowerMaUs(int which);
|
public abstract long getCpuPowerMaUs(int which);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed.
|
* Returns the approximate cpu time (in milliseconds) spent at a certain CPU speed for a
|
||||||
|
* given CPU cluster.
|
||||||
|
* @param cluster the index of the CPU cluster.
|
||||||
* @param step 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.
|
* @param which one of STATS_SINCE_CHARGED, STATS_SINCE_UNPLUGGED, or STATS_CURRENT.
|
||||||
* @see BatteryStats#getCpuSpeedSteps()
|
* @see PowerProfile.getNumCpuClusters()
|
||||||
|
* @see PowerProfile.getNumSpeedStepsInCpuCluster(int)
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public abstract long getTimeAtCpuSpeed(int cluster, int step, int which);
|
||||||
public abstract long getTimeAtCpuSpeed(int step, int which);
|
|
||||||
|
|
||||||
public static abstract class Sensor {
|
public static abstract class Sensor {
|
||||||
/*
|
/*
|
||||||
@@ -2276,9 +2278,6 @@ public abstract class BatteryStats implements Parcelable {
|
|||||||
|
|
||||||
public abstract Map<String, ? extends Timer> getKernelWakelockStats();
|
public abstract Map<String, ? extends Timer> getKernelWakelockStats();
|
||||||
|
|
||||||
/** Returns the number of different speeds that the CPU can run at */
|
|
||||||
public abstract int getCpuSpeedSteps();
|
|
||||||
|
|
||||||
public abstract void writeToParcelWithoutUids(Parcel out, int flags);
|
public abstract void writeToParcelWithoutUids(Parcel out, int flags);
|
||||||
|
|
||||||
private final static void formatTimeRaw(StringBuilder out, long seconds) {
|
private final static void formatTimeRaw(StringBuilder out, long seconds) {
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ public final class BatteryStatsHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mCpuPowerCalculator == null) {
|
if (mCpuPowerCalculator == null) {
|
||||||
mCpuPowerCalculator = new CpuPowerCalculator();
|
mCpuPowerCalculator = new CpuPowerCalculator(mPowerProfile);
|
||||||
}
|
}
|
||||||
mCpuPowerCalculator.reset();
|
mCpuPowerCalculator.reset();
|
||||||
|
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
|
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
|
||||||
|
|
||||||
// Current on-disk Parcel version
|
// Current on-disk Parcel version
|
||||||
private static final int VERSION = 130 + (USE_OLD_HISTORY ? 1000 : 0);
|
private static final int VERSION = 131 + (USE_OLD_HISTORY ? 1000 : 0);
|
||||||
|
|
||||||
// Maximum number of items we will record in the history.
|
// Maximum number of items we will record in the history.
|
||||||
private static final int MAX_HISTORY_ITEMS = 2000;
|
private static final int MAX_HISTORY_ITEMS = 2000;
|
||||||
@@ -118,8 +118,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
// in to one common name.
|
// in to one common name.
|
||||||
private static final int MAX_WAKELOCKS_PER_UID = 100;
|
private static final int MAX_WAKELOCKS_PER_UID = 100;
|
||||||
|
|
||||||
private static int sNumSpeedSteps;
|
|
||||||
|
|
||||||
private final JournaledFile mFile;
|
private final JournaledFile mFile;
|
||||||
public final AtomicFile mCheckinFile;
|
public final AtomicFile mCheckinFile;
|
||||||
public final AtomicFile mDailyFile;
|
public final AtomicFile mDailyFile;
|
||||||
@@ -133,7 +131,7 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
|
private final KernelWakelockStats mTmpWakelockStats = new KernelWakelockStats();
|
||||||
|
|
||||||
private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
|
private final KernelUidCpuTimeReader mKernelUidCpuTimeReader = new KernelUidCpuTimeReader();
|
||||||
private final KernelCpuSpeedReader mKernelCpuSpeedReader = new KernelCpuSpeedReader();
|
private KernelCpuSpeedReader[] mKernelCpuSpeedReaders;
|
||||||
|
|
||||||
public interface BatteryCallback {
|
public interface BatteryCallback {
|
||||||
public void batteryNeedsCpuUpdate();
|
public void batteryNeedsCpuUpdate();
|
||||||
@@ -4411,7 +4409,7 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
|
LongSamplingCounter mUserCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
|
||||||
LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
|
LongSamplingCounter mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase);
|
||||||
LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
|
LongSamplingCounter mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase);
|
||||||
LongSamplingCounter[] mSpeedBins;
|
LongSamplingCounter[][] mCpuClusterSpeed;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The statistics we have collected for this uid's wake locks.
|
* The statistics we have collected for this uid's wake locks.
|
||||||
@@ -4470,7 +4468,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
|
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
|
||||||
mWifiMulticastTimers, mOnBatteryTimeBase);
|
mWifiMulticastTimers, mOnBatteryTimeBase);
|
||||||
mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
|
mProcessStateTimer = new StopwatchTimer[NUM_PROCESS_STATE];
|
||||||
mSpeedBins = new LongSamplingCounter[getCpuSpeedSteps()];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -5008,10 +5005,18 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long getTimeAtCpuSpeed(int step, int which) {
|
public long getTimeAtCpuSpeed(int cluster, int step, int which) {
|
||||||
if (step >= 0 && step < mSpeedBins.length) {
|
if (mCpuClusterSpeed != null) {
|
||||||
if (mSpeedBins[step] != null) {
|
if (cluster >= 0 && cluster < mCpuClusterSpeed.length) {
|
||||||
return mSpeedBins[step].getCountLocked(which);
|
final LongSamplingCounter[] cpuSpeeds = mCpuClusterSpeed[cluster];
|
||||||
|
if (cpuSpeeds != null) {
|
||||||
|
if (step >= 0 && step < cpuSpeeds.length) {
|
||||||
|
final LongSamplingCounter c = cpuSpeeds[step];
|
||||||
|
if (c != null) {
|
||||||
|
return c.getCountLocked(which);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@@ -5128,10 +5133,16 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mUserCpuTime.reset(false);
|
mUserCpuTime.reset(false);
|
||||||
mSystemCpuTime.reset(false);
|
mSystemCpuTime.reset(false);
|
||||||
mCpuPower.reset(false);
|
mCpuPower.reset(false);
|
||||||
for (int i = 0; i < mSpeedBins.length; i++) {
|
|
||||||
LongSamplingCounter c = mSpeedBins[i];
|
if (mCpuClusterSpeed != null) {
|
||||||
if (c != null) {
|
for (LongSamplingCounter[] speeds : mCpuClusterSpeed) {
|
||||||
c.reset(false);
|
if (speeds != null) {
|
||||||
|
for (LongSamplingCounter speed : speeds) {
|
||||||
|
if (speed != null) {
|
||||||
|
speed.reset(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5280,10 +5291,16 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mUserCpuTime.detach();
|
mUserCpuTime.detach();
|
||||||
mSystemCpuTime.detach();
|
mSystemCpuTime.detach();
|
||||||
mCpuPower.detach();
|
mCpuPower.detach();
|
||||||
for (int i = 0; i < mSpeedBins.length; i++) {
|
|
||||||
LongSamplingCounter c = mSpeedBins[i];
|
if (mCpuClusterSpeed != null) {
|
||||||
if (c != null) {
|
for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
|
||||||
c.detach();
|
if (cpuSpeeds != null) {
|
||||||
|
for (LongSamplingCounter c : cpuSpeeds) {
|
||||||
|
if (c != null) {
|
||||||
|
c.detach();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5461,15 +5478,27 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mSystemCpuTime.writeToParcel(out);
|
mSystemCpuTime.writeToParcel(out);
|
||||||
mCpuPower.writeToParcel(out);
|
mCpuPower.writeToParcel(out);
|
||||||
|
|
||||||
out.writeInt(mSpeedBins.length);
|
if (mCpuClusterSpeed != null) {
|
||||||
for (int i = 0; i < mSpeedBins.length; i++) {
|
out.writeInt(1);
|
||||||
LongSamplingCounter c = mSpeedBins[i];
|
out.writeInt(mCpuClusterSpeed.length);
|
||||||
if (c != null) {
|
for (LongSamplingCounter[] cpuSpeeds : mCpuClusterSpeed) {
|
||||||
out.writeInt(1);
|
if (cpuSpeeds != null) {
|
||||||
c.writeToParcel(out);
|
out.writeInt(1);
|
||||||
} else {
|
out.writeInt(cpuSpeeds.length);
|
||||||
out.writeInt(0);
|
for (LongSamplingCounter c : cpuSpeeds) {
|
||||||
|
if (c != null) {
|
||||||
|
out.writeInt(1);
|
||||||
|
c.writeToParcel(out);
|
||||||
|
} else {
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
out.writeInt(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5653,13 +5682,32 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
|
mSystemCpuTime = new LongSamplingCounter(mOnBatteryTimeBase, in);
|
||||||
mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
|
mCpuPower = new LongSamplingCounter(mOnBatteryTimeBase, in);
|
||||||
|
|
||||||
int bins = in.readInt();
|
if (in.readInt() != 0) {
|
||||||
int steps = getCpuSpeedSteps();
|
int numCpuClusters = in.readInt();
|
||||||
mSpeedBins = new LongSamplingCounter[bins >= steps ? bins : steps];
|
if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numCpuClusters) {
|
||||||
for (int i = 0; i < bins; i++) {
|
throw new ParcelFormatException("Incompatible number of cpu clusters");
|
||||||
if (in.readInt() != 0) {
|
|
||||||
mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase, in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mCpuClusterSpeed = new LongSamplingCounter[numCpuClusters][];
|
||||||
|
for (int cluster = 0; cluster < numCpuClusters; cluster++) {
|
||||||
|
if (in.readInt() != 0) {
|
||||||
|
int numSpeeds = in.readInt();
|
||||||
|
if (mPowerProfile != null &&
|
||||||
|
mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != numSpeeds) {
|
||||||
|
throw new ParcelFormatException("Incompatible number of cpu speeds");
|
||||||
|
}
|
||||||
|
|
||||||
|
final LongSamplingCounter[] cpuSpeeds = new LongSamplingCounter[numSpeeds];
|
||||||
|
mCpuClusterSpeed[cluster] = cpuSpeeds;
|
||||||
|
for (int speed = 0; speed < numSpeeds; speed++) {
|
||||||
|
if (in.readInt() != 0) {
|
||||||
|
cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase, in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mCpuClusterSpeed = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6874,6 +6922,19 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
public void setPowerProfile(PowerProfile profile) {
|
public void setPowerProfile(PowerProfile profile) {
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
mPowerProfile = profile;
|
mPowerProfile = profile;
|
||||||
|
|
||||||
|
// We need to initialize the KernelCpuSpeedReaders to read from
|
||||||
|
// the first cpu of each core. Once we have the PowerProfile, we have access to this
|
||||||
|
// information.
|
||||||
|
final int numClusters = mPowerProfile.getNumCpuClusters();
|
||||||
|
mKernelCpuSpeedReaders = new KernelCpuSpeedReader[numClusters];
|
||||||
|
int firstCpuOfCluster = 0;
|
||||||
|
for (int i = 0; i < numClusters; i++) {
|
||||||
|
final int numSpeedSteps = mPowerProfile.getNumSpeedStepsInCpuCluster(i);
|
||||||
|
mKernelCpuSpeedReaders[i] = new KernelCpuSpeedReader(firstCpuOfCluster,
|
||||||
|
numSpeedSteps);
|
||||||
|
firstCpuOfCluster += mPowerProfile.getNumCoresInCpuCluster(i);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6881,10 +6942,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mCallback = cb;
|
mCallback = cb;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setNumSpeedSteps(int steps) {
|
|
||||||
if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setRadioScanningTimeout(long timeout) {
|
public void setRadioScanningTimeout(long timeout) {
|
||||||
if (mPhoneSignalScanningTimer != null) {
|
if (mPhoneSignalScanningTimer != null) {
|
||||||
mPhoneSignalScanningTimer.setTimeout(timeout);
|
mPhoneSignalScanningTimer.setTimeout(timeout);
|
||||||
@@ -7997,9 +8054,11 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
// If no app is holding a wakelock, then the distribution is normal.
|
// If no app is holding a wakelock, then the distribution is normal.
|
||||||
final int wakelockWeight = 50;
|
final int wakelockWeight = 50;
|
||||||
|
|
||||||
// Read the time spent at various cpu frequencies.
|
// Read the time spent for each cluster at various cpu frequencies.
|
||||||
final int cpuSpeedSteps = getCpuSpeedSteps();
|
final long[][] clusterSpeeds = new long[mKernelCpuSpeedReaders.length][];
|
||||||
final long[] cpuSpeeds = mKernelCpuSpeedReader.readDelta();
|
for (int cluster = 0; cluster < mKernelCpuSpeedReaders.length; cluster++) {
|
||||||
|
clusterSpeeds[cluster] = mKernelCpuSpeedReaders[cluster].readDelta();
|
||||||
|
}
|
||||||
|
|
||||||
int numWakelocks = 0;
|
int numWakelocks = 0;
|
||||||
|
|
||||||
@@ -8072,11 +8131,23 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
|
|
||||||
// Add the cpu speeds to this UID. These are used as a ratio
|
// Add the cpu speeds to this UID. These are used as a ratio
|
||||||
// for computing the power this UID used.
|
// for computing the power this UID used.
|
||||||
for (int i = 0; i < cpuSpeedSteps; i++) {
|
if (u.mCpuClusterSpeed == null) {
|
||||||
if (u.mSpeedBins[i] == null) {
|
u.mCpuClusterSpeed = new LongSamplingCounter[clusterSpeeds.length][];
|
||||||
u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
|
}
|
||||||
|
|
||||||
|
for (int cluster = 0; cluster < clusterSpeeds.length; cluster++) {
|
||||||
|
if (u.mCpuClusterSpeed[cluster] == null) {
|
||||||
|
u.mCpuClusterSpeed[cluster] =
|
||||||
|
new LongSamplingCounter[clusterSpeeds[cluster].length];
|
||||||
|
}
|
||||||
|
|
||||||
|
final LongSamplingCounter[] cpuSpeeds = u.mCpuClusterSpeed[cluster];
|
||||||
|
for (int speed = 0; speed < clusterSpeeds[cluster].length; speed++) {
|
||||||
|
if (cpuSpeeds[speed] == null) {
|
||||||
|
cpuSpeeds[speed] = new LongSamplingCounter(mOnBatteryTimeBase);
|
||||||
|
}
|
||||||
|
cpuSpeeds[speed].addCountLocked(clusterSpeeds[cluster][speed]);
|
||||||
}
|
}
|
||||||
u.mSpeedBins[i].addCountLocked(cpuSpeeds[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -8776,11 +8847,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCpuSpeedSteps() {
|
|
||||||
return sNumSpeedSteps;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the statistics object for a particular uid, creating if needed.
|
* Retrieve the statistics object for a particular uid, creating if needed.
|
||||||
*/
|
*/
|
||||||
@@ -9216,11 +9282,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sNumSpeedSteps = in.readInt();
|
|
||||||
if (sNumSpeedSteps < 0 || sNumSpeedSteps > 100) {
|
|
||||||
throw new ParcelFormatException("Bad speed steps in data: " + sNumSpeedSteps);
|
|
||||||
}
|
|
||||||
|
|
||||||
final int NU = in.readInt();
|
final int NU = in.readInt();
|
||||||
if (NU > 10000) {
|
if (NU > 10000) {
|
||||||
throw new ParcelFormatException("File corrupt: too many uids " + NU);
|
throw new ParcelFormatException("File corrupt: too many uids " + NU);
|
||||||
@@ -9304,17 +9365,33 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
u.mSystemCpuTime.readSummaryFromParcelLocked(in);
|
u.mSystemCpuTime.readSummaryFromParcelLocked(in);
|
||||||
u.mCpuPower.readSummaryFromParcelLocked(in);
|
u.mCpuPower.readSummaryFromParcelLocked(in);
|
||||||
|
|
||||||
int NSB = in.readInt();
|
if (in.readInt() != 0) {
|
||||||
if (NSB > 100) {
|
final int numClusters = in.readInt();
|
||||||
throw new ParcelFormatException("File corrupt: too many speed bins " + NSB);
|
if (mPowerProfile != null && mPowerProfile.getNumCpuClusters() != numClusters) {
|
||||||
}
|
throw new ParcelFormatException("Incompatible cpu cluster arrangement");
|
||||||
|
|
||||||
u.mSpeedBins = new LongSamplingCounter[NSB];
|
|
||||||
for (int i=0; i<NSB; i++) {
|
|
||||||
if (in.readInt() != 0) {
|
|
||||||
u.mSpeedBins[i] = new LongSamplingCounter(mOnBatteryTimeBase);
|
|
||||||
u.mSpeedBins[i].readSummaryFromParcelLocked(in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u.mCpuClusterSpeed = new LongSamplingCounter[numClusters][];
|
||||||
|
for (int cluster = 0; cluster < numClusters; cluster++) {
|
||||||
|
int NSB = in.readInt();
|
||||||
|
if (mPowerProfile != null &&
|
||||||
|
mPowerProfile.getNumSpeedStepsInCpuCluster(cluster) != NSB) {
|
||||||
|
throw new ParcelFormatException("File corrupt: too many speed bins " + NSB);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in.readInt() != 0) {
|
||||||
|
u.mCpuClusterSpeed[cluster] = new LongSamplingCounter[NSB];
|
||||||
|
for (int speed = 0; speed < NSB; speed++) {
|
||||||
|
if (in.readInt() != 0) {
|
||||||
|
u.mCpuClusterSpeed[cluster][speed] = new LongSamplingCounter(
|
||||||
|
mOnBatteryTimeBase);
|
||||||
|
u.mCpuClusterSpeed[cluster][speed].readSummaryFromParcelLocked(in);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
u.mCpuClusterSpeed = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
int NW = in.readInt();
|
int NW = in.readInt();
|
||||||
@@ -9531,7 +9608,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeInt(sNumSpeedSteps);
|
|
||||||
final int NU = mUidStats.size();
|
final int NU = mUidStats.size();
|
||||||
out.writeInt(NU);
|
out.writeInt(NU);
|
||||||
for (int iu = 0; iu < NU; iu++) {
|
for (int iu = 0; iu < NU; iu++) {
|
||||||
@@ -9640,15 +9716,27 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
|
u.mSystemCpuTime.writeSummaryFromParcelLocked(out);
|
||||||
u.mCpuPower.writeSummaryFromParcelLocked(out);
|
u.mCpuPower.writeSummaryFromParcelLocked(out);
|
||||||
|
|
||||||
out.writeInt(u.mSpeedBins.length);
|
if (u.mCpuClusterSpeed != null) {
|
||||||
for (int i = 0; i < u.mSpeedBins.length; i++) {
|
out.writeInt(1);
|
||||||
LongSamplingCounter speedBin = u.mSpeedBins[i];
|
out.writeInt(u.mCpuClusterSpeed.length);
|
||||||
if (speedBin != null) {
|
for (LongSamplingCounter[] cpuSpeeds : u.mCpuClusterSpeed) {
|
||||||
out.writeInt(1);
|
if (cpuSpeeds != null) {
|
||||||
speedBin.writeSummaryFromParcelLocked(out);
|
out.writeInt(1);
|
||||||
} else {
|
out.writeInt(cpuSpeeds.length);
|
||||||
out.writeInt(0);
|
for (LongSamplingCounter c : cpuSpeeds) {
|
||||||
|
if (c != null) {
|
||||||
|
out.writeInt(1);
|
||||||
|
c.writeSummaryFromParcelLocked(out);
|
||||||
|
} else {
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.writeInt(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
out.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
|
final ArrayMap<String, Uid.Wakelock> wakeStats = u.mWakelockStats.getMap();
|
||||||
@@ -9897,8 +9985,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
mFlashlightTurnedOnTimers.clear();
|
mFlashlightTurnedOnTimers.clear();
|
||||||
mCameraTurnedOnTimers.clear();
|
mCameraTurnedOnTimers.clear();
|
||||||
|
|
||||||
sNumSpeedSteps = in.readInt();
|
|
||||||
|
|
||||||
int numUids = in.readInt();
|
int numUids = in.readInt();
|
||||||
mUidStats.clear();
|
mUidStats.clear();
|
||||||
for (int i = 0; i < numUids; i++) {
|
for (int i = 0; i < numUids; i++) {
|
||||||
@@ -10037,8 +10123,6 @@ public final class BatteryStatsImpl extends BatteryStats {
|
|||||||
out.writeInt(0);
|
out.writeInt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
out.writeInt(sNumSpeedSteps);
|
|
||||||
|
|
||||||
if (inclUids) {
|
if (inclUids) {
|
||||||
int size = mUidStats.size();
|
int size = mUidStats.size();
|
||||||
out.writeInt(size);
|
out.writeInt(size);
|
||||||
|
|||||||
@@ -22,12 +22,47 @@ import android.util.Log;
|
|||||||
public class CpuPowerCalculator extends PowerCalculator {
|
public class CpuPowerCalculator extends PowerCalculator {
|
||||||
private static final String TAG = "CpuPowerCalculator";
|
private static final String TAG = "CpuPowerCalculator";
|
||||||
private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
|
private static final boolean DEBUG = BatteryStatsHelper.DEBUG;
|
||||||
|
private final PowerProfile mProfile;
|
||||||
|
|
||||||
|
public CpuPowerCalculator(PowerProfile profile) {
|
||||||
|
mProfile = profile;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
|
public void calculateApp(BatterySipper app, BatteryStats.Uid u, long rawRealtimeUs,
|
||||||
long rawUptimeUs, int statsType) {
|
long rawUptimeUs, int statsType) {
|
||||||
|
|
||||||
app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
|
app.cpuTimeMs = (u.getUserCpuTimeUs(statsType) + u.getSystemCpuTimeUs(statsType)) / 1000;
|
||||||
app.cpuPowerMah = (double) u.getCpuPowerMaUs(statsType) / (60.0 * 60.0 * 1000.0 * 1000.0);
|
|
||||||
|
// Aggregate total time spent on each cluster.
|
||||||
|
long totalTime = 0;
|
||||||
|
final int numClusters = mProfile.getNumCpuClusters();
|
||||||
|
for (int cluster = 0; cluster < numClusters; cluster++) {
|
||||||
|
final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
|
||||||
|
for (int speed = 0; speed < speedsForCluster; speed++) {
|
||||||
|
totalTime += u.getTimeAtCpuSpeed(cluster, speed, statsType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
totalTime = Math.max(totalTime, 1);
|
||||||
|
|
||||||
|
double cpuPowerMaMs = 0;
|
||||||
|
for (int cluster = 0; cluster < numClusters; cluster++) {
|
||||||
|
final int speedsForCluster = mProfile.getNumSpeedStepsInCpuCluster(cluster);
|
||||||
|
for (int speed = 0; speed < speedsForCluster; speed++) {
|
||||||
|
final double ratio = (double) u.getTimeAtCpuSpeed(cluster, speed, statsType) /
|
||||||
|
totalTime;
|
||||||
|
final double cpuSpeedStepPower = ratio * app.cpuTimeMs *
|
||||||
|
mProfile.getAveragePowerForCpu(cluster, speed);
|
||||||
|
if (DEBUG && ratio != 0) {
|
||||||
|
Log.d(TAG, "UID " + u.getUid() + ": CPU cluster #" + cluster + " step #"
|
||||||
|
+ speed + " ratio=" + BatteryStatsHelper.makemAh(ratio) + " power="
|
||||||
|
+ BatteryStatsHelper.makemAh(cpuSpeedStepPower / (60 * 60 * 1000)));
|
||||||
|
}
|
||||||
|
cpuPowerMaMs += cpuSpeedStepPower;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
app.cpuPowerMah = cpuPowerMaMs / (60 * 60 * 1000);
|
||||||
|
|
||||||
if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
|
if (DEBUG && (app.cpuTimeMs != 0 || app.cpuPowerMah != 0)) {
|
||||||
Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
|
Log.d(TAG, "UID " + u.getUid() + ": CPU time=" + app.cpuTimeMs + " ms power="
|
||||||
+ BatteryStatsHelper.makemAh(app.cpuPowerMah));
|
+ BatteryStatsHelper.makemAh(app.cpuPowerMah));
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ import java.io.IOException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads CPU time spent at various frequencies and provides a delta from the last call to
|
* Reads CPU time of a specific core spent at various frequencies and provides a delta from the
|
||||||
* {@link #readDelta}. Each line in the proc file has the format:
|
* last call to {@link #readDelta}. Each line in the proc file has the format:
|
||||||
*
|
*
|
||||||
* freq time
|
* freq time
|
||||||
*
|
*
|
||||||
@@ -33,12 +33,20 @@ import java.util.Arrays;
|
|||||||
*/
|
*/
|
||||||
public class KernelCpuSpeedReader {
|
public class KernelCpuSpeedReader {
|
||||||
private static final String TAG = "KernelCpuSpeedReader";
|
private static final String TAG = "KernelCpuSpeedReader";
|
||||||
private static final String sProcFile =
|
|
||||||
"/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state";
|
|
||||||
private static final int MAX_SPEEDS = 60;
|
|
||||||
|
|
||||||
private long[] mLastSpeedTimes = new long[MAX_SPEEDS];
|
private final String mProcFile;
|
||||||
private long[] mDeltaSpeedTimes = new long[MAX_SPEEDS];
|
private final long[] mLastSpeedTimes;
|
||||||
|
private final long[] mDeltaSpeedTimes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cpuNumber The cpu (cpu0, cpu1, etc) whose state to read.
|
||||||
|
*/
|
||||||
|
public KernelCpuSpeedReader(int cpuNumber, int numSpeedSteps) {
|
||||||
|
mProcFile = String.format("/sys/devices/system/cpu/cpu%d/cpufreq/stats/time_in_state",
|
||||||
|
cpuNumber);
|
||||||
|
mLastSpeedTimes = new long[numSpeedSteps];
|
||||||
|
mDeltaSpeedTimes = new long[numSpeedSteps];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The returned array is modified in subsequent calls to {@link #readDelta}.
|
* The returned array is modified in subsequent calls to {@link #readDelta}.
|
||||||
@@ -46,7 +54,7 @@ public class KernelCpuSpeedReader {
|
|||||||
* {@link #readDelta}.
|
* {@link #readDelta}.
|
||||||
*/
|
*/
|
||||||
public long[] readDelta() {
|
public long[] readDelta() {
|
||||||
try (BufferedReader reader = new BufferedReader(new FileReader(sProcFile))) {
|
try (BufferedReader reader = new BufferedReader(new FileReader(mProcFile))) {
|
||||||
TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
|
TextUtils.SimpleStringSplitter splitter = new TextUtils.SimpleStringSplitter(' ');
|
||||||
String line;
|
String line;
|
||||||
int speedIndex = 0;
|
int speedIndex = 0;
|
||||||
@@ -56,12 +64,18 @@ public class KernelCpuSpeedReader {
|
|||||||
|
|
||||||
// The proc file reports time in 1/100 sec, so convert to milliseconds.
|
// The proc file reports time in 1/100 sec, so convert to milliseconds.
|
||||||
long time = Long.parseLong(splitter.next()) * 10;
|
long time = Long.parseLong(splitter.next()) * 10;
|
||||||
mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex];
|
if (time < mLastSpeedTimes[speedIndex]) {
|
||||||
|
// The stats reset when the cpu hotplugged. That means that the time
|
||||||
|
// we read is offset from 0, so the time is the delta.
|
||||||
|
mDeltaSpeedTimes[speedIndex] = time;
|
||||||
|
} else {
|
||||||
|
mDeltaSpeedTimes[speedIndex] = time - mLastSpeedTimes[speedIndex];
|
||||||
|
}
|
||||||
mLastSpeedTimes[speedIndex] = time;
|
mLastSpeedTimes[speedIndex] = time;
|
||||||
speedIndex++;
|
speedIndex++;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Slog.e(TAG, "Failed to read cpu-freq", e);
|
Slog.e(TAG, "Failed to read cpu-freq: " + e.getMessage());
|
||||||
Arrays.fill(mDeltaSpeedTimes, 0);
|
Arrays.fill(mDeltaSpeedTimes, 0);
|
||||||
}
|
}
|
||||||
return mDeltaSpeedTimes;
|
return mDeltaSpeedTimes;
|
||||||
|
|||||||
@@ -59,6 +59,7 @@ public class PowerProfile {
|
|||||||
/**
|
/**
|
||||||
* Power consumption when CPU is in power collapse mode.
|
* Power consumption when CPU is in power collapse mode.
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static final String POWER_CPU_ACTIVE = "cpu.active";
|
public static final String POWER_CPU_ACTIVE = "cpu.active";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -163,6 +164,7 @@ public class PowerProfile {
|
|||||||
*/
|
*/
|
||||||
public static final String POWER_CAMERA = "camera.avg";
|
public static final String POWER_CAMERA = "camera.avg";
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public static final String POWER_CPU_SPEEDS = "cpu.speeds";
|
public static final String POWER_CPU_SPEEDS = "cpu.speeds";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -191,6 +193,7 @@ public class PowerProfile {
|
|||||||
if (sPowerMap.size() == 0) {
|
if (sPowerMap.size() == 0) {
|
||||||
readPowerValuesFromXml(context);
|
readPowerValuesFromXml(context);
|
||||||
}
|
}
|
||||||
|
initCpuClusters();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readPowerValuesFromXml(Context context) {
|
private void readPowerValuesFromXml(Context context) {
|
||||||
@@ -249,7 +252,7 @@ public class PowerProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now collect other config variables.
|
// Now collect other config variables.
|
||||||
int[] configResIds = new int[] {
|
int[] configResIds = new int[]{
|
||||||
com.android.internal.R.integer.config_bluetooth_idle_cur_ma,
|
com.android.internal.R.integer.config_bluetooth_idle_cur_ma,
|
||||||
com.android.internal.R.integer.config_bluetooth_rx_cur_ma,
|
com.android.internal.R.integer.config_bluetooth_rx_cur_ma,
|
||||||
com.android.internal.R.integer.config_bluetooth_tx_cur_ma,
|
com.android.internal.R.integer.config_bluetooth_tx_cur_ma,
|
||||||
@@ -260,7 +263,7 @@ public class PowerProfile {
|
|||||||
com.android.internal.R.integer.config_wifi_operating_voltage_mv,
|
com.android.internal.R.integer.config_wifi_operating_voltage_mv,
|
||||||
};
|
};
|
||||||
|
|
||||||
String[] configResIdKeys = new String[] {
|
String[] configResIdKeys = new String[]{
|
||||||
POWER_BLUETOOTH_CONTROLLER_IDLE,
|
POWER_BLUETOOTH_CONTROLLER_IDLE,
|
||||||
POWER_BLUETOOTH_CONTROLLER_RX,
|
POWER_BLUETOOTH_CONTROLLER_RX,
|
||||||
POWER_BLUETOOTH_CONTROLLER_TX,
|
POWER_BLUETOOTH_CONTROLLER_TX,
|
||||||
@@ -279,6 +282,69 @@ public class PowerProfile {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CpuClusterKey[] mCpuClusters;
|
||||||
|
|
||||||
|
private static final String POWER_CPU_CLUSTER_CORE_COUNT = "cpu.clusters.cores";
|
||||||
|
private static final String POWER_CPU_CLUSTER_SPEED_PREFIX = "cpu.speeds.cluster";
|
||||||
|
private static final String POWER_CPU_CLUSTER_ACTIVE_PREFIX = "cpu.active.cluster";
|
||||||
|
|
||||||
|
@SuppressWarnings("deprecated")
|
||||||
|
private void initCpuClusters() {
|
||||||
|
// Figure out how many CPU clusters we're dealing with
|
||||||
|
final Object obj = sPowerMap.get(POWER_CPU_CLUSTER_CORE_COUNT);
|
||||||
|
if (obj == null || !(obj instanceof Double[])) {
|
||||||
|
// Default to single.
|
||||||
|
mCpuClusters = new CpuClusterKey[1];
|
||||||
|
mCpuClusters[0] = new CpuClusterKey(POWER_CPU_SPEEDS, POWER_CPU_ACTIVE, 1);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final Double[] array = (Double[]) obj;
|
||||||
|
mCpuClusters = new CpuClusterKey[array.length];
|
||||||
|
for (int cluster = 0; cluster < array.length; cluster++) {
|
||||||
|
int numCpusInCluster = (int) Math.round(array[cluster]);
|
||||||
|
mCpuClusters[cluster] = new CpuClusterKey(
|
||||||
|
POWER_CPU_CLUSTER_SPEED_PREFIX + cluster,
|
||||||
|
POWER_CPU_CLUSTER_ACTIVE_PREFIX + cluster,
|
||||||
|
numCpusInCluster);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class CpuClusterKey {
|
||||||
|
private final String timeKey;
|
||||||
|
private final String powerKey;
|
||||||
|
private final int numCpus;
|
||||||
|
|
||||||
|
private CpuClusterKey(String timeKey, String powerKey, int numCpus) {
|
||||||
|
this.timeKey = timeKey;
|
||||||
|
this.powerKey = powerKey;
|
||||||
|
this.numCpus = numCpus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumCpuClusters() {
|
||||||
|
return mCpuClusters.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumCoresInCpuCluster(int index) {
|
||||||
|
return mCpuClusters[index].numCpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNumSpeedStepsInCpuCluster(int index) {
|
||||||
|
Object value = sPowerMap.get(mCpuClusters[index].timeKey);
|
||||||
|
if (value != null && value instanceof Double[]) {
|
||||||
|
return ((Double[])value).length;
|
||||||
|
}
|
||||||
|
return 1; // Only one speed
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getAveragePowerForCpu(int cluster, int step) {
|
||||||
|
if (cluster >= 0 && cluster < mCpuClusters.length) {
|
||||||
|
return getAveragePower(mCpuClusters[cluster].powerKey, step);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the average current in mA consumed by the subsystem, or the given
|
* Returns the average current in mA consumed by the subsystem, or the given
|
||||||
* default value if the subsystem has no recorded value.
|
* default value if the subsystem has no recorded value.
|
||||||
@@ -344,16 +410,4 @@ public class PowerProfile {
|
|||||||
public double getBatteryCapacity() {
|
public double getBatteryCapacity() {
|
||||||
return getAveragePower(POWER_BATTERY_CAPACITY);
|
return getAveragePower(POWER_BATTERY_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the number of speeds that the CPU can be run at.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public int getNumSpeedSteps() {
|
|
||||||
Object value = sPowerMap.get(POWER_CPU_SPEEDS);
|
|
||||||
if (value != null && value instanceof Double[]) {
|
|
||||||
return ((Double[])value).length;
|
|
||||||
}
|
|
||||||
return 1; // Only one speed
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,17 +47,38 @@
|
|||||||
<value>0.2</value> <!-- ~2mA -->
|
<value>0.2</value> <!-- ~2mA -->
|
||||||
<value>0.1</value> <!-- ~1mA -->
|
<value>0.1</value> <!-- ~1mA -->
|
||||||
</array>
|
</array>
|
||||||
<!-- Different CPU speeds as reported in
|
|
||||||
/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state -->
|
<!-- A list of heterogeneous CPU clusters, where the value for each cluster represents the
|
||||||
<array name="cpu.speeds">
|
number of CPU cores for that cluster.
|
||||||
|
|
||||||
|
Ex:
|
||||||
|
<array name="cpu.clusters.cores">
|
||||||
|
<value>4</value> // cluster 0 has cpu0, cpu1, cpu2, cpu3
|
||||||
|
<value>2</value> // cluster 1 has cpu4, cpu5
|
||||||
|
</array> -->
|
||||||
|
<array name="cpu.clusters.cores">
|
||||||
|
<value>1</value> <!-- cluster 0 has cpu0 -->
|
||||||
|
</array>
|
||||||
|
|
||||||
|
<!-- Different CPU speeds for cluster 0 as reported in
|
||||||
|
/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state.
|
||||||
|
|
||||||
|
There must be one of these for each cluster, labeled:
|
||||||
|
cpu.speeds.cluster0, cpu.speeds.cluster1, etc... -->
|
||||||
|
<array name="cpu.speeds.cluster0">
|
||||||
<value>400000</value> <!-- 400 MHz CPU speed -->
|
<value>400000</value> <!-- 400 MHz CPU speed -->
|
||||||
</array>
|
</array>
|
||||||
<!-- Current when CPU is idle -->
|
|
||||||
<item name="cpu.idle">0.1</item>
|
<!-- Current at each CPU speed for cluster 0, as per 'cpu.speeds.cluster0'.
|
||||||
<!-- Current at each CPU speed, as per 'cpu.speeds' -->
|
Like cpu.speeds.cluster0, there must be one of these present for
|
||||||
<array name="cpu.active">
|
each heterogeneous CPU cluster. -->
|
||||||
|
<array name="cpu.active.cluster0">
|
||||||
<value>0.1</value> <!-- ~100mA -->
|
<value>0.1</value> <!-- ~100mA -->
|
||||||
</array>
|
</array>
|
||||||
|
|
||||||
|
<!-- Current when CPU is idle -->
|
||||||
|
<item name="cpu.idle">0.1</item>
|
||||||
|
|
||||||
<!-- This is the battery capacity in mAh (measured at nominal voltage) -->
|
<!-- This is the battery capacity in mAh (measured at nominal voltage) -->
|
||||||
<item name="battery.capacity">1000</item>
|
<item name="battery.capacity">1000</item>
|
||||||
|
|
||||||
|
|||||||
@@ -171,12 +171,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub
|
|||||||
|
|
||||||
public void publish(Context context) {
|
public void publish(Context context) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
|
|
||||||
mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
|
|
||||||
mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
|
mStats.setRadioScanningTimeout(mContext.getResources().getInteger(
|
||||||
com.android.internal.R.integer.config_radioScanningTimeout)
|
com.android.internal.R.integer.config_radioScanningTimeout)
|
||||||
* 1000L);
|
* 1000L);
|
||||||
mStats.setPowerProfile(new PowerProfile(context));
|
mStats.setPowerProfile(new PowerProfile(context));
|
||||||
|
ServiceManager.addService(BatteryStats.SERVICE_NAME, asBinder());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user