11059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey/*
21059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * Copyright (C) 2011 The Android Open Source Project
31059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey *
41059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
51059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * you may not use this file except in compliance with the License.
61059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * You may obtain a copy of the License at
71059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey *
81059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
91059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey *
101059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * Unless required by applicable law or agreed to in writing, software
111059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
121059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * See the License for the specific language governing permissions and
141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * limitations under the License.
151059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey */
161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeypackage com.android.internal.net;
181059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
198fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkeyimport static android.net.NetworkStats.SET_ALL;
201059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport static android.net.NetworkStats.TAG_NONE;
211059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport static android.net.NetworkStats.UID_ALL;
221059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.kernelToTag;
231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
241059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport android.net.NetworkStats;
25453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkeyimport android.os.StrictMode;
261059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport android.os.SystemClock;
271059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
288b2c3a14603d163d7564e6f60286995079687690Jeff Sharkeyimport com.android.internal.annotations.VisibleForTesting;
29163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport com.android.internal.util.ProcFileReader;
301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.io.File;
32163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport java.io.FileInputStream;
331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.io.IOException;
349a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkeyimport java.net.ProtocolException;
351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport libcore.io.IoUtils;
371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey/**
391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * Creates {@link NetworkStats} instances by parsing various {@code /proc/}
401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * files as needed.
411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey */
421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeypublic class NetworkStatsFactory {
431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String TAG = "NetworkStatsFactory";
441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
459a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    private static final boolean USE_NATIVE_PARSING = true;
469a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    private static final boolean SANITY_CHECK_NATIVE = false;
471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
481059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final File mStatsXtIfaceAll;
50e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_fmt}. */
51e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey    private final File mStatsXtIfaceFmt;
521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final File mStatsXtUid;
541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStatsFactory() {
561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        this(new File("/proc/"));
571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
598b2c3a14603d163d7564e6f60286995079687690Jeff Sharkey    @VisibleForTesting
601059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStatsFactory(File procRoot) {
611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
62e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        mStatsXtIfaceFmt = new File(procRoot, "net/xt_qtaguid/iface_stat_fmt");
63e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
641059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
651059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
67e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * Parse and return interface-level summary {@link NetworkStats} measured
68e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * using {@code /proc/net/dev} style hooks, which may include non IP layer
69e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * traffic. Values monotonically increase since device boot, and may include
70e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * details about inactive interfaces.
711059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *
721059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * @throws IllegalStateException when problem parsing stats.
731059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
749a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public NetworkStats readNetworkStatsSummaryDev() throws IOException {
75453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
76453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey
771059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
781059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry();
791059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
801d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey        ProcFileReader reader = null;
811059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        try {
821d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey            reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceAll));
831059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
841d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey            while (reader.hasMoreData()) {
851d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                entry.iface = reader.nextString();
861059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.uid = UID_ALL;
878fc27e8b87bd1def854a03d84009143b315d4176Jeff Sharkey                entry.set = SET_ALL;
881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.tag = TAG_NONE;
891059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
901d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                final boolean active = reader.nextInt() != 0;
911d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey
921059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                // always include snapshot values
931d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                entry.rxBytes = reader.nextLong();
941d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                entry.rxPackets = reader.nextLong();
951d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                entry.txBytes = reader.nextLong();
961d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                entry.txPackets = reader.nextLong();
971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                // fold in active numbers, but only when active
991059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (active) {
1001d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                    entry.rxBytes += reader.nextLong();
1011d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                    entry.rxPackets += reader.nextLong();
1021d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                    entry.txBytes += reader.nextLong();
1031d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                    entry.txPackets += reader.nextLong();
1041059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
1051059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1061059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                stats.addValues(entry);
1071d29a3064f20652416f81ea292adcc07566ba974Jeff Sharkey                reader.finishLine();
1081059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
1091059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NullPointerException e) {
1109a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new ProtocolException("problem parsing stats", e);
1111059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
1129a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new ProtocolException("problem parsing stats", e);
1131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } finally {
1141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            IoUtils.closeQuietly(reader);
115453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey            StrictMode.setThreadPolicy(savedPolicy);
1161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
1171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
1181059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
1191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1201059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
121e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * Parse and return interface-level summary {@link NetworkStats}. Designed
122e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * to return only IP layer traffic. Values monotonically increase since
123e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * device boot, and may include details about inactive interfaces.
124e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     *
125e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey     * @throws IllegalStateException when problem parsing stats.
1261059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
1279a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public NetworkStats readNetworkStatsSummaryXt() throws IOException {
128453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
129453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey
130e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        // return null when kernel doesn't support
131e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        if (!mStatsXtIfaceFmt.exists()) return null;
132e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey
1331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
1341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry();
1351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
136e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        ProcFileReader reader = null;
137e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey        try {
138e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey            // open and consume header line
139e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey            reader = new ProcFileReader(new FileInputStream(mStatsXtIfaceFmt));
140e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey            reader.finishLine();
1411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
142e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey            while (reader.hasMoreData()) {
143e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.iface = reader.nextString();
144e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.uid = UID_ALL;
145e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.set = SET_ALL;
146e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.tag = TAG_NONE;
1471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
148e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.rxBytes = reader.nextLong();
149e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.rxPackets = reader.nextLong();
150e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.txBytes = reader.nextLong();
151e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                entry.txPackets = reader.nextLong();
1521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
153e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                stats.addValues(entry);
154e8914c36276710de50b347c1e6aecfa45d6a56cdJeff Sharkey                reader.finishLine();
1551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
1561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NullPointerException e) {
1579a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new ProtocolException("problem parsing stats", e);
1581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
1599a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new ProtocolException("problem parsing stats", e);
1601059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } finally {
1611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            IoUtils.closeQuietly(reader);
162453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey            StrictMode.setThreadPolicy(savedPolicy);
1631059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
1641059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
1651059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
1661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1679a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public NetworkStats readNetworkStatsDetail() throws IOException {
1681059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return readNetworkStatsDetail(UID_ALL);
1691059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
1701059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1719a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public NetworkStats readNetworkStatsDetail(int limitUid) throws IOException {
1729a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        if (USE_NATIVE_PARSING) {
1739a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
1749a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            if (nativeReadNetworkStatsDetail(stats, mStatsXtUid.getAbsolutePath(), limitUid) != 0) {
1759a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                throw new IOException("Failed to parse network stats");
1769a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            }
1779a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            if (SANITY_CHECK_NATIVE) {
1789a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                final NetworkStats javaStats = javaReadNetworkStatsDetail(mStatsXtUid, limitUid);
1799a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                assertEquals(javaStats, stats);
1809a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            }
1819a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            return stats;
1829a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        } else {
1839a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            return javaReadNetworkStatsDetail(mStatsXtUid, limitUid);
1849a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        }
1859a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    }
1869a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey
1871059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
1889a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey     * Parse and return {@link NetworkStats} with UID-level details. Values are
1899a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey     * expected to monotonically increase since device boot.
1901059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
1919a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    @VisibleForTesting
1929a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public static NetworkStats javaReadNetworkStatsDetail(File detailPath, int limitUid)
1939a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throws IOException {
194453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
195453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey
1961059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
1971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry();
1981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
199163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        int idx = 1;
200163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        int lastIdx = 1;
2011059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
202163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        ProcFileReader reader = null;
2031059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        try {
204163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            // open and consume header line
2059a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            reader = new ProcFileReader(new FileInputStream(detailPath));
206163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            reader.finishLine();
2071059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
208163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            while (reader.hasMoreData()) {
209163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                idx = reader.nextInt();
2101059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (idx != lastIdx + 1) {
2119a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                    throw new ProtocolException(
2121059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                            "inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
2131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
2141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                lastIdx = idx;
2151059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
216163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.iface = reader.nextString();
217163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.tag = kernelToTag(reader.nextString());
218163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.uid = reader.nextInt();
219163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.set = reader.nextInt();
220163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.rxBytes = reader.nextLong();
221163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.rxPackets = reader.nextLong();
222163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.txBytes = reader.nextLong();
223163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.txPackets = reader.nextLong();
2241059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2251059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (limitUid == UID_ALL || limitUid == entry.uid) {
2261059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    stats.addValues(entry);
2271059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
228163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
229163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                reader.finishLine();
2301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
2311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NullPointerException e) {
2329a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new ProtocolException("problem parsing idx " + idx, e);
2331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
2349a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new ProtocolException("problem parsing idx " + idx, e);
2351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } finally {
2361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            IoUtils.closeQuietly(reader);
237453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey            StrictMode.setThreadPolicy(savedPolicy);
2381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
239163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
2401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
2411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
2429a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey
2439a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public void assertEquals(NetworkStats expected, NetworkStats actual) {
2449a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        if (expected.size() != actual.size()) {
2459a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            throw new AssertionError(
2469a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                    "Expected size " + expected.size() + ", actual size " + actual.size());
2479a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        }
2489a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey
2499a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        NetworkStats.Entry expectedRow = null;
2509a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        NetworkStats.Entry actualRow = null;
2519a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        for (int i = 0; i < expected.size(); i++) {
2529a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            expectedRow = expected.getValues(i, expectedRow);
2539a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            actualRow = actual.getValues(i, actualRow);
2549a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            if (!expectedRow.equals(actualRow)) {
2559a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                throw new AssertionError(
2569a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey                        "Expected row " + i + ": " + expectedRow + ", actual row " + actualRow);
2579a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            }
2589a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey        }
2599a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    }
2609a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey
2619a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    /**
2629a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey     * Parse statistics from file into given {@link NetworkStats} object. Values
2639a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey     * are expected to monotonically increase since device boot.
2649a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey     */
2659a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    @VisibleForTesting
2669a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey    public static native int nativeReadNetworkStatsDetail(
2679a2c2a6da90abbcc9a064c20e93ed885651f4ae1Jeff Sharkey            NetworkStats stats, String path, int limitUid);
2681059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey}
269