Merge "Move battery stats to xt_qtaguid for data stats."
This commit is contained in:
@ -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();
|
||||
|
379
core/java/com/android/internal/net/NetworkStatsFactory.java
Normal file
379
core/java/com/android/internal/net/NetworkStatsFactory.java
Normal file
@ -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];
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user