NetworkStatsService.java revision 39ebc2195ed16b9e955dd57f5c95212bb7b934b6
175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/*
2d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey * Copyright (C) 2011 The Android Open Source Project
375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey *
475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * you may not use this file except in compliance with the License.
675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * You may obtain a copy of the License at
775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey *
875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey *
1075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
1175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
1275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * See the License for the specific language governing permissions and
1475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * limitations under the License.
1575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */
1675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypackage com.android.server.net;
1875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
19d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
2075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.Manifest.permission.DUMP;
2121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
2275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.Manifest.permission.SHUTDOWN;
23d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
2461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.net.NetworkStats.IFACE_ALL;
2575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL;
2639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
2739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
2861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
2961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
3039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
3139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
3261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
3361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.HOUR_IN_MILLIS;
3461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.MINUTE_IN_MILLIS;
35d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
3675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.AlarmManager;
3875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.IAlarmManager;
3975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.PendingIntent;
4075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.BroadcastReceiver;
4139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport android.content.ContentResolver;
4275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Context;
4375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Intent;
4475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.IntentFilter;
4561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.content.pm.ApplicationInfo;
46d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.IConnectivityManager;
4775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
48d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkInfo;
49d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkState;
5075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStats;
5175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStatsHistory;
523f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport android.os.Environment;
5375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Handler;
5475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.HandlerThread;
5575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.INetworkManagementService;
5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.RemoteException;
5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.SystemClock;
5861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.provider.Settings;
5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.telephony.TelephonyManager;
6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.NtpTrustedTime;
6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.Slog;
6261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.util.SparseArray;
6375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.TrustedTime;
6475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
653f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport com.android.internal.os.AtomicFile;
66d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport com.google.android.collect.Lists;
6775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport com.google.android.collect.Maps;
6875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
693f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.DataInputStream;
703f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.DataOutputStream;
713f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.File;
7275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.FileDescriptor;
733f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileInputStream;
743f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileNotFoundException;
753f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileOutputStream;
763f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.IOException;
7775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.PrintWriter;
783f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.net.ProtocolException;
79d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport java.util.ArrayList;
8075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashMap;
8161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.HashSet;
8275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
833f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport libcore.io.IoUtils;
843f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
8575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/**
8675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collect and persist detailed network statistics, and provide this data to
8775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * other system services.
8875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */
8975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsService extends INetworkStatsService.Stub {
9021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG = "NetworkStats";
9175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private static final boolean LOGD = true;
9239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static final boolean LOGV = false;
9375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
943f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    /** File header magic number: "ANET" */
953f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static final int FILE_MAGIC = 0x414E4554;
963f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static final int VERSION_CURRENT = 1;
973f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
9875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
9975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkManagementService mNetworkManager;
10075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IAlarmManager mAlarmManager;
10175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final TrustedTime mTime;
10239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final NetworkStatsSettings mSettings;
10375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
104d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private IConnectivityManager mConnManager;
105d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
1063f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    // @VisibleForTesting
1073f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    public static final String ACTION_NETWORK_STATS_POLL =
10875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            "com.android.server.action.NETWORK_STATS_POLL";
10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
11075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private PendingIntent mPollIntent;
11175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    // TODO: listen for kernel push events through netd instead of polling
11375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
11475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private static final long KB_IN_BYTES = 1024;
11561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
11661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static final long GB_IN_BYTES = 1024 * MB_IN_BYTES;
11775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
11839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
11939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Settings that can be changed externally.
12039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
12139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    public interface NetworkStatsSettings {
12239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval();
12339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPersistThreshold();
12439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkBucketDuration();
12539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkMaxHistory();
12639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidBucketDuration();
12739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidMaxHistory();
12839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge();
12939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
13075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
13175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mStatsLock = new Object();
13275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
13375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** Set of active ifaces during this boot. */
134d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private HashMap<String, InterfaceIdentity> mActiveIface = Maps.newHashMap();
13561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
13675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /** Set of historical stats for known ifaces. */
13739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private HashMap<InterfaceIdentity, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
13861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /** Set of historical stats for known UIDs. */
13939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private SparseArray<NetworkStatsHistory> mUidStats = new SparseArray<NetworkStatsHistory>();
14039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
14139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /** Flag if {@link #mUidStats} have been loaded from disk. */
14239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private boolean mUidStatsLoaded = false;
14375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
14439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private NetworkStats mLastNetworkPoll;
14539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private NetworkStats mLastNetworkPersist;
14661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
14739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private NetworkStats mLastUidPoll;
14875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
14975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final HandlerThread mHandlerThread;
15075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Handler mHandler;
15175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
15239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final AtomicFile mNetworkFile;
15339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final AtomicFile mUidFile;
1543f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
15575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    // TODO: collect detailed uid stats, storing tag-granularity data until next
15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    // dropbox, and uid summary for a specific bucket count.
15775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
15875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    // TODO: periodically compile statistics and send to dropbox.
15975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
16075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(
16175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
16275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // TODO: move to using cached NtpTrustedTime
16339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        this(context, networkManager, alarmManager, new NtpTrustedTime(), getSystemDir(),
16439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                new DefaultNetworkStatsSettings(context));
1653f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
1663f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
1673f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static File getSystemDir() {
1683f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
16975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
17075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
17175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(Context context, INetworkManagementService networkManager,
17239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            IAlarmManager alarmManager, TrustedTime time, File systemDir,
17339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            NetworkStatsSettings settings) {
17475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext = checkNotNull(context, "missing Context");
17575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
17675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
17775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
17839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
17975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
18075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
18175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread.start();
18275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper());
1833f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
18439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkFile = new AtomicFile(new File(systemDir, "netstats.bin"));
18539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
18675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
18775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
18821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
18921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
19021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
19121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
19275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public void systemReady() {
1933f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        synchronized (mStatsLock) {
19439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // read historical network stats from disk, since policy service
19539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // might need them right away. we delay loading detailed UID stats
19639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // until actually needed.
19739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            readNetworkStatsLocked();
1983f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
19975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
20021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
201d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final IntentFilter ifaceFilter = new IntentFilter();
202d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        ifaceFilter.addAction(CONNECTIVITY_ACTION);
203d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        mContext.registerReceiver(mIfaceReceiver, ifaceFilter, CONNECTIVITY_INTERNAL, mHandler);
20475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
20575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // listen for periodic polling events
20621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // TODO: switch to stronger internal permission
20775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
20821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
20975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
21075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // persist stats during clean shutdown
21175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final IntentFilter shutdownFilter = new IntentFilter(Intent.ACTION_SHUTDOWN);
21275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.registerReceiver(mShutdownReceiver, shutdownFilter, SHUTDOWN, null);
21375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
21475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
21575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            registerPollAlarmLocked();
21675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } catch (RemoteException e) {
21775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            Slog.w(TAG, "unable to register poll alarm");
21875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
21975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
22075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
2213f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private void shutdownLocked() {
2223f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mIfaceReceiver);
2233f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mPollReceiver);
2243f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mShutdownReceiver);
2253f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
22639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        writeNetworkStatsLocked();
22739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        writeUidStatsLocked();
22839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkStats.clear();
22939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
23039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStatsLoaded = false;
2313f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
2323f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
23375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
23475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
23539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
23675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
23775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private void registerPollAlarmLocked() throws RemoteException {
23875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        if (mPollIntent != null) {
23975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mAlarmManager.remove(mPollIntent);
24075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
24175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
24275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mPollIntent = PendingIntent.getBroadcast(
24375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
24475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
24575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final long currentRealtime = SystemClock.elapsedRealtime();
24639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
24739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mSettings.getPollInterval(), mPollIntent);
24875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
24975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
251d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    public NetworkStatsHistory getHistoryForNetwork(int networkTemplate) {
25221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
253d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
254d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        synchronized (mStatsLock) {
255d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // combine all interfaces that match template
256d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            final String subscriberId = getActiveSubscriberId();
25761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final NetworkStatsHistory combined = new NetworkStatsHistory(
25839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    mSettings.getNetworkBucketDuration());
25939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            for (InterfaceIdentity ident : mNetworkStats.keySet()) {
26039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = mNetworkStats.get(ident);
261d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                if (ident.matchesTemplate(networkTemplate, subscriberId)) {
26219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey                    combined.recordEntireHistory(history);
263d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                }
264d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
265d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return combined;
266d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
26775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
26875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
26975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
270d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    public NetworkStatsHistory getHistoryForUid(int uid, int networkTemplate) {
27121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
272d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
27339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        synchronized (mStatsLock) {
27439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // TODO: combine based on template, if we store that granularity
27539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            ensureUidStatsLoadedLocked();
27639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return mUidStats.get(uid);
27739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
27875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
27975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
280d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    @Override
28121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public NetworkStats getSummaryForNetwork(
28221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            long start, long end, int networkTemplate, String subscriberId) {
28321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
28421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
28521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mStatsLock) {
28621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            long rx = 0;
28721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            long tx = 0;
28821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            long[] networkTotal = new long[2];
28921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
29021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // combine total from all interfaces that match template
29139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            for (InterfaceIdentity ident : mNetworkStats.keySet()) {
29239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = mNetworkStats.get(ident);
29321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                if (ident.matchesTemplate(networkTemplate, subscriberId)) {
29421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    networkTotal = history.getTotalData(start, end, networkTotal);
29521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    rx += networkTotal[0];
29621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                    tx += networkTotal[1];
29721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
29821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
29921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
30021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            final NetworkStats.Builder stats = new NetworkStats.Builder(end - start, 1);
30121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            stats.addEntry(IFACE_ALL, UID_ALL, tx, tx);
30221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            return stats.build();
30321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
30421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
30521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
30621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
3073f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    public NetworkStats getSummaryForAllUid(long start, long end, int networkTemplate) {
30821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
309d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
31019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        // TODO: apply networktemplate once granular uid stats are stored.
31119862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
31219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        synchronized (mStatsLock) {
31339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            ensureUidStatsLoadedLocked();
31439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
31539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int size = mUidStats.size();
31619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            final NetworkStats.Builder stats = new NetworkStats.Builder(end - start, size);
31719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey
31821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            long[] total = new long[2];
31919862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            for (int i = 0; i < size; i++) {
32039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final int uid = mUidStats.keyAt(i);
32139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = mUidStats.valueAt(i);
32221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                total = history.getTotalData(start, end, total);
32319862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey                stats.addEntry(IFACE_ALL, uid, total[0], total[1]);
32419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            }
32519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            return stats.build();
32619862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        }
327d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
328d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
32975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
330d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
33175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
33275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * with mobile interfaces.
33375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
334d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private BroadcastReceiver mIfaceReceiver = new BroadcastReceiver() {
33575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
33675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
337d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
338d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
339d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            synchronized (mStatsLock) {
340d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                updateIfacesLocked();
34175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
34275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
34375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
34475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
34575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
34675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
34775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
348d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified UPDATE_DEVICE_STATS
349d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
35075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            synchronized (mStatsLock) {
35175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                // TODO: acquire wakelock while performing poll
35239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                performPollLocked(true);
35375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
35475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
35575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
35675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
35775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
35875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
35975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
360d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // verified SHUTDOWN permission above.
36175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            synchronized (mStatsLock) {
3623f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                shutdownLocked();
36375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
36475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
36575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
36675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
367d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    /**
368d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Inspect all current {@link NetworkState} to derive mapping from {@code
369d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
370d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * are active on a single {@code iface}, they are combined under a single
371d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * {@link InterfaceIdentity}.
372d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     */
373d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private void updateIfacesLocked() {
37439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
375d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
376d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // take one last stats snapshot before updating iface mapping. this
377d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // isn't perfect, since the kernel may already be counting traffic from
378d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // the updated network.
37939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        performPollLocked(false);
380d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
381d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final NetworkState[] states;
382d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        try {
383d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            states = mConnManager.getAllNetworkState();
384d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        } catch (RemoteException e) {
385d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            Slog.w(TAG, "problem reading network state");
386d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return;
387d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
388d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
389d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // rebuild active interfaces based on connected networks
390d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        mActiveIface.clear();
391d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
392d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        for (NetworkState state : states) {
393d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (state.networkInfo.isConnected()) {
394d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                // collect networks under their parent interfaces
395d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
396d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                final InterfaceIdentity ident = findOrCreateInterfaceLocked(iface);
397d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
398d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
399d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
400d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
401d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
40239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
40339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Periodic poll operation, reading current statistics and recording into
40439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * {@link NetworkStatsHistory}.
40539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     *
40639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * @param detailedPoll Indicate if detailed UID stats should be collected
40739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     *            during this poll operation.
40839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
40939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void performPollLocked(boolean detailedPoll) {
41039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "performPollLocked()");
41175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
41275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // try refreshing time source when stale
41339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
41475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mTime.forceRefresh();
41575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
41675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
41775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // TODO: consider marking "untrusted" times in historical stats
41875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
41975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                : System.currentTimeMillis();
42075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
42139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStats networkStats;
42239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStats uidStats;
42375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
42439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            networkStats = mNetworkManager.getNetworkStatsSummary();
42539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            uidStats = detailedPoll ? mNetworkManager.getNetworkStatsDetail() : null;
42675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } catch (RemoteException e) {
42775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            Slog.w(TAG, "problem reading network stats");
42875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            return;
42975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
43075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
43139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        performNetworkPollLocked(networkStats, currentTime);
43239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (detailedPoll) {
43339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            performUidPollLocked(uidStats, currentTime);
43439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
43561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
43661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        // decide if enough has changed to trigger persist
43739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStats persistDelta = computeStatsDelta(mLastNetworkPersist, networkStats);
43839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final long persistThreshold = mSettings.getPersistThreshold();
43961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (String iface : persistDelta.getUniqueIfaces()) {
44061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final int index = persistDelta.findIndex(iface, UID_ALL);
44161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (persistDelta.rx[index] > persistThreshold
44261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                    || persistDelta.tx[index] > persistThreshold) {
44339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                writeNetworkStatsLocked();
44439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                writeUidStatsLocked();
44539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mLastNetworkPersist = networkStats;
44661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                break;
44761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
44861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
44961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
45061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
45161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
45239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Update {@link #mNetworkStats} historical usage.
45361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
45439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void performNetworkPollLocked(NetworkStats networkStats, long currentTime) {
455d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final ArrayList<String> unknownIface = Lists.newArrayList();
456d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
45739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStats delta = computeStatsDelta(mLastNetworkPoll, networkStats);
45861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final long timeStart = currentTime - delta.elapsedRealtime;
45939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final long maxHistory = mSettings.getNetworkMaxHistory();
46061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (String iface : delta.getUniqueIfaces()) {
461d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            final InterfaceIdentity ident = mActiveIface.get(iface);
462d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (ident == null) {
463d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                unknownIface.add(iface);
46475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                continue;
46575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
46675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
46761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final int index = delta.findIndex(iface, UID_ALL);
46861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final long rx = delta.rx[index];
46961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final long tx = delta.tx[index];
47075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
47139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final NetworkStatsHistory history = findOrCreateNetworkLocked(ident);
47275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            history.recordData(timeStart, currentTime, rx, tx);
47361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            history.removeBucketsBefore(currentTime - maxHistory);
47475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
47539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mLastNetworkPoll = networkStats;
47675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
477d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        if (LOGD && unknownIface.size() > 0) {
478d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats");
479d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
48061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
481d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
48261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
48339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Update {@link #mUidStats} historical usage.
48461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
48539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void performUidPollLocked(NetworkStats uidStats, long currentTime) {
48639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        ensureUidStatsLoadedLocked();
48739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
48839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStats delta = computeStatsDelta(mLastUidPoll, uidStats);
48961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final long timeStart = currentTime - delta.elapsedRealtime;
49039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final long maxHistory = mSettings.getUidMaxHistory();
49161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (int uid : delta.getUniqueUids()) {
49239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // TODO: traverse all ifaces once surfaced in stats
49361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final int index = delta.findIndex(IFACE_ALL, uid);
49439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (index != -1) {
49539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final long rx = delta.rx[index];
49639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final long tx = delta.tx[index];
49761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
49839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = findOrCreateUidLocked(uid);
49939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                history.recordData(timeStart, currentTime, rx, tx);
50039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                history.removeBucketsBefore(currentTime - maxHistory);
50139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
50261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
50339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mLastUidPoll = uidStats;
50461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
50575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
50639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private NetworkStatsHistory findOrCreateNetworkLocked(InterfaceIdentity ident) {
50739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final long bucketDuration = mSettings.getNetworkBucketDuration();
50839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStatsHistory existing = mNetworkStats.get(ident);
50939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
51039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // update when no existing, or when bucket duration changed
51139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        NetworkStatsHistory updated = null;
51239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (existing == null) {
51339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration);
51439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else if (existing.bucketDuration != bucketDuration) {
51539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration);
51639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated.recordEntireHistory(existing);
51739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
51839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
51939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (updated != null) {
52039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mNetworkStats.put(ident, updated);
52139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return updated;
52239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else {
52339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return existing;
52475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
52575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
52675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
52739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private NetworkStatsHistory findOrCreateUidLocked(int uid) {
52839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final long bucketDuration = mSettings.getUidBucketDuration();
52939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStatsHistory existing = mUidStats.get(uid);
53039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
53139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // update when no existing, or when bucket duration changed
53239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        NetworkStatsHistory updated = null;
53339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (existing == null) {
53439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration);
53539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else if (existing.bucketDuration != bucketDuration) {
53639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration);
53739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated.recordEntireHistory(existing);
53839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
53939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
54039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (updated != null) {
54139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidStats.put(uid, updated);
54239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return updated;
54339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else {
54439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return existing;
54575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
54675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
54775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
548d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private InterfaceIdentity findOrCreateInterfaceLocked(String iface) {
549d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        InterfaceIdentity ident = mActiveIface.get(iface);
550d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        if (ident == null) {
551d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            ident = new InterfaceIdentity();
552d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            mActiveIface.put(iface, ident);
553d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
554d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        return ident;
555d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
556d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
55739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void readNetworkStatsLocked() {
55839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
5593f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
5603f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        // clear any existing stats and read from disk
56139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkStats.clear();
5623f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
5633f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        FileInputStream fis = null;
5643f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        try {
56539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fis = mNetworkFile.openRead();
5663f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final DataInputStream in = new DataInputStream(fis);
5673f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
5683f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            // verify file magic header intact
5693f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final int magic = in.readInt();
5703f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (magic != FILE_MAGIC) {
5713f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                throw new ProtocolException("unexpected magic: " + magic);
5723f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
5733f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
5743f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final int version = in.readInt();
5753f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            switch (version) {
5763f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                case VERSION_CURRENT: {
5773f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    // file format is pairs of interfaces and stats:
57839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    // network := size *(InterfaceIdentity NetworkStatsHistory)
5793f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
5803f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    final int size = in.readInt();
5813f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    for (int i = 0; i < size; i++) {
5823f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                        final InterfaceIdentity ident = new InterfaceIdentity(in);
5833f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                        final NetworkStatsHistory history = new NetworkStatsHistory(in);
58439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
58539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                        mNetworkStats.put(ident, history);
5863f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    }
5873f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    break;
5883f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
5893f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                default: {
5903f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    throw new ProtocolException("unexpected version: " + version);
5913f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
5923f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
5933f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (FileNotFoundException e) {
5943f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            // missing stats is okay, probably first boot
5953f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (IOException e) {
5963f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            Slog.e(TAG, "problem reading network stats", e);
5973f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } finally {
5983f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            IoUtils.closeQuietly(fis);
5993f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
60075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
60175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
60239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void ensureUidStatsLoadedLocked() {
60339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (!mUidStatsLoaded) {
60439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            readUidStatsLocked();
60539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidStatsLoaded = true;
60639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
60739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
60839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
60939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void readUidStatsLocked() {
61039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "readUidStatsLocked()");
61139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
61239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // clear any existing stats and read from disk
61339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
61439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
61539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        FileInputStream fis = null;
61639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        try {
61739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fis = mUidFile.openRead();
61839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final DataInputStream in = new DataInputStream(fis);
61939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
62039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // verify file magic header intact
62139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int magic = in.readInt();
62239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (magic != FILE_MAGIC) {
62339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                throw new ProtocolException("unexpected magic: " + magic);
62439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
62539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
62639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int version = in.readInt();
62739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            switch (version) {
62839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                case VERSION_CURRENT: {
62939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    // file format is pairs of UIDs and stats:
63039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    // uid := size *(UID NetworkStatsHistory)
63139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
63239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    final int size = in.readInt();
63339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    for (int i = 0; i < size; i++) {
63439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                        final int uid = in.readInt();
63539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                        final NetworkStatsHistory history = new NetworkStatsHistory(in);
63639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
63739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                        mUidStats.put(uid, history);
63839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    }
63939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    break;
64039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                }
64139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                default: {
64239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    throw new ProtocolException("unexpected version: " + version);
64339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                }
64439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
64539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (FileNotFoundException e) {
64639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // missing stats is okay, probably first boot
64739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (IOException e) {
64839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            Slog.e(TAG, "problem reading uid stats", e);
64939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } finally {
65039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            IoUtils.closeQuietly(fis);
65139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
65239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
65339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
65439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void writeNetworkStatsLocked() {
65539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "writeNetworkStatsLocked()");
6563f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
657d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // TODO: consider duplicating stats and releasing lock while writing
6583f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
6593f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        FileOutputStream fos = null;
6603f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        try {
66139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fos = mNetworkFile.startWrite();
6623f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final DataOutputStream out = new DataOutputStream(fos);
6633f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
6643f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            out.writeInt(FILE_MAGIC);
6653f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            out.writeInt(VERSION_CURRENT);
6663f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
66739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(mNetworkStats.size());
66839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            for (InterfaceIdentity ident : mNetworkStats.keySet()) {
66939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = mNetworkStats.get(ident);
6703f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                ident.writeToStream(out);
6713f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                history.writeToStream(out);
6723f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
6733f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
67439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mNetworkFile.finishWrite(fos);
67539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (IOException e) {
67639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (fos != null) {
67739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mNetworkFile.failWrite(fos);
67839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
67939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
68039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
68139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
68239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void writeUidStatsLocked() {
68339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "writeUidStatsLocked()");
68439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
68539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // TODO: consider duplicating stats and releasing lock while writing
68639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
68739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        FileOutputStream fos = null;
68839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        try {
68939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fos = mUidFile.startWrite();
69039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final DataOutputStream out = new DataOutputStream(fos);
69139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
69239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(FILE_MAGIC);
69339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(VERSION_CURRENT);
69439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
69539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int size = mUidStats.size();
69639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
69739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(size);
69839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            for (int i = 0; i < size; i++) {
69939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final int uid = mUidStats.keyAt(i);
70039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = mUidStats.valueAt(i);
70139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                out.writeInt(uid);
70239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                history.writeToStream(out);
70339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
70439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
70539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidFile.finishWrite(fos);
7063f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (IOException e) {
7073f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (fos != null) {
70839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mUidFile.failWrite(fos);
7093f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
7103f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
71175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
71275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
71375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
71475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
71575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
71675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
71761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final HashSet<String> argSet = new HashSet<String>();
71861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (String arg : args) {
71961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            argSet.add(arg);
72061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
72161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
72261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        synchronized (mStatsLock) {
72361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            // TODO: remove this testing code, since it corrupts stats
72461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (argSet.contains("generate")) {
72561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                generateRandomLocked();
72661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.println("Generated stub stats");
72761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                return;
72861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
72961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
7303f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (argSet.contains("poll")) {
73139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                performPollLocked(true);
7323f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                pw.println("Forced poll");
7333f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                return;
7343f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
7353f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
73661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.println("Active interfaces:");
73761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            for (String iface : mActiveIface.keySet()) {
73861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                final InterfaceIdentity ident = mActiveIface.get(iface);
73961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print("  iface="); pw.print(iface);
74061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print(" ident="); pw.println(ident.toString());
74161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
74261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
74361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.println("Known historical stats:");
74439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            for (InterfaceIdentity ident : mNetworkStats.keySet()) {
74539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory stats = mNetworkStats.get(ident);
74661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print("  ident="); pw.println(ident.toString());
74761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                stats.dump("    ", pw);
74861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
74961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
75061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (argSet.contains("detail")) {
75139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                // since explicitly requested with argument, we're okay to load
75239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                // from disk if not already in memory.
75339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                ensureUidStatsLoadedLocked();
75439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                pw.println("Known UID stats:");
75539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                for (int i = 0; i < mUidStats.size(); i++) {
75639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    final int uid = mUidStats.keyAt(i);
75739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    final NetworkStatsHistory stats = mUidStats.valueAt(i);
75861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                    pw.print("  UID="); pw.println(uid);
75961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                    stats.dump("    ", pw);
76061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                }
76161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
76275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
76361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
76475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
76561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
76661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     * @deprecated only for temporary testing
76761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
76861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    @Deprecated
76961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private void generateRandomLocked() {
77061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        long end = System.currentTimeMillis();
77139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        long start = end - mSettings.getNetworkMaxHistory();
77261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        long rx = 3 * GB_IN_BYTES;
77361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        long tx = 2 * GB_IN_BYTES;
77461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
77539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkStats.clear();
77661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (InterfaceIdentity ident : mActiveIface.values()) {
77739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final NetworkStatsHistory stats = findOrCreateNetworkLocked(ident);
77861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            stats.generateRandom(start, end, rx, tx);
77961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
78061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
78161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        end = System.currentTimeMillis();
78239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        start = end - mSettings.getUidMaxHistory();
78361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        rx = 500 * MB_IN_BYTES;
78461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        tx = 100 * MB_IN_BYTES;
78561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
78639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
78761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (ApplicationInfo info : mContext.getPackageManager().getInstalledApplications(0)) {
78861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final int uid = info.uid;
78939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final NetworkStatsHistory stats = findOrCreateUidLocked(uid);
79061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            stats.generateRandom(start, end, rx, tx);
79161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
79261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
79361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
79475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
79575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Return the delta between two {@link NetworkStats} snapshots, where {@code
79675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * before} can be {@code null}.
79775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
79875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private static NetworkStats computeStatsDelta(NetworkStats before, NetworkStats current) {
79975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        if (before != null) {
8003f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            return current.subtractClamped(before);
80175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } else {
80275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            return current;
80375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
80475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
80575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
806d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private String getActiveSubscriberId() {
807d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final TelephonyManager telephony = (TelephonyManager) mContext.getSystemService(
808d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                Context.TELEPHONY_SERVICE);
809d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        return telephony.getSubscriberId();
81075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
81175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
81239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
81339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Default external settings that read from {@link Settings.Secure}.
81439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
81539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
81639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private final ContentResolver mResolver;
81739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
81839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public DefaultNetworkStatsSettings(Context context) {
81939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mResolver = checkNotNull(context.getContentResolver());
82039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // TODO: adjust these timings for production builds
82139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
82239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
82339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private long getSecureLong(String name, long def) {
82439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return Settings.Secure.getLong(mResolver, name, def);
82539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
82639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
82739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval() {
82839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_POLL_INTERVAL, 15 * MINUTE_IN_MILLIS);
82939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
83039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPersistThreshold() {
83139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 16 * KB_IN_BYTES);
83239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
83339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkBucketDuration() {
83439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS);
83539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
83639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkMaxHistory() {
83739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_NETWORK_MAX_HISTORY, 90 * DAY_IN_MILLIS);
83839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
83939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidBucketDuration() {
84039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS);
84139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
84239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidMaxHistory() {
84339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_UID_MAX_HISTORY, 90 * DAY_IN_MILLIS);
84439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
84539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge() {
84639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return DAY_IN_MILLIS;
84739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
84839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
84939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
85075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey}
851