diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/core/java/com/android/internal/net/NetworkStatsFactory.java index 47666b57e8..902bd120e8 100644 --- a/core/java/com/android/internal/net/NetworkStatsFactory.java +++ b/core/java/com/android/internal/net/NetworkStatsFactory.java @@ -31,13 +31,17 @@ import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.ProcFileReader; +import com.google.android.collect.Lists; import libcore.io.IoUtils; +import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; +import java.io.FileReader; import java.io.IOException; import java.net.ProtocolException; +import java.util.ArrayList; import java.util.Objects; /** @@ -55,6 +59,8 @@ public class NetworkStatsFactory { // Used for correct stats accounting on clatd interfaces. 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}. */ private final File mStatsXtIfaceAll; /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */ @@ -84,12 +90,51 @@ public class NetworkStatsFactory { @VisibleForTesting public NetworkStatsFactory(File procRoot, boolean useBpfStats) { + mStatsIfaceDev = new File(procRoot, "net/dev"); mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all"); mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt"); mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats"); 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 * 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. */ 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 NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6); @@ -150,6 +200,11 @@ public class NetworkStatsFactory { * @throws IllegalStateException when problem parsing stats. */ 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(); // return null when kernel doesn't support