2424import android .net .NetworkStats ;
2525import android .os .StrictMode ;
2626import android .os .SystemClock ;
27- import android .util .Slog ;
2827
2928import com .android .internal .util .ProcFileReader ;
30- import com .google .android .collect .Lists ;
31- import com .google .android .collect .Sets ;
3229
33- import java .io .BufferedReader ;
3430import java .io .File ;
3531import java .io .FileInputStream ;
36- import java .io .FileReader ;
3732import java .io .IOException ;
38- import java .util .ArrayList ;
39- import java .util .HashSet ;
40- import java .util .StringTokenizer ;
4133
4234import libcore .io .IoUtils ;
4335
@@ -50,14 +42,10 @@ public class NetworkStatsFactory {
5042
5143 // TODO: consider moving parsing to native code
5244
53- /** Path to {@code /proc/net/dev}. */
54- @ Deprecated
55- private final File mStatsIface ;
56- /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
57- @ Deprecated
58- private final File mStatsXtIface ;
5945 /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
6046 private final File mStatsXtIfaceAll ;
47+ /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
48+ private final File mStatsXtIfaceFmt ;
6149 /** Path to {@code /proc/net/xt_qtaguid/stats}. */
6250 private final File mStatsXtUid ;
6351
@@ -67,28 +55,20 @@ public NetworkStatsFactory() {
6755
6856 // @VisibleForTesting
6957 public NetworkStatsFactory (File procRoot ) {
70- mStatsIface = new File (procRoot , "net/dev" );
71- mStatsXtUid = new File (procRoot , "net/xt_qtaguid/stats" );
72- mStatsXtIface = new File (procRoot , "net/xt_qtaguid/iface_stat" );
7358 mStatsXtIfaceAll = new File (procRoot , "net/xt_qtaguid/iface_stat_all" );
59+ mStatsXtIfaceFmt = new File (procRoot , "net/xt_qtaguid/iface_stat_fmt" );
60+ mStatsXtUid = new File (procRoot , "net/xt_qtaguid/stats" );
7461 }
7562
7663 /**
77- * Parse and return interface-level summary {@link NetworkStats}. Values
78- * monotonically increase since device boot, and may include details about
79- * inactive interfaces.
64+ * Parse and return interface-level summary {@link NetworkStats} measured
65+ * using {@code /proc/net/dev} style hooks, which may include non IP layer
66+ * traffic. Values monotonically increase since device boot, and may include
67+ * details about inactive interfaces.
8068 *
8169 * @throws IllegalStateException when problem parsing stats.
8270 */
83- public NetworkStats readNetworkStatsSummary () throws IllegalStateException {
84- if (mStatsXtIfaceAll .exists ()) {
85- return readNetworkStatsSummarySingleFile ();
86- } else {
87- return readNetworkStatsSummaryMultipleFiles ();
88- }
89- }
90-
91- private NetworkStats readNetworkStatsSummarySingleFile () {
71+ public NetworkStats readNetworkStatsSummaryDev () throws IllegalStateException {
9272 final StrictMode .ThreadPolicy savedPolicy = StrictMode .allowThreadDiskReads ();
9373
9474 final NetworkStats stats = new NetworkStats (SystemClock .elapsedRealtime (), 6 );
@@ -137,79 +117,40 @@ private NetworkStats readNetworkStatsSummarySingleFile() {
137117 }
138118
139119 /**
140- * @deprecated remove once {@code iface_stat_all} is merged to all kernels.
120+ * Parse and return interface-level summary {@link NetworkStats}. Designed
121+ * to return only IP layer traffic. Values monotonically increase since
122+ * device boot, and may include details about inactive interfaces.
123+ *
124+ * @throws IllegalStateException when problem parsing stats.
141125 */
142- @ Deprecated
143- private NetworkStats readNetworkStatsSummaryMultipleFiles () {
126+ public NetworkStats readNetworkStatsSummaryXt () throws IllegalStateException {
144127 final StrictMode .ThreadPolicy savedPolicy = StrictMode .allowThreadDiskReads ();
145128
129+ // return null when kernel doesn't support
130+ if (!mStatsXtIfaceFmt .exists ()) return null ;
131+
146132 final NetworkStats stats = new NetworkStats (SystemClock .elapsedRealtime (), 6 );
147133 final NetworkStats .Entry entry = new NetworkStats .Entry ();
148134
149- final HashSet <String > knownIfaces = Sets .newHashSet ();
150- final HashSet <String > activeIfaces = Sets .newHashSet ();
151-
152- // collect any historical stats and active state
153- for (String iface : fileListWithoutNull (mStatsXtIface )) {
154- final File ifacePath = new File (mStatsXtIface , iface );
155-
156- final long active = readSingleLongFromFile (new File (ifacePath , "active" ));
157- if (active == 1 ) {
158- knownIfaces .add (iface );
159- activeIfaces .add (iface );
160- } else if (active == 0 ) {
161- knownIfaces .add (iface );
162- } else {
163- continue ;
164- }
165-
166- entry .iface = iface ;
167- entry .uid = UID_ALL ;
168- entry .set = SET_ALL ;
169- entry .tag = TAG_NONE ;
170- entry .rxBytes = readSingleLongFromFile (new File (ifacePath , "rx_bytes" ));
171- entry .rxPackets = readSingleLongFromFile (new File (ifacePath , "rx_packets" ));
172- entry .txBytes = readSingleLongFromFile (new File (ifacePath , "tx_bytes" ));
173- entry .txPackets = readSingleLongFromFile (new File (ifacePath , "tx_packets" ));
135+ ProcFileReader reader = null ;
136+ try {
137+ // open and consume header line
138+ reader = new ProcFileReader (new FileInputStream (mStatsXtIfaceFmt ));
139+ reader .finishLine ();
174140
175- stats .addValues (entry );
176- }
141+ while (reader .hasMoreData ()) {
142+ entry .iface = reader .nextString ();
143+ entry .uid = UID_ALL ;
144+ entry .set = SET_ALL ;
145+ entry .tag = TAG_NONE ;
177146
178- final ArrayList <String > values = Lists .newArrayList ();
147+ entry .rxBytes = reader .nextLong ();
148+ entry .rxPackets = reader .nextLong ();
149+ entry .txBytes = reader .nextLong ();
150+ entry .txPackets = reader .nextLong ();
179151
180- BufferedReader reader = null ;
181- try {
182- reader = new BufferedReader (new FileReader (mStatsIface ));
183-
184- // skip first two header lines
185- reader .readLine ();
186- reader .readLine ();
187-
188- // parse remaining lines
189- String line ;
190- while ((line = reader .readLine ()) != null ) {
191- splitLine (line , values );
192-
193- try {
194- entry .iface = values .get (0 );
195- entry .uid = UID_ALL ;
196- entry .set = SET_ALL ;
197- entry .tag = TAG_NONE ;
198- entry .rxBytes = Long .parseLong (values .get (1 ));
199- entry .rxPackets = Long .parseLong (values .get (2 ));
200- entry .txBytes = Long .parseLong (values .get (9 ));
201- entry .txPackets = Long .parseLong (values .get (10 ));
202-
203- if (activeIfaces .contains (entry .iface )) {
204- // combine stats when iface is active
205- stats .combineValues (entry );
206- } else if (!knownIfaces .contains (entry .iface )) {
207- // add stats when iface is unknown
208- stats .addValues (entry );
209- }
210- } catch (NumberFormatException e ) {
211- Slog .w (TAG , "problem parsing stats row '" + line + "': " + e );
212- }
152+ stats .addValues (entry );
153+ reader .finishLine ();
213154 }
214155 } catch (NullPointerException e ) {
215156 throw new IllegalStateException ("problem parsing stats: " + e );
@@ -221,7 +162,6 @@ private NetworkStats readNetworkStatsSummaryMultipleFiles() {
221162 IoUtils .closeQuietly (reader );
222163 StrictMode .setThreadPolicy (savedPolicy );
223164 }
224-
225165 return stats ;
226166 }
227167
@@ -286,41 +226,4 @@ public NetworkStats readNetworkStatsDetail(int limitUid) throws IllegalStateExce
286226
287227 return stats ;
288228 }
289-
290- /**
291- * Split given line into {@link ArrayList}.
292- */
293- @ Deprecated
294- private static void splitLine (String line , ArrayList <String > outSplit ) {
295- outSplit .clear ();
296-
297- final StringTokenizer t = new StringTokenizer (line , " \t \n \r \f :" );
298- while (t .hasMoreTokens ()) {
299- outSplit .add (t .nextToken ());
300- }
301- }
302-
303- /**
304- * Utility method to read a single plain-text {@link Long} from the given
305- * {@link File}, usually from a {@code /proc/} filesystem.
306- */
307- private static long readSingleLongFromFile (File file ) {
308- try {
309- final byte [] buffer = IoUtils .readFileAsByteArray (file .toString ());
310- return Long .parseLong (new String (buffer ).trim ());
311- } catch (NumberFormatException e ) {
312- return -1 ;
313- } catch (IOException e ) {
314- return -1 ;
315- }
316- }
317-
318- /**
319- * Wrapper for {@link File#list()} that returns empty array instead of
320- * {@code null}.
321- */
322- private static String [] fileListWithoutNull (File file ) {
323- final String [] list = file .list ();
324- return list != null ? list : new String [0 ];
325- }
326229}
0 commit comments