NetworkStatsService.java revision 367d15ab1a33b6159447fa8542d4fa8ff148371c
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;
2961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.net.NetworkStats.IFACE_ALL;
30b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_ALL;
31b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_DEFAULT;
32b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static android.net.NetworkStats.SET_FOREGROUND;
331b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport static android.net.NetworkStats.TAG_NONE;
3475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport static android.net.NetworkStats.UID_ALL;
3507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateMobileAll;
3607b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport static android.net.NetworkTemplate.buildTemplateWifi;
37b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkeyimport static android.net.TrafficStats.UID_REMOVED;
38cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkeyimport static android.net.TrafficStats.UID_TETHERING;
3939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
4039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
4161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
4261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
43d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY;
4439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
4539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
46367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
47367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.telephony.PhoneStateListener.LISTEN_NONE;
4861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
4961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.HOUR_IN_MILLIS;
5061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.MINUTE_IN_MILLIS;
51367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS;
52d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
538e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeyimport static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
54b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
55b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.AlarmManager;
5875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.IAlarmManager;
5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.PendingIntent;
6075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.BroadcastReceiver;
6139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport android.content.ContentResolver;
6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Context;
6375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Intent;
6475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.IntentFilter;
6561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.content.pm.ApplicationInfo;
66d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.IConnectivityManager;
678e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeyimport android.net.INetworkManagementEventObserver;
6875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity;
70d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkInfo;
71d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkState;
7275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStats;
7375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStatsHistory;
741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate;
75cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkeyimport android.net.TrafficStats;
76a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport android.os.Binder;
773f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport android.os.Environment;
7875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Handler;
7975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.HandlerThread;
8075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.INetworkManagementService;
81b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.os.Message;
826248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkeyimport android.os.PowerManager;
8375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.RemoteException;
8475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.SystemClock;
8561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.provider.Settings;
86367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport android.telephony.PhoneStateListener;
8775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.telephony.TelephonyManager;
8807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport android.util.EventLog;
89b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkeyimport android.util.Log;
9075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.NtpTrustedTime;
9175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.Slog;
92b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.util.SparseIntArray;
9375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.TrustedTime;
9475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
953f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport com.android.internal.os.AtomicFile;
96b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport com.android.internal.util.Objects;
9707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport com.android.server.EventLogTags;
98cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkeyimport com.android.server.connectivity.Tethering;
99b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport com.google.android.collect.Lists;
10075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport com.google.android.collect.Maps;
1011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport com.google.android.collect.Sets;
10275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1034e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport java.io.BufferedInputStream;
1044e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport java.io.BufferedOutputStream;
1053f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.DataInputStream;
1063f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.DataOutputStream;
1073f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.File;
10875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.FileDescriptor;
1093f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileNotFoundException;
1103f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileOutputStream;
1113f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.IOException;
11275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.PrintWriter;
1133f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.net.ProtocolException;
114b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.ArrayList;
115b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.Collections;
11675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashMap;
11761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.HashSet;
1181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport java.util.List;
11975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1203f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport libcore.io.IoUtils;
1213f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
12275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/**
12375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collect and persist detailed network statistics, and provide this data to
12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * other system services.
12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */
12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsService extends INetworkStatsService.Stub {
12721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG = "NetworkStats";
128367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final boolean LOGD = false;
12939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static final boolean LOGV = false;
13075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1313f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    /** File header magic number: "ANET" */
1323f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static final int FILE_MAGIC = 0x414E4554;
1331b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_NETWORK_INIT = 1;
1341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_UID_INIT = 1;
1351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_UID_WITH_IDENT = 2;
136d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    private static final int VERSION_UID_WITH_TAG = 3;
137b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private static final int VERSION_UID_WITH_SET = 4;
138b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
139367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final int MSG_PERFORM_POLL = 1;
140367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final int MSG_UPDATE_IFACES = 2;
141b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
142b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    /** Flags to control detail level of poll event. */
143b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private static final int FLAG_PERSIST_NETWORK = 0x10;
144b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private static final int FLAG_PERSIST_UID = 0x20;
145b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
1461f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey    private static final int FLAG_PERSIST_FORCE = 0x100;
1473f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
14875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
14975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkManagementService mNetworkManager;
15075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IAlarmManager mAlarmManager;
15175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final TrustedTime mTime;
152367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private final TelephonyManager mTeleManager;
15339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final NetworkStatsSettings mSettings;
15475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1556248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey    private final PowerManager.WakeLock mWakeLock;
1566248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey
157d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private IConnectivityManager mConnManager;
158d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
1593f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    // @VisibleForTesting
1603f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    public static final String ACTION_NETWORK_STATS_POLL =
16175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            "com.android.server.action.NETWORK_STATS_POLL";
162497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    public static final String ACTION_NETWORK_STATS_UPDATED =
163497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            "com.android.server.action.NETWORK_STATS_UPDATED";
16475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
16575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private PendingIntent mPollIntent;
16675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
167d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    // TODO: trim empty history objects entirely
168d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
16975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private static final long KB_IN_BYTES = 1024;
17061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
17161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static final long GB_IN_BYTES = 1024 * MB_IN_BYTES;
17275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
17339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
17439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Settings that can be changed externally.
17539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
17639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    public interface NetworkStatsSettings {
17739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval();
17839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPersistThreshold();
17939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkBucketDuration();
18039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkMaxHistory();
18139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidBucketDuration();
18239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidMaxHistory();
183d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        public long getTagMaxHistory();
18439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge();
18539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
18675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
18775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mStatsLock = new Object();
18875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /** Set of currently active ifaces. */
1901b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
191a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /** Set of historical network layer stats for known networks. */
1921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkStats = Maps.newHashMap();
193a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /** Set of historical network layer stats for known UIDs. */
194b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
19539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
19639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /** Flag if {@link #mUidStats} have been loaded from disk. */
19739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private boolean mUidStatsLoaded = false;
19875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1998e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPollNetworkSnapshot;
2008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPollUidSnapshot;
2018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPollOperationsSnapshot;
202cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private NetworkStats mLastPollTetherSnapshot;
20361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
2048e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPersistNetworkSnapshot;
2058e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPersistUidSnapshot;
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. */
211a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    private NetworkStats mOperations = new NetworkStats(0L, 10);
212a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
21375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final HandlerThread mHandlerThread;
21475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Handler mHandler;
21575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
21639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final AtomicFile mNetworkFile;
21739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final AtomicFile mUidFile;
2183f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
21975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(
22075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
221104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
222104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey                getSystemDir(), new DefaultNetworkStatsSettings(context));
2233f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
2243f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
2253f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static File getSystemDir() {
2263f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
22775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
22875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
22975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(Context context, INetworkManagementService networkManager,
23039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            IAlarmManager alarmManager, TrustedTime time, File systemDir,
23139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            NetworkStatsSettings settings) {
23275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext = checkNotNull(context, "missing Context");
23375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
23475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
23575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
236367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
23739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
23875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
2396248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey        final PowerManager powerManager = (PowerManager) context.getSystemService(
2406248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                Context.POWER_SERVICE);
2416248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
2426248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey
24375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
24475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread.start();
245b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
2463f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
24739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkFile = new AtomicFile(new File(systemDir, "netstats.bin"));
24839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
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() {
2563f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        synchronized (mStatsLock) {
25739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // read historical network stats from disk, since policy service
25839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // might need them right away. we delay loading detailed UID stats
25939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // until actually needed.
26039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            readNetworkStatsLocked();
2613f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
26275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
26321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
264961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkey        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
265b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
26675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
267cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        // watch for tethering changes
268cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
269cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
270cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
27175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // listen for periodic polling events
27275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
27321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
27475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
275b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // listen for uid removal to clean stats
276b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
277b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
278b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
27975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // persist stats during clean shutdown
280b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
281b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
28275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
28375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
2848e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mNetworkManager.registerObserver(mAlertObserver);
28575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } catch (RemoteException e) {
286b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
28775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
288b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
289367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        // watch for networkType changes that aren't broadcast through
290367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        // CONNECTIVITY_ACTION_IMMEDIATE above.
291367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
292367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
2938e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        registerPollAlarmLocked();
2948e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        registerGlobalAlert();
2958e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
2968e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        // bootstrap initial stats to prevent double-counting later
2978e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        bootstrapStats();
29875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
29975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3003f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private void shutdownLocked() {
301b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.unregisterReceiver(mConnReceiver);
302367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mContext.unregisterReceiver(mTetherReceiver);
3033f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mPollReceiver);
304b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.unregisterReceiver(mRemovedReceiver);
3053f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mShutdownReceiver);
3063f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
307367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager.listen(mPhoneListener, LISTEN_NONE);
308367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
30939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        writeNetworkStatsLocked();
310af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey        if (mUidStatsLoaded) {
311af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey            writeUidStatsLocked();
312af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey        }
31339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkStats.clear();
31439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
31539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStatsLoaded = false;
3163f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
3173f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
31875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
31975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
32039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
32175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
3228e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void registerPollAlarmLocked() {
3238e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
3248e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            if (mPollIntent != null) {
3258e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mAlarmManager.remove(mPollIntent);
3268e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
32775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3288e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mPollIntent = PendingIntent.getBroadcast(
3298e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                    mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
33075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3318e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long currentRealtime = SystemClock.elapsedRealtime();
3328e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
3338e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                    mSettings.getPollInterval(), mPollIntent);
3348e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
335b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
3368e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
3378e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
3388e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
3398e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
3408e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Register for a global alert that is delivered through
3418e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * {@link INetworkManagementEventObserver} once a threshold amount of data
3428e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * has been transferred.
3438e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
3448e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void registerGlobalAlert() {
3458e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
3468e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long alertBytes = mSettings.getPersistThreshold();
3478e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mNetworkManager.setGlobalAlert(alertBytes);
3488e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (IllegalStateException e) {
3498e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.w(TAG, "problem registering for global alert: " + e);
3508e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
351b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
3528e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
35375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
35475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
35575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
35663d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
35721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
358d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
359d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        synchronized (mStatsLock) {
360d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // combine all interfaces that match template
36161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final NetworkStatsHistory combined = new NetworkStatsHistory(
36263d27a9233fed934340231f438493746084a681dJeff Sharkey                    mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields);
3631b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
3641b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (templateMatches(template, ident)) {
3651b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    final NetworkStatsHistory history = mNetworkStats.get(ident);
366d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    if (history != null) {
367d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                        combined.recordEntireHistory(history);
368d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    }
369d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                }
370d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
371d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return combined;
372d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
37375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
37475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
37575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
37663d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory getHistoryForUid(
377b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            NetworkTemplate template, int uid, int set, int tag, int fields) {
37821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
379d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
38039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        synchronized (mStatsLock) {
38139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            ensureUidStatsLoadedLocked();
3821b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
3831b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            // combine all interfaces that match template
3841b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            final NetworkStatsHistory combined = new NetworkStatsHistory(
38563d27a9233fed934340231f438493746084a681dJeff Sharkey                    mSettings.getUidBucketDuration(), estimateUidBuckets(), fields);
386b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            for (UidStatsKey key : mUidStats.keySet()) {
387b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final boolean setMatches = set == SET_ALL || key.set == set;
388b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                if (templateMatches(template, key.ident) && key.uid == uid && setMatches
389b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        && key.tag == tag) {
390b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory history = mUidStats.get(key);
391b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    combined.recordEntireHistory(history);
3921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
3931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
394b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
3951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            return combined;
39639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
39775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
39875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
399d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    @Override
4001b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
40121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
40221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
40321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mStatsLock) {
404434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            // use system clock to be externally consistent
405434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            final long now = System.currentTimeMillis();
406434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
407d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStats stats = new NetworkStats(end - start, 1);
408d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStats.Entry entry = new NetworkStats.Entry();
409434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            NetworkStatsHistory.Entry historyEntry = null;
41021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
41121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // combine total from all interfaces that match template
4121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
4131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (templateMatches(template, ident)) {
4141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    final NetworkStatsHistory history = mNetworkStats.get(ident);
415434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                    historyEntry = history.getValues(start, end, now, historyEntry);
416d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
417d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    entry.iface = IFACE_ALL;
418d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    entry.uid = UID_ALL;
419d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    entry.tag = TAG_NONE;
420434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                    entry.rxBytes = historyEntry.rxBytes;
42107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                    entry.rxPackets = historyEntry.rxPackets;
422434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                    entry.txBytes = historyEntry.txBytes;
42307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                    entry.txPackets = historyEntry.txPackets;
424d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
425d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    stats.combineValues(entry);
42621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
42721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
42821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
4294a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            return stats;
43021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
43121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
43221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
43321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
434d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    public NetworkStats getSummaryForAllUid(
435d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey            NetworkTemplate template, long start, long end, boolean includeTags) {
43621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
437d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
43819862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        synchronized (mStatsLock) {
43939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            ensureUidStatsLoadedLocked();
44039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
441434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            // use system clock to be externally consistent
442434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            final long now = System.currentTimeMillis();
443434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
4441b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            final NetworkStats stats = new NetworkStats(end - start, 24);
445d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStats.Entry entry = new NetworkStats.Entry();
446434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            NetworkStatsHistory.Entry historyEntry = null;
4471b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
448b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            for (UidStatsKey key : mUidStats.keySet()) {
449b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                if (templateMatches(template, key.ident)) {
450b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    // always include summary under TAG_NONE, and include
451b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    // other tags when requested.
452b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    if (key.tag == TAG_NONE || includeTags) {
453b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        final NetworkStatsHistory history = mUidStats.get(key);
454b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        historyEntry = history.getValues(start, end, now, historyEntry);
455b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
456b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.iface = IFACE_ALL;
457b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.uid = key.uid;
458b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.set = key.set;
459b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.tag = key.tag;
460b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.rxBytes = historyEntry.rxBytes;
461b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.rxPackets = historyEntry.rxPackets;
462b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.txBytes = historyEntry.txBytes;
463b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.txPackets = historyEntry.txPackets;
464b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.operations = historyEntry.operations;
465b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
466b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
467b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                                || entry.txPackets > 0 || entry.operations > 0) {
468b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            stats.combineValues(entry);
469d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                        }
4701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    }
4711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
47219862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            }
4731b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
4744a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            return stats;
47519862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        }
476d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
477d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
478350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    @Override
479a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
480a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (Binder.getCallingUid() != uid) {
481a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
482a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
483a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
484a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // TODO: switch to data layer stats once kernel exports
485a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // for now, read network layer stats and flatten across all ifaces
486a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
487a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats dataLayer = new NetworkStats(
488a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                networkLayer.getElapsedRealtime(), networkLayer.size());
489a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
490a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        NetworkStats.Entry entry = null;
491a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        for (int i = 0; i < networkLayer.size(); i++) {
492a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            entry = networkLayer.getValues(i, entry);
493a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            entry.iface = IFACE_ALL;
494a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            dataLayer.combineValues(entry);
495a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
496a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
497a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // splice in operation counts
498a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dataLayer.spliceOperationsFrom(mOperations);
499a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        return dataLayer;
500a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
501a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
502a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Override
503a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void incrementOperationCount(int uid, int tag, int operationCount) {
504a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (Binder.getCallingUid() != uid) {
505a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
506a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
507a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
508b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        if (operationCount < 0) {
509b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            throw new IllegalArgumentException("operation count can only be incremented");
510b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
511b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        if (tag == TAG_NONE) {
512b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            throw new IllegalArgumentException("operation count must have specific tag");
513b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
514b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
515a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        synchronized (mStatsLock) {
516b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
517b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mOperations.combineValues(IFACE_ALL, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
518b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mOperations.combineValues(IFACE_ALL, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
519b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
520b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
521b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
522b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    @Override
523b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public void setUidForeground(int uid, boolean uidForeground) {
524b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
525b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
526b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        synchronized (mStatsLock) {
527b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
528b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
529b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (oldSet != set) {
530b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                mActiveUidCounterSet.put(uid, set);
531b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                setKernelCounterSet(uid, set);
532b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
533a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
534a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
535a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
536a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Override
537350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    public void forceUpdate() {
538350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
5391f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        performPoll(FLAG_PERSIST_ALL);
540350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    }
541350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
54275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
543d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
54475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
54575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * with mobile interfaces.
54675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
547b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
54875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
54975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
550d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
551d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
552367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            updateIfaces();
55375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
55475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
55575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
556cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    /**
557cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     * Receiver that watches for {@link Tethering} to claim interface pairs.
558cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     */
559cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
560cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        @Override
561cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public void onReceive(Context context, Intent intent) {
562cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
563cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            // permission above.
5641f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performPoll(FLAG_PERSIST_NETWORK);
565cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
566cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    };
567cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
56875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
56975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
57075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
571d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified UPDATE_DEVICE_STATS
572d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
5731f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performPoll(FLAG_PERSIST_ALL);
5748e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
5758e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            // verify that we're watching global alert
5768e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            registerGlobalAlert();
57775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
57875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
57975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
580b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
581b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        @Override
582b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        public void onReceive(Context context, Intent intent) {
583b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // on background handler thread, and UID_REMOVED is protected
584b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // broadcast.
585b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, 0);
586b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            synchronized (mStatsLock) {
587434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                // TODO: perform one last stats poll for UID
5886248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                mWakeLock.acquire();
5896248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                try {
5906248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                    removeUidLocked(uid);
5916248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                } finally {
5926248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                    mWakeLock.release();
5936248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                }
594b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
595b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
596b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    };
597b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
59875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
59975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
60075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
601b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // SHUTDOWN is protected broadcast.
60275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            synchronized (mStatsLock) {
6033f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                shutdownLocked();
60475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
60575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
60675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
60775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
608d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    /**
6098e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Observer that watches for {@link INetworkManagementService} alerts.
6108e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
6118e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
6128e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        @Override
6138e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        public void limitReached(String limitName, String iface) {
6148e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            // only someone like NMS should be calling us
6158e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
6168e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6178e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
6188e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // kick off background poll to collect network stats; UID stats
6198e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // are handled during normal polling interval.
6201f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                final int flags = FLAG_PERSIST_NETWORK;
621b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
6228e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6238e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // re-arm global alert for next update
6248e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                registerGlobalAlert();
6258e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
6268e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
6278e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    };
6288e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
629367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
630367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
631367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
632367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    /**
633367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     * Receiver that watches for {@link TelephonyManager} changes, such as
634367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     * transitioning between network types.
635367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     */
636367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private PhoneStateListener mPhoneListener = new PhoneStateListener() {
637367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        @Override
638367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        public void onDataConnectionStateChanged(int state, int networkType) {
639367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean stateChanged = state != mLastPhoneState;
640367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
641367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
642367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            if (networkTypeChanged && !stateChanged) {
643367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // networkType changed without a state change, which means we
644367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // need to roll our own update. delay long enough for
645367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // ConnectivityManager to process.
646367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // TODO: add direct event to ConnectivityService instead of
647367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // relying on this delay.
648367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
649367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mHandler.sendMessageDelayed(
650367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                        mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
651367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
652367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
653367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mLastPhoneState = state;
654367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mLastPhoneNetworkType = networkType;
655367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        }
656367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    };
657367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
658367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private void updateIfaces() {
659367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        synchronized (mStatsLock) {
660367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mWakeLock.acquire();
661367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            try {
662367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                updateIfacesLocked();
663367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            } finally {
664367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mWakeLock.release();
665367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
666367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        }
667367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    }
668367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
6698e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
670d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Inspect all current {@link NetworkState} to derive mapping from {@code
671d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
672d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * are active on a single {@code iface}, they are combined under a single
6731b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * {@link NetworkIdentitySet}.
674d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     */
675d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private void updateIfacesLocked() {
67639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
677d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
678d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // take one last stats snapshot before updating iface mapping. this
679d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // isn't perfect, since the kernel may already be counting traffic from
680d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // the updated network.
681b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
6821f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // poll, but only persist network stats to keep codepath fast. UID stats
6831f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // will be persisted during next alarm poll event.
6841f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        performPollLocked(FLAG_PERSIST_NETWORK);
685d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
686d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final NetworkState[] states;
687d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        try {
688d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            states = mConnManager.getAllNetworkState();
689d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        } catch (RemoteException e) {
690b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
691d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return;
692d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
693d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
694d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // rebuild active interfaces based on connected networks
6951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        mActiveIfaces.clear();
696d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
697d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        for (NetworkState state : states) {
698d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (state.networkInfo.isConnected()) {
699d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                // collect networks under their parent interfaces
700d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
7011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
7021b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                NetworkIdentitySet ident = mActiveIfaces.get(iface);
7031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (ident == null) {
7041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    ident = new NetworkIdentitySet();
7051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    mActiveIfaces.put(iface, ident);
7061b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
7071b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
708d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
709d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
710d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
711d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
712d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
71339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
7148e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
7158e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * so we have baseline values without double-counting.
7168e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
7178e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void bootstrapStats() {
7188e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
7198e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mLastPollNetworkSnapshot = mNetworkManager.getNetworkStatsSummary();
7208e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
7218e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mLastPollOperationsSnapshot = new NetworkStats(0L, 0);
7228e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (IllegalStateException e) {
7238e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.w(TAG, "problem reading network stats: " + e);
7248e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
725b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
7268e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
7278e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
7288e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
729b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private void performPoll(int flags) {
7308e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        synchronized (mStatsLock) {
7318e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mWakeLock.acquire();
7328e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            try {
733b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                performPollLocked(flags);
7348e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            } finally {
7358e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mWakeLock.release();
7368e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
7378e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
7388e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
7398e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
7408e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
74139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Periodic poll operation, reading current statistics and recording into
74239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * {@link NetworkStatsHistory}.
74339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
744b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private void performPollLocked(int flags) {
745b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
7468e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        final long startRealtime = SystemClock.elapsedRealtime();
74775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
748b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
749b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
7501f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
751b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
75275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // try refreshing time source when stale
75339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
75475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mTime.forceRefresh();
75575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
75675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
75775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // TODO: consider marking "untrusted" times in historical stats
75875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
75975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                : System.currentTimeMillis();
760b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final long threshold = mSettings.getPersistThreshold();
76175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
76275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
7631f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            // record tethering stats; persisted during normal UID cycle below
7641f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final String[] ifacePairs = mConnManager.getTetheredIfacePairs();
7651f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering(
7661f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                    ifacePairs);
7671f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performTetherPollLocked(tetherSnapshot, currentTime);
7681f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
7691f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            // record uid stats
7701f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
7711f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performUidPollLocked(uidSnapshot, currentTime);
7721f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
7731f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            // persist when enough network data has occurred
7741f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final NetworkStats persistUidDelta = computeStatsDelta(
7751f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                    mLastPersistUidSnapshot, uidSnapshot, true);
7761f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final boolean uidPastThreshold = persistUidDelta.getTotalBytes() > threshold;
7771f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            if (persistForce || (persistUid && uidPastThreshold)) {
7781f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                writeUidStatsLocked();
7791f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                mLastPersistUidSnapshot = uidSnapshot;
78061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
781367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
782367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            // record network stats
783367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final NetworkStats networkSnapshot = mNetworkManager.getNetworkStatsSummary();
784367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            performNetworkPollLocked(networkSnapshot, currentTime);
785367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
786367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            // persist when enough network data has occurred
787367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final NetworkStats persistNetworkDelta = computeStatsDelta(
788367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    mLastPersistNetworkSnapshot, networkSnapshot, true);
789367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean networkPastThreshold = persistNetworkDelta.getTotalBytes() > threshold;
790367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            if (persistForce || (persistNetwork && networkPastThreshold)) {
791367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                writeNetworkStatsLocked();
792367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mLastPersistNetworkSnapshot = networkSnapshot;
793367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
794b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        } catch (IllegalStateException e) {
795b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
796b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        } catch (RemoteException e) {
797b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
79861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
799497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
8008e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        if (LOGV) {
8018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long duration = SystemClock.elapsedRealtime() - startRealtime;
8028e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.v(TAG, "performPollLocked() took " + duration + "ms");
8038e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
8048e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
805b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        // sample stats after each full poll
8061f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        performSample();
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    /**
81539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Update {@link #mNetworkStats} historical usage.
81661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
817d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    private void performNetworkPollLocked(NetworkStats networkSnapshot, long currentTime) {
8181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        final HashSet<String> unknownIface = Sets.newHashSet();
819d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
8208e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        final NetworkStats delta = computeStatsDelta(mLastPollNetworkSnapshot, networkSnapshot, false);
821d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        final long timeStart = currentTime - delta.getElapsedRealtime();
822d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
823d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        NetworkStats.Entry entry = null;
824d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        for (int i = 0; i < delta.size(); i++) {
825d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            entry = delta.getValues(i, entry);
826d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
827d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (ident == null) {
828d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                unknownIface.add(entry.iface);
82975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                continue;
83075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
83175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
8321b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            final NetworkStatsHistory history = findOrCreateNetworkStatsLocked(ident);
833a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            history.recordData(timeStart, currentTime, entry);
834d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        }
835d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
8368e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        mLastPollNetworkSnapshot = networkSnapshot;
83775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
838d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        if (LOGD && unknownIface.size() > 0) {
839d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            Slog.w(TAG, "unknown interfaces " + unknownIface.toString() + ", ignoring those stats");
840d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
84161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
842d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
84361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
84439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Update {@link #mUidStats} historical usage.
84561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
846d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
84739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        ensureUidStatsLoadedLocked();
84839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
8498e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        final NetworkStats delta = computeStatsDelta(mLastPollUidSnapshot, uidSnapshot, false);
850a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats operationsDelta = computeStatsDelta(
8518e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mLastPollOperationsSnapshot, mOperations, false);
852d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        final long timeStart = currentTime - delta.getElapsedRealtime();
8531b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
854d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        NetworkStats.Entry entry = null;
855a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        NetworkStats.Entry operationsEntry = null;
856d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        for (int i = 0; i < delta.size(); i++) {
857d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            entry = delta.getValues(i, entry);
858d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
8591b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            if (ident == null) {
860b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
861b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                        || entry.txPackets > 0) {
862b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    Log.w(TAG, "dropping UID delta from unknown iface: " + entry);
863b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                }
8641b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                continue;
86539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
8661b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
867a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // splice in operation counts since last poll
868b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.set, entry.tag);
869a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            if (j != -1) {
870a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                operationsEntry = operationsDelta.getValues(j, operationsEntry);
871a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                entry.operations = operationsEntry.operations;
872a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            }
873a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
874d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStatsHistory history = findOrCreateUidStatsLocked(
875b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    ident, entry.uid, entry.set, entry.tag);
876a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            history.recordData(timeStart, currentTime, entry);
87761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
8781b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
8798e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        mLastPollUidSnapshot = uidSnapshot;
8808e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        mLastPollOperationsSnapshot = mOperations;
881a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        mOperations = new NetworkStats(0L, 10);
88261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
88375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
884b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    /**
885cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     * Update {@link #mUidStats} historical usage for
886cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     * {@link TrafficStats#UID_TETHERING} based on tethering statistics.
887cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     */
888cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private void performTetherPollLocked(NetworkStats tetherSnapshot, long currentTime) {
889cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        ensureUidStatsLoadedLocked();
890cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
891cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final NetworkStats delta = computeStatsDelta(
892cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                mLastPollTetherSnapshot, tetherSnapshot, false);
893cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final long timeStart = currentTime - delta.getElapsedRealtime();
894cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
895cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        NetworkStats.Entry entry = null;
896cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        for (int i = 0; i < delta.size(); i++) {
897cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry = delta.getValues(i, entry);
898cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
899cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            if (ident == null) {
900cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
901cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                        || entry.txPackets > 0) {
902cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    Log.w(TAG, "dropping tether delta from unknown iface: " + entry);
903cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                }
904cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                continue;
905cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            }
906cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
907cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final NetworkStatsHistory history = findOrCreateUidStatsLocked(
908cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                    ident, UID_TETHERING, SET_DEFAULT, TAG_NONE);
909cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            history.recordData(timeStart, currentTime, entry);
910cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
911cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
912cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        // normal UID poll will trim any history beyond max
913cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        mLastPollTetherSnapshot = tetherSnapshot;
914cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    }
915cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
916cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    /**
91707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     * Sample recent statistics summary into {@link EventLog}.
91807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     */
91907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    private void performSample() {
9201f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long largestBucketSize = Math.max(
9211f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                mSettings.getNetworkBucketDuration(), mSettings.getUidBucketDuration());
9221f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
9231f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // take sample as atomic buckets
9241f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long now = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
9251f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long end = now - (now % largestBucketSize) + largestBucketSize;
9261f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long start = end - largestBucketSize;
92707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
92807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        NetworkTemplate template = null;
92907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        NetworkStats.Entry ifaceTotal = null;
93007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        NetworkStats.Entry uidTotal = null;
93107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
93207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        // collect mobile sample
93307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
93407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
93507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
9361f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        EventLogTags.writeNetstatsMobileSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets,
9371f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets,
93892cefaeb319b2642d119abb8640828ff0bbf2ac7Jeff Sharkey                uidTotal.txBytes, uidTotal.txPackets);
93907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
94007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        // collect wifi sample
94107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        template = buildTemplateWifi();
94207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        ifaceTotal = getSummaryForNetwork(template, start, end).getTotal(ifaceTotal);
94307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
9441f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        EventLogTags.writeNetstatsWifiSample(ifaceTotal.rxBytes, ifaceTotal.rxPackets,
9451f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                ifaceTotal.txBytes, ifaceTotal.txPackets, uidTotal.rxBytes, uidTotal.rxPackets,
94692cefaeb319b2642d119abb8640828ff0bbf2ac7Jeff Sharkey                uidTotal.txBytes, uidTotal.txPackets);
94707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
94807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
94907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    /**
950b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey     * Clean up {@link #mUidStats} after UID is removed.
951b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey     */
952b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private void removeUidLocked(int uid) {
953b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        ensureUidStatsLoadedLocked();
954b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
955b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final ArrayList<UidStatsKey> knownKeys = Lists.newArrayList();
956b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        knownKeys.addAll(mUidStats.keySet());
957b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
958b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // migrate all UID stats into special "removed" bucket
959b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        for (UidStatsKey key : knownKeys) {
960b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (key.uid == uid) {
961b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                // only migrate combined TAG_NONE history
962b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                if (key.tag == TAG_NONE) {
963b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory uidHistory = mUidStats.get(key);
964b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked(
965b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE);
966b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    removedHistory.recordEntireHistory(uidHistory);
967d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                }
968b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                mUidStats.remove(key);
969b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
970b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
971b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
972b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        // clear kernel stats associated with UID
973b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        resetKernelUidStats(uid);
974b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
975b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // since this was radical rewrite, push to disk
976b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        writeUidStatsLocked();
977b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    }
978b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
9791b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private NetworkStatsHistory findOrCreateNetworkStatsLocked(NetworkIdentitySet ident) {
98039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        final NetworkStatsHistory existing = mNetworkStats.get(ident);
98139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
98239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // update when no existing, or when bucket duration changed
983d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        final long bucketDuration = mSettings.getNetworkBucketDuration();
98439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        NetworkStatsHistory updated = null;
98539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (existing == null) {
9864a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration, 10);
987d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        } else if (existing.getBucketDuration() != bucketDuration) {
9884a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(
9894a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey                    bucketDuration, estimateResizeBuckets(existing, bucketDuration));
99039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated.recordEntireHistory(existing);
99139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
99239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
99339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (updated != null) {
99439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mNetworkStats.put(ident, updated);
99539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return updated;
99639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else {
99739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return existing;
99875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
99975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
100075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1001d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    private NetworkStatsHistory findOrCreateUidStatsLocked(
1002b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            NetworkIdentitySet ident, int uid, int set, int tag) {
1003b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        ensureUidStatsLoadedLocked();
1004b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
1005b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final UidStatsKey key = new UidStatsKey(ident, uid, set, tag);
1006b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final NetworkStatsHistory existing = mUidStats.get(key);
100739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
100839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // update when no existing, or when bucket duration changed
1009d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        final long bucketDuration = mSettings.getUidBucketDuration();
101039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        NetworkStatsHistory updated = null;
101139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (existing == null) {
10124a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration, 10);
1013d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        } else if (existing.getBucketDuration() != bucketDuration) {
10144a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(
10154a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey                    bucketDuration, estimateResizeBuckets(existing, bucketDuration));
101639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated.recordEntireHistory(existing);
101739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
101839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
101939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (updated != null) {
1020b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mUidStats.put(key, updated);
102139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return updated;
102239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else {
102339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return existing;
102475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
102575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
102675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
102739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void readNetworkStatsLocked() {
102839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "readNetworkStatsLocked()");
10293f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
10303f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        // clear any existing stats and read from disk
103139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mNetworkStats.clear();
10323f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
10334e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        DataInputStream in = null;
10343f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        try {
10354e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            in = new DataInputStream(new BufferedInputStream(mNetworkFile.openRead()));
10363f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
10373f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            // verify file magic header intact
10383f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final int magic = in.readInt();
10393f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (magic != FILE_MAGIC) {
10403f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                throw new ProtocolException("unexpected magic: " + magic);
10413f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
10423f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
10433f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final int version = in.readInt();
10443f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            switch (version) {
10451b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case VERSION_NETWORK_INIT: {
10461b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // network := size *(NetworkIdentitySet NetworkStatsHistory)
10473f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    final int size = in.readInt();
10483f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    for (int i = 0; i < size; i++) {
10491b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        final NetworkIdentitySet ident = new NetworkIdentitySet(in);
10503f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                        final NetworkStatsHistory history = new NetworkStatsHistory(in);
105139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                        mNetworkStats.put(ident, history);
10523f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    }
10533f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    break;
10543f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
10553f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                default: {
10563f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    throw new ProtocolException("unexpected version: " + version);
10573f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
10583f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
10593f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (FileNotFoundException e) {
10603f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            // missing stats is okay, probably first boot
10613f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (IOException e) {
1062b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
10633f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } finally {
10644e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            IoUtils.closeQuietly(in);
10653f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
106675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
106775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
106839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void ensureUidStatsLoadedLocked() {
106939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (!mUidStatsLoaded) {
107039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            readUidStatsLocked();
107139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidStatsLoaded = true;
107239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
107339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
107439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
107539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void readUidStatsLocked() {
107639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "readUidStatsLocked()");
107739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
107839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // clear any existing stats and read from disk
107939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
108039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
10814e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        DataInputStream in = null;
108239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        try {
10834e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            in = new DataInputStream(new BufferedInputStream(mUidFile.openRead()));
108439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
108539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // verify file magic header intact
108639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int magic = in.readInt();
108739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (magic != FILE_MAGIC) {
108839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                throw new ProtocolException("unexpected magic: " + magic);
108939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
109039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
109139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int version = in.readInt();
109239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            switch (version) {
10931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case VERSION_UID_INIT: {
109439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    // uid := size *(UID NetworkStatsHistory)
109539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
10961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // drop this data version, since we don't have a good
10971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // mapping into NetworkIdentitySet.
10981b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    break;
10991b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
11001b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case VERSION_UID_WITH_IDENT: {
11011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
1102d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
1103d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    // drop this data version, since this version only existed
1104d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    // for a short time.
1105d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    break;
1106d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                }
1107b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                case VERSION_UID_WITH_TAG:
1108b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                case VERSION_UID_WITH_SET: {
1109b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
1110b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final int identSize = in.readInt();
1111b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    for (int i = 0; i < identSize; i++) {
11121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        final NetworkIdentitySet ident = new NetworkIdentitySet(in);
11131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1114b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        final int size = in.readInt();
1115b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        for (int j = 0; j < size; j++) {
11161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                            final int uid = in.readInt();
1117b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt()
1118b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                                    : SET_DEFAULT;
1119d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                            final int tag = in.readInt();
1120d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
1121b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            final UidStatsKey key = new UidStatsKey(ident, uid, set, tag);
11221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                            final NetworkStatsHistory history = new NetworkStatsHistory(in);
1123b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            mUidStats.put(key, history);
11241b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        }
112539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    }
112639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    break;
112739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                }
112839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                default: {
112939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    throw new ProtocolException("unexpected version: " + version);
113039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                }
113139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
113239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (FileNotFoundException e) {
113339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // missing stats is okay, probably first boot
113439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (IOException e) {
1135b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading uid stats", e);
113639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } finally {
11374e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            IoUtils.closeQuietly(in);
113839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
113939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
114039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
114139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void writeNetworkStatsLocked() {
114239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "writeNetworkStatsLocked()");
11433f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
1144d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // TODO: consider duplicating stats and releasing lock while writing
11453f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11461f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // trim any history beyond max
11471f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        if (mTime.hasCache()) {
11481f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long currentTime = mTime.currentTimeMillis();
11491f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long maxHistory = mSettings.getNetworkMaxHistory();
11501f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            for (NetworkStatsHistory history : mNetworkStats.values()) {
11511f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                history.removeBucketsBefore(currentTime - maxHistory);
11521f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            }
11531f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        }
11541f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
11553f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        FileOutputStream fos = null;
11563f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        try {
115739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fos = mNetworkFile.startWrite();
11584e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
11593f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11603f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            out.writeInt(FILE_MAGIC);
11611b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            out.writeInt(VERSION_NETWORK_INIT);
11623f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
116339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(mNetworkStats.size());
11641b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
116539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                final NetworkStatsHistory history = mNetworkStats.get(ident);
11663f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                ident.writeToStream(out);
11673f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                history.writeToStream(out);
11683f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
11693f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11704e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            out.flush();
117139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mNetworkFile.finishWrite(fos);
117239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (IOException e) {
1173b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem writing stats", e);
117439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (fos != null) {
117539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mNetworkFile.failWrite(fos);
117639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
117739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
117839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
117939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
118039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void writeUidStatsLocked() {
118139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "writeUidStatsLocked()");
118239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1183b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        if (!mUidStatsLoaded) {
1184b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            Slog.w(TAG, "asked to write UID stats when not loaded; skipping");
1185b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            return;
1186b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
1187b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
118839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // TODO: consider duplicating stats and releasing lock while writing
118939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
11901f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // trim any history beyond max
11911f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        if (mTime.hasCache()) {
11921f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long currentTime = mTime.currentTimeMillis();
11931f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long maxUidHistory = mSettings.getUidMaxHistory();
11941f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long maxTagHistory = mSettings.getTagMaxHistory();
11951f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            for (UidStatsKey key : mUidStats.keySet()) {
11961f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                final NetworkStatsHistory history = mUidStats.get(key);
11971f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
11981f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                // detailed tags are trimmed sooner than summary in TAG_NONE
11991f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                if (key.tag == TAG_NONE) {
12001f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                    history.removeBucketsBefore(currentTime - maxUidHistory);
12011f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                } else {
12021f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                    history.removeBucketsBefore(currentTime - maxTagHistory);
12031f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                }
12041f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            }
12051f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        }
12061f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
1207b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        // build UidStatsKey lists grouped by ident
1208b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final HashMap<NetworkIdentitySet, ArrayList<UidStatsKey>> keysByIdent = Maps.newHashMap();
1209b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        for (UidStatsKey key : mUidStats.keySet()) {
1210b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            ArrayList<UidStatsKey> keys = keysByIdent.get(key.ident);
1211b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (keys == null) {
1212b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                keys = Lists.newArrayList();
1213b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                keysByIdent.put(key.ident, keys);
1214b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
1215b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            keys.add(key);
1216b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1217b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
121839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        FileOutputStream fos = null;
121939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        try {
122039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fos = mUidFile.startWrite();
12214e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
122239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
122339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(FILE_MAGIC);
1224b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            out.writeInt(VERSION_UID_WITH_SET);
122539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1226b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            out.writeInt(keysByIdent.size());
1227b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            for (NetworkIdentitySet ident : keysByIdent.keySet()) {
1228b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final ArrayList<UidStatsKey> keys = keysByIdent.get(ident);
12291b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                ident.writeToStream(out);
123039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1231b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                out.writeInt(keys.size());
1232b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                for (UidStatsKey key : keys) {
1233b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory history = mUidStats.get(key);
1234b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    out.writeInt(key.uid);
1235b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    out.writeInt(key.set);
1236b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    out.writeInt(key.tag);
12371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    history.writeToStream(out);
12381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
123939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
124039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
12414e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            out.flush();
124239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidFile.finishWrite(fos);
12433f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (IOException e) {
1244b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem writing stats", e);
12453f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (fos != null) {
124639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mUidFile.failWrite(fos);
12473f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
12483f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
124975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
125075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
125175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
125275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
125375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
125475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
125561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final HashSet<String> argSet = new HashSet<String>();
125661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (String arg : args) {
125761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            argSet.add(arg);
125861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
125961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
1260350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        final boolean fullHistory = argSet.contains("full");
1261350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
126261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        synchronized (mStatsLock) {
126361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            // TODO: remove this testing code, since it corrupts stats
126461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (argSet.contains("generate")) {
126561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                generateRandomLocked();
126661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.println("Generated stub stats");
126761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                return;
126861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
126961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
12703f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (argSet.contains("poll")) {
12711f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
12723f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                pw.println("Forced poll");
12733f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                return;
12743f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
12753f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
127661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.println("Active interfaces:");
12771b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (String iface : mActiveIfaces.keySet()) {
12781b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkIdentitySet ident = mActiveIfaces.get(iface);
127961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print("  iface="); pw.print(iface);
128061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print(" ident="); pw.println(ident.toString());
128161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
128261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
128361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.println("Known historical stats:");
12841b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (NetworkIdentitySet ident : mNetworkStats.keySet()) {
12851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkStatsHistory history = mNetworkStats.get(ident);
128661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print("  ident="); pw.println(ident.toString());
1287350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey                history.dump("  ", pw, fullHistory);
128861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
128961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
129061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (argSet.contains("detail")) {
129139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                // since explicitly requested with argument, we're okay to load
129239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                // from disk if not already in memory.
129339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                ensureUidStatsLoadedLocked();
12941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1295b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final ArrayList<UidStatsKey> keys = Lists.newArrayList();
1296b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                keys.addAll(mUidStats.keySet());
1297b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                Collections.sort(keys);
1298b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
12991b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                pw.println("Detailed UID stats:");
1300b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                for (UidStatsKey key : keys) {
1301b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print("  ident="); pw.print(key.ident.toString());
1302b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print(" uid="); pw.print(key.uid);
1303b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
1304b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
1305b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1306b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory history = mUidStats.get(key);
1307b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    history.dump("    ", pw, fullHistory);
130861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                }
130961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
131075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
131161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
131275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
131361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
131461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     * @deprecated only for temporary testing
131561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
131661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    @Deprecated
131761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private void generateRandomLocked() {
131863d27a9233fed934340231f438493746084a681dJeff Sharkey        final long NET_END = System.currentTimeMillis();
131963d27a9233fed934340231f438493746084a681dJeff Sharkey        final long NET_START = NET_END - mSettings.getNetworkMaxHistory();
132063d27a9233fed934340231f438493746084a681dJeff Sharkey        final long NET_RX_BYTES = 3 * GB_IN_BYTES;
132163d27a9233fed934340231f438493746084a681dJeff Sharkey        final long NET_RX_PACKETS = NET_RX_BYTES / 1024;
132263d27a9233fed934340231f438493746084a681dJeff Sharkey        final long NET_TX_BYTES = 2 * GB_IN_BYTES;
132363d27a9233fed934340231f438493746084a681dJeff Sharkey        final long NET_TX_PACKETS = NET_TX_BYTES / 1024;
132463d27a9233fed934340231f438493746084a681dJeff Sharkey
132563d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_END = System.currentTimeMillis();
132663d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_START = UID_END - mSettings.getUidMaxHistory();
132763d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_RX_BYTES = 500 * MB_IN_BYTES;
132863d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_RX_PACKETS = UID_RX_BYTES / 1024;
132963d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_TX_BYTES = 100 * MB_IN_BYTES;
133063d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_TX_PACKETS = UID_TX_BYTES / 1024;
133163d27a9233fed934340231f438493746084a681dJeff Sharkey        final long UID_OPERATIONS = UID_RX_BYTES / 2048;
133261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
13331b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        final List<ApplicationInfo> installedApps = mContext
13341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                .getPackageManager().getInstalledApplications(0);
133561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
13361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        mNetworkStats.clear();
133739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
13381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        for (NetworkIdentitySet ident : mActiveIfaces.values()) {
133963d27a9233fed934340231f438493746084a681dJeff Sharkey            findOrCreateNetworkStatsLocked(ident).generateRandom(NET_START, NET_END, NET_RX_BYTES,
134063d27a9233fed934340231f438493746084a681dJeff Sharkey                    NET_RX_PACKETS, NET_TX_BYTES, NET_TX_PACKETS, 0L);
13411b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
13421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (ApplicationInfo info : installedApps) {
13431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final int uid = info.uid;
1344b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                findOrCreateUidStatsLocked(ident, uid, SET_DEFAULT, TAG_NONE).generateRandom(
1345b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        UID_START, UID_END, UID_RX_BYTES, UID_RX_PACKETS, UID_TX_BYTES,
1346b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        UID_TX_PACKETS, UID_OPERATIONS);
1347b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                findOrCreateUidStatsLocked(ident, uid, SET_FOREGROUND, TAG_NONE).generateRandom(
1348b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        UID_START, UID_END, UID_RX_BYTES, UID_RX_PACKETS, UID_TX_BYTES,
1349b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        UID_TX_PACKETS, UID_OPERATIONS);
13501b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
135161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
135261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
135361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
135475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
135575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Return the delta between two {@link NetworkStats} snapshots, where {@code
135675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * before} can be {@code null}.
135775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
135863d27a9233fed934340231f438493746084a681dJeff Sharkey    private static NetworkStats computeStatsDelta(
135963d27a9233fed934340231f438493746084a681dJeff Sharkey            NetworkStats before, NetworkStats current, boolean collectStale) {
136075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        if (before != null) {
13613f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            return current.subtractClamped(before);
136263d27a9233fed934340231f438493746084a681dJeff Sharkey        } else if (collectStale) {
136363d27a9233fed934340231f438493746084a681dJeff Sharkey            // caller is okay collecting stale stats for first call.
136463d27a9233fed934340231f438493746084a681dJeff Sharkey            return current;
136575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } else {
1366a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // this is first snapshot; to prevent from double-counting we only
1367a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // observe traffic occuring between known snapshots.
1368a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            return new NetworkStats(0L, 10);
136975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
137075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
137175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
13724a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    private int estimateNetworkBuckets() {
13734a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
13744a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
13754a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
13764a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    private int estimateUidBuckets() {
13774a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return (int) (mSettings.getUidMaxHistory() / mSettings.getUidBucketDuration());
13784a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
13794a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
13804a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    private static int estimateResizeBuckets(NetworkStatsHistory existing, long newBucketDuration) {
1381d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration);
13824a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
13834a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
138439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
13851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
13861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * in the given {@link NetworkIdentitySet}.
13871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
13881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
13891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        for (NetworkIdentity ident : identSet) {
13901b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            if (template.matches(ident)) {
13911b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return true;
13921b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
13931b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
13941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return false;
13951b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
13961b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1397b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private Handler.Callback mHandlerCallback = new Handler.Callback() {
1398b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        /** {@inheritDoc} */
1399b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public boolean handleMessage(Message msg) {
1400b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            switch (msg.what) {
14018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                case MSG_PERFORM_POLL: {
1402b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    final int flags = msg.arg1;
1403b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    performPoll(flags);
1404b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    return true;
1405b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                }
1406367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                case MSG_UPDATE_IFACES: {
1407367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    updateIfaces();
1408367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    return true;
1409367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                }
1410b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                default: {
1411b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    return false;
1412b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                }
1413b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
1414b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1415b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    };
1416b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
141707b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    private static String getActiveSubscriberId(Context context) {
141807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
141907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                Context.TELEPHONY_SERVICE);
142007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return telephony.getSubscriberId();
142107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
142207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
1423b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /**
1424b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * Key uniquely identifying a {@link NetworkStatsHistory} for a UID.
1425b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     */
1426b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private static class UidStatsKey implements Comparable<UidStatsKey> {
1427b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final NetworkIdentitySet ident;
1428b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final int uid;
1429b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final int set;
1430b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final int tag;
1431b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1432b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public UidStatsKey(NetworkIdentitySet ident, int uid, int set, int tag) {
1433b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.ident = ident;
1434b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.uid = uid;
1435b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.set = set;
1436b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.tag = tag;
1437b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1438b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1439b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        @Override
1440b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public int hashCode() {
1441b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            return Objects.hashCode(ident, uid, set, tag);
1442b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1443b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1444b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        @Override
1445b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public boolean equals(Object obj) {
1446b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (obj instanceof UidStatsKey) {
1447b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final UidStatsKey key = (UidStatsKey) obj;
1448b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return Objects.equal(ident, key.ident) && uid == key.uid && set == key.set
1449b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        && tag == key.tag;
1450b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
1451b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            return false;
1452b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1453b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1454b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        /** {@inheritDoc} */
1455b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public int compareTo(UidStatsKey another) {
1456b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            return Integer.compare(uid, another.uid);
1457b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1458b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
1459b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
14601b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
146139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Default external settings that read from {@link Settings.Secure}.
146239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
146339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
146439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private final ContentResolver mResolver;
146539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
146639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public DefaultNetworkStatsSettings(Context context) {
146739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mResolver = checkNotNull(context.getContentResolver());
146839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // TODO: adjust these timings for production builds
146939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
147039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
147139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private long getSecureLong(String name, long def) {
147239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return Settings.Secure.getLong(mResolver, name, def);
147339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
1474991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey        private boolean getSecureBoolean(String name, boolean def) {
1475991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey            final int defInt = def ? 1 : 0;
1476991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey            return Settings.Secure.getInt(mResolver, name, defInt) != 0;
1477991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey        }
147839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
147939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval() {
14808e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
148139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
148239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPersistThreshold() {
1483b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 2 * MB_IN_BYTES);
148439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
148539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkBucketDuration() {
148639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS);
148739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
148839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkMaxHistory() {
148939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_NETWORK_MAX_HISTORY, 90 * DAY_IN_MILLIS);
149039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
149139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidBucketDuration() {
149239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS);
149339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
149439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidMaxHistory() {
149539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_UID_MAX_HISTORY, 90 * DAY_IN_MILLIS);
149639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
1497d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        public long getTagMaxHistory() {
1498d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey            return getSecureLong(NETSTATS_TAG_MAX_HISTORY, 30 * DAY_IN_MILLIS);
1499d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        }
150039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge() {
150139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return DAY_IN_MILLIS;
150239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
150339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
150475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey}
1505