am 5ea916b1: Merge change 26050 into eclair
Merge commit '5ea916b17cf0071f4d49936a370f4b873e4eb3e3' into eclair-plus-aosp * commit '5ea916b17cf0071f4d49936a370f4b873e4eb3e3': Track CPU speed stepping to get more accurate CPU cost per app.
This commit is contained in:
@@ -314,6 +314,15 @@ public abstract class BatteryStats implements Parcelable {
|
||||
* @return foreground cpu time in microseconds
|
||||
*/
|
||||
public abstract long getForegroundTime(int which);
|
||||
|
||||
/**
|
||||
* Returns the approximate cpu time spent in microseconds, at a certain CPU speed.
|
||||
* @param speedStep the index of the CPU speed. This is not the actual speed of the
|
||||
* CPU.
|
||||
* @param which one of STATS_TOTAL, STATS_LAST, STATS_CURRENT or STATS_UNPLUGGED
|
||||
* @see BatteryStats#getCpuSpeedSteps()
|
||||
*/
|
||||
public abstract long getTimeAtCpuSpeedStep(int speedStep, int which);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -573,6 +582,9 @@ public abstract class BatteryStats implements Parcelable {
|
||||
|
||||
public abstract Map<String, ? extends Timer> getKernelWakelockStats();
|
||||
|
||||
/** Returns the number of different speeds that the CPU can run at */
|
||||
public abstract int getCpuSpeedSteps();
|
||||
|
||||
private final static void formatTimeRaw(StringBuilder out, long seconds) {
|
||||
long days = seconds / (60 * 60 * 24);
|
||||
if (days != 0) {
|
||||
|
||||
@@ -121,6 +121,9 @@ public class VolumePreference extends SeekBarPreference implements
|
||||
if (mSeekBarVolumizer != null) {
|
||||
Dialog dialog = getDialog();
|
||||
if (dialog != null && dialog.isShowing()) {
|
||||
View view = dialog.getWindow().getDecorView()
|
||||
.findViewById(com.android.internal.R.id.seekbar);
|
||||
if (view != null) view.setOnKeyListener(null);
|
||||
// Stopped while dialog was showing, revert changes
|
||||
mSeekBarVolumizer.revertVolume();
|
||||
}
|
||||
|
||||
@@ -56,7 +56,9 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
|
||||
|
||||
// Current on-disk Parcel version
|
||||
private static final int VERSION = 39;
|
||||
private static final int VERSION = 40;
|
||||
|
||||
private static int sNumSpeedSteps;
|
||||
|
||||
private final File mFile;
|
||||
private final File mBackupFile;
|
||||
@@ -213,7 +215,7 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
/**
|
||||
* State for keeping track of counting information.
|
||||
*/
|
||||
public static final class Counter extends BatteryStats.Counter implements Unpluggable {
|
||||
public static class Counter extends BatteryStats.Counter implements Unpluggable {
|
||||
int mCount;
|
||||
int mLoadedCount;
|
||||
int mLastCount;
|
||||
@@ -302,7 +304,22 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
mUnpluggedCount = mPluggedCount = mCount;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SamplingCounter extends Counter {
|
||||
|
||||
SamplingCounter(ArrayList<Unpluggable> unpluggables, Parcel in) {
|
||||
super(unpluggables, in);
|
||||
}
|
||||
|
||||
SamplingCounter(ArrayList<Unpluggable> unpluggables) {
|
||||
super(unpluggables);
|
||||
}
|
||||
|
||||
public void addCountLocked(long count) {
|
||||
mCount += count;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* State for keeping track of timing information.
|
||||
*/
|
||||
@@ -1940,10 +1957,16 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
*/
|
||||
long mUnpluggedForegroundTime;
|
||||
|
||||
SamplingCounter[] mSpeedBins;
|
||||
|
||||
Proc() {
|
||||
mUnpluggables.add(this);
|
||||
mSpeedBins = new SamplingCounter[getCpuSpeedSteps()];
|
||||
for (int i = 0; i < mSpeedBins.length; i++) {
|
||||
mSpeedBins[i] = new SamplingCounter(mUnpluggables);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void unplug(long batteryUptime, long batteryRealtime) {
|
||||
mUnpluggedUserTime = mUserTime;
|
||||
mUnpluggedSystemTime = mSystemTime;
|
||||
@@ -1974,6 +1997,11 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
out.writeLong(mUnpluggedSystemTime);
|
||||
out.writeLong(mUnpluggedForegroundTime);
|
||||
out.writeInt(mUnpluggedStarts);
|
||||
|
||||
out.writeInt(mSpeedBins.length);
|
||||
for (int i = 0; i < mSpeedBins.length; i++) {
|
||||
mSpeedBins[i].writeToParcel(out);
|
||||
}
|
||||
}
|
||||
|
||||
void readFromParcelLocked(Parcel in) {
|
||||
@@ -1993,6 +2021,12 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
mUnpluggedSystemTime = in.readLong();
|
||||
mUnpluggedForegroundTime = in.readLong();
|
||||
mUnpluggedStarts = in.readInt();
|
||||
|
||||
int bins = in.readInt();
|
||||
mSpeedBins = new SamplingCounter[bins];
|
||||
for (int i = 0; i < bins; i++) {
|
||||
mSpeedBins[i] = new SamplingCounter(mUnpluggables, in);
|
||||
}
|
||||
}
|
||||
|
||||
public BatteryStatsImpl getBatteryStats() {
|
||||
@@ -2075,6 +2109,22 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Called by ActivityManagerService when CPU times are updated. */
|
||||
public void addSpeedStepTimes(long[] values) {
|
||||
for (int i = 0; i < mSpeedBins.length && i < values.length; i++) {
|
||||
mSpeedBins[i].addCountLocked(values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getTimeAtCpuSpeedStep(int speedStep, int which) {
|
||||
if (speedStep < mSpeedBins.length) {
|
||||
return mSpeedBins[speedStep].getCountLocked(which);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2625,6 +2675,10 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
readFromParcel(p);
|
||||
}
|
||||
|
||||
public void setNumSpeedSteps(int steps) {
|
||||
if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStartCount() {
|
||||
return mStartCount;
|
||||
@@ -2853,6 +2907,11 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
return mDischargeCurrentLevel;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCpuSpeedSteps() {
|
||||
return sNumSpeedSteps;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the statistics object for a particular uid, creating if needed.
|
||||
*/
|
||||
@@ -3063,7 +3122,9 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
getKernelWakelockTimerLocked(kwltName).readSummaryFromParcelLocked(in);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sNumSpeedSteps = in.readInt();
|
||||
|
||||
final int NU = in.readInt();
|
||||
for (int iu = 0; iu < NU; iu++) {
|
||||
int uid = in.readInt();
|
||||
@@ -3206,6 +3267,7 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
}
|
||||
}
|
||||
|
||||
out.writeInt(sNumSpeedSteps);
|
||||
final int NU = mUidStats.size();
|
||||
out.writeInt(NU);
|
||||
for (int iu = 0; iu < NU; iu++) {
|
||||
@@ -3404,6 +3466,8 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
mFullTimers.clear();
|
||||
mWindowTimers.clear();
|
||||
|
||||
sNumSpeedSteps = in.readInt();
|
||||
|
||||
int numUids = in.readInt();
|
||||
mUidStats.clear();
|
||||
for (int i = 0; i < numUids; i++) {
|
||||
@@ -3484,7 +3548,9 @@ public final class BatteryStatsImpl extends BatteryStats {
|
||||
out.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
out.writeInt(sNumSpeedSteps);
|
||||
|
||||
int size = mUidStats.size();
|
||||
out.writeInt(size);
|
||||
for (int i = 0; i < size; i++) {
|
||||
|
||||
@@ -47,14 +47,9 @@ public class PowerProfile {
|
||||
public static final String POWER_CPU_IDLE = "cpu.idle";
|
||||
|
||||
/**
|
||||
* Power consumption when CPU is running at normal speed.
|
||||
* Power consumption when CPU is in power collapse mode.
|
||||
*/
|
||||
public static final String POWER_CPU_NORMAL = "cpu.normal";
|
||||
|
||||
/**
|
||||
* Power consumption when CPU is running at full speed.
|
||||
*/
|
||||
public static final String POWER_CPU_FULL = "cpu.full";
|
||||
public static final String POWER_CPU_ACTIVE = "cpu.active";
|
||||
|
||||
/**
|
||||
* Power consumption when WiFi driver is scanning for networks.
|
||||
@@ -124,6 +119,8 @@ public class PowerProfile {
|
||||
*/
|
||||
public static final String POWER_VIDEO = "dsp.video";
|
||||
|
||||
public static final String POWER_CPU_SPEEDS = "cpu.speeds";
|
||||
|
||||
static final HashMap<String, Object> sPowerMap = new HashMap<String, Object>();
|
||||
|
||||
private static final String TAG_DEVICE = "device";
|
||||
@@ -214,10 +211,10 @@ public class PowerProfile {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the average current in mA consumed by the subsystem for the given level.
|
||||
* Returns the average current in mA consumed by the subsystem for the given level.
|
||||
* @param type the subsystem type
|
||||
* @param level the level of power at which the subsystem is running. For instance, the
|
||||
* signal strength of the cell network between 0 and 4 (if there are 4 bars max.).
|
||||
* signal strength of the cell network between 0 and 4 (if there are 4 bars max.)
|
||||
* If there is no data for multiple levels, the level is ignored.
|
||||
* @return the average current in milliAmps.
|
||||
*/
|
||||
@@ -240,4 +237,12 @@ public class PowerProfile {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,15 +26,24 @@
|
||||
<item name="wifi.on">0.1</item>
|
||||
<item name="wifi.active">0.1</item>
|
||||
<item name="wifi.scan">0.1</item>
|
||||
<item name="cpu.idle">0.1</item>
|
||||
<item name="cpu.normal">0.2</item>
|
||||
<item name="cpu.full">1</item>
|
||||
<item name="dsp.audio">0.1</item>
|
||||
<item name="dsp.video">0.1</item>
|
||||
<item name="radio.active">1</item>
|
||||
<item name="gps.on">1</item>
|
||||
<!-- Current consumed by the radio at different signal strengths, when paging -->
|
||||
<array name="radio.on"> <!-- Strength 0 to BINS-1 -->
|
||||
<value>1</value>
|
||||
<value>0.1</value>
|
||||
</array>
|
||||
<!-- Different CPU speeds as reported in
|
||||
/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state -->
|
||||
<array name="cpu.speeds">
|
||||
<value>400000</value> <!-- 400 MHz CPU speed -->
|
||||
</array>
|
||||
<!-- Power consumption when CPU is idle -->
|
||||
<item name="cpu.idle">0.1</item>
|
||||
<!-- Power consumption at different speeds -->
|
||||
<array name="cpu.active">
|
||||
<value>0.2</value>
|
||||
</array>
|
||||
</device>
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
public class ProcessStats {
|
||||
private static final String TAG = "ProcessStats";
|
||||
@@ -138,7 +139,22 @@ public class ProcessStats {
|
||||
private boolean mFirst = true;
|
||||
|
||||
private byte[] mBuffer = new byte[256];
|
||||
|
||||
|
||||
/**
|
||||
* The time in microseconds that the CPU has been running at each speed.
|
||||
*/
|
||||
private long[] mCpuSpeedTimes;
|
||||
|
||||
/**
|
||||
* The relative time in microseconds that the CPU has been running at each speed.
|
||||
*/
|
||||
private long[] mRelCpuSpeedTimes;
|
||||
|
||||
/**
|
||||
* The different speeds that the CPU can be running at.
|
||||
*/
|
||||
private long[] mCpuSpeeds;
|
||||
|
||||
public static class Stats {
|
||||
public final int pid;
|
||||
final String statFile;
|
||||
@@ -460,6 +476,67 @@ public class ProcessStats {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the times spent at each CPU speed, since the last call to this method. If this
|
||||
* is the first time, it will return 1 for each value.
|
||||
* @return relative times spent at different speed steps.
|
||||
*/
|
||||
public long[] getLastCpuSpeedTimes() {
|
||||
if (mCpuSpeedTimes == null) {
|
||||
mCpuSpeedTimes = getCpuSpeedTimes(null);
|
||||
mRelCpuSpeedTimes = new long[mCpuSpeedTimes.length];
|
||||
for (int i = 0; i < mCpuSpeedTimes.length; i++) {
|
||||
mRelCpuSpeedTimes[i] = 1; // Initialize
|
||||
}
|
||||
} else {
|
||||
getCpuSpeedTimes(mRelCpuSpeedTimes);
|
||||
for (int i = 0; i < mCpuSpeedTimes.length; i++) {
|
||||
long temp = mRelCpuSpeedTimes[i];
|
||||
mRelCpuSpeedTimes[i] -= mCpuSpeedTimes[i];
|
||||
mCpuSpeedTimes[i] = temp;
|
||||
}
|
||||
}
|
||||
return mRelCpuSpeedTimes;
|
||||
}
|
||||
|
||||
private long[] getCpuSpeedTimes(long[] out) {
|
||||
long[] tempTimes = out;
|
||||
long[] tempSpeeds = mCpuSpeeds;
|
||||
final int MAX_SPEEDS = 20;
|
||||
if (out == null) {
|
||||
tempTimes = new long[MAX_SPEEDS]; // Hopefully no more than that
|
||||
tempSpeeds = new long[MAX_SPEEDS];
|
||||
}
|
||||
int speed = 0;
|
||||
String file = readFile("/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state", '\0');
|
||||
StringTokenizer st = new StringTokenizer(file, "\n ");
|
||||
while (st.hasMoreElements()) {
|
||||
String token = st.nextToken();
|
||||
try {
|
||||
long val = Long.parseLong(token);
|
||||
tempSpeeds[speed] = val;
|
||||
token = st.nextToken();
|
||||
val = Long.parseLong(token);
|
||||
tempTimes[speed] = val;
|
||||
speed++;
|
||||
if (speed == MAX_SPEEDS) break; // No more
|
||||
if (localLOGV && out == null) {
|
||||
Log.v(TAG, "First time : Speed/Time = " + tempSpeeds[speed - 1]
|
||||
+ "\t" + tempTimes[speed - 1]);
|
||||
}
|
||||
} catch (NumberFormatException nfe) {
|
||||
Log.i(TAG, "Unable to parse time_in_state");
|
||||
}
|
||||
}
|
||||
if (out == null) {
|
||||
out = new long[speed];
|
||||
mCpuSpeeds = new long[speed];
|
||||
System.arraycopy(tempSpeeds, 0, mCpuSpeeds, 0, speed);
|
||||
System.arraycopy(tempTimes, 0, out, 0, speed);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
final public int getLastUserTime() {
|
||||
return mRelUserTime;
|
||||
}
|
||||
|
||||
@@ -1572,6 +1572,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
}
|
||||
}
|
||||
|
||||
long[] cpuSpeedTimes = mProcessStats.getLastCpuSpeedTimes();
|
||||
final BatteryStatsImpl bstats = mBatteryStatsService.getActiveStatistics();
|
||||
synchronized(bstats) {
|
||||
synchronized(mPidsSelfLocked) {
|
||||
@@ -1585,11 +1586,13 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
|
||||
if (pr != null) {
|
||||
BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
|
||||
ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
|
||||
ps.addSpeedStepTimes(cpuSpeedTimes);
|
||||
} else {
|
||||
BatteryStatsImpl.Uid.Proc ps =
|
||||
bstats.getProcessStatsLocked(st.name, st.pid);
|
||||
if (ps != null) {
|
||||
ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
|
||||
ps.addSpeedStepTimes(cpuSpeedTimes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.util.Log;
|
||||
|
||||
import com.android.internal.app.IBatteryStats;
|
||||
import com.android.internal.os.BatteryStatsImpl;
|
||||
import com.android.internal.os.PowerProfile;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.PrintWriter;
|
||||
@@ -49,6 +50,7 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
|
||||
public void publish(Context context) {
|
||||
mContext = context;
|
||||
ServiceManager.addService("batteryinfo", asBinder());
|
||||
mStats.setNumSpeedSteps(new PowerProfile(mContext).getNumSpeedSteps());
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
|
||||
Reference in New Issue
Block a user