NetworkStatsService.java revision d4dd7716fb825f29a609c5c4cb31204eea78183a
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
19a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport static android.Manifest.permission.ACCESS_NETWORK_STATE;
2063d27a9233fed934340231f438493746084a681dJeff Sharkeyimport static android.Manifest.permission.CONNECTIVITY_INTERNAL;
2175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.Manifest.permission.DUMP;
2263d27a9233fed934340231f438493746084a681dJeff Sharkeyimport static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING;
2321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkeyimport static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
24b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_SHUTDOWN;
25b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.ACTION_UID_REMOVED;
26b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.content.Intent.EXTRA_UID;
27cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkeyimport static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
28367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
29d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkeyimport static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
3061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.net.NetworkStats.IFACE_ALL;
31b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_ALL;
32b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT;
33b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_FOREGROUND;
341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE;
3575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL;
3607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobileAll;
3707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateWifi;
38241dde2306202e7655fdf41d5381f2874e47e108Jeff Sharkeyimport static android.net.TrafficStats.MB_IN_BYTES;
3963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
4063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE;
4163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_DEV_PERSIST_BYTES;
4263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_DEV_ROTATE_AGE;
4363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_GLOBAL_ALERT_BYTES;
4461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
4563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_SAMPLE_ENABLED;
4663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_TIME_CACHE_MAX_AGE;
4739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
4863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_DELETE_AGE;
4963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_PERSIST_BYTES;
5063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_ROTATE_AGE;
51367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
52367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.telephony.PhoneStateListener.LISTEN_NONE;
5361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
5461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.HOUR_IN_MILLIS;
5561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.MINUTE_IN_MILLIS;
56367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS;
57d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
588e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeyimport static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
59b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
60b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.AlarmManager;
6375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.IAlarmManager;
6475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.PendingIntent;
6575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.BroadcastReceiver;
6639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport android.content.ContentResolver;
6775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Context;
6875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Intent;
6975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.IntentFilter;
70d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.IConnectivityManager;
718e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeyimport android.net.INetworkManagementEventObserver;
7275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
7363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.LinkProperties;
741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity;
75d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkInfo;
76d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkState;
7775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStats;
785a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkeyimport android.net.NetworkStats.NonMonotonicObserver;
7975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStatsHistory;
801b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate;
8163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport android.net.TrafficStats;
82a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport android.os.Binder;
83163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport android.os.DropBoxManager;
843f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport android.os.Environment;
8575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Handler;
8675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.HandlerThread;
8775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.INetworkManagementService;
88b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.os.Message;
896248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkeyimport android.os.PowerManager;
9075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.RemoteException;
9175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.SystemClock;
9261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.provider.Settings;
93367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport android.telephony.PhoneStateListener;
9475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.telephony.TelephonyManager;
9507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport android.util.EventLog;
96b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkeyimport android.util.Log;
9775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.NtpTrustedTime;
9875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.Slog;
99b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.util.SparseIntArray;
10075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.TrustedTime;
10175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
10263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.FileRotator;
10363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkeyimport com.android.internal.util.IndentingPrintWriter;
10407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport com.android.server.EventLogTags;
105cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkeyimport com.android.server.connectivity.Tethering;
10675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport com.google.android.collect.Maps;
10775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1083f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.File;
10975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.FileDescriptor;
1103f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.IOException;
11175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.PrintWriter;
11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashMap;
11361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.HashSet;
1143f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/**
11675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collect and persist detailed network statistics, and provide this data to
11775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * other system services.
11875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */
11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsService extends INetworkStatsService.Stub {
12021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG = "NetworkStats";
121706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey    private static final boolean LOGV = false;
122b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
123367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final int MSG_PERFORM_POLL = 1;
124367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final int MSG_UPDATE_IFACES = 2;
12525ce9ed57f137dc0b21045ab90fe595640ebf926Jeff Sharkey    private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
126b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
127b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    /** Flags to control detail level of poll event. */
128905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static final int FLAG_PERSIST_NETWORK = 0x1;
129905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static final int FLAG_PERSIST_UID = 0x2;
130b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
1311f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey    private static final int FLAG_PERSIST_FORCE = 0x100;
1323f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
133163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    private static final String TAG_NETSTATS_ERROR = "netstats_error";
134163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
13575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
13675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkManagementService mNetworkManager;
13775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IAlarmManager mAlarmManager;
13875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final TrustedTime mTime;
139367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private final TelephonyManager mTeleManager;
14039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final NetworkStatsSettings mSettings;
14175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
14263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private final File mSystemDir;
14363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private final File mBaseDir;
14463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
1456248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey    private final PowerManager.WakeLock mWakeLock;
1466248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey
147d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private IConnectivityManager mConnManager;
148d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
1493f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    // @VisibleForTesting
1503f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    public static final String ACTION_NETWORK_STATS_POLL =
15175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            "com.android.server.action.NETWORK_STATS_POLL";
152497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    public static final String ACTION_NETWORK_STATS_UPDATED =
153497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            "com.android.server.action.NETWORK_STATS_UPDATED";
15475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
15575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private PendingIntent mPollIntent;
15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
15763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private static final String PREFIX_DEV = "dev";
15863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private static final String PREFIX_UID = "uid";
15963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private static final String PREFIX_UID_TAG = "uid_tag";
16063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
16139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
16239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Settings that can be changed externally.
16339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
16439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    public interface NetworkStatsSettings {
16539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval();
16639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge();
16763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public long getGlobalAlertBytes();
16863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public boolean getSampleEnabled();
16963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
17063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public static class Config {
17163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            public final long bucketDuration;
17263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            public final long persistBytes;
17363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            public final long rotateAgeMillis;
17463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            public final long deleteAgeMillis;
17563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
17663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            public Config(long bucketDuration, long persistBytes, long rotateAgeMillis,
17763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    long deleteAgeMillis) {
17863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                this.bucketDuration = bucketDuration;
17963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                this.persistBytes = persistBytes;
18063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                this.rotateAgeMillis = rotateAgeMillis;
18163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                this.deleteAgeMillis = deleteAgeMillis;
18263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            }
18363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        }
18463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
18563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public Config getDevConfig();
18663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public Config getUidConfig();
18763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public Config getUidTagConfig();
18839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
18975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
19075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mStatsLock = new Object();
19175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /** Set of currently active ifaces. */
1931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
19463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    /** Current default active iface. */
19563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private String mActiveIface;
19663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
19763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
19863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            new DropBoxNonMonotonicObserver();
19963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
20063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStatsRecorder mDevRecorder;
20163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStatsRecorder mUidRecorder;
20263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStatsRecorder mUidTagRecorder;
20363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
20463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    /** Cached {@link #mDevRecorder} stats. */
20563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStatsCollection mDevStatsCached;
20675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
207b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** Current counter sets for each UID. */
208b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
209b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
210a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /** Data layer operation counters for splicing into other structures. */
21163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStats mUidOperations = new NetworkStats(0L, 10);
212a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
21375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final HandlerThread mHandlerThread;
21475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Handler mHandler;
21575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
2166341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey    private boolean mSystemReady;
2176341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey
21875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(
21975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
220104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
22163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                getDefaultSystemDir(), new DefaultNetworkStatsSettings(context));
2223f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
2233f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
22463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private static File getDefaultSystemDir() {
2253f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
22675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
22775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
22875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(Context context, INetworkManagementService networkManager,
22939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            IAlarmManager alarmManager, TrustedTime time, File systemDir,
23039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            NetworkStatsSettings settings) {
23175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext = checkNotNull(context, "missing Context");
23275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
23375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
23475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
235367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
23639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
23775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
2386248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey        final PowerManager powerManager = (PowerManager) context.getSystemService(
2396248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                Context.POWER_SERVICE);
2406248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
2416248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey
24275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
24375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread.start();
244b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
2453f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
24663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mSystemDir = checkNotNull(systemDir);
24763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mBaseDir = new File(systemDir, "netstats");
24863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mBaseDir.mkdirs();
24975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
25121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
25221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
25321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
25421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
25575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public void systemReady() {
2566341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey        mSystemReady = true;
2576341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey
258418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey        if (!isBandwidthControlEnabled()) {
259418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey            Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
260418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey            return;
261418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey        }
262418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey
26363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // create data recorders along with historical rotators
26463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
26563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
26663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
26763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
2683f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        synchronized (mStatsLock) {
26963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // upgrade any legacy stats, migrating them to rotated files
27063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            maybeUpgradeLegacyStatsLocked();
27163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
27239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // read historical network stats from disk, since policy service
27363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // might need them right away.
27463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mDevStatsCached = mDevRecorder.getOrLoadCompleteLocked();
27575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
27663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // bootstrap initial stats to prevent double-counting later
27763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            bootstrapStatsLocked();
27863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        }
2793359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey
28021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
281961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkey        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
282b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
28375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
284cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        // watch for tethering changes
285cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
286cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
287cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
28875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // listen for periodic polling events
28975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
29021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
29175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
292b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // listen for uid removal to clean stats
293b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
294b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
295b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
29675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // persist stats during clean shutdown
297b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
298b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
29975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
30075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
3018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mNetworkManager.registerObserver(mAlertObserver);
30275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } catch (RemoteException e) {
303b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
30475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
305b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
306367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        // watch for networkType changes that aren't broadcast through
307367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        // CONNECTIVITY_ACTION_IMMEDIATE above.
308d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        if (!COMBINE_SUBTYPE_ENABLED) {
309d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey            mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
310d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        }
311367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
3128e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        registerPollAlarmLocked();
3138e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        registerGlobalAlert();
31463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    }
3158e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
31663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStatsRecorder buildRecorder(
31763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
31863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return new NetworkStatsRecorder(
31963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                new FileRotator(mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
32063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mNonMonotonicObserver, prefix, config.bucketDuration, config.persistBytes,
32163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                includeTags);
32275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
32375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3243f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private void shutdownLocked() {
325b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.unregisterReceiver(mConnReceiver);
326367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mContext.unregisterReceiver(mTetherReceiver);
3273f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mPollReceiver);
328b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.unregisterReceiver(mRemovedReceiver);
3293f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mShutdownReceiver);
3303f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
331d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        if (!COMBINE_SUBTYPE_ENABLED) {
332d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey            mTeleManager.listen(mPhoneListener, LISTEN_NONE);
333d4dd7716fb825f29a609c5c4cb31204eea78183aJeff Sharkey        }
334367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
33563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
33663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                : System.currentTimeMillis();
33763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
33863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // persist any pending stats
33963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mDevRecorder.forcePersistLocked(currentTime);
34063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidRecorder.forcePersistLocked(currentTime);
34163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidTagRecorder.forcePersistLocked(currentTime);
34263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
34363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mDevRecorder = null;
34463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidRecorder = null;
34563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidTagRecorder = null;
34663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
34763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mDevStatsCached = null;
3486341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey
3496341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey        mSystemReady = false;
35063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    }
35163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
35263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private void maybeUpgradeLegacyStatsLocked() {
35363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        File file;
35463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        try {
35563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            file = new File(mSystemDir, "netstats.bin");
35663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (file.exists()) {
35763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mDevRecorder.importLegacyNetworkLocked(file);
35863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                file.delete();
35963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            }
36063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
36163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            file = new File(mSystemDir, "netstats_xt.bin");
36263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (file.exists()) {
36363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                file.delete();
36463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            }
36563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
36663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            file = new File(mSystemDir, "netstats_uid.bin");
36763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (file.exists()) {
36863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mUidRecorder.importLegacyUidLocked(file);
36963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mUidTagRecorder.importLegacyUidLocked(file);
37063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                file.delete();
37163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            }
37263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        } catch (IOException e) {
37363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            Log.wtf(TAG, "problem during legacy upgrade", e);
374af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey        }
3753f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
3763f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
37775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
37875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
37939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
38075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
3818e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void registerPollAlarmLocked() {
3828e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
3838e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            if (mPollIntent != null) {
3848e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mAlarmManager.remove(mPollIntent);
3858e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
38675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3878e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mPollIntent = PendingIntent.getBroadcast(
3888e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                    mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
38975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3908e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long currentRealtime = SystemClock.elapsedRealtime();
3918e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
3928e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                    mSettings.getPollInterval(), mPollIntent);
3938e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
394b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
3958e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
3968e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
3978e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
3988e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
3998e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Register for a global alert that is delivered through
4008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * {@link INetworkManagementEventObserver} once a threshold amount of data
4018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * has been transferred.
4028e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
4038e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void registerGlobalAlert() {
4048e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
40563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final long alertBytes = mSettings.getGlobalAlertBytes();
4068e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mNetworkManager.setGlobalAlert(alertBytes);
4078e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (IllegalStateException e) {
4088e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.w(TAG, "problem registering for global alert: " + e);
4098e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
410b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
4118e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
41275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
41375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
41475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
41563d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
41663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
417905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
418d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
41963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    @Override
42063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
42163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return mDevStatsCached.getSummary(template, start, end);
42275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
42375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
42475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
42563d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory getHistoryForUid(
426b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            NetworkTemplate template, int uid, int set, int tag, int fields) {
42763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // TODO: transition to stats sessions to avoid WeakReferences
42863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        if (tag == TAG_NONE) {
42963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return mUidRecorder.getOrLoadCompleteLocked().getHistory(
43063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    template, uid, set, tag, fields);
43163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        } else {
43263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return mUidTagRecorder.getOrLoadCompleteLocked().getHistory(
43363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    template, uid, set, tag, fields);
434684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey        }
435684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey    }
436684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey
43721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
438d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    public NetworkStats getSummaryForAllUid(
439d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey            NetworkTemplate template, long start, long end, boolean includeTags) {
44063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // TODO: transition to stats sessions to avoid WeakReferences
44163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final NetworkStats stats = mUidRecorder.getOrLoadCompleteLocked().getSummary(
44263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                template, start, end);
44363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        if (includeTags) {
44463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final NetworkStats tagStats = mUidTagRecorder.getOrLoadCompleteLocked().getSummary(
44563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    template, start, end);
44663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            stats.combineAllValues(tagStats);
44763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        }
44863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return stats;
449d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
450d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
451350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    @Override
452a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
453a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (Binder.getCallingUid() != uid) {
454a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
455a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
456a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
457a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // TODO: switch to data layer stats once kernel exports
458a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // for now, read network layer stats and flatten across all ifaces
4594529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        final long token = Binder.clearCallingIdentity();
4604529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        final NetworkStats networkLayer;
4614529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        try {
4624529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey            networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
4634529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        } finally {
4644529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey            Binder.restoreCallingIdentity(token);
4654529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey        }
4664529bb66c47fd02b990ecb0810031157b4f36c2fJeff Sharkey
467a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats dataLayer = new NetworkStats(
468a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                networkLayer.getElapsedRealtime(), networkLayer.size());
469a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
470a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        NetworkStats.Entry entry = null;
471a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        for (int i = 0; i < networkLayer.size(); i++) {
472a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            entry = networkLayer.getValues(i, entry);
473a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            entry.iface = IFACE_ALL;
474a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            dataLayer.combineValues(entry);
475a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
476a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
477a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // splice in operation counts
47863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        dataLayer.spliceOperationsFrom(mUidOperations);
479a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        return dataLayer;
480a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
481a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
482a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Override
483a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void incrementOperationCount(int uid, int tag, int operationCount) {
484a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (Binder.getCallingUid() != uid) {
485a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
486a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
487a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
488b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        if (operationCount < 0) {
489b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            throw new IllegalArgumentException("operation count can only be incremented");
490b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
491b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        if (tag == TAG_NONE) {
492b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            throw new IllegalArgumentException("operation count must have specific tag");
493b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
494b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
495a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        synchronized (mStatsLock) {
496b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
49763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidOperations.combineValues(
49863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
49963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidOperations.combineValues(
50063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
501b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
502b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
503b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
504b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    @Override
505b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public void setUidForeground(int uid, boolean uidForeground) {
506b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
507b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
508b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        synchronized (mStatsLock) {
509b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
510b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
511b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (oldSet != set) {
512b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                mActiveUidCounterSet.put(uid, set);
513b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                setKernelCounterSet(uid, set);
514b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
515a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
516a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
517a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
518a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Override
519350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    public void forceUpdate() {
520350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
521e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey
522e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey        final long token = Binder.clearCallingIdentity();
523e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey        try {
524e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey            performPoll(FLAG_PERSIST_ALL);
525e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey        } finally {
526e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey            Binder.restoreCallingIdentity(token);
527e630f7b31bb1e77a2eb4ef3102a25f2927cfd5c3Jeff Sharkey        }
528350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    }
529350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
53075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
531d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
53275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
53375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * with mobile interfaces.
53475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
535b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
53675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
53775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
538d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
539d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
540367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            updateIfaces();
54175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
54275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
54375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
544cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    /**
545cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     * Receiver that watches for {@link Tethering} to claim interface pairs.
546cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     */
547cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
548cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        @Override
549cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public void onReceive(Context context, Intent intent) {
550cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
551cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            // permission above.
5521f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performPoll(FLAG_PERSIST_NETWORK);
553cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
554cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    };
555cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
55675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
55775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
55875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
559d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified UPDATE_DEVICE_STATS
560d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
5611f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performPoll(FLAG_PERSIST_ALL);
5628e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
5638e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            // verify that we're watching global alert
5648e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            registerGlobalAlert();
56575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
56675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
56775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
568b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
569b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        @Override
570b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        public void onReceive(Context context, Intent intent) {
571b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // on background handler thread, and UID_REMOVED is protected
572b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // broadcast.
573b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, 0);
574b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            synchronized (mStatsLock) {
5756248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                mWakeLock.acquire();
5766248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                try {
5776248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                    removeUidLocked(uid);
5786248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                } finally {
5796248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                    mWakeLock.release();
5806248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                }
581b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
582b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
583b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    };
584b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
58575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
58675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
58775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
588b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // SHUTDOWN is protected broadcast.
58975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            synchronized (mStatsLock) {
5903f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                shutdownLocked();
59175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
59275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
59375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
59475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
595d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    /**
5968e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Observer that watches for {@link INetworkManagementService} alerts.
5978e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
5988e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
5998e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        @Override
6008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        public void limitReached(String limitName, String iface) {
6018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            // only someone like NMS should be calling us
6028e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
6038e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6048e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
6058e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // kick off background poll to collect network stats; UID stats
6068e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // are handled during normal polling interval.
6071f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                final int flags = FLAG_PERSIST_NETWORK;
608b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
6098e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6108e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // re-arm global alert for next update
61125ce9ed57f137dc0b21045ab90fe595640ebf926Jeff Sharkey                mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
6128e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
6138e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
6148e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    };
6158e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
616367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
617367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
618367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
619367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    /**
620367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     * Receiver that watches for {@link TelephonyManager} changes, such as
621367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     * transitioning between network types.
622367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     */
623367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private PhoneStateListener mPhoneListener = new PhoneStateListener() {
624367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        @Override
625367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        public void onDataConnectionStateChanged(int state, int networkType) {
626367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean stateChanged = state != mLastPhoneState;
627367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
628367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
629367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            if (networkTypeChanged && !stateChanged) {
630367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // networkType changed without a state change, which means we
631367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // need to roll our own update. delay long enough for
632367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // ConnectivityManager to process.
633367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // TODO: add direct event to ConnectivityService instead of
634367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // relying on this delay.
635367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
636367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mHandler.sendMessageDelayed(
637367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                        mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
638367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
639367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
640367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mLastPhoneState = state;
641367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mLastPhoneNetworkType = networkType;
642367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        }
643367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    };
644367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
645367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private void updateIfaces() {
646367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        synchronized (mStatsLock) {
647367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mWakeLock.acquire();
648367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            try {
649367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                updateIfacesLocked();
650367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            } finally {
651367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mWakeLock.release();
652367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
653367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        }
654367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    }
655367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
6568e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
657d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Inspect all current {@link NetworkState} to derive mapping from {@code
658d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
659d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * are active on a single {@code iface}, they are combined under a single
6601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * {@link NetworkIdentitySet}.
661d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     */
662d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private void updateIfacesLocked() {
6636341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey        if (!mSystemReady) return;
66439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
665d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
666d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // take one last stats snapshot before updating iface mapping. this
667d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // isn't perfect, since the kernel may already be counting traffic from
668d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // the updated network.
669b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
6701f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // poll, but only persist network stats to keep codepath fast. UID stats
6711f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // will be persisted during next alarm poll event.
6721f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        performPollLocked(FLAG_PERSIST_NETWORK);
673d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
674d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final NetworkState[] states;
67563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final LinkProperties activeLink;
676d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        try {
677d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            states = mConnManager.getAllNetworkState();
67863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            activeLink = mConnManager.getActiveLinkProperties();
679d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        } catch (RemoteException e) {
680b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
681d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return;
682d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
683d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
68463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
68563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
686d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // rebuild active interfaces based on connected networks
6871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        mActiveIfaces.clear();
688d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
689d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        for (NetworkState state : states) {
690d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (state.networkInfo.isConnected()) {
691d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                // collect networks under their parent interfaces
692d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
6931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
6941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                NetworkIdentitySet ident = mActiveIfaces.get(iface);
6951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (ident == null) {
6961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    ident = new NetworkIdentitySet();
6971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    mActiveIfaces.put(iface, ident);
6981b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
6991b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
700d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
701d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
702d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
703d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
704d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
70539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
7068e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
7078e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * so we have baseline values without double-counting.
7088e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
70963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private void bootstrapStatsLocked() {
71063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
71163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                : System.currentTimeMillis();
71263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
7138e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
71463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // snapshot and record current counters; read UID stats first to
71563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // avoid overcounting dev stats.
71663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
71763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final NetworkStats devSnapshot = getNetworkStatsSummary();
71863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
71963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
72063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
72163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
72263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
7238e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (IllegalStateException e) {
7248e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.w(TAG, "problem reading network stats: " + e);
7258e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
726b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
7278e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
7288e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
7298e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
730b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private void performPoll(int flags) {
7318e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        synchronized (mStatsLock) {
7328e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mWakeLock.acquire();
733684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey
734684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey            // try refreshing time source when stale
735684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey            if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
736684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey                mTime.forceRefresh();
737684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey            }
738684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey
7398e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            try {
740b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                performPollLocked(flags);
7418e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            } finally {
7428e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mWakeLock.release();
7438e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
7448e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
7458e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
7468e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
7478e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
74839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Periodic poll operation, reading current statistics and recording into
74939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * {@link NetworkStatsHistory}.
75039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
751b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private void performPollLocked(int flags) {
7526341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey        if (!mSystemReady) return;
753b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
7546341fcecc8826924a4bb24169aaf80fec9a20894Jeff Sharkey
7558e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        final long startRealtime = SystemClock.elapsedRealtime();
75675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
757b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
758b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
7591f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
760b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
76175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // TODO: consider marking "untrusted" times in historical stats
76275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
76375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                : System.currentTimeMillis();
76475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
76575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
76663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // snapshot and record current counters; read UID stats first to
76763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // avoid overcounting dev stats.
76863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
76963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final NetworkStats devSnapshot = getNetworkStatsSummary();
7701f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
77163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
77263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
77363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime);
774367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
775b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        } catch (IllegalStateException e) {
776b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
777905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            return;
778b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        } catch (RemoteException e) {
779b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
780905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            return;
781905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
782905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
78363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // persist any pending data depending on requested flags
78463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        if (persistForce) {
78563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mDevRecorder.forcePersistLocked(currentTime);
78663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidRecorder.forcePersistLocked(currentTime);
78763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mUidTagRecorder.forcePersistLocked(currentTime);
78863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        } else {
78963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (persistNetwork) {
79063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mDevRecorder.maybePersistLocked(currentTime);
79163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            }
79263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (persistUid) {
79363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mUidRecorder.maybePersistLocked(currentTime);
79463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mUidTagRecorder.maybePersistLocked(currentTime);
79563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            }
79661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
797497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
7988e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        if (LOGV) {
7998e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long duration = SystemClock.elapsedRealtime() - startRealtime;
8008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.v(TAG, "performPollLocked() took " + duration + "ms");
8018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
8028e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
80363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        if (mSettings.getSampleEnabled()) {
804905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // sample stats after each full poll
80563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            performSampleLocked();
806905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
80707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
808497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // finally, dispatch updated event to any listeners
809497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
810497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
811497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.sendBroadcast(updatedIntent, READ_NETWORK_USAGE_HISTORY);
81261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
81361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
81461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
81507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     * Sample recent statistics summary into {@link EventLog}.
81607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     */
81763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private void performSampleLocked() {
81863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // TODO: migrate trustedtime fixes to separate binary log events
819905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
820905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
82163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        NetworkTemplate template;
82263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        NetworkStats.Entry devTotal;
82363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        NetworkStats.Entry xtTotal;
82463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        NetworkStats.Entry uidTotal;
82507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
82607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        // collect mobile sample
82707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
82863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
82963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        xtTotal = new NetworkStats.Entry();
83063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
831684c54a2eb860062f1960f4eba6bc71aa1cfa71dJeff Sharkey
832905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        EventLogTags.writeNetstatsMobileSample(
833905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
834905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
835905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
83663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                trustedTime);
83707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
83807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        // collect wifi sample
83907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        template = buildTemplateWifi();
84063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
84163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        xtTotal = new NetworkStats.Entry();
84263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
84363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
844905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        EventLogTags.writeNetstatsWifiSample(
845905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
846905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
847905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
84863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                trustedTime);
84907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
85007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
85107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    /**
85263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey     * Clean up {@link #mUidRecorder} after UID is removed.
853b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey     */
854b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private void removeUidLocked(int uid) {
855163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        // perform one last poll before removing
856163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        performPollLocked(FLAG_PERSIST_ALL);
857163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
85863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidRecorder.removeUidLocked(uid);
85963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        mUidTagRecorder.removeUidLocked(uid);
860163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
861b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        // clear kernel stats associated with UID
862b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        resetKernelUidStats(uid);
86375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
86475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
86575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
86663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
86775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
86875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
86961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final HashSet<String> argSet = new HashSet<String>();
87061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (String arg : args) {
87161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            argSet.add(arg);
87261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
87361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
874706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey        // usage: dumpsys netstats --full --uid --tag --poll --checkin
87563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
876706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey        final boolean checkin = argSet.contains("--checkin");
87763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
87863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
87963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
880350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
88163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
88261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
88363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        synchronized (mStatsLock) {
88463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (poll) {
8851f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
8863f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                pw.println("Forced poll");
8873f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                return;
8883f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
8893f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
890706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey            if (checkin) {
891706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                // list current stats files to verify rotation
892706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                pw.println("Current files:");
893706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                pw.increaseIndent();
894706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                for (String file : mBaseDir.list()) {
895706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                    pw.println(file);
896706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                }
897706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                pw.decreaseIndent();
898706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey                return;
899706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey            }
900706498d387eaceb574cf4aa982fee3c288819dadJeff Sharkey
90161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.println("Active interfaces:");
90263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            pw.increaseIndent();
9031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (String iface : mActiveIfaces.keySet()) {
9041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkIdentitySet ident = mActiveIfaces.get(iface);
90563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.print("iface="); pw.print(iface);
90661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print(" ident="); pw.println(ident.toString());
90761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
90863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            pw.decreaseIndent();
90963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
91063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            pw.println("Dev stats:");
91163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            pw.increaseIndent();
91263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            mDevRecorder.dumpLocked(pw, fullHistory);
91363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            pw.decreaseIndent();
91463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
91563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (includeUid) {
91663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.println("UID stats:");
91763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.increaseIndent();
91863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mUidRecorder.dumpLocked(pw, fullHistory);
91963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.decreaseIndent();
92061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
92161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
92263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            if (includeTag) {
92363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.println("UID tag stats:");
92463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.increaseIndent();
92563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                mUidTagRecorder.dumpLocked(pw, fullHistory);
92663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                pw.decreaseIndent();
92761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
92875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
92961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
93075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
93163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStats getNetworkStatsSummary() throws RemoteException {
93263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return mNetworkManager.getNetworkStatsSummary();
9335a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey    }
9345a7bcf31a44d9875ca5fc010dc213aa2bd5b1168Jeff Sharkey
93575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
93663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey     * Return snapshot of current UID statistics, including any
93763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey     * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
93875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
93963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
94063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
94163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
94263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        // fold tethering stats and operations into uid snapshot
94363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        final NetworkStats tetherSnapshot = getNetworkStatsTethering();
94463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        uidSnapshot.combineAllValues(tetherSnapshot);
94563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        uidSnapshot.combineAllValues(mUidOperations);
94663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
94763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        return uidSnapshot;
94875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
94975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
950d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    /**
951d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     * Return snapshot of current tethering statistics. Will return empty
952d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     * {@link NetworkStats} if any problems are encountered.
953d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     */
954d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    private NetworkStats getNetworkStatsTethering() throws RemoteException {
955d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey        try {
956d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
957d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs);
958d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey        } catch (IllegalStateException e) {
959d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
960d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            return new NetworkStats(0L, 10);
961d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey        }
962d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    }
963d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey
964b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private Handler.Callback mHandlerCallback = new Handler.Callback() {
965b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        /** {@inheritDoc} */
966b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public boolean handleMessage(Message msg) {
967b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            switch (msg.what) {
9688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                case MSG_PERFORM_POLL: {
969b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    final int flags = msg.arg1;
970b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    performPoll(flags);
971b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    return true;
972b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                }
973367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                case MSG_UPDATE_IFACES: {
974367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    updateIfaces();
975367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    return true;
976367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                }
97725ce9ed57f137dc0b21045ab90fe595640ebf926Jeff Sharkey                case MSG_REGISTER_GLOBAL_ALERT: {
97825ce9ed57f137dc0b21045ab90fe595640ebf926Jeff Sharkey                    registerGlobalAlert();
97925ce9ed57f137dc0b21045ab90fe595640ebf926Jeff Sharkey                    return true;
98025ce9ed57f137dc0b21045ab90fe595640ebf926Jeff Sharkey                }
981b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                default: {
982b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    return false;
983b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                }
984b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
985b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
986b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    };
987b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
98807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    private static String getActiveSubscriberId(Context context) {
98907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
99007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                Context.TELEPHONY_SERVICE);
99107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return telephony.getSubscriberId();
99207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
99307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
994418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey    private boolean isBandwidthControlEnabled() {
995418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey        try {
996418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey            return mNetworkManager.isBandwidthControlEnabled();
997418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey        } catch (RemoteException e) {
998418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey            // ignored; service lives in system_server
999418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey            return false;
1000418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey        }
1001418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey    }
1002418d12dc8f2c518b673ebc522de4af6f7dbf0bf3Jeff Sharkey
100363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey    private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
100463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        /** {@inheritDoc} */
100563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
100663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                int rightIndex, String cookie) {
100763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            Log.w(TAG, "found non-monotonic values; saving to dropbox");
1008b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
100963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            // record error for debugging
101063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final StringBuilder builder = new StringBuilder();
101163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
101263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    + "] - right[" + rightIndex + "]\n");
101363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            builder.append("left=").append(left).append('\n');
101463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            builder.append("right=").append(right).append('\n');
1015b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
101663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
101763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    Context.DROPBOX_SERVICE);
101863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
1019b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1020b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
1021b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
10221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
102339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Default external settings that read from {@link Settings.Secure}.
102439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
102539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
102639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private final ContentResolver mResolver;
102739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
102839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public DefaultNetworkStatsSettings(Context context) {
102939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mResolver = checkNotNull(context.getContentResolver());
103039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // TODO: adjust these timings for production builds
103139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
103239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
103339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private long getSecureLong(String name, long def) {
103439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return Settings.Secure.getLong(mResolver, name, def);
103539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
1036991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey        private boolean getSecureBoolean(String name, boolean def) {
1037991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey            final int defInt = def ? 1 : 0;
1038991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey            return Settings.Secure.getInt(mResolver, name, defInt) != 0;
1039991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey        }
104039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
104139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval() {
10428e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
104339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
104463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public long getTimeCacheMaxAge() {
104563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return getSecureLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
104639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
104763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public long getGlobalAlertBytes() {
104863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return getSecureLong(NETSTATS_GLOBAL_ALERT_BYTES, 2 * MB_IN_BYTES);
104939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
105063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public boolean getSampleEnabled() {
105163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return getSecureBoolean(NETSTATS_SAMPLE_ENABLED, true);
105239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
105363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
105463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public Config getDevConfig() {
105563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
105663abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_DEV_PERSIST_BYTES, 2 * MB_IN_BYTES),
105763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
105863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
105939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
106063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
106163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public Config getUidConfig() {
106263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
106363abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES),
106463abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
106563abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
1066d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        }
106763abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey
106863abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey        public Config getUidTagConfig() {
106963abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey            return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
107063abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_UID_PERSIST_BYTES, 2 * MB_IN_BYTES),
107163abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_UID_ROTATE_AGE, 5 * DAY_IN_MILLIS),
107263abc37356728c0575d6a62a203102ae6d97953bJeff Sharkey                    getSecureLong(NETSTATS_UID_DELETE_AGE, 15 * DAY_IN_MILLIS));
107339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
107439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
107575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey}
1076