summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Dianne Hackborn <hackbod@google.com> 2014-01-16 01:39:06 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2014-01-16 01:39:06 +0000
commitc8345b32c9636d4d2984a2e9f23dd0391c664ba4 (patch)
treeea6a78f3820b7bd2c567d47334a9644991d5cfbb
parent0430ee5acb1afe4d1e950eb586d302e35d0c49b1 (diff)
parenta7c837f043c1ca0bdecd42645ba7da8c5717566d (diff)
Merge "Add battery power use reporting to batterystats service."
-rw-r--r--core/java/android/os/BatteryStats.java146
-rw-r--r--core/java/com/android/internal/os/BatterySipper.java92
-rw-r--r--core/java/com/android/internal/os/BatteryStatsHelper.java726
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java22
-rw-r--r--services/core/java/com/android/server/am/BatteryStatsService.java4
5 files changed, 969 insertions, 21 deletions
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 58b94ca8cb1c..10c386a0a665 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -24,11 +24,14 @@ import java.util.Formatter;
import java.util.List;
import java.util.Map;
+import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.telephony.SignalStrength;
import android.util.Printer;
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.os.BatterySipper;
+import com.android.internal.os.BatteryStatsHelper;
/**
* A class providing access to battery usage statistics, including information on
@@ -166,6 +169,8 @@ public abstract class BatteryStats implements Parcelable {
private static final String SIGNAL_STRENGTH_COUNT_DATA = "sgc";
private static final String DATA_CONNECTION_TIME_DATA = "dct";
private static final String DATA_CONNECTION_COUNT_DATA = "dcc";
+ private static final String POWER_USE_SUMMARY_DATA = "pws";
+ private static final String POWER_USE_ITEM_DATA = "pwi";
private final StringBuilder mFormatBuilder = new StringBuilder(32);
private final Formatter mFormatter = new Formatter(mFormatBuilder);
@@ -865,6 +870,8 @@ public abstract class BatteryStats implements Parcelable {
*/
public abstract long getBluetoothOnTime(long batteryRealtime, int which);
+ public abstract int getBluetoothPingCount();
+
public static final int NETWORK_MOBILE_RX_DATA = 0;
public static final int NETWORK_MOBILE_TX_DATA = 1;
public static final int NETWORK_WIFI_RX_DATA = 2;
@@ -997,6 +1004,8 @@ public abstract class BatteryStats implements Parcelable {
/** Returns the number of different speeds that the CPU can run at */
public abstract int getCpuSpeedSteps();
+ public abstract void writeToParcelWithoutUids(Parcel out, int flags);
+
private final static void formatTimeRaw(StringBuilder out, long seconds) {
long days = seconds / (60 * 60 * 24);
if (days != 0) {
@@ -1163,7 +1172,7 @@ public abstract class BatteryStats implements Parcelable {
*
* NOTE: all times are expressed in 'ms'.
*/
- public final void dumpCheckinLocked(PrintWriter pw, int which, int reqUid) {
+ public final void dumpCheckinLocked(Context context, PrintWriter pw, int which, int reqUid) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
@@ -1300,6 +1309,61 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ BatteryStatsHelper helper = new BatteryStatsHelper(context);
+ helper.create(this);
+ helper.refreshStats(which, UserHandle.USER_ALL);
+ List<BatterySipper> sippers = helper.getUsageList();
+ if (sippers != null && sippers.size() > 0) {
+ dumpLine(pw, 0 /* uid */, category, POWER_USE_SUMMARY_DATA,
+ BatteryStatsHelper.makemAh(helper.getPowerProfile().getBatteryCapacity()),
+ BatteryStatsHelper.makemAh(helper.getTotalPower()),
+ BatteryStatsHelper.makemAh(helper.getMinDrainedPower()),
+ BatteryStatsHelper.makemAh(helper.getMaxDrainedPower()));
+ for (int i=0; i<sippers.size(); i++) {
+ BatterySipper bs = sippers.get(i);
+ int uid = 0;
+ String label;
+ switch (bs.drainType) {
+ case IDLE:
+ label="idle";
+ break;
+ case CELL:
+ label="cell";
+ break;
+ case PHONE:
+ label="phone";
+ break;
+ case WIFI:
+ label="wifi";
+ break;
+ case BLUETOOTH:
+ label="blue";
+ break;
+ case SCREEN:
+ label="scrn";
+ break;
+ case APP:
+ uid = bs.uidObj.getUid();
+ label = "uid";
+ break;
+ case USER:
+ uid = UserHandle.getUid(bs.userId, 0);
+ label = "user";
+ break;
+ case UNACCOUNTED:
+ label = "unacc";
+ break;
+ case OVERCOUNTED:
+ label = "over";
+ break;
+ default:
+ label = "???";
+ }
+ dumpLine(pw, uid, category, POWER_USE_ITEM_DATA, label,
+ BatteryStatsHelper.makemAh(bs.value));
+ }
+ }
+
for (int iu = 0; iu < NU; iu++) {
final int uid = uidStats.keyAt(iu);
if (reqUid >= 0 && uid != reqUid) {
@@ -1471,8 +1535,13 @@ public abstract class BatteryStats implements Parcelable {
}
}
+ private void printmAh(PrintWriter printer, double power) {
+ printer.print(BatteryStatsHelper.makemAh(power));
+ }
+
@SuppressWarnings("unused")
- public final void dumpLocked(PrintWriter pw, String prefix, final int which, int reqUid) {
+ public final void dumpLocked(Context context, PrintWriter pw, String prefix, final int which,
+ int reqUid) {
final long rawUptime = SystemClock.uptimeMillis() * 1000;
final long rawRealtime = SystemClock.elapsedRealtime() * 1000;
final long batteryUptime = getBatteryUptime(rawUptime);
@@ -1758,6 +1827,65 @@ public abstract class BatteryStats implements Parcelable {
pw.println();
}
+ BatteryStatsHelper helper = new BatteryStatsHelper(context);
+ helper.create(this);
+ helper.refreshStats(which, UserHandle.USER_ALL);
+ List<BatterySipper> sippers = helper.getUsageList();
+ if (sippers != null && sippers.size() > 0) {
+ pw.print(prefix); pw.println(" Estimated power use (mAh):");
+ pw.print(prefix); pw.print(" Capacity: ");
+ printmAh(pw, helper.getPowerProfile().getBatteryCapacity());
+ pw.print(", Computed drain: "); printmAh(pw, helper.getTotalPower());
+ pw.print(", Min drain: "); printmAh(pw, helper.getMinDrainedPower());
+ pw.print(", Max drain: "); printmAh(pw, helper.getMaxDrainedPower());
+ pw.println();
+ for (int i=0; i<sippers.size(); i++) {
+ BatterySipper bs = sippers.get(i);
+ switch (bs.drainType) {
+ case IDLE:
+ pw.print(prefix); pw.print(" Idle: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case CELL:
+ pw.print(prefix); pw.print(" Cell standby: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case PHONE:
+ pw.print(prefix); pw.print(" Phone calls: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case WIFI:
+ pw.print(prefix); pw.print(" Wifi: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case BLUETOOTH:
+ pw.print(prefix); pw.print(" Bluetooth: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case SCREEN:
+ pw.print(prefix); pw.print(" Screen: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case APP:
+ pw.print(prefix); pw.print(" Uid "); pw.print(bs.uidObj.getUid());
+ pw.print(": "); printmAh(pw, bs.value); pw.println();
+ break;
+ case USER:
+ pw.print(prefix); pw.print(" User "); pw.print(bs.userId);
+ pw.print(": "); printmAh(pw, bs.value); pw.println();
+ break;
+ case UNACCOUNTED:
+ pw.print(prefix); pw.print(" Unaccounted: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ case OVERCOUNTED:
+ pw.print(prefix); pw.print(" Over-counted: "); printmAh(pw, bs.value);
+ pw.println();
+ break;
+ }
+ }
+ }
+
if (timers.size() > 0) {
Collections.sort(timers, timerComparator);
pw.print(prefix); pw.println(" All partial wake locks:");
@@ -2287,7 +2415,7 @@ public abstract class BatteryStats implements Parcelable {
* @param pw a Printer to receive the dump output.
*/
@SuppressWarnings("unused")
- public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
+ public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
prepareForDumpLocked();
long now = getHistoryBaseTime() + SystemClock.elapsedRealtime();
@@ -2344,15 +2472,15 @@ public abstract class BatteryStats implements Parcelable {
pw.println("Statistics since last charge:");
pw.println(" System starts: " + getStartCount()
+ ", currently on battery: " + getIsOnBattery());
- dumpLocked(pw, "", STATS_SINCE_CHARGED, reqUid);
+ dumpLocked(context, pw, "", STATS_SINCE_CHARGED, reqUid);
pw.println("");
}
pw.println("Statistics since last unplugged:");
- dumpLocked(pw, "", STATS_SINCE_UNPLUGGED, reqUid);
+ dumpLocked(context, pw, "", STATS_SINCE_UNPLUGGED, reqUid);
}
@SuppressWarnings("unused")
- public void dumpCheckinLocked(
+ public void dumpCheckinLocked(Context context,
PrintWriter pw, List<ApplicationInfo> apps, boolean isUnpluggedOnly,
boolean includeHistory) {
prepareForDumpLocked();
@@ -2400,11 +2528,11 @@ public abstract class BatteryStats implements Parcelable {
}
}
if (isUnpluggedOnly) {
- dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
+ dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
}
else {
- dumpCheckinLocked(pw, STATS_SINCE_CHARGED, -1);
- dumpCheckinLocked(pw, STATS_SINCE_UNPLUGGED, -1);
+ dumpCheckinLocked(context, pw, STATS_SINCE_CHARGED, -1);
+ dumpCheckinLocked(context, pw, STATS_SINCE_UNPLUGGED, -1);
}
}
}
diff --git a/core/java/com/android/internal/os/BatterySipper.java b/core/java/com/android/internal/os/BatterySipper.java
new file mode 100644
index 000000000000..4eff5acfc079
--- /dev/null
+++ b/core/java/com/android/internal/os/BatterySipper.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.internal.os;
+
+import android.os.BatteryStats.Uid;
+
+/**
+ * Contains power usage of an application, system service, or hardware type.
+ */
+public class BatterySipper implements Comparable<BatterySipper> {
+ public int userId;
+ public Uid uidObj;
+ public double value;
+ public double[] values;
+ public DrainType drainType;
+ public long usageTime;
+ public long cpuTime;
+ public long gpsTime;
+ public long wifiRunningTime;
+ public long cpuFgTime;
+ public long wakeLockTime;
+ public long mobileRxPackets;
+ public long mobileTxPackets;
+ public long wifiRxPackets;
+ public long wifiTxPackets;
+ public long mobileRxBytes;
+ public long mobileTxBytes;
+ public long wifiRxBytes;
+ public long wifiTxBytes;
+ public double percent;
+ public double noCoveragePercent;
+ public String[] mPackages;
+ public String packageWithHighestDrain;
+
+ public enum DrainType {
+ IDLE,
+ CELL,
+ PHONE,
+ WIFI,
+ BLUETOOTH,
+ SCREEN,
+ APP,
+ USER,
+ UNACCOUNTED,
+ OVERCOUNTED
+ }
+
+ public BatterySipper(DrainType drainType, Uid uid, double[] values) {
+ this.values = values;
+ if (values != null) value = values[0];
+ this.drainType = drainType;
+ uidObj = uid;
+ }
+
+ public double[] getValues() {
+ return values;
+ }
+
+ @Override
+ public int compareTo(BatterySipper other) {
+ // Return the flipped value because we want the items in descending order
+ return Double.compare(other.value, value);
+ }
+
+ /**
+ * Gets a list of packages associated with the current user
+ */
+ public String[] getPackages() {
+ return mPackages;
+ }
+
+ public int getUid() {
+ // Bail out if the current sipper is not an App sipper.
+ if (uidObj == null) {
+ return 0;
+ }
+ return uidObj.getUid();
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsHelper.java b/core/java/com/android/internal/os/BatteryStatsHelper.java
new file mode 100644
index 000000000000..4c851e79e619
--- /dev/null
+++ b/core/java/com/android/internal/os/BatteryStatsHelper.java
@@ -0,0 +1,726 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.os;
+
+import static android.os.BatteryStats.NETWORK_MOBILE_RX_DATA;
+import static android.os.BatteryStats.NETWORK_MOBILE_TX_DATA;
+import static android.os.BatteryStats.NETWORK_WIFI_RX_DATA;
+import static android.os.BatteryStats.NETWORK_WIFI_TX_DATA;
+
+import android.content.Context;
+import android.hardware.Sensor;
+import android.hardware.SensorManager;
+import android.net.ConnectivityManager;
+import android.os.BatteryStats;
+import android.os.BatteryStats.Uid;
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.UserHandle;
+import android.telephony.SignalStrength;
+import android.util.Log;
+import android.util.SparseArray;
+
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.os.BatterySipper.DrainType;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A helper class for retrieving the power usage information for all applications and services.
+ *
+ * The caller must initialize this class as soon as activity object is ready to use (for example, in
+ * onAttach() for Fragment), call create() in onCreate() and call destroy() in onDestroy().
+ */
+public class BatteryStatsHelper {
+
+ private static final boolean DEBUG = true;
+
+ private static final String TAG = BatteryStatsHelper.class.getSimpleName();
+
+ private static BatteryStats sStatsXfer;
+
+ final private Context mContext;
+
+ private IBatteryStats mBatteryInfo;
+ private BatteryStats mStats;
+ private PowerProfile mPowerProfile;
+
+ private final List<BatterySipper> mUsageList = new ArrayList<BatterySipper>();
+ private final List<BatterySipper> mWifiSippers = new ArrayList<BatterySipper>();
+ private final List<BatterySipper> mBluetoothSippers = new ArrayList<BatterySipper>();
+ private final SparseArray<List<BatterySipper>> mUserSippers
+ = new SparseArray<List<BatterySipper>>();
+ private final SparseArray<Double> mUserPower = new SparseArray<Double>();
+
+ private int mStatsType = BatteryStats.STATS_SINCE_CHARGED;
+ private int mAsUser = 0;
+
+ long mBatteryRealtime;
+ long mBatteryUptime;
+ long mTypeBatteryRealtime;
+ long mTypeBatteryUptime;
+
+ private long mStatsPeriod = 0;
+ private double mMaxPower = 1;
+ private double mTotalPower;
+ private double mWifiPower;
+ private double mBluetoothPower;
+ private double mMinDrainedPower;
+ private double mMaxDrainedPower;
+
+ // How much the apps together have left WIFI running.
+ private long mAppWifiRunning;
+
+ public BatteryStatsHelper(Context context) {
+ mContext = context;
+ }
+
+ /** Clears the current stats and forces recreating for future use. */
+ public void clearStats() {
+ mStats = null;
+ }
+
+ public BatteryStats getStats() {
+ if (mStats == null) {
+ load();
+ }
+ return mStats;
+ }
+
+ public PowerProfile getPowerProfile() {
+ return mPowerProfile;
+ }
+
+ public void create(BatteryStats stats) {
+ mPowerProfile = new PowerProfile(mContext);
+ mStats = stats;
+ }
+
+ public void create(Bundle icicle) {
+ if (icicle != null) {
+ mStats = sStatsXfer;
+ }
+ mBatteryInfo = IBatteryStats.Stub.asInterface(
+ ServiceManager.getService(BatteryStats.SERVICE_NAME));
+ mPowerProfile = new PowerProfile(mContext);
+ }
+
+ public void storeState() {
+ sStatsXfer = mStats;
+ }
+
+ public static String makemAh(double power) {
+ if (power < .0001) return String.format("%.8f", power);
+ else if (power < .0001) return String.format("%.7f", power);
+ else if (power < .001) return String.format("%.6f", power);
+ else if (power < .01) return String.format("%.5f", power);
+ else if (power < .1) return String.format("%.4f", power);
+ else if (power < 1) return String.format("%.3f", power);
+ else if (power < 10) return String.format("%.2f", power);
+ else if (power < 100) return String.format("%.1f", power);
+ else return String.format("%.0f", power);
+ }
+
+ /**
+ * Refreshes the power usage list.
+ */
+ public void refreshStats(int statsType, int asUser) {
+ refreshStats(statsType, asUser, SystemClock.elapsedRealtime() * 1000,
+ SystemClock.uptimeMillis() * 1000);
+ }
+
+ public void refreshStats(int statsType, int asUser, long rawRealtimeNano, long rawUptimeNano) {
+ // Initialize mStats if necessary.
+ getStats();
+
+ mMaxPower = 0;
+ mTotalPower = 0;
+ mWifiPower = 0;
+ mBluetoothPower = 0;
+ mAppWifiRunning = 0;
+
+ mUsageList.clear();
+ mWifiSippers.clear();
+ mBluetoothSippers.clear();
+ mUserSippers.clear();
+ mUserPower.clear();
+
+ if (mStats == null) {
+ return;
+ }
+
+ mStatsType = statsType;
+ mAsUser = asUser;
+ mBatteryUptime = mStats.getBatteryUptime(rawUptimeNano);
+ mBatteryRealtime = mStats.getBatteryRealtime(rawRealtimeNano);
+ mTypeBatteryUptime = mStats.computeBatteryUptime(rawUptimeNano, mStatsType);
+ mTypeBatteryRealtime = mStats.computeBatteryRealtime(rawRealtimeNano, mStatsType);
+
+ if (DEBUG) {
+ Log.d(TAG, "Raw time: realtime=" + (rawRealtimeNano/1000) + " uptime="
+ + (rawUptimeNano/1000));
+ Log.d(TAG, "Battery time: realtime=" + (mBatteryRealtime/1000) + " uptime="
+ + (mBatteryUptime/1000));
+ Log.d(TAG, "Battery type time: realtime=" + (mTypeBatteryRealtime/1000) + " uptime="
+ + (mTypeBatteryUptime/1000));
+ }
+ mMinDrainedPower = (mStats.getLowDischargeAmountSinceCharge()
+ * mPowerProfile.getBatteryCapacity()) / 100;
+ mMaxDrainedPower = (mStats.getHighDischargeAmountSinceCharge()
+ * mPowerProfile.getBatteryCapacity()) / 100;
+
+ processAppUsage();
+ processMiscUsage();
+
+ if (DEBUG) {
+ Log.d(TAG, "Accuracy: total computed=" + makemAh(mTotalPower) + ", min discharge="
+ + makemAh(mMinDrainedPower) + ", max discharge=" + makemAh(mMaxDrainedPower));
+ }
+ if (true || mStats.getLowDischargeAmountSinceCharge() > 10) {
+ if (mMinDrainedPower > mTotalPower) {
+ double amount = mMinDrainedPower - mTotalPower;
+ if (mMaxPower < amount) {
+ mMaxPower = amount;
+ }
+ addEntryNoTotal(BatterySipper.DrainType.UNACCOUNTED, 0, amount);
+ } else if (mMaxDrainedPower < mTotalPower) {
+ double amount = mTotalPower - mMaxDrainedPower;
+ if (mMaxPower < amount) {
+ mMaxPower = amount;
+ }
+ addEntryNoTotal(BatterySipper.DrainType.OVERCOUNTED, 0, amount);
+ }
+ }
+
+ Collections.sort(mUsageList);
+ }
+
+ private void processAppUsage() {
+ SensorManager sensorManager = (SensorManager) mContext.getSystemService(
+ Context.SENSOR_SERVICE);
+ final int which = mStatsType;
+ final int speedSteps = mPowerProfile.getNumSpeedSteps();
+ final double[] powerCpuNormal = new double[speedSteps];
+ final long[] cpuSpeedStepTimes = new long[speedSteps];
+ for (int p = 0; p < speedSteps; p++) {
+ powerCpuNormal[p] = mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_ACTIVE, p);
+ }
+ final double mobilePowerPerPacket = getMobilePowerPerPacket();
+ final double wifiPowerPerPacket = getWifiPowerPerPacket();
+ long appWakelockTime = 0;
+ BatterySipper osApp = null;
+ mStatsPeriod = mTypeBatteryRealtime;
+ SparseArray<? extends Uid> uidStats = mStats.getUidStats();
+ final int NU = uidStats.size();
+ for (int iu = 0; iu < NU; iu++) {
+ Uid u = uidStats.valueAt(iu);
+ double p; // in mAs
+ double power = 0; // in mAs
+ double highestDrain = 0;
+ String packageWithHighestDrain = null;
+ //mUsageList.add(new AppUsage(u.getUid(), new double[] {power}));
+ Map<String, ? extends BatteryStats.Uid.Proc> processStats = u.getProcessStats();
+ long cpuTime = 0;
+ long cpuFgTime = 0;
+ long wakelockTime = 0;
+ long gpsTime = 0;
+ if (processStats.size() > 0) {
+ // Process CPU time
+ for (Map.Entry<String, ? extends BatteryStats.Uid.Proc> ent
+ : processStats.entrySet()) {
+ Uid.Proc ps = ent.getValue();
+ final long userTime = ps.getUserTime(which);
+ final long systemTime = ps.getSystemTime(which);
+ final long foregroundTime = ps.getForegroundTime(which);
+ cpuFgTime += foregroundTime * 10; // convert to millis
+ final long tmpCpuTime = (userTime + systemTime) * 10; // convert to millis
+ int totalTimeAtSpeeds = 0;
+ // Get the total first
+ for (int step = 0; step < speedSteps; step++) {
+ cpuSpeedStepTimes[step] = ps.getTimeAtCpuSpeedStep(step, which);
+ totalTimeAtSpeeds += cpuSpeedStepTimes[step];
+ }
+ if (totalTimeAtSpeeds == 0) totalTimeAtSpeeds = 1;
+ // Then compute the ratio of time spent at each speed
+ double processPower = 0;
+ for (int step = 0; step < speedSteps; step++) {
+ double ratio = (double) cpuSpeedStepTimes[step] / totalTimeAtSpeeds;
+ if (DEBUG && ratio != 0) Log.d(TAG, "UID " + u.getUid() + ": CPU step #"
+ + step + " ratio=" + makemAh(ratio) + " power="
+ + makemAh(ratio*tmpCpuTime*powerCpuNormal[step] / (60*60*1000)));
+ processPower += ratio * tmpCpuTime * powerCpuNormal[step];
+ }
+ cpuTime += tmpCpuTime;
+ if (DEBUG && processPower != 0) {
+ Log.d(TAG, String.format("process %s, cpu power=%s",
+ ent.getKey(), makemAh(processPower / (60*60*1000))));
+ }
+ power += processPower;
+ if (packageWithHighestDrain == null
+ || packageWithHighestDrain.startsWith("*")) {
+ highestDrain = processPower;
+ packageWithHighestDrain = ent.getKey();
+ } else if (highestDrain < processPower
+ && !ent.getKey().startsWith("*")) {
+ highestDrain = processPower;
+ packageWithHighestDrain = ent.getKey();
+ }
+ }
+ }
+ if (cpuFgTime > cpuTime) {
+ if (DEBUG && cpuFgTime > cpuTime + 10000) {
+ Log.d(TAG, "WARNING! Cputime is more than 10 seconds behind Foreground time");
+ }
+ cpuTime = cpuFgTime; // Statistics may not have been gathered yet.
+ }
+ power /= (60*60*1000);
+
+ // Process wake lock usage
+ Map<String, ? extends BatteryStats.Uid.Wakelock> wakelockStats = u.getWakelockStats();
+ for (Map.Entry<String, ? extends BatteryStats.Uid.Wakelock> wakelockEntry
+ : wakelockStats.entrySet()) {
+ Uid.Wakelock wakelock = wakelockEntry.getValue();
+ // Only care about partial wake locks since full wake locks
+ // are canceled when the user turns the screen off.
+ BatteryStats.Timer timer = wakelock.getWakeTime(BatteryStats.WAKE_TYPE_PARTIAL);
+ if (timer != null) {
+ wakelockTime += timer.getTotalTimeLocked(mBatteryRealtime, which);
+ }
+ }
+ wakelockTime /= 1000; // convert to millis
+ appWakelockTime += wakelockTime;
+
+ // Add cost of holding a wake lock
+ p = (wakelockTime
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE)) / (60*60*1000);
+ if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wake "
+ + wakelockTime + " power=" + makemAh(p));
+ power += p;
+
+ // Add cost of mobile traffic
+ final long mobileRx = u.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
+ final long mobileTx = u.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
+ final long mobileRxB = u.getNetworkActivityBytes(NETWORK_MOBILE_RX_DATA, mStatsType);
+ final long mobileTxB = u.getNetworkActivityBytes(NETWORK_MOBILE_TX_DATA, mStatsType);
+ p = (mobileRx + mobileTx) * mobilePowerPerPacket;
+ if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": mobile packets "
+ + (mobileRx+mobileTx) + " power=" + makemAh(p));
+ power += p;
+
+ // Add cost of wifi traffic
+ final long wifiRx = u.getNetworkActivityPackets(NETWORK_WIFI_RX_DATA, mStatsType);
+ final long wifiTx = u.getNetworkActivityPackets(NETWORK_WIFI_TX_DATA, mStatsType);
+ final long wifiRxB = u.getNetworkActivityBytes(NETWORK_WIFI_RX_DATA, mStatsType);
+ final long wifiTxB = u.getNetworkActivityBytes(NETWORK_WIFI_TX_DATA, mStatsType);
+ p = (wifiRx + wifiTx) * wifiPowerPerPacket;
+ if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wifi packets "
+ + (mobileRx+mobileTx) + " power=" + makemAh(p));
+ power += p;
+
+ // Add cost of keeping WIFI running.
+ long wifiRunningTimeMs = u.getWifiRunningTime(mBatteryRealtime, which) / 1000;
+ mAppWifiRunning += wifiRunningTimeMs;
+ p = (wifiRunningTimeMs
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)) / (60*60*1000);
+ if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wifi running "
+ + wifiRunningTimeMs + " power=" + makemAh(p));
+ power += p;
+
+ // Add cost of WIFI scans
+ long wifiScanTimeMs = u.getWifiScanTime(mBatteryRealtime, which) / 1000;
+ p = (wifiScanTimeMs
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_SCAN)) / (60*60*1000);
+ if (DEBUG) Log.d(TAG, "UID " + u.getUid() + ": wifi scan " + wifiScanTimeMs
+ + " power=" + makemAh(p));
+ power += p;
+ for (int bin = 0; bin < BatteryStats.Uid.NUM_WIFI_BATCHED_SCAN_BINS; bin++) {
+ long batchScanTimeMs = u.getWifiBatchedScanTime(bin, mBatteryRealtime, which) / 1000;
+ p = ((batchScanTimeMs
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_BATCHED_SCAN, bin))
+ ) / (60*60*1000);
+ if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": wifi batched scan # " + bin
+ + " time=" + batchScanTimeMs + " power=" + makemAh(p));
+ power += p;
+ }
+
+ // Process Sensor usage
+ Map<Integer, ? extends BatteryStats.Uid.Sensor> sensorStats = u.getSensorStats();
+ for (Map.Entry<Integer, ? extends BatteryStats.Uid.Sensor> sensorEntry
+ : sensorStats.entrySet()) {
+ Uid.Sensor sensor = sensorEntry.getValue();
+ int sensorHandle = sensor.getHandle();
+ BatteryStats.Timer timer = sensor.getSensorTime();
+ long sensorTime = timer.getTotalTimeLocked(mBatteryRealtime, which) / 1000;
+ double multiplier = 0;
+ switch (sensorHandle) {
+ case Uid.Sensor.GPS:
+ multiplier = mPowerProfile.getAveragePower(PowerProfile.POWER_GPS_ON);
+ gpsTime = sensorTime;
+ break;
+ default:
+ List<Sensor> sensorList = sensorManager.getSensorList(
+ android.hardware.Sensor.TYPE_ALL);
+ for (android.hardware.Sensor s : sensorList) {
+ if (s.getHandle() == sensorHandle) {
+ multiplier = s.getPower();
+ break;
+ }
+ }
+ }
+ p = (multiplier * sensorTime) / (60*60*1000);
+ if (DEBUG && p != 0) Log.d(TAG, "UID " + u.getUid() + ": sensor #" + sensorHandle
+ + " time=" + sensorTime + " power=" + makemAh(p));
+ power += p;
+ }
+
+ if (DEBUG && power != 0) Log.d(TAG, String.format("UID %d: total power=%s",
+ u.getUid(), makemAh(power)));
+
+ // Add the app to the list if it is consuming power
+ boolean isOtherUser = false;
+ final int userId = UserHandle.getUserId(u.getUid());
+ if (power != 0 || u.getUid() == 0) {
+ BatterySipper app = new BatterySipper(BatterySipper.DrainType.APP, u,
+ new double[] {power});
+ app.cpuTime = cpuTime;
+ app.gpsTime = gpsTime;
+ app.wifiRunningTime = wifiRunningTimeMs;
+ app.cpuFgTime = cpuFgTime;
+ app.wakeLockTime = wakelockTime;
+ app.mobileRxPackets = mobileRx;
+ app.mobileTxPackets = mobileTx;
+ app.wifiRxPackets = wifiRx;
+ app.wifiTxPackets = wifiTx;
+ app.mobileRxBytes = mobileRxB;
+ app.mobileTxBytes = mobileTxB;
+ app.wifiRxBytes = wifiRxB;
+ app.wifiTxBytes = wifiTxB;
+ app.packageWithHighestDrain = packageWithHighestDrain;
+ if (u.getUid() == Process.WIFI_UID) {
+ mWifiSippers.add(app);
+ } else if (u.getUid() == Process.BLUETOOTH_UID) {
+ mBluetoothSippers.add(app);
+ } else if (mAsUser != UserHandle.USER_ALL && userId != mAsUser
+ && UserHandle.getAppId(u.getUid()) >= Process.FIRST_APPLICATION_UID) {
+ isOtherUser = true;
+ List<BatterySipper> list = mUserSippers.get(userId);
+ if (list == null) {
+ list = new ArrayList<BatterySipper>();
+ mUserSippers.put(userId, list);
+ }
+ list.add(app);
+ } else {
+ mUsageList.add(app);
+ }
+ if (u.getUid() == 0) {
+ osApp = app;
+ }
+ }
+ if (power != 0) {
+ if (u.getUid() == Process.WIFI_UID) {
+ mWifiPower += power;
+ } else if (u.getUid() == Process.BLUETOOTH_UID) {
+ mBluetoothPower += power;
+ } else if (isOtherUser) {
+ Double userPower = mUserPower.get(userId);
+ if (userPower == null) {
+ userPower = power;
+ } else {
+ userPower += power;
+ }
+ mUserPower.put(userId, userPower);
+ } else {
+ if (power > mMaxPower) mMaxPower = power;
+ mTotalPower += power;
+ }
+ }
+ }
+
+ // The device has probably been awake for longer than the screen on
+ // time and application wake lock time would account for. Assign
+ // this remainder to the OS, if possible.
+ if (osApp != null) {
+ long wakeTimeMillis = mBatteryUptime / 1000;
+ wakeTimeMillis -= appWakelockTime
+ + (mStats.getScreenOnTime(mBatteryRealtime, which) / 1000);
+ if (wakeTimeMillis > 0) {
+ double power = (wakeTimeMillis
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_AWAKE))
+ / (60*60*1000);
+ if (DEBUG) Log.d(TAG, "OS wakeLockTime " + wakeTimeMillis + " power "
+ + makemAh(power));
+ osApp.wakeLockTime += wakeTimeMillis;
+ osApp.value += power;
+ osApp.values[0] += power;
+ if (osApp.value > mMaxPower) mMaxPower = osApp.value;
+ mTotalPower += power;
+ }
+ }
+ }
+
+ private void addPhoneUsage() {
+ long phoneOnTimeMs = mStats.getPhoneOnTime(mBatteryRealtime, mStatsType) / 1000;
+ double phoneOnPower = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
+ * phoneOnTimeMs / (60*60*1000);
+ addEntry(BatterySipper.DrainType.PHONE, phoneOnTimeMs, phoneOnPower);
+ }
+
+ private void addScreenUsage() {
+ double power = 0;
+ long screenOnTimeMs = mStats.getScreenOnTime(mBatteryRealtime, mStatsType) / 1000;
+ power += screenOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_ON);
+ final double screenFullPower =
+ mPowerProfile.getAveragePower(PowerProfile.POWER_SCREEN_FULL);
+ for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
+ double screenBinPower = screenFullPower * (i + 0.5f)
+ / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+ long brightnessTime = mStats.getScreenBrightnessTime(i, mBatteryRealtime, mStatsType)
+ / 1000;
+ double p = screenBinPower*brightnessTime;
+ if (DEBUG && p != 0) {
+ Log.d(TAG, "Screen bin #" + i + ": time=" + brightnessTime
+ + " power=" + makemAh(p/(60*60*1000)));
+ }
+ power += p;
+ }
+ power /= (60*60*1000); // To hours
+ addEntry(BatterySipper.DrainType.SCREEN, screenOnTimeMs, power);
+ }
+
+ private void addRadioUsage() {
+ double power = 0;
+ final int BINS = SignalStrength.NUM_SIGNAL_STRENGTH_BINS;
+ long signalTimeMs = 0;
+ long noCoverageTimeMs = 0;
+ for (int i = 0; i < BINS; i++) {
+ long strengthTimeMs = mStats.getPhoneSignalStrengthTime(i, mBatteryRealtime, mStatsType)
+ / 1000;
+ double p = (strengthTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ON, i))
+ / (60*60*1000);
+ if (DEBUG && p != 0) {
+ Log.d(TAG, "Cell strength #" + i + ": time=" + strengthTimeMs + " power="
+ + makemAh(p));
+ }
+ power += p;
+ signalTimeMs += strengthTimeMs;
+ if (i == 0) {
+ noCoverageTimeMs = strengthTimeMs;
+ }
+ }
+ long scanningTimeMs = mStats.getPhoneSignalScanningTime(mBatteryRealtime, mStatsType)
+ / 1000;
+ double p = (scanningTimeMs * mPowerProfile.getAveragePower(
+ PowerProfile.POWER_RADIO_SCANNING))
+ / (60*60*1000);
+ if (DEBUG && p != 0) {
+ Log.d(TAG, "Cell radio scanning: time=" + scanningTimeMs + " power=" + makemAh(p));
+ }
+ power += p;
+ BatterySipper bs =
+ addEntry(BatterySipper.DrainType.CELL, signalTimeMs, power);
+ if (signalTimeMs != 0) {
+ bs.noCoveragePercent = noCoverageTimeMs * 100.0 / signalTimeMs;
+ }
+ }
+
+ private void aggregateSippers(BatterySipper bs, List<BatterySipper> from, String tag) {
+ for (int i=0; i<from.size(); i++) {
+ BatterySipper wbs = from.get(i);
+ if (DEBUG) Log.d(TAG, tag + " adding sipper " + wbs + ": cpu=" + wbs.cpuTime);
+ bs.cpuTime += wbs.cpuTime;
+ bs.gpsTime += wbs.gpsTime;
+ bs.wifiRunningTime += wbs.wifiRunningTime;
+ bs.cpuFgTime += wbs.cpuFgTime;
+ bs.wakeLockTime += wbs.wakeLockTime;
+ bs.mobileRxPackets += wbs.mobileRxPackets;
+ bs.mobileTxPackets += wbs.mobileTxPackets;
+ bs.wifiRxPackets += wbs.wifiRxPackets;
+ bs.wifiTxPackets += wbs.wifiTxPackets;
+ bs.mobileRxBytes += wbs.mobileRxBytes;
+ bs.mobileTxBytes += wbs.mobileTxBytes;
+ bs.wifiRxBytes += wbs.wifiRxBytes;
+ bs.wifiTxBytes += wbs.wifiTxBytes;
+ }
+ }
+
+ private void addWiFiUsage() {
+ long onTimeMs = mStats.getWifiOnTime(mBatteryRealtime, mStatsType) / 1000;
+ long runningTimeMs = mStats.getGlobalWifiRunningTime(mBatteryRealtime, mStatsType) / 1000;
+ if (DEBUG) Log.d(TAG, "WIFI runningTime=" + runningTimeMs
+ + " app runningTime=" + mAppWifiRunning);
+ runningTimeMs -= mAppWifiRunning;
+ if (runningTimeMs < 0) runningTimeMs = 0;
+ double wifiPower = (onTimeMs * 0 /* TODO */
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON)
+ + runningTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ON))
+ / (60*60*1000);
+ if (DEBUG && wifiPower != 0) {
+ Log.d(TAG, "Wifi: time=" + runningTimeMs + " power=" + makemAh(wifiPower));
+ }
+ BatterySipper bs = addEntry(BatterySipper.DrainType.WIFI, runningTimeMs,
+ wifiPower + mWifiPower);
+ aggregateSippers(bs, mWifiSippers, "WIFI");
+ }
+
+ private void addIdleUsage() {
+ long idleTimeMs = (mTypeBatteryRealtime
+ - mStats.getScreenOnTime(mBatteryRealtime, mStatsType)) / 1000;
+ double idlePower = (idleTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_CPU_IDLE))
+ / (60*60*1000);
+ if (DEBUG && idlePower != 0) {
+ Log.d(TAG, "Idle: time=" + idleTimeMs + " power=" + makemAh(idlePower));
+ }
+ addEntry(BatterySipper.DrainType.IDLE, idleTimeMs, idlePower);
+ }
+
+ private void addBluetoothUsage() {
+ long btOnTimeMs = mStats.getBluetoothOnTime(mBatteryRealtime, mStatsType) / 1000;
+ double btPower = btOnTimeMs * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_ON)
+ / (60*60*1000);
+ if (DEBUG && btPower != 0) {
+ Log.d(TAG, "Bluetooth: time=" + btOnTimeMs + " power=" + makemAh(btPower));
+ }
+ int btPingCount = mStats.getBluetoothPingCount();
+ double pingPower = (btPingCount
+ * mPowerProfile.getAveragePower(PowerProfile.POWER_BLUETOOTH_AT_CMD))
+ / (60*60*1000);
+ if (DEBUG && pingPower != 0) {
+ Log.d(TAG, "Bluetooth ping: count=" + btPingCount + " power=" + makemAh(pingPower));
+ }
+ btPower += pingPower;
+ BatterySipper bs = addEntry(BatterySipper.DrainType.BLUETOOTH, btOnTimeMs,
+ btPower + mBluetoothPower);
+ aggregateSippers(bs, mBluetoothSippers, "Bluetooth");
+ }
+
+ private void addUserUsage() {
+ for (int i=0; i<mUserSippers.size(); i++) {
+ final int userId = mUserSippers.keyAt(i);
+ final List<BatterySipper> sippers = mUserSippers.valueAt(i);
+ Double userPower = mUserPower.get(userId);
+ double power = (userPower != null) ? userPower : 0.0;
+ BatterySipper bs = addEntry(BatterySipper.DrainType.USER, 0, power);
+ bs.userId = userId;
+ aggregateSippers(bs, sippers, "User");
+ }
+ }
+
+ /**
+ * Return estimated power (in mAs) of sending or receiving a packet with the mobile radio.
+ */
+ private double getMobilePowerPerPacket() {
+ final long MOBILE_BPS = 200000; // TODO: Extract average bit rates from system
+ final double MOBILE_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_RADIO_ACTIVE)
+ / 3600;
+
+ final long mobileRx = mStats.getNetworkActivityPackets(NETWORK_MOBILE_RX_DATA, mStatsType);
+ final long mobileTx = mStats.getNetworkActivityPackets(NETWORK_MOBILE_TX_DATA, mStatsType);
+ final long mobileData = mobileRx + mobileTx;
+
+ final long radioDataUptimeMs = mStats.getRadioDataUptime() / 1000;
+ final double mobilePps = radioDataUptimeMs != 0
+ ? mobileData / (double)radioDataUptimeMs
+ : (((double)MOBILE_BPS) / 8 / 2048);
+
+ return (MOBILE_POWER / mobilePps) / (60*60);
+ }
+
+ /**
+ * Return estimated power (in mAs) of sending a byte with the Wi-Fi radio.
+ */
+ private double getWifiPowerPerPacket() {
+ final long WIFI_BPS = 1000000; // TODO: Extract average bit rates from system
+ final double WIFI_POWER = mPowerProfile.getAveragePower(PowerProfile.POWER_WIFI_ACTIVE)
+ / 3600;
+ return (WIFI_POWER / (((double)WIFI_BPS) / 8 / 2048)) / (60*60);
+ }
+
+ private void processMiscUsage() {
+ addUserUsage();
+ addPhoneUsage();
+ addScreenUsage();
+ addWiFiUsage();
+ addBluetoothUsage();
+ addIdleUsage(); // Not including cellular idle power
+ // Don't compute radio usage if it's a wifi-only device
+ ConnectivityManager cm = (ConnectivityManager)mContext.getSystemService(
+ Context.CONNECTIVITY_SERVICE);
+ if (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE)) {
+ addRadioUsage();
+ }
+ }
+
+ private BatterySipper addEntry(DrainType drainType, long time, double power) {
+ mTotalPower += power;
+ return addEntryNoTotal(drainType, time, power);
+ }
+
+ private BatterySipper addEntryNoTotal(DrainType drainType, long time, double power) {
+ if (power > mMaxPower) mMaxPower = power;
+ mTotalPower += power;
+ BatterySipper bs = new BatterySipper(drainType, null, new double[] {power});
+ bs.usageTime = time;
+ mUsageList.add(bs);
+ return bs;
+ }
+
+ public List<BatterySipper> getUsageList() {
+ return mUsageList;
+ }
+
+ public long getStatsPeriod() { return mStatsPeriod; }
+
+ public int getStatsType() { return mStatsType; };
+
+ public double getMaxPower() { return mMaxPower; }
+
+ public double getTotalPower() { return mTotalPower; }
+
+ public double getMinDrainedPower() {
+ return mMinDrainedPower;
+ }
+
+ public double getMaxDrainedPower() {
+ return mMaxDrainedPower;
+ }
+
+ private void load() {
+ if (mBatteryInfo == null) {
+ return;
+ }
+ try {
+ byte[] data = mBatteryInfo.getStatistics();
+ Parcel parcel = Parcel.obtain();
+ parcel.unmarshall(data, 0, data.length);
+ parcel.setDataPosition(0);
+ BatteryStatsImpl stats = com.android.internal.os.BatteryStatsImpl.CREATOR
+ .createFromParcel(parcel);
+ stats.distributeWorkLocked(BatteryStats.STATS_SINCE_CHARGED);
+ mStats = stats;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException:", e);
+ }
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 794c6859515e..7d178393d6ed 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -20,6 +20,7 @@ import static com.android.server.NetworkManagementSocketTagger.PROP_QTAGUID_ENAB
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
+import android.content.Context;
import android.net.ConnectivityManager;
import android.net.NetworkStats;
import android.os.BatteryManager;
@@ -4940,6 +4941,11 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void pullPendingStateUpdatesLocked() {
+ updateKernelWakelocksLocked();
+ updateNetworkActivityLocked();
+ }
+
void setOnBatteryLocked(boolean onBattery, int oldStatus, int level) {
boolean doWrite = false;
Message m = mHandler.obtainMessage(MSG_REPORT_POWER_CHANGE);
@@ -4962,8 +4968,7 @@ public final class BatteryStatsImpl extends BatteryStats {
resetAllStatsLocked();
mDischargeStartLevel = level;
}
- updateKernelWakelocksLocked();
- updateNetworkActivityLocked();
+ pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states &= ~HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Battery unplugged to: "
@@ -4985,8 +4990,7 @@ public final class BatteryStatsImpl extends BatteryStats {
mDischargeAmountScreenOff = 0;
doUnplugLocked(realtime, mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
} else {
- updateKernelWakelocksLocked();
- updateNetworkActivityLocked();
+ pullPendingStateUpdatesLocked();
mHistoryCur.batteryLevel = (byte)level;
mHistoryCur.states |= HistoryItem.STATE_BATTERY_PLUGGED_FLAG;
if (DEBUG_HISTORY) Slog.v(TAG, "Battery plugged to: "
@@ -6282,8 +6286,7 @@ public final class BatteryStatsImpl extends BatteryStats {
@SuppressWarnings("unused")
void writeToParcelLocked(Parcel out, boolean inclUids, int flags) {
// Need to update with current kernel wake lock counts.
- updateKernelWakelocksLocked();
- updateNetworkActivityLocked();
+ pullPendingStateUpdatesLocked();
final long uSecUptime = SystemClock.uptimeMillis() * 1000;
final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
@@ -6388,11 +6391,10 @@ public final class BatteryStatsImpl extends BatteryStats {
public void prepareForDumpLocked() {
// Need to retrieve current kernel wake lock stats before printing.
- updateKernelWakelocksLocked();
- updateNetworkActivityLocked();
+ pullPendingStateUpdatesLocked();
}
- public void dumpLocked(PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
+ public void dumpLocked(Context context, PrintWriter pw, boolean isUnpluggedOnly, int reqUid) {
if (DEBUG) {
Printer pr = new PrintWriterPrinter(pw);
pr.println("*** Screen timer:");
@@ -6422,6 +6424,6 @@ public final class BatteryStatsImpl extends BatteryStats {
pr.println("*** Bluetooth timer:");
mBluetoothOnTimer.logState(pr, " ");
}
- super.dumpLocked(pw, isUnpluggedOnly, reqUid);
+ super.dumpLocked(context, pw, isUnpluggedOnly, reqUid);
}
}
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index 2d596788a829..9805efe7d099 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -568,11 +568,11 @@ public final class BatteryStatsService extends IBatteryStats.Stub {
if (isCheckin) {
List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(0);
synchronized (mStats) {
- mStats.dumpCheckinLocked(pw, apps, isUnpluggedOnly, includeHistory);
+ mStats.dumpCheckinLocked(mContext, pw, apps, isUnpluggedOnly, includeHistory);
}
} else {
synchronized (mStats) {
- mStats.dumpLocked(pw, isUnpluggedOnly, reqUid);
+ mStats.dumpLocked(mContext, pw, isUnpluggedOnly, reqUid);
}
}
}