summaryrefslogtreecommitdiffstats
path: root/core/java/com
diff options
context:
space:
mode:
authorJeff Sharkey <jsharkey@android.com>2011-10-04 16:54:49 -0700
committerJeff Sharkey <jsharkey@android.com>2011-10-09 13:49:08 -0700
commit1059c3c30ad96a15695c1a92ae8896e078a6309f (patch)
tree3f73fd2918711f25b2ad4dd643db73b6f5483856 /core/java/com
parent650c53aad5a49c793bbcddad9bfce63a3b3d0360 (diff)
downloadframeworks_base-1059c3c30ad96a15695c1a92ae8896e078a6309f.zip
frameworks_base-1059c3c30ad96a15695c1a92ae8896e078a6309f.tar.gz
frameworks_base-1059c3c30ad96a15695c1a92ae8896e078a6309f.tar.bz2
Move battery stats to xt_qtaguid for data stats.
Replace TrafficStats calls by reading values from xt_qtaguid kernel module. To keep BatteryStatsImpl changes lightweight, cache recently parsed stats. Tracks mobile ifaces from ConnectivityService. Refactor xt_qtaguid parsing into factory outside of NMS. Add stats grouping based on UID, and total based on limiting filters like iface prefix and UID. Bug: 4902271 Change-Id: I533f116c434b77f93355bf95b839e7478528505b
Diffstat (limited to 'core/java/com')
-rw-r--r--core/java/com/android/internal/app/IBatteryStats.aidl1
-rw-r--r--core/java/com/android/internal/net/NetworkStatsFactory.java379
-rw-r--r--core/java/com/android/internal/os/BatteryStatsImpl.java142
3 files changed, 500 insertions, 22 deletions
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 351714e..6a0cd36 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -68,6 +68,7 @@ interface IBatteryStats {
void noteScanWifiLockReleasedFromSource(in WorkSource ws);
void noteWifiMulticastEnabledFromSource(in WorkSource ws);
void noteWifiMulticastDisabledFromSource(in WorkSource ws);
+ void noteNetworkInterfaceType(String iface, int type);
void setBatteryState(int status, int health, int plugType, int level, int temp, int volt);
long getAwakeTimeBattery();
long getAwakeTimePlugged();
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java
new file mode 100644
index 0000000..ee3f23b
--- /dev/null
+++ b/core/java/com/android/internal/net/NetworkStatsFactory.java
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2011 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.net;
+
+import static android.net.NetworkStats.SET_DEFAULT;
+import static android.net.NetworkStats.TAG_NONE;
+import static android.net.NetworkStats.UID_ALL;
+import static com.android.server.NetworkManagementSocketTagger.kernelToTag;
+
+import android.net.NetworkStats;
+import android.os.SystemClock;
+import android.util.Slog;
+
+import com.google.android.collect.Lists;
+import com.google.android.collect.Maps;
+import com.google.android.collect.Sets;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.StringTokenizer;
+
+import libcore.io.IoUtils;
+
+/**
+ * Creates {@link NetworkStats} instances by parsing various {@code /proc/}
+ * files as needed.
+ */
+public class NetworkStatsFactory {
+ private static final String TAG = "NetworkStatsFactory";
+
+ // TODO: consider moving parsing to native code
+
+ /** Path to {@code /proc/net/dev}. */
+ @Deprecated
+ private final File mStatsIface;
+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
+ @Deprecated
+ private final File mStatsXtIface;
+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
+ private final File mStatsXtIfaceAll;
+ /** Path to {@code /proc/net/xt_qtaguid/stats}. */
+ private final File mStatsXtUid;
+
+ /** {@link #mStatsXtUid} and {@link #mStatsXtIfaceAll} headers. */
+ private static final String KEY_IDX = "idx";
+ private static final String KEY_IFACE = "iface";
+ private static final String KEY_ACTIVE = "active";
+ private static final String KEY_UID = "uid_tag_int";
+ private static final String KEY_COUNTER_SET = "cnt_set";
+ private static final String KEY_TAG_HEX = "acct_tag_hex";
+ private static final String KEY_SNAP_RX_BYTES = "snap_rx_bytes";
+ private static final String KEY_SNAP_RX_PACKETS = "snap_rx_packets";
+ private static final String KEY_SNAP_TX_BYTES = "snap_tx_bytes";
+ private static final String KEY_SNAP_TX_PACKETS = "snap_tx_packets";
+ private static final String KEY_RX_BYTES = "rx_bytes";
+ private static final String KEY_RX_PACKETS = "rx_packets";
+ private static final String KEY_TX_BYTES = "tx_bytes";
+ private static final String KEY_TX_PACKETS = "tx_packets";
+
+ public NetworkStatsFactory() {
+ this(new File("/proc/"));
+ }
+
+ // @VisibleForTesting
+ public NetworkStatsFactory(File procRoot) {
+ mStatsIface = new File(procRoot, "net/dev");
+ mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
+ mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
+ mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
+ }
+
+ /**
+ * Parse and return interface-level summary {@link NetworkStats}. Values
+ * monotonically increase since device boot, and may include details about
+ * inactive interfaces.
+ *
+ * @throws IllegalStateException when problem parsing stats.
+ */
+ public NetworkStats readNetworkStatsSummary() throws IllegalStateException {
+ if (mStatsXtIfaceAll.exists()) {
+ return readNetworkStatsSummarySingleFile();
+ } else {
+ return readNetworkStatsSummaryMultipleFiles();
+ }
+ }
+
+ private NetworkStats readNetworkStatsSummarySingleFile() {
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ // TODO: read directly from proc once headers are added
+ final ArrayList<String> keys = Lists.newArrayList(KEY_IFACE, KEY_ACTIVE, KEY_SNAP_RX_BYTES,
+ KEY_SNAP_RX_PACKETS, KEY_SNAP_TX_BYTES, KEY_SNAP_TX_PACKETS, KEY_RX_BYTES,
+ KEY_RX_PACKETS, KEY_TX_BYTES, KEY_TX_PACKETS);
+ final ArrayList<String> values = Lists.newArrayList();
+ final HashMap<String, String> parsed = Maps.newHashMap();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mStatsXtIfaceAll));
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ splitLine(line, values);
+ parseLine(keys, values, parsed);
+
+ entry.iface = parsed.get(KEY_IFACE);
+ entry.uid = UID_ALL;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+
+ // always include snapshot values
+ entry.rxBytes = getParsedLong(parsed, KEY_SNAP_RX_BYTES);
+ entry.rxPackets = getParsedLong(parsed, KEY_SNAP_RX_PACKETS);
+ entry.txBytes = getParsedLong(parsed, KEY_SNAP_TX_BYTES);
+ entry.txPackets = getParsedLong(parsed, KEY_SNAP_TX_PACKETS);
+
+ // fold in active numbers, but only when active
+ final boolean active = getParsedInt(parsed, KEY_ACTIVE) != 0;
+ if (active) {
+ entry.rxBytes += getParsedLong(parsed, KEY_RX_BYTES);
+ entry.rxPackets += getParsedLong(parsed, KEY_RX_PACKETS);
+ entry.txBytes += getParsedLong(parsed, KEY_TX_BYTES);
+ entry.txPackets += getParsedLong(parsed, KEY_TX_PACKETS);
+ }
+
+ stats.addValues(entry);
+ }
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (IOException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+ return stats;
+ }
+
+ /**
+ * @deprecated remove once {@code iface_stat_all} is merged to all kernels.
+ */
+ @Deprecated
+ private NetworkStats readNetworkStatsSummaryMultipleFiles() {
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ final HashSet<String> knownIfaces = Sets.newHashSet();
+ final HashSet<String> activeIfaces = Sets.newHashSet();
+
+ // collect any historical stats and active state
+ for (String iface : fileListWithoutNull(mStatsXtIface)) {
+ final File ifacePath = new File(mStatsXtIface, iface);
+
+ final long active = readSingleLongFromFile(new File(ifacePath, "active"));
+ if (active == 1) {
+ knownIfaces.add(iface);
+ activeIfaces.add(iface);
+ } else if (active == 0) {
+ knownIfaces.add(iface);
+ } else {
+ continue;
+ }
+
+ entry.iface = iface;
+ entry.uid = UID_ALL;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
+ entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
+ entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
+ entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
+
+ stats.addValues(entry);
+ }
+
+ final ArrayList<String> values = Lists.newArrayList();
+
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new FileReader(mStatsIface));
+
+ // skip first two header lines
+ reader.readLine();
+ reader.readLine();
+
+ // parse remaining lines
+ String line;
+ while ((line = reader.readLine()) != null) {
+ splitLine(line, values);
+
+ try {
+ entry.iface = values.get(0);
+ entry.uid = UID_ALL;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = Long.parseLong(values.get(1));
+ entry.rxPackets = Long.parseLong(values.get(2));
+ entry.txBytes = Long.parseLong(values.get(9));
+ entry.txPackets = Long.parseLong(values.get(10));
+
+ if (activeIfaces.contains(entry.iface)) {
+ // combine stats when iface is active
+ stats.combineValues(entry);
+ } else if (!knownIfaces.contains(entry.iface)) {
+ // add stats when iface is unknown
+ stats.addValues(entry);
+ }
+ } catch (NumberFormatException e) {
+ Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
+ }
+ }
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } catch (IOException e) {
+ throw new IllegalStateException("problem parsing stats: " + e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+
+ return stats;
+ }
+
+ public NetworkStats readNetworkStatsDetail() {
+ return readNetworkStatsDetail(UID_ALL);
+ }
+
+ /**
+ * Parse and return {@link NetworkStats} with UID-level details. Values
+ * monotonically increase since device boot.
+ *
+ * @throws IllegalStateException when problem parsing stats.
+ */
+ public NetworkStats readNetworkStatsDetail(int limitUid) throws IllegalStateException {
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+
+ // TODO: remove knownLines check once 5087722 verified
+ final HashSet<String> knownLines = Sets.newHashSet();
+ // TODO: remove lastIdx check once 5270106 verified
+ int lastIdx;
+
+ final ArrayList<String> keys = Lists.newArrayList();
+ final ArrayList<String> values = Lists.newArrayList();
+ final HashMap<String, String> parsed = Maps.newHashMap();
+
+ BufferedReader reader = null;
+ String line = null;
+ try {
+ reader = new BufferedReader(new FileReader(mStatsXtUid));
+
+ // parse first line as header
+ line = reader.readLine();
+ splitLine(line, keys);
+ lastIdx = 1;
+
+ // parse remaining lines
+ while ((line = reader.readLine()) != null) {
+ splitLine(line, values);
+ parseLine(keys, values, parsed);
+
+ if (!knownLines.add(line)) {
+ throw new IllegalStateException("duplicate proc entry: " + line);
+ }
+
+ final int idx = getParsedInt(parsed, KEY_IDX);
+ if (idx != lastIdx + 1) {
+ throw new IllegalStateException(
+ "inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
+ }
+ lastIdx = idx;
+
+ entry.iface = parsed.get(KEY_IFACE);
+ entry.uid = getParsedInt(parsed, KEY_UID);
+ entry.set = getParsedInt(parsed, KEY_COUNTER_SET);
+ entry.tag = kernelToTag(parsed.get(KEY_TAG_HEX));
+ entry.rxBytes = getParsedLong(parsed, KEY_RX_BYTES);
+ entry.rxPackets = getParsedLong(parsed, KEY_RX_PACKETS);
+ entry.txBytes = getParsedLong(parsed, KEY_TX_BYTES);
+ entry.txPackets = getParsedLong(parsed, KEY_TX_PACKETS);
+
+ if (limitUid == UID_ALL || limitUid == entry.uid) {
+ stats.addValues(entry);
+ }
+ }
+ } catch (NullPointerException e) {
+ throw new IllegalStateException("problem parsing line: " + line, e);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("problem parsing line: " + line, e);
+ } catch (IOException e) {
+ throw new IllegalStateException("problem parsing line: " + line, e);
+ } finally {
+ IoUtils.closeQuietly(reader);
+ }
+ return stats;
+ }
+
+ private static int getParsedInt(HashMap<String, String> parsed, String key) {
+ final String value = parsed.get(key);
+ return value != null ? Integer.parseInt(value) : 0;
+ }
+
+ private static long getParsedLong(HashMap<String, String> parsed, String key) {
+ final String value = parsed.get(key);
+ return value != null ? Long.parseLong(value) : 0;
+ }
+
+ /**
+ * Split given line into {@link ArrayList}.
+ */
+ private static void splitLine(String line, ArrayList<String> outSplit) {
+ outSplit.clear();
+
+ final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:");
+ while (t.hasMoreTokens()) {
+ outSplit.add(t.nextToken());
+ }
+ }
+
+ /**
+ * Zip the two given {@link ArrayList} as key and value pairs into
+ * {@link HashMap}.
+ */
+ private static void parseLine(
+ ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) {
+ outParsed.clear();
+
+ final int size = Math.min(keys.size(), values.size());
+ for (int i = 0; i < size; i++) {
+ outParsed.put(keys.get(i), values.get(i));
+ }
+ }
+
+ /**
+ * Utility method to read a single plain-text {@link Long} from the given
+ * {@link File}, usually from a {@code /proc/} filesystem.
+ */
+ private static long readSingleLongFromFile(File file) {
+ try {
+ final byte[] buffer = IoUtils.readFileAsByteArray(file.toString());
+ return Long.parseLong(new String(buffer).trim());
+ } catch (NumberFormatException e) {
+ return -1;
+ } catch (IOException e) {
+ return -1;
+ }
+ }
+
+ /**
+ * Wrapper for {@link File#list()} that returns empty array instead of
+ * {@code null}.
+ */
+ private static String[] fileListWithoutNull(File file) {
+ final String[] list = file.list();
+ return list != null ? list : new String[0];
+ }
+}
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index df5071f..e2a2566 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -16,11 +16,15 @@
package com.android.internal.os;
-import com.android.internal.util.JournaledFile;
+import static android.net.NetworkStats.IFACE_ALL;
+import static android.net.NetworkStats.UID_ALL;
+import static android.text.format.DateUtils.SECOND_IN_MILLIS;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
-import android.net.TrafficStats;
+import android.content.res.Resources;
+import android.net.ConnectivityManager;
+import android.net.NetworkStats;
import android.os.BatteryManager;
import android.os.BatteryStats;
import android.os.FileUtils;
@@ -43,6 +47,11 @@ import android.util.Slog;
import android.util.SparseArray;
import android.util.TimeUtils;
+import com.android.internal.R;
+import com.android.internal.net.NetworkStatsFactory;
+import com.android.internal.util.JournaledFile;
+import com.google.android.collect.Sets;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
@@ -52,6 +61,7 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@@ -69,6 +79,8 @@ public final class BatteryStatsImpl extends BatteryStats {
private static final boolean DEBUG_HISTORY = false;
private static final boolean USE_OLD_HISTORY = false; // for debugging.
+ // TODO: remove "tcp" from network methods, since we measure total stats.
+
// In-memory Parcel magic number, used to detect attempts to unmarshall bad data
private static final int MAGIC = 0xBA757475; // 'BATSTATS'
@@ -314,6 +326,11 @@ public final class BatteryStatsImpl extends BatteryStats {
private HashMap<String, Integer> mUidCache = new HashMap<String, Integer>();
+ private final NetworkStatsFactory mNetworkStatsFactory = new NetworkStatsFactory();
+
+ /** Network ifaces that {@link ConnectivityManager} has claimed as mobile. */
+ private HashSet<String> mMobileIfaces = Sets.newHashSet();
+
// For debugging
public BatteryStatsImpl() {
mFile = null;
@@ -1036,7 +1053,8 @@ public final class BatteryStatsImpl extends BatteryStats {
String name;
int count;
long totalTime;
- int startIndex, endIndex;
+ int startIndex;
+ int endIndex;
int numUpdatedWlNames = 0;
// Advance past the first line.
@@ -1390,30 +1408,48 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public void doUnplugLocked(long batteryUptime, long batteryRealtime) {
- for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
- Uid u = mUidStats.valueAt(iu);
- u.mStartedTcpBytesReceived = TrafficStats.getUidRxBytes(u.mUid);
- u.mStartedTcpBytesSent = TrafficStats.getUidTxBytes(u.mUid);
+ NetworkStats.Entry entry = null;
+
+ // Track UID data usage
+ final NetworkStats uidStats = getNetworkStatsDetailGroupedByUid();
+ final int size = uidStats.size();
+ for (int i = 0; i < size; i++) {
+ entry = uidStats.getValues(i, entry);
+
+ final Uid u = mUidStats.get(entry.uid);
+ if (u == null) continue;
+
+ u.mStartedTcpBytesReceived = entry.rxBytes;
+ u.mStartedTcpBytesSent = entry.txBytes;
u.mTcpBytesReceivedAtLastUnplug = u.mCurrentTcpBytesReceived;
u.mTcpBytesSentAtLastUnplug = u.mCurrentTcpBytesSent;
}
+
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).unplug(batteryUptime, batteryRealtime);
}
- // Track total mobile data
- doDataUnplug(mMobileDataRx, TrafficStats.getMobileRxBytes());
- doDataUnplug(mMobileDataTx, TrafficStats.getMobileTxBytes());
- doDataUnplug(mTotalDataRx, TrafficStats.getTotalRxBytes());
- doDataUnplug(mTotalDataTx, TrafficStats.getTotalTxBytes());
+
+ // Track both mobile and total overall data
+ final NetworkStats ifaceStats = getNetworkStatsSummary();
+ entry = ifaceStats.getTotal(entry, mMobileIfaces);
+ doDataUnplug(mMobileDataRx, entry.rxBytes);
+ doDataUnplug(mMobileDataTx, entry.txBytes);
+ entry = ifaceStats.getTotal(entry);
+ doDataUnplug(mTotalDataRx, entry.rxBytes);
+ doDataUnplug(mTotalDataTx, entry.txBytes);
+
// Track radio awake time
mRadioDataStart = getCurrentRadioDataUptime();
mRadioDataUptime = 0;
+
// Track bt headset ping count
mBluetoothPingStart = getCurrentBluetoothPingCount();
mBluetoothPingCount = 0;
}
public void doPlugLocked(long batteryUptime, long batteryRealtime) {
+ NetworkStats.Entry entry = null;
+
for (int iu = mUidStats.size() - 1; iu >= 0; iu--) {
Uid u = mUidStats.valueAt(iu);
if (u.mStartedTcpBytesReceived >= 0) {
@@ -1428,10 +1464,16 @@ public final class BatteryStatsImpl extends BatteryStats {
for (int i = mUnpluggables.size() - 1; i >= 0; i--) {
mUnpluggables.get(i).plug(batteryUptime, batteryRealtime);
}
- doDataPlug(mMobileDataRx, TrafficStats.getMobileRxBytes());
- doDataPlug(mMobileDataTx, TrafficStats.getMobileTxBytes());
- doDataPlug(mTotalDataRx, TrafficStats.getTotalRxBytes());
- doDataPlug(mTotalDataTx, TrafficStats.getTotalTxBytes());
+
+ // Track both mobile and total overall data
+ final NetworkStats ifaceStats = getNetworkStatsSummary();
+ entry = ifaceStats.getTotal(entry, mMobileIfaces);
+ doDataPlug(mMobileDataRx, entry.rxBytes);
+ doDataPlug(mMobileDataTx, entry.txBytes);
+ entry = ifaceStats.getTotal(entry);
+ doDataPlug(mTotalDataRx, entry.rxBytes);
+ doDataPlug(mTotalDataTx, entry.txBytes);
+
// Track radio awake time
mRadioDataUptime = getRadioDataUptime();
mRadioDataStart = -1;
@@ -2216,6 +2258,14 @@ public final class BatteryStatsImpl extends BatteryStats {
}
}
+ public void noteNetworkInterfaceTypeLocked(String iface, int networkType) {
+ if (ConnectivityManager.isNetworkTypeMobile(networkType)) {
+ mMobileIfaces.add(iface);
+ } else {
+ mMobileIfaces.remove(iface);
+ }
+ }
+
@Override public long getScreenOnTime(long batteryRealtime, int which) {
return mScreenOnTimer.getTotalTimeLocked(batteryRealtime, which);
}
@@ -2400,8 +2450,10 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public long computeCurrentTcpBytesReceived() {
+ final long uidRxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
+ null, mUid).rxBytes;
return mCurrentTcpBytesReceived + (mStartedTcpBytesReceived >= 0
- ? (TrafficStats.getUidRxBytes(mUid) - mStartedTcpBytesReceived) : 0);
+ ? (uidRxBytes - mStartedTcpBytesReceived) : 0);
}
@Override
@@ -2619,8 +2671,10 @@ public final class BatteryStatsImpl extends BatteryStats {
}
public long computeCurrentTcpBytesSent() {
+ final long uidTxBytes = getNetworkStatsDetailGroupedByUid().getTotal(
+ null, mUid).txBytes;
return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
- ? (TrafficStats.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
+ ? (uidTxBytes - mStartedTcpBytesSent) : 0);
}
/**
@@ -4518,22 +4572,26 @@ public final class BatteryStatsImpl extends BatteryStats {
/** Only STATS_UNPLUGGED works properly */
public long getMobileTcpBytesSent(int which) {
- return getTcpBytes(TrafficStats.getMobileTxBytes(), mMobileDataTx, which);
+ final long mobileTxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).txBytes;
+ return getTcpBytes(mobileTxBytes, mMobileDataTx, which);
}
/** Only STATS_UNPLUGGED works properly */
public long getMobileTcpBytesReceived(int which) {
- return getTcpBytes(TrafficStats.getMobileRxBytes(), mMobileDataRx, which);
+ final long mobileRxBytes = getNetworkStatsSummary().getTotal(null, mMobileIfaces).rxBytes;
+ return getTcpBytes(mobileRxBytes, mMobileDataRx, which);
}
/** Only STATS_UNPLUGGED works properly */
public long getTotalTcpBytesSent(int which) {
- return getTcpBytes(TrafficStats.getTotalTxBytes(), mTotalDataTx, which);
+ final long totalTxBytes = getNetworkStatsSummary().getTotal(null).txBytes;
+ return getTcpBytes(totalTxBytes, mTotalDataTx, which);
}
/** Only STATS_UNPLUGGED works properly */
public long getTotalTcpBytesReceived(int which) {
- return getTcpBytes(TrafficStats.getTotalRxBytes(), mTotalDataRx, which);
+ final long totalRxBytes = getNetworkStatsSummary().getTotal(null).rxBytes;
+ return getTcpBytes(totalRxBytes, mTotalDataRx, which);
}
@Override
@@ -5637,7 +5695,47 @@ public final class BatteryStatsImpl extends BatteryStats {
mGlobalWifiRunningTimer.logState(pr, " ");
pr.println("*** Bluetooth timer:");
mBluetoothOnTimer.logState(pr, " ");
+ pr.println("*** Mobile ifaces:");
+ pr.println(mMobileIfaces.toString());
}
super.dumpLocked(pw);
}
+
+ private NetworkStats mNetworkSummaryCache;
+ private NetworkStats mNetworkDetailCache;
+
+ private NetworkStats getNetworkStatsSummary() {
+ // NOTE: calls from BatteryStatsService already hold this lock
+ synchronized (this) {
+ if (mNetworkSummaryCache == null
+ || mNetworkSummaryCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
+ try {
+ mNetworkSummaryCache = mNetworkStatsFactory.readNetworkStatsSummary();
+ } catch (IllegalStateException e) {
+ // log problem and return empty object
+ Log.wtf(TAG, "problem reading network stats", e);
+ mNetworkSummaryCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
+ }
+ }
+ return mNetworkSummaryCache;
+ }
+ }
+
+ private NetworkStats getNetworkStatsDetailGroupedByUid() {
+ // NOTE: calls from BatteryStatsService already hold this lock
+ synchronized (this) {
+ if (mNetworkDetailCache == null
+ || mNetworkDetailCache.getElapsedRealtimeAge() > SECOND_IN_MILLIS) {
+ try {
+ mNetworkDetailCache = mNetworkStatsFactory
+ .readNetworkStatsDetail().groupedByUid();
+ } catch (IllegalStateException e) {
+ // log problem and return empty object
+ Log.wtf(TAG, "problem reading network stats", e);
+ mNetworkDetailCache = new NetworkStats(SystemClock.elapsedRealtime(), 0);
+ }
+ }
+ return mNetworkDetailCache;
+ }
+ }
}