Use /proc/net/dev to get stats summary
If the qtaguid proc file is no longer exist, the device is running new eBPF module to do traffic accounting. So the NetworkStatsFactory need to use the proc/net/dev interface to get the per interface traffic stats summary. Also, adding a test to verify the helper function work properly Bug: 30950746 Test: run NetworkStatsFactoryTest Change-Id: Ia36808bf02f1637dd41a3e7c50917b91b1a77524
This commit is contained in:
@@ -31,13 +31,17 @@ import com.android.internal.annotations.GuardedBy;
|
|||||||
import com.android.internal.annotations.VisibleForTesting;
|
import com.android.internal.annotations.VisibleForTesting;
|
||||||
import com.android.internal.util.ArrayUtils;
|
import com.android.internal.util.ArrayUtils;
|
||||||
import com.android.internal.util.ProcFileReader;
|
import com.android.internal.util.ProcFileReader;
|
||||||
|
import com.google.android.collect.Lists;
|
||||||
|
|
||||||
import libcore.io.IoUtils;
|
import libcore.io.IoUtils;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.ProtocolException;
|
import java.net.ProtocolException;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -55,6 +59,8 @@ public class NetworkStatsFactory {
|
|||||||
// Used for correct stats accounting on clatd interfaces.
|
// Used for correct stats accounting on clatd interfaces.
|
||||||
private static final int IPV4V6_HEADER_DELTA = 20;
|
private static final int IPV4V6_HEADER_DELTA = 20;
|
||||||
|
|
||||||
|
/** Path to {@code /proc/net/dev}. */
|
||||||
|
private final File mStatsIfaceDev;
|
||||||
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
|
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
|
||||||
private final File mStatsXtIfaceAll;
|
private final File mStatsXtIfaceAll;
|
||||||
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
|
/** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
|
||||||
@@ -84,12 +90,51 @@ public class NetworkStatsFactory {
|
|||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
|
public NetworkStatsFactory(File procRoot, boolean useBpfStats) {
|
||||||
|
mStatsIfaceDev = new File(procRoot, "net/dev");
|
||||||
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
|
mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
|
||||||
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
|
mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
|
||||||
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
|
mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
|
||||||
mUseBpfStats = useBpfStats;
|
mUseBpfStats = useBpfStats;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting
|
||||||
|
public NetworkStats readNetworkStatsIfaceDev() throws IOException {
|
||||||
|
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
|
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
|
||||||
|
final NetworkStats.Entry entry = new NetworkStats.Entry();
|
||||||
|
|
||||||
|
BufferedReader reader = null;
|
||||||
|
try {
|
||||||
|
reader = new BufferedReader(new FileReader(mStatsIfaceDev));
|
||||||
|
|
||||||
|
// skip first two header lines
|
||||||
|
reader.readLine();
|
||||||
|
reader.readLine();
|
||||||
|
|
||||||
|
// parse remaining lines
|
||||||
|
String line;
|
||||||
|
while ((line = reader.readLine()) != null) {
|
||||||
|
String[] values = line.trim().split("\\:?\\s+");
|
||||||
|
entry.iface = values[0];
|
||||||
|
entry.uid = UID_ALL;
|
||||||
|
entry.set = SET_ALL;
|
||||||
|
entry.tag = TAG_NONE;
|
||||||
|
entry.rxBytes = Long.parseLong(values[1]);
|
||||||
|
entry.rxPackets = Long.parseLong(values[2]);
|
||||||
|
entry.txBytes = Long.parseLong(values[9]);
|
||||||
|
entry.txPackets = Long.parseLong(values[10]);
|
||||||
|
stats.addValues(entry);
|
||||||
|
}
|
||||||
|
} catch (NullPointerException|NumberFormatException e) {
|
||||||
|
throw new ProtocolException("problem parsing stats", e);
|
||||||
|
} finally {
|
||||||
|
IoUtils.closeQuietly(reader);
|
||||||
|
StrictMode.setThreadPolicy(savedPolicy);
|
||||||
|
}
|
||||||
|
return stats;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse and return interface-level summary {@link NetworkStats} measured
|
* Parse and return interface-level summary {@link NetworkStats} measured
|
||||||
* using {@code /proc/net/dev} style hooks, which may include non IP layer
|
* using {@code /proc/net/dev} style hooks, which may include non IP layer
|
||||||
@@ -99,6 +144,11 @@ public class NetworkStatsFactory {
|
|||||||
* @throws IllegalStateException when problem parsing stats.
|
* @throws IllegalStateException when problem parsing stats.
|
||||||
*/
|
*/
|
||||||
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
|
public NetworkStats readNetworkStatsSummaryDev() throws IOException {
|
||||||
|
|
||||||
|
// Return the stats get from /proc/net/dev if switched to bpf module.
|
||||||
|
if (mUseBpfStats)
|
||||||
|
return readNetworkStatsIfaceDev();
|
||||||
|
|
||||||
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
|
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
|
||||||
@@ -150,6 +200,11 @@ public class NetworkStatsFactory {
|
|||||||
* @throws IllegalStateException when problem parsing stats.
|
* @throws IllegalStateException when problem parsing stats.
|
||||||
*/
|
*/
|
||||||
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
|
public NetworkStats readNetworkStatsSummaryXt() throws IOException {
|
||||||
|
|
||||||
|
// Return the stats get from /proc/net/dev if qtaguid module is replaced.
|
||||||
|
if (mUseBpfStats)
|
||||||
|
return readNetworkStatsIfaceDev();
|
||||||
|
|
||||||
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
|
||||||
|
|
||||||
// return null when kernel doesn't support
|
// return null when kernel doesn't support
|
||||||
|
|||||||
Reference in New Issue
Block a user