People holding partial wake locks now get blamed for CPU usage.

For the duration of the wake lock, 50% of all CPU usage is now
accounted against the app(s) holding partial wake locks, evenly
distributed between them.  This is only while the device is on
battery and screen off.

Change-Id: I3e5c978b792b6ef17bf8540705bfe8343dadd464
This commit is contained in:
Dianne Hackborn
2010-09-07 23:51:03 -07:00
parent de2f3340d6
commit 0d903a84d0
4 changed files with 271 additions and 54 deletions

View File

@ -1586,8 +1586,10 @@ public abstract class BatteryStats implements Parcelable {
sb.append(prefix); sb.append(" CPU: ");
formatTime(sb, userTime); sb.append("usr + ");
formatTime(sb, systemTime); sb.append("krn\n");
sb.append(prefix); sb.append(" "); sb.append(starts);
sb.append(" proc starts");
if (starts != 0) {
sb.append(prefix); sb.append(" "); sb.append(starts);
sb.append(" proc starts");
}
pw.println(sb.toString());
for (int e=0; e<numExcessive; e++) {
Uid.Proc.ExcessiveWake ew = ps.getExcessiveWake(e);

View File

@ -22,6 +22,8 @@ import android.bluetooth.BluetoothHeadset;
import android.net.TrafficStats;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.Handler;
import android.os.Message;
import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
@ -79,6 +81,38 @@ public final class BatteryStatsImpl extends BatteryStats {
private final JournaledFile mFile;
static final int MSG_UPDATE_WAKELOCKS = 1;
static final int MSG_REPORT_POWER_CHANGE = 2;
static final long DELAY_UPDATE_WAKELOCKS = 15*1000;
public interface BatteryCallback {
public void batteryNeedsCpuUpdate();
public void batteryPowerChanged(boolean onBattery);
}
final class MyHandler extends Handler {
@Override
public void handleMessage(Message msg) {
BatteryCallback cb = mCallback;
switch (msg.what) {
case MSG_UPDATE_WAKELOCKS:
if (cb != null) {
cb.batteryNeedsCpuUpdate();
}
break;
case MSG_REPORT_POWER_CHANGE:
if (cb != null) {
cb.batteryPowerChanged(msg.arg1 != 0);
}
break;
}
}
}
private final MyHandler mHandler;
private BatteryCallback mCallback;
/**
* The statistics we have collected organized by uids.
*/
@ -95,6 +129,9 @@ public final class BatteryStatsImpl extends BatteryStats {
final SparseArray<ArrayList<StopwatchTimer>> mSensorTimers
= new SparseArray<ArrayList<StopwatchTimer>>();
// Last partial timers we use for distributing CPU usage.
final ArrayList<StopwatchTimer> mLastPartialTimers = new ArrayList<StopwatchTimer>();
// These are the objects that will want to do something when the device
// is unplugged from power.
final ArrayList<Unpluggable> mUnpluggables = new ArrayList<Unpluggable>();
@ -240,6 +277,7 @@ public final class BatteryStatsImpl extends BatteryStats {
// For debugging
public BatteryStatsImpl() {
mFile = null;
mHandler = null;
}
public static interface Unpluggable {
@ -739,7 +777,9 @@ public final class BatteryStatsImpl extends BatteryStats {
* State for keeping track of timing information.
*/
public static final class StopwatchTimer extends Timer {
final Uid mUid;
final ArrayList<StopwatchTimer> mTimerPool;
int mNesting;
/**
@ -757,16 +797,24 @@ public final class BatteryStatsImpl extends BatteryStats {
long mTimeout;
StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
/**
* For partial wake locks, keep track of whether we are in the list
* to consume CPU cycles.
*/
boolean mInList;
StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
ArrayList<Unpluggable> unpluggables, Parcel in) {
super(type, unpluggables, in);
mUid = uid;
mTimerPool = timerPool;
mUpdateTime = in.readLong();
}
StopwatchTimer(int type, ArrayList<StopwatchTimer> timerPool,
StopwatchTimer(Uid uid, int type, ArrayList<StopwatchTimer> timerPool,
ArrayList<Unpluggable> unpluggables) {
super(type, unpluggables);
mUid = uid;
mTimerPool = timerPool;
}
@ -1252,6 +1300,10 @@ public final class BatteryStatsImpl extends BatteryStats {
mWakeLockNesting++;
}
if (uid >= 0) {
if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
}
getUidStatsLocked(uid).noteStartWakeLocked(pid, name, type);
}
}
@ -1267,10 +1319,112 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
if (uid >= 0) {
if (!mHandler.hasMessages(MSG_UPDATE_WAKELOCKS)) {
Message m = mHandler.obtainMessage(MSG_UPDATE_WAKELOCKS);
mHandler.sendMessageDelayed(m, DELAY_UPDATE_WAKELOCKS);
}
getUidStatsLocked(uid).noteStopWakeLocked(pid, name, type);
}
}
public int startAddingCpuLocked() {
mHandler.removeMessages(MSG_UPDATE_WAKELOCKS);
if (mScreenOn) {
return 0;
}
final int N = mPartialTimers.size();
if (N == 0) {
mLastPartialTimers.clear();
return 0;
}
// How many timers should consume CPU? Only want to include ones
// that have already been in the list.
for (int i=0; i<N; i++) {
StopwatchTimer st = mPartialTimers.get(i);
if (st.mInList) {
Uid uid = st.mUid;
// We don't include the system UID, because it so often
// holds wake locks at one request or another of an app.
if (uid != null && uid.mUid != Process.SYSTEM_UID) {
return 50;
}
}
}
return 0;
}
public void finishAddingCpuLocked(int perc, int utime, int stime, long[] cpuSpeedTimes) {
final int N = mPartialTimers.size();
if (perc != 0) {
int num = 0;
for (int i=0; i<N; i++) {
StopwatchTimer st = mPartialTimers.get(i);
if (st.mInList) {
Uid uid = st.mUid;
// We don't include the system UID, because it so often
// holds wake locks at one request or another of an app.
if (uid != null && uid.mUid != Process.SYSTEM_UID) {
num++;
}
}
}
if (num != 0) {
for (int i=0; i<N; i++) {
StopwatchTimer st = mPartialTimers.get(i);
if (st.mInList) {
int myUTime = utime/num;
int mySTime = stime/num;
utime -= myUTime;
stime -= mySTime;
num--;
Uid uid = st.mUid;
if (uid != null && uid.mUid != Process.SYSTEM_UID) {
Uid.Proc proc = uid.getProcessStatsLocked("*wakelock*");
proc.addCpuTimeLocked(myUTime, mySTime);
proc.addSpeedStepTimes(cpuSpeedTimes);
}
}
}
}
// Just in case, collect any lost CPU time.
if (utime != 0 || stime != 0) {
Uid uid = getUidStatsLocked(Process.SYSTEM_UID);
if (uid != null) {
Uid.Proc proc = uid.getProcessStatsLocked("*lost*");
proc.addCpuTimeLocked(utime, stime);
proc.addSpeedStepTimes(cpuSpeedTimes);
}
}
}
final int NL = mLastPartialTimers.size();
boolean diff = N != NL;
for (int i=0; i<NL && !diff; i++) {
diff |= mPartialTimers.get(i) != mLastPartialTimers.get(i);
}
if (!diff) {
for (int i=0; i<NL; i++) {
mPartialTimers.get(i).mInList = true;
}
return;
}
for (int i=0; i<NL; i++) {
mLastPartialTimers.get(i).mInList = false;
}
mLastPartialTimers.clear();
for (int i=0; i<N; i++) {
StopwatchTimer st = mPartialTimers.get(i);
st.mInList = true;
mLastPartialTimers.add(st);
}
}
public void noteProcessDiedLocked(int uid, int pid) {
Uid u = mUidStats.get(uid);
if (u != null) {
@ -1922,13 +2076,18 @@ public final class BatteryStatsImpl extends BatteryStats {
public Uid(int uid) {
mUid = uid;
mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON, null, mUnpluggables);
mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK, null, mUnpluggables);
mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK, null, mUnpluggables);
mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
null, mUnpluggables);
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
null, mUnpluggables);
mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
null, mUnpluggables);
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
null, mUnpluggables);
mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
null, mUnpluggables);
mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
null, mUnpluggables);
mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON, null, mUnpluggables);
mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON, null, mUnpluggables);
}
@Override
@ -1996,7 +2155,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mWifiTurnedOn) {
mWifiTurnedOn = true;
if (mWifiTurnedOnTimer == null) {
mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON,
mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
null, mUnpluggables);
}
mWifiTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@ -2016,7 +2175,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mFullWifiLockOut) {
mFullWifiLockOut = true;
if (mFullWifiLockTimer == null) {
mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK,
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
null, mUnpluggables);
}
mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
@ -2036,7 +2195,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mScanWifiLockOut) {
mScanWifiLockOut = true;
if (mScanWifiLockTimer == null) {
mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK,
mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
null, mUnpluggables);
}
mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
@ -2056,7 +2215,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mWifiMulticastEnabled) {
mWifiMulticastEnabled = true;
if (mWifiMulticastTimer == null) {
mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
null, mUnpluggables);
}
mWifiMulticastTimer.startRunningLocked(BatteryStatsImpl.this);
@ -2076,7 +2235,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mAudioTurnedOn) {
mAudioTurnedOn = true;
if (mAudioTurnedOnTimer == null) {
mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON,
mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
null, mUnpluggables);
}
mAudioTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@ -2096,7 +2255,7 @@ public final class BatteryStatsImpl extends BatteryStats {
if (!mVideoTurnedOn) {
mVideoTurnedOn = true;
if (mVideoTurnedOnTimer == null) {
mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON,
mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
null, mUnpluggables);
}
mVideoTurnedOnTimer.startRunningLocked(BatteryStatsImpl.this);
@ -2456,42 +2615,42 @@ public final class BatteryStatsImpl extends BatteryStats {
mTcpBytesSentAtLastUnplug = in.readLong();
mWifiTurnedOn = false;
if (in.readInt() != 0) {
mWifiTurnedOnTimer = new StopwatchTimer(WIFI_TURNED_ON,
mWifiTurnedOnTimer = new StopwatchTimer(Uid.this, WIFI_TURNED_ON,
null, mUnpluggables, in);
} else {
mWifiTurnedOnTimer = null;
}
mFullWifiLockOut = false;
if (in.readInt() != 0) {
mFullWifiLockTimer = new StopwatchTimer(FULL_WIFI_LOCK,
mFullWifiLockTimer = new StopwatchTimer(Uid.this, FULL_WIFI_LOCK,
null, mUnpluggables, in);
} else {
mFullWifiLockTimer = null;
}
mScanWifiLockOut = false;
if (in.readInt() != 0) {
mScanWifiLockTimer = new StopwatchTimer(SCAN_WIFI_LOCK,
mScanWifiLockTimer = new StopwatchTimer(Uid.this, SCAN_WIFI_LOCK,
null, mUnpluggables, in);
} else {
mScanWifiLockTimer = null;
}
mWifiMulticastEnabled = false;
if (in.readInt() != 0) {
mWifiMulticastTimer = new StopwatchTimer(WIFI_MULTICAST_ENABLED,
mWifiMulticastTimer = new StopwatchTimer(Uid.this, WIFI_MULTICAST_ENABLED,
null, mUnpluggables, in);
} else {
mWifiMulticastTimer = null;
}
mAudioTurnedOn = false;
if (in.readInt() != 0) {
mAudioTurnedOnTimer = new StopwatchTimer(AUDIO_TURNED_ON,
mAudioTurnedOnTimer = new StopwatchTimer(Uid.this, AUDIO_TURNED_ON,
null, mUnpluggables, in);
} else {
mAudioTurnedOnTimer = null;
}
mVideoTurnedOn = false;
if (in.readInt() != 0) {
mVideoTurnedOnTimer = new StopwatchTimer(VIDEO_TURNED_ON,
mVideoTurnedOnTimer = new StopwatchTimer(Uid.this, VIDEO_TURNED_ON,
null, mUnpluggables, in);
} else {
mVideoTurnedOnTimer = null;
@ -2538,7 +2697,7 @@ public final class BatteryStatsImpl extends BatteryStats {
return null;
}
return new StopwatchTimer(type, pool, unpluggables, in);
return new StopwatchTimer(Uid.this, type, pool, unpluggables, in);
}
boolean reset() {
@ -2614,7 +2773,7 @@ public final class BatteryStatsImpl extends BatteryStats {
pool = new ArrayList<StopwatchTimer>();
mSensorTimers.put(mHandle, pool);
}
return new StopwatchTimer(0, pool, unpluggables, in);
return new StopwatchTimer(Uid.this, 0, pool, unpluggables, in);
}
boolean reset() {
@ -3416,21 +3575,24 @@ public final class BatteryStatsImpl extends BatteryStats {
case WAKE_TYPE_PARTIAL:
t = wl.mTimerPartial;
if (t == null) {
t = new StopwatchTimer(WAKE_TYPE_PARTIAL, mPartialTimers, mUnpluggables);
t = new StopwatchTimer(Uid.this, WAKE_TYPE_PARTIAL,
mPartialTimers, mUnpluggables);
wl.mTimerPartial = t;
}
return t;
case WAKE_TYPE_FULL:
t = wl.mTimerFull;
if (t == null) {
t = new StopwatchTimer(WAKE_TYPE_FULL, mFullTimers, mUnpluggables);
t = new StopwatchTimer(Uid.this, WAKE_TYPE_FULL,
mFullTimers, mUnpluggables);
wl.mTimerFull = t;
}
return t;
case WAKE_TYPE_WINDOW:
t = wl.mTimerWindow;
if (t == null) {
t = new StopwatchTimer(WAKE_TYPE_WINDOW, mWindowTimers, mUnpluggables);
t = new StopwatchTimer(Uid.this, WAKE_TYPE_WINDOW,
mWindowTimers, mUnpluggables);
wl.mTimerWindow = t;
}
return t;
@ -3457,7 +3619,7 @@ public final class BatteryStatsImpl extends BatteryStats {
timers = new ArrayList<StopwatchTimer>();
mSensorTimers.put(sensor, timers);
}
t = new StopwatchTimer(BatteryStats.SENSOR, timers, mUnpluggables);
t = new StopwatchTimer(Uid.this, BatteryStats.SENSOR, timers, mUnpluggables);
se.mTimer = t;
return t;
}
@ -3530,25 +3692,26 @@ public final class BatteryStatsImpl extends BatteryStats {
public BatteryStatsImpl(String filename) {
mFile = new JournaledFile(new File(filename), new File(filename + ".tmp"));
mHandler = new MyHandler();
mStartCount++;
mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables);
mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables);
mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i, null, mUnpluggables);
}
mInputEventCounter = new Counter(mUnpluggables);
mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables);
mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables);
mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i, null, mUnpluggables);
}
mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables);
mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables);
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i, null, mUnpluggables);
}
mWifiOnTimer = new StopwatchTimer(-3, null, mUnpluggables);
mWifiRunningTimer = new StopwatchTimer(-4, null, mUnpluggables);
mBluetoothOnTimer = new StopwatchTimer(-5, null, mUnpluggables);
mAudioOnTimer = new StopwatchTimer(-6, null, mUnpluggables);
mVideoOnTimer = new StopwatchTimer(-7, null, mUnpluggables);
mWifiOnTimer = new StopwatchTimer(null, -3, null, mUnpluggables);
mWifiRunningTimer = new StopwatchTimer(null, -4, null, mUnpluggables);
mBluetoothOnTimer = new StopwatchTimer(null, -5, null, mUnpluggables);
mAudioOnTimer = new StopwatchTimer(null, -6, null, mUnpluggables);
mVideoOnTimer = new StopwatchTimer(null, -7, null, mUnpluggables);
mOnBattery = mOnBatteryInternal = false;
initTimes();
mTrackBatteryPastUptime = 0;
@ -3566,9 +3729,14 @@ public final class BatteryStatsImpl extends BatteryStats {
public BatteryStatsImpl(Parcel p) {
mFile = null;
mHandler = null;
readFromParcel(p);
}
public void setCallback(BatteryCallback cb) {
mCallback = cb;
}
public void setNumSpeedSteps(int steps) {
if (sNumSpeedSteps == 0) sNumSpeedSteps = steps;
}
@ -3653,6 +3821,9 @@ public final class BatteryStatsImpl extends BatteryStats {
void setOnBattery(boolean onBattery, int oldStatus, int level) {
synchronized(this) {
boolean doWrite = false;
Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
m.arg1 = onBattery ? 1 : 0;
mHandler.sendMessage(m);
mOnBattery = mOnBatteryInternal = onBattery;
long uptime = SystemClock.uptimeMillis() * 1000;
@ -4553,26 +4724,29 @@ public final class BatteryStatsImpl extends BatteryStats {
mBatteryRealtime = in.readLong();
mBatteryLastRealtime = 0;
mScreenOn = false;
mScreenOnTimer = new StopwatchTimer(-1, null, mUnpluggables, in);
mScreenOnTimer = new StopwatchTimer(null, -1, null, mUnpluggables, in);
for (int i=0; i<NUM_SCREEN_BRIGHTNESS_BINS; i++) {
mScreenBrightnessTimer[i] = new StopwatchTimer(-100-i, null, mUnpluggables, in);
mScreenBrightnessTimer[i] = new StopwatchTimer(null, -100-i,
null, mUnpluggables, in);
}
mInputEventCounter = new Counter(mUnpluggables, in);
mPhoneOn = false;
mPhoneOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mPhoneOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
for (int i=0; i<NUM_SIGNAL_STRENGTH_BINS; i++) {
mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(-200-i, null, mUnpluggables, in);
mPhoneSignalStrengthsTimer[i] = new StopwatchTimer(null, -200-i,
null, mUnpluggables, in);
}
mPhoneSignalScanningTimer = new StopwatchTimer(-200+1, null, mUnpluggables, in);
mPhoneSignalScanningTimer = new StopwatchTimer(null, -200+1, null, mUnpluggables, in);
for (int i=0; i<NUM_DATA_CONNECTION_TYPES; i++) {
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(-300-i, null, mUnpluggables, in);
mPhoneDataConnectionsTimer[i] = new StopwatchTimer(null, -300-i,
null, mUnpluggables, in);
}
mWifiOn = false;
mWifiOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mWifiOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mWifiRunning = false;
mWifiRunningTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mWifiRunningTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mBluetoothOn = false;
mBluetoothOnTimer = new StopwatchTimer(-2, null, mUnpluggables, in);
mBluetoothOnTimer = new StopwatchTimer(null, -2, null, mUnpluggables, in);
mUptime = in.readLong();
mUptimeStart = in.readLong();
mLastUptime = 0;

View File

@ -131,7 +131,8 @@ import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
public final class ActivityManagerService extends ActivityManagerNative implements Watchdog.Monitor {
public final class ActivityManagerService extends ActivityManagerNative
implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
static final String TAG = "ActivityManager";
static final boolean DEBUG = false;
static final boolean localLOGV = DEBUG ? Config.LOGD : Config.LOGV;
@ -750,6 +751,7 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
boolean mBooting = false;
boolean mWaitingUpdate = false;
boolean mDidUpdate = false;
boolean mOnBattery = false;
Context mContext;
@ -1381,8 +1383,10 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
systemDir, "batterystats.bin").toString());
mBatteryStatsService.getActiveStatistics().readLocked();
mBatteryStatsService.getActiveStatistics().writeLocked();
mOnBattery = mBatteryStatsService.getActiveStatistics().getIsOnBattery();
mBatteryStatsService.getActiveStatistics().setCallback(this);
mUsageStatsService = new UsageStatsService( new File(
mUsageStatsService = new UsageStatsService(new File(
systemDir, "usagestats").toString());
GL_ES_VERSION = SystemProperties.getInt("ro.opengles.version",
@ -1495,25 +1499,36 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
synchronized(bstats) {
synchronized(mPidsSelfLocked) {
if (haveNewCpuStats) {
if (mBatteryStatsService.isOnBattery()) {
if (mOnBattery) {
int perc = bstats.startAddingCpuLocked();
int totalUTime = 0;
int totalSTime = 0;
final int N = mProcessStats.countWorkingStats();
for (int i=0; i<N; i++) {
ProcessStats.Stats st
= mProcessStats.getWorkingStats(i);
ProcessRecord pr = mPidsSelfLocked.get(st.pid);
int otherUTime = (st.rel_utime*perc)/100;
int otherSTime = (st.rel_stime*perc)/100;
totalUTime += otherUTime;
totalSTime += otherSTime;
if (pr != null) {
BatteryStatsImpl.Uid.Proc ps = pr.batteryStats;
ps.addCpuTimeLocked(st.rel_utime, st.rel_stime);
ps.addCpuTimeLocked(st.rel_utime-otherUTime,
st.rel_stime-otherSTime);
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.addCpuTimeLocked(st.rel_utime-otherUTime,
st.rel_stime-otherSTime);
ps.addSpeedStepTimes(cpuSpeedTimes);
}
}
}
bstats.finishAddingCpuLocked(perc, totalUTime,
totalSTime, cpuSpeedTimes);
}
}
}
@ -1526,6 +1541,23 @@ public final class ActivityManagerService extends ActivityManagerNative implemen
}
}
@Override
public void batteryNeedsCpuUpdate() {
updateCpuStatsNow();
}
@Override
public void batteryPowerChanged(boolean onBattery) {
// When plugging in, update the CPU stats first before changing
// the plug state.
updateCpuStatsNow();
synchronized (this) {
synchronized(mPidsSelfLocked) {
mOnBattery = onBattery;
}
}
}
/**
* Initialize the application bind args. These are passed to each
* process when the bindApplication() IPC is sent to the process. They're

View File

@ -131,6 +131,13 @@ class ProcessRecord {
void dump(PrintWriter pw, String prefix) {
final long now = SystemClock.uptimeMillis();
long wtime;
synchronized (batteryStats.getBatteryStats()) {
wtime = batteryStats.getBatteryStats().getProcessWakeTime(info.uid,
pid, SystemClock.elapsedRealtime());
}
long timeUsed = wtime - lastWakeTime;
if (info.className != null) {
pw.print(prefix); pw.print("class="); pw.println(info.className);
}
@ -182,7 +189,9 @@ class ProcessRecord {
pw.print(prefix); pw.print("adjSeq="); pw.print(adjSeq);
pw.print(" lruSeq="); pw.println(lruSeq);
pw.print(prefix); pw.print("lastWakeTime="); pw.print(lastWakeTime);
pw.print(" lastRequestedGc=");
pw.print(" time used=");
TimeUtils.formatDuration(timeUsed, pw); pw.println("");
pw.print(prefix); pw.print("lastRequestedGc=");
TimeUtils.formatDuration(lastRequestedGc, now, pw);
pw.print(" lastLowMemory=");
TimeUtils.formatDuration(lastLowMemory, now, pw);