NetworkStatsFactory.java revision 453dafa66372308fd5200f1749a2ef8e3e1846e9
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
191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT;
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 Sharkeyimport android.util.Slog;
281059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
29163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport com.android.internal.util.ProcFileReader;
301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.google.android.collect.Lists;
311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.google.android.collect.Maps;
321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport com.google.android.collect.Sets;
331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.io.BufferedReader;
351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.io.File;
36163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport java.io.FileInputStream;
371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.io.FileReader;
381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.io.IOException;
391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.util.ArrayList;
401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.util.HashMap;
411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.util.HashSet;
421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport java.util.StringTokenizer;
431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeyimport libcore.io.IoUtils;
451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
461059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey/**
471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * Creates {@link NetworkStats} instances by parsing various {@code /proc/}
481059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey * files as needed.
491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey */
501059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkeypublic class NetworkStatsFactory {
511059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String TAG = "NetworkStatsFactory";
521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    // TODO: consider moving parsing to native code
541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** Path to {@code /proc/net/dev}. */
561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    @Deprecated
571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final File mStatsIface;
581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** Path to {@code /proc/net/xt_qtaguid/iface_stat}. */
591059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    @Deprecated
601059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final File mStatsXtIface;
611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** Path to {@code /proc/net/xt_qtaguid/iface_stat_all}. */
621059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final File mStatsXtIfaceAll;
631059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** Path to {@code /proc/net/xt_qtaguid/stats}. */
641059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private final File mStatsXtUid;
651059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /** {@link #mStatsXtUid} and {@link #mStatsXtIfaceAll} headers. */
671059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_IDX = "idx";
681059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_IFACE = "iface";
691059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_ACTIVE = "active";
701059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_UID = "uid_tag_int";
711059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_COUNTER_SET = "cnt_set";
721059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_TAG_HEX = "acct_tag_hex";
731059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_SNAP_RX_BYTES = "snap_rx_bytes";
741059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_SNAP_RX_PACKETS = "snap_rx_packets";
751059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_SNAP_TX_BYTES = "snap_tx_bytes";
761059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_SNAP_TX_PACKETS = "snap_tx_packets";
771059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_RX_BYTES = "rx_bytes";
781059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_RX_PACKETS = "rx_packets";
791059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_TX_BYTES = "tx_bytes";
801059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static final String KEY_TX_PACKETS = "tx_packets";
811059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
821059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStatsFactory() {
831059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        this(new File("/proc/"));
841059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
851059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
861059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    // @VisibleForTesting
871059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStatsFactory(File procRoot) {
881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        mStatsIface = new File(procRoot, "net/dev");
891059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        mStatsXtUid = new File(procRoot, "net/xt_qtaguid/stats");
901059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        mStatsXtIface = new File(procRoot, "net/xt_qtaguid/iface_stat");
911059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        mStatsXtIfaceAll = new File(procRoot, "net/xt_qtaguid/iface_stat_all");
921059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
931059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
941059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
951059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Parse and return interface-level summary {@link NetworkStats}. Values
961059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * monotonically increase since device boot, and may include details about
971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * inactive interfaces.
981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *
991059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * @throws IllegalStateException when problem parsing stats.
1001059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
1011059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStats readNetworkStatsSummary() throws IllegalStateException {
1021059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        if (mStatsXtIfaceAll.exists()) {
1031059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            return readNetworkStatsSummarySingleFile();
1041059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } else {
1051059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            return readNetworkStatsSummaryMultipleFiles();
1061059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
1071059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
1081059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1091059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private NetworkStats readNetworkStatsSummarySingleFile() {
110453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
111453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey
1121059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
1131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry();
1141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
115163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        // TODO: transition to ProcFileReader
1161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        // TODO: read directly from proc once headers are added
1171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final ArrayList<String> keys = Lists.newArrayList(KEY_IFACE, KEY_ACTIVE, KEY_SNAP_RX_BYTES,
1181059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                KEY_SNAP_RX_PACKETS, KEY_SNAP_TX_BYTES, KEY_SNAP_TX_PACKETS, KEY_RX_BYTES,
1191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                KEY_RX_PACKETS, KEY_TX_BYTES, KEY_TX_PACKETS);
1201059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final ArrayList<String> values = Lists.newArrayList();
1211059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final HashMap<String, String> parsed = Maps.newHashMap();
1221059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        BufferedReader reader = null;
1241059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        try {
1251059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            reader = new BufferedReader(new FileReader(mStatsXtIfaceAll));
1261059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1271059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            String line;
1281059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            while ((line = reader.readLine()) != null) {
1291059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                splitLine(line, values);
1301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                parseLine(keys, values, parsed);
1311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.iface = parsed.get(KEY_IFACE);
1331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.uid = UID_ALL;
1341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.set = SET_DEFAULT;
1351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.tag = TAG_NONE;
1361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                // always include snapshot values
1381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.rxBytes = getParsedLong(parsed, KEY_SNAP_RX_BYTES);
1391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.rxPackets = getParsedLong(parsed, KEY_SNAP_RX_PACKETS);
1401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.txBytes = getParsedLong(parsed, KEY_SNAP_TX_BYTES);
1411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                entry.txPackets = getParsedLong(parsed, KEY_SNAP_TX_PACKETS);
1421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                // fold in active numbers, but only when active
1441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                final boolean active = getParsedInt(parsed, KEY_ACTIVE) != 0;
1451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (active) {
1461059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.rxBytes += getParsedLong(parsed, KEY_RX_BYTES);
1471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.rxPackets += getParsedLong(parsed, KEY_RX_PACKETS);
1481059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.txBytes += getParsedLong(parsed, KEY_TX_BYTES);
1491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.txPackets += getParsedLong(parsed, KEY_TX_PACKETS);
1501059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
1511059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                stats.addValues(entry);
1531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
1541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NullPointerException e) {
1551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            throw new IllegalStateException("problem parsing stats: " + e);
1561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
1571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            throw new IllegalStateException("problem parsing stats: " + e);
1581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (IOException e) {
1591059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            throw new IllegalStateException("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
1671059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
1681059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * @deprecated remove once {@code iface_stat_all} is merged to all kernels.
1691059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
1701059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    @Deprecated
1711059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private NetworkStats readNetworkStatsSummaryMultipleFiles() {
172453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
173453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey
1741059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 6);
1751059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry();
1761059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1771059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final HashSet<String> knownIfaces = Sets.newHashSet();
1781059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final HashSet<String> activeIfaces = Sets.newHashSet();
1791059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1801059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        // collect any historical stats and active state
1811059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        for (String iface : fileListWithoutNull(mStatsXtIface)) {
1821059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final File ifacePath = new File(mStatsXtIface, iface);
1831059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1841059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final long active = readSingleLongFromFile(new File(ifacePath, "active"));
1851059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            if (active == 1) {
1861059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                knownIfaces.add(iface);
1871059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                activeIfaces.add(iface);
1881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            } else if (active == 0) {
1891059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                knownIfaces.add(iface);
1901059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            } else {
1911059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                continue;
1921059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
1931059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
1941059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.iface = iface;
1951059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.uid = UID_ALL;
1961059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.set = SET_DEFAULT;
1971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.tag = TAG_NONE;
1981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.rxBytes = readSingleLongFromFile(new File(ifacePath, "rx_bytes"));
1991059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.rxPackets = readSingleLongFromFile(new File(ifacePath, "rx_packets"));
2001059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.txBytes = readSingleLongFromFile(new File(ifacePath, "tx_bytes"));
2011059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            entry.txPackets = readSingleLongFromFile(new File(ifacePath, "tx_packets"));
2021059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2031059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            stats.addValues(entry);
2041059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
2051059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2061059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final ArrayList<String> values = Lists.newArrayList();
2071059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2081059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        BufferedReader reader = null;
2091059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        try {
2101059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            reader = new BufferedReader(new FileReader(mStatsIface));
2111059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2121059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            // skip first two header lines
2131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            reader.readLine();
2141059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            reader.readLine();
2151059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            // parse remaining lines
2171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            String line;
2181059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            while ((line = reader.readLine()) != null) {
2191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                splitLine(line, values);
2201059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2211059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                try {
2221059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.iface = values.get(0);
2231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.uid = UID_ALL;
2241059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.set = SET_DEFAULT;
2251059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.tag = TAG_NONE;
2261059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.rxBytes = Long.parseLong(values.get(1));
2271059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.rxPackets = Long.parseLong(values.get(2));
2281059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.txBytes = Long.parseLong(values.get(9));
2291059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    entry.txPackets = Long.parseLong(values.get(10));
2301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    if (activeIfaces.contains(entry.iface)) {
2321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                        // combine stats when iface is active
2331059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                        stats.combineValues(entry);
2341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    } else if (!knownIfaces.contains(entry.iface)) {
2351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                        // add stats when iface is unknown
2361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                        stats.addValues(entry);
2371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    }
2381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                } catch (NumberFormatException e) {
2391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    Slog.w(TAG, "problem parsing stats row '" + line + "': " + e);
2401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
2411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
2421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NullPointerException e) {
2431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            throw new IllegalStateException("problem parsing stats: " + e);
2441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
2451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            throw new IllegalStateException("problem parsing stats: " + e);
2461059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (IOException e) {
2471059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            throw new IllegalStateException("problem parsing stats: " + e);
2481059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } finally {
2491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            IoUtils.closeQuietly(reader);
250453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey            StrictMode.setThreadPolicy(savedPolicy);
2511059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
2521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
2541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
2551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStats readNetworkStatsDetail() {
2571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return readNetworkStatsDetail(UID_ALL);
2581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
2591059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2601059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
2611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Parse and return {@link NetworkStats} with UID-level details. Values
2621059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * monotonically increase since device boot.
2631059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     *
2641059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * @throws IllegalStateException when problem parsing stats.
2651059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
2661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    public NetworkStats readNetworkStatsDetail(int limitUid) throws IllegalStateException {
267453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey        final StrictMode.ThreadPolicy savedPolicy = StrictMode.allowThreadDiskReads();
268453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey
2691059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 24);
2701059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final NetworkStats.Entry entry = new NetworkStats.Entry();
2711059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
272163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        int idx = 1;
273163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        int lastIdx = 1;
2741059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
275163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        ProcFileReader reader = null;
2761059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        try {
277163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            // open and consume header line
278163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            reader = new ProcFileReader(new FileInputStream(mStatsXtUid));
279163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            reader.finishLine();
2801059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
281163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            while (reader.hasMoreData()) {
282163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                idx = reader.nextInt();
2831059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (idx != lastIdx + 1) {
2841059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    throw new IllegalStateException(
2851059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                            "inconsistent idx=" + idx + " after lastIdx=" + lastIdx);
2861059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
2871059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                lastIdx = idx;
2881059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
289163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.iface = reader.nextString();
290163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.tag = kernelToTag(reader.nextString());
291163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.uid = reader.nextInt();
292163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.set = reader.nextInt();
293163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.rxBytes = reader.nextLong();
294163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.rxPackets = reader.nextLong();
295163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.txBytes = reader.nextLong();
296163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                entry.txPackets = reader.nextLong();
2971059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
2981059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                if (limitUid == UID_ALL || limitUid == entry.uid) {
2991059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                    stats.addValues(entry);
3001059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey                }
301163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
302163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                reader.finishLine();
3031059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            }
3041059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NullPointerException e) {
305163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            throw new IllegalStateException("problem parsing idx " + idx, e);
3061059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
307163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            throw new IllegalStateException("problem parsing idx " + idx, e);
3081059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (IOException e) {
309163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            throw new IllegalStateException("problem parsing idx " + idx, e);
3101059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } finally {
3111059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            IoUtils.closeQuietly(reader);
312453dafa66372308fd5200f1749a2ef8e3e1846e9Jeff Sharkey            StrictMode.setThreadPolicy(savedPolicy);
3131059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
314163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
3151059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return stats;
3161059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3171059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
318163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    @Deprecated
3191059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static int getParsedInt(HashMap<String, String> parsed, String key) {
3201059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final String value = parsed.get(key);
3211059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return value != null ? Integer.parseInt(value) : 0;
3221059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3231059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
324163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    @Deprecated
3251059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static long getParsedLong(HashMap<String, String> parsed, String key) {
3261059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final String value = parsed.get(key);
3271059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return value != null ? Long.parseLong(value) : 0;
3281059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3291059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3301059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
3311059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Split given line into {@link ArrayList}.
3321059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
333163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    @Deprecated
3341059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static void splitLine(String line, ArrayList<String> outSplit) {
3351059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        outSplit.clear();
3361059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3371059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final StringTokenizer t = new StringTokenizer(line, " \t\n\r\f:");
3381059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        while (t.hasMoreTokens()) {
3391059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            outSplit.add(t.nextToken());
3401059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
3411059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3421059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3431059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
3441059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Zip the two given {@link ArrayList} as key and value pairs into
3451059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * {@link HashMap}.
3461059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
347163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    @Deprecated
3481059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static void parseLine(
3491059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            ArrayList<String> keys, ArrayList<String> values, HashMap<String, String> outParsed) {
3501059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        outParsed.clear();
3511059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3521059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final int size = Math.min(keys.size(), values.size());
3531059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        for (int i = 0; i < size; i++) {
3541059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            outParsed.put(keys.get(i), values.get(i));
3551059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
3561059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3571059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3581059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
3591059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Utility method to read a single plain-text {@link Long} from the given
3601059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * {@link File}, usually from a {@code /proc/} filesystem.
3611059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
3621059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static long readSingleLongFromFile(File file) {
3631059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        try {
3641059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            final byte[] buffer = IoUtils.readFileAsByteArray(file.toString());
3651059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            return Long.parseLong(new String(buffer).trim());
3661059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (NumberFormatException e) {
3671059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            return -1;
3681059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        } catch (IOException e) {
3691059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey            return -1;
3701059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        }
3711059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3721059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey
3731059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    /**
3741059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * Wrapper for {@link File#list()} that returns empty array instead of
3751059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     * {@code null}.
3761059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey     */
3771059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    private static String[] fileListWithoutNull(File file) {
3781059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        final String[] list = file.list();
3791059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey        return list != null ? list : new String[0];
3801059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey    }
3811059c3c30ad96a15695c1a92ae8896e078a6309fJeff Sharkey}
382