NetworkStatsService.java revision d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903f
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;
3839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
3939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
4061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
4161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL;
42d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY;
4339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION;
4439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY;
45367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
46367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.telephony.PhoneStateListener.LISTEN_NONE;
4761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.DAY_IN_MILLIS;
4861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.HOUR_IN_MILLIS;
4961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport static android.text.format.DateUtils.MINUTE_IN_MILLIS;
50367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport static android.text.format.DateUtils.SECOND_IN_MILLIS;
51d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport static com.android.internal.util.Preconditions.checkNotNull;
528e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeyimport static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
53b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
54b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
5575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
5675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.AlarmManager;
5775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.IAlarmManager;
5875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.app.PendingIntent;
5975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.BroadcastReceiver;
6039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkeyimport android.content.ContentResolver;
6175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Context;
6275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.Intent;
6375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.content.IntentFilter;
6461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.content.pm.ApplicationInfo;
65293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkeyimport android.content.pm.PackageManager;
66293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkeyimport android.content.pm.PackageManager.NameNotFoundException;
67d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.IConnectivityManager;
688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkeyimport android.net.INetworkManagementEventObserver;
6975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.INetworkStatsService;
701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkIdentity;
71d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkInfo;
72d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkeyimport android.net.NetworkState;
7375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStats;
74163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport android.net.NetworkStats.NonMonotonicException;
7575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.net.NetworkStatsHistory;
761b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport android.net.NetworkTemplate;
77a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkeyimport android.os.Binder;
78163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkeyimport android.os.DropBoxManager;
793f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport android.os.Environment;
8075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.Handler;
8175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.HandlerThread;
8275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.INetworkManagementService;
83b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.os.Message;
846248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkeyimport android.os.PowerManager;
8575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.RemoteException;
8675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.os.SystemClock;
8761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport android.provider.Settings;
88367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkeyimport android.telephony.PhoneStateListener;
8975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.telephony.TelephonyManager;
9007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport android.util.EventLog;
91b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkeyimport android.util.Log;
9275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.NtpTrustedTime;
9375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.Slog;
94b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport android.util.SparseIntArray;
9575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport android.util.TrustedTime;
9675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
973f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport com.android.internal.os.AtomicFile;
98b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport com.android.internal.util.Objects;
9907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkeyimport com.android.server.EventLogTags;
100cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkeyimport com.android.server.connectivity.Tethering;
101b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport com.google.android.collect.Lists;
10275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport com.google.android.collect.Maps;
1031b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkeyimport com.google.android.collect.Sets;
10475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1054e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport java.io.BufferedInputStream;
1064e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkeyimport java.io.BufferedOutputStream;
1073f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.DataInputStream;
1083f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.DataOutputStream;
1093f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.File;
11075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.FileDescriptor;
1113f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileNotFoundException;
1123f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.FileOutputStream;
1133f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.io.IOException;
11475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.io.PrintWriter;
1153f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport java.net.ProtocolException;
116b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.ArrayList;
117b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkeyimport java.util.Collections;
11875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeyimport java.util.HashMap;
11961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkeyimport java.util.HashSet;
120293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkeyimport java.util.Random;
12175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1223f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkeyimport libcore.io.IoUtils;
1233f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
12475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey/**
12575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * Collect and persist detailed network statistics, and provide this data to
12675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey * other system services.
12775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey */
12875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkeypublic class NetworkStatsService extends INetworkStatsService.Stub {
12921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    private static final String TAG = "NetworkStats";
130367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final boolean LOGD = false;
13139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static final boolean LOGV = false;
13275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1333f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    /** File header magic number: "ANET" */
1343f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static final int FILE_MAGIC = 0x414E4554;
1351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_NETWORK_INIT = 1;
1361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_UID_INIT = 1;
1371b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static final int VERSION_UID_WITH_IDENT = 2;
138d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    private static final int VERSION_UID_WITH_TAG = 3;
139b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private static final int VERSION_UID_WITH_SET = 4;
140b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
141367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final int MSG_PERFORM_POLL = 1;
142367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private static final int MSG_UPDATE_IFACES = 2;
143b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
144b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    /** Flags to control detail level of poll event. */
145905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static final int FLAG_PERSIST_NETWORK = 0x1;
146905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static final int FLAG_PERSIST_UID = 0x2;
147b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
1481f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey    private static final int FLAG_PERSIST_FORCE = 0x100;
1493f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
150905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /** Sample recent usage after each poll event. */
151905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static final boolean ENABLE_SAMPLE_AFTER_POLL = true;
152905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
153163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    private static final String TAG_NETSTATS_ERROR = "netstats_error";
154163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
15575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Context mContext;
15675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final INetworkManagementService mNetworkManager;
15775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final IAlarmManager mAlarmManager;
15875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final TrustedTime mTime;
159367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private final TelephonyManager mTeleManager;
16039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final NetworkStatsSettings mSettings;
16175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1626248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey    private final PowerManager.WakeLock mWakeLock;
1636248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey
164d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private IConnectivityManager mConnManager;
165163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    private DropBoxManager mDropBox;
166d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
1673f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    // @VisibleForTesting
1683f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    public static final String ACTION_NETWORK_STATS_POLL =
16975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            "com.android.server.action.NETWORK_STATS_POLL";
170497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey    public static final String ACTION_NETWORK_STATS_UPDATED =
171497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey            "com.android.server.action.NETWORK_STATS_UPDATED";
17275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
17375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private PendingIntent mPollIntent;
17475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
175d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    // TODO: trim empty history objects entirely
176d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
17775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private static final long KB_IN_BYTES = 1024;
17861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES;
17961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    private static final long GB_IN_BYTES = 1024 * MB_IN_BYTES;
18075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
18139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
18239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Settings that can be changed externally.
18339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
18439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    public interface NetworkStatsSettings {
18539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval();
18639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPersistThreshold();
18739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkBucketDuration();
18839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkMaxHistory();
18939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidBucketDuration();
19039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidMaxHistory();
191d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        public long getTagMaxHistory();
19239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge();
19339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
19475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
19575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Object mStatsLock = new Object();
19675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1971b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /** Set of currently active ifaces. */
1981b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
199905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /** Set of historical {@code dev} stats for known networks. */
200905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkDevStats = Maps.newHashMap();
201905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /** Set of historical {@code xtables} stats for known networks. */
202905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkXtStats = Maps.newHashMap();
203905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    /** Set of historical {@code xtables} stats for known UIDs. */
204b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap();
20539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
20639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /** Flag if {@link #mUidStats} have been loaded from disk. */
20739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private boolean mUidStatsLoaded = false;
20875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
209905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats mLastPollNetworkDevSnapshot;
210905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats mLastPollNetworkXtSnapshot;
2118e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPollUidSnapshot;
2128e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPollOperationsSnapshot;
21361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
214905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats mLastPersistNetworkDevSnapshot;
215905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats mLastPersistNetworkXtSnapshot;
2168e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private NetworkStats mLastPersistUidSnapshot;
21775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
218b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /** Current counter sets for each UID. */
219b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
220b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
221a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    /** Data layer operation counters for splicing into other structures. */
222a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    private NetworkStats mOperations = new NetworkStats(0L, 10);
223a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
22475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final HandlerThread mHandlerThread;
22575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private final Handler mHandler;
22675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
227905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private final AtomicFile mNetworkDevFile;
228905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private final AtomicFile mNetworkXtFile;
22939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private final AtomicFile mUidFile;
2303f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
23175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(
23275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
233104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey        this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
234104344e507610be42fb70c7deda3c422c543bfcbJeff Sharkey                getSystemDir(), new DefaultNetworkStatsSettings(context));
2353f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
2363f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
2373f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private static File getSystemDir() {
2383f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        return new File(Environment.getDataDirectory(), "system");
23975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
24075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
24175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public NetworkStatsService(Context context, INetworkManagementService networkManager,
24239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            IAlarmManager alarmManager, TrustedTime time, File systemDir,
24339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            NetworkStatsSettings settings) {
24475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext = checkNotNull(context, "missing Context");
24575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
24675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager");
24775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mTime = checkNotNull(time, "missing TrustedTime");
248367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
24939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
25075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
2516248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey        final PowerManager powerManager = (PowerManager) context.getSystemService(
2526248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                Context.POWER_SERVICE);
2536248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey        mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
2546248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey
25575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread = new HandlerThread(TAG);
25675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mHandlerThread.start();
257b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback);
2583f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
259905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mNetworkDevFile = new AtomicFile(new File(systemDir, "netstats.bin"));
260905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mNetworkXtFile = new AtomicFile(new File(systemDir, "netstats_xt.bin"));
26139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin"));
26275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
26375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
26421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    public void bindConnectivityManager(IConnectivityManager connManager) {
26521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
26621c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
26721c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
26875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    public void systemReady() {
2693f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        synchronized (mStatsLock) {
27039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // read historical network stats from disk, since policy service
27139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // might need them right away. we delay loading detailed UID stats
27239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // until actually needed.
273905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            readNetworkDevStatsLocked();
274905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            readNetworkXtStatsLocked();
2753f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
27675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
2773359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey        // bootstrap initial stats to prevent double-counting later
2783359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey        bootstrapStats();
2793359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey
28021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        // watch for network interfaces to be claimed
281961e30458319cfd50e1892ba7dd14a1d0ebe4cc7Jeff Sharkey        final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
282b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
28375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
284cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        // watch for tethering changes
285cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
286cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
287cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
28875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // listen for periodic polling events
28975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
29021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
29175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
292b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // listen for uid removal to clean stats
293b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
294b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
295b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
29675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // persist stats during clean shutdown
297b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
298b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
29975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
30075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
3018e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mNetworkManager.registerObserver(mAlertObserver);
30275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } catch (RemoteException e) {
303b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
30475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
305b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
306367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        // watch for networkType changes that aren't broadcast through
307367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        // CONNECTIVITY_ACTION_IMMEDIATE above.
308367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
309367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
3108e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        registerPollAlarmLocked();
3118e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        registerGlobalAlert();
3128e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
313163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        mDropBox = (DropBoxManager) mContext.getSystemService(Context.DROPBOX_SERVICE);
31475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
31575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3163f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    private void shutdownLocked() {
317b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.unregisterReceiver(mConnReceiver);
318367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mContext.unregisterReceiver(mTetherReceiver);
3193f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mPollReceiver);
320b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        mContext.unregisterReceiver(mRemovedReceiver);
3213f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        mContext.unregisterReceiver(mShutdownReceiver);
3223f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
323367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        mTeleManager.listen(mPhoneListener, LISTEN_NONE);
324367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
325905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        writeNetworkDevStatsLocked();
326905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        writeNetworkXtStatsLocked();
327af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey        if (mUidStatsLoaded) {
328af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey            writeUidStatsLocked();
329af8339374fbf1e2f57b0be918c7fc772f4250f13Jeff Sharkey        }
330905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mNetworkDevStats.clear();
331905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mNetworkXtStats.clear();
33239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
33339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStatsLoaded = false;
3343f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey    }
3353f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
33675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
33775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
33839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
33975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
3408e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void registerPollAlarmLocked() {
3418e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
3428e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            if (mPollIntent != null) {
3438e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mAlarmManager.remove(mPollIntent);
3448e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
34575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3468e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mPollIntent = PendingIntent.getBroadcast(
3478e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                    mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
34875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
3498e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long currentRealtime = SystemClock.elapsedRealtime();
3508e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
3518e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                    mSettings.getPollInterval(), mPollIntent);
3528e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
353b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
3548e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
3558e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
3568e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
3578e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
3588e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Register for a global alert that is delivered through
3598e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * {@link INetworkManagementEventObserver} once a threshold amount of data
3608e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * has been transferred.
3618e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
3628e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void registerGlobalAlert() {
3638e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
3648e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long alertBytes = mSettings.getPersistThreshold();
3658e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mNetworkManager.setGlobalAlert(alertBytes);
3668e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (IllegalStateException e) {
3678e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.w(TAG, "problem registering for global alert: " + e);
3688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
369b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
3708e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
37175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
37275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
37375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
37463d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
37521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
376905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return getHistoryForNetworkDev(template, fields);
377905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
378905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
379905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStatsHistory getHistoryForNetworkDev(NetworkTemplate template, int fields) {
380905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return getHistoryForNetwork(template, fields, mNetworkDevStats);
381905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
382905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
383905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStatsHistory getHistoryForNetworkXt(NetworkTemplate template, int fields) {
384905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return getHistoryForNetwork(template, fields, mNetworkXtStats);
385905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
386d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
387905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields,
388905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
389d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        synchronized (mStatsLock) {
390d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // combine all interfaces that match template
39161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            final NetworkStatsHistory combined = new NetworkStatsHistory(
39263d27a9233fed934340231f438493746084a681dJeff Sharkey                    mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields);
393905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            for (NetworkIdentitySet ident : source.keySet()) {
3941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (templateMatches(template, ident)) {
395905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                    final NetworkStatsHistory history = source.get(ident);
396d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    if (history != null) {
397d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                        combined.recordEntireHistory(history);
398d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    }
399d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                }
400d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
401d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return combined;
402d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
40375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
40475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
40575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
40663d27a9233fed934340231f438493746084a681dJeff Sharkey    public NetworkStatsHistory getHistoryForUid(
407b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            NetworkTemplate template, int uid, int set, int tag, int fields) {
40821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
409d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
41039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        synchronized (mStatsLock) {
41139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            ensureUidStatsLoadedLocked();
4121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
4131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            // combine all interfaces that match template
4141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            final NetworkStatsHistory combined = new NetworkStatsHistory(
41563d27a9233fed934340231f438493746084a681dJeff Sharkey                    mSettings.getUidBucketDuration(), estimateUidBuckets(), fields);
416b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            for (UidStatsKey key : mUidStats.keySet()) {
417b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final boolean setMatches = set == SET_ALL || key.set == set;
418b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                if (templateMatches(template, key.ident) && key.uid == uid && setMatches
419b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        && key.tag == tag) {
420b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory history = mUidStats.get(key);
421b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    combined.recordEntireHistory(history);
4221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
4231b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
424b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
4251b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            return combined;
42639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
42775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
42875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
429d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    @Override
4301b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) {
43121c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
432905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return getSummaryForNetworkDev(template, start, end);
433905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
434905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
435905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats getSummaryForNetworkDev(NetworkTemplate template, long start, long end) {
436905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return getSummaryForNetwork(template, start, end, mNetworkDevStats);
437905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
438905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
439905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats getSummaryForNetworkXt(NetworkTemplate template, long start, long end) {
440905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return getSummaryForNetwork(template, start, end, mNetworkXtStats);
441905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
44221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
443905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end,
444905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
44521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        synchronized (mStatsLock) {
446434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            // use system clock to be externally consistent
447434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            final long now = System.currentTimeMillis();
448434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
449d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStats stats = new NetworkStats(end - start, 1);
450d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStats.Entry entry = new NetworkStats.Entry();
451434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            NetworkStatsHistory.Entry historyEntry = null;
45221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
45321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            // combine total from all interfaces that match template
454905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            for (NetworkIdentitySet ident : source.keySet()) {
4551b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (templateMatches(template, ident)) {
456905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                    final NetworkStatsHistory history = source.get(ident);
457434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                    historyEntry = history.getValues(start, end, now, historyEntry);
458d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
459d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    entry.iface = IFACE_ALL;
460d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    entry.uid = UID_ALL;
461d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    entry.tag = TAG_NONE;
462434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                    entry.rxBytes = historyEntry.rxBytes;
46307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                    entry.rxPackets = historyEntry.rxPackets;
464434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey                    entry.txBytes = historyEntry.txBytes;
46507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                    entry.txPackets = historyEntry.txPackets;
466d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
467d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                    stats.combineValues(entry);
46821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey                }
46921c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey            }
47021c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
4714a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            return stats;
47221c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        }
47321c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    }
47421c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey
47521c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey    @Override
476d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    public NetworkStats getSummaryForAllUid(
477d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey            NetworkTemplate template, long start, long end, boolean includeTags) {
47821c9c45e5caf62b935354b74392fb40c4bf18529Jeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
479d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
48019862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        synchronized (mStatsLock) {
48139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            ensureUidStatsLoadedLocked();
48239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
483434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            // use system clock to be externally consistent
484434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            final long now = System.currentTimeMillis();
485434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey
4861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            final NetworkStats stats = new NetworkStats(end - start, 24);
487d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkStats.Entry entry = new NetworkStats.Entry();
488434962e44ea93b1c4d216c55f636a435bf54aa54Jeff Sharkey            NetworkStatsHistory.Entry historyEntry = null;
4891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
490b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            for (UidStatsKey key : mUidStats.keySet()) {
491b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                if (templateMatches(template, key.ident)) {
492b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    // always include summary under TAG_NONE, and include
493b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    // other tags when requested.
494b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    if (key.tag == TAG_NONE || includeTags) {
495b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        final NetworkStatsHistory history = mUidStats.get(key);
496b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        historyEntry = history.getValues(start, end, now, historyEntry);
497b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
498b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.iface = IFACE_ALL;
499b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.uid = key.uid;
500b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.set = key.set;
501b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.tag = key.tag;
502b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.rxBytes = historyEntry.rxBytes;
503b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.rxPackets = historyEntry.rxPackets;
504b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.txBytes = historyEntry.txBytes;
505b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.txPackets = historyEntry.txPackets;
506b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        entry.operations = historyEntry.operations;
507b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
508b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
509b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                                || entry.txPackets > 0 || entry.operations > 0) {
510b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            stats.combineValues(entry);
511d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                        }
5121b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    }
5131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
51419862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey            }
5151b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
5164a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            return stats;
51719862bf5d058b6ab0c2979e7a5e0297dae6b170bJeff Sharkey        }
518d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
519d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
520350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    @Override
521a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
522a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (Binder.getCallingUid() != uid) {
523a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
524a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
525a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
526a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // TODO: switch to data layer stats once kernel exports
527a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // for now, read network layer stats and flatten across all ifaces
528a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
529a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        final NetworkStats dataLayer = new NetworkStats(
530a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey                networkLayer.getElapsedRealtime(), networkLayer.size());
531a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
532a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        NetworkStats.Entry entry = null;
533a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        for (int i = 0; i < networkLayer.size(); i++) {
534a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            entry = networkLayer.getValues(i, entry);
535a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            entry.iface = IFACE_ALL;
536a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            dataLayer.combineValues(entry);
537a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
538a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
539a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        // splice in operation counts
540a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        dataLayer.spliceOperationsFrom(mOperations);
541a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        return dataLayer;
542a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
543a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
544a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Override
545a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    public void incrementOperationCount(int uid, int tag, int operationCount) {
546a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        if (Binder.getCallingUid() != uid) {
547a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
548a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
549a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
550b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        if (operationCount < 0) {
551b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            throw new IllegalArgumentException("operation count can only be incremented");
552b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
553b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        if (tag == TAG_NONE) {
554b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            throw new IllegalArgumentException("operation count must have specific tag");
555b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
556b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
557a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        synchronized (mStatsLock) {
558b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
559b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mOperations.combineValues(IFACE_ALL, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
560b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mOperations.combineValues(IFACE_ALL, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
561b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
562b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
563b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
564b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    @Override
565b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    public void setUidForeground(int uid, boolean uidForeground) {
566b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
567b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
568b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        synchronized (mStatsLock) {
569b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
570b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
571b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (oldSet != set) {
572b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                mActiveUidCounterSet.put(uid, set);
573b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                setKernelCounterSet(uid, set);
574b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
575a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey        }
576a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    }
577a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey
578a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey    @Override
579350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    public void forceUpdate() {
580350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
5811f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        performPoll(FLAG_PERSIST_ALL);
582350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey    }
583350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
58475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
585d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Receiver that watches for {@link IConnectivityManager} to claim network
58675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
58775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * with mobile interfaces.
58875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
589b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
59075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
59175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
592d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
593d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
594367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            updateIfaces();
59575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
59675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
59775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
598cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    /**
599cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     * Receiver that watches for {@link Tethering} to claim interface pairs.
600cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     */
601cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
602cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        @Override
603cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        public void onReceive(Context context, Intent intent) {
604cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            // on background handler thread, and verified CONNECTIVITY_INTERNAL
605cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            // permission above.
6061f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performPoll(FLAG_PERSIST_NETWORK);
607cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
608cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    };
609cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
61075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
61175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
61275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
613d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // on background handler thread, and verified UPDATE_DEVICE_STATS
614d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            // permission above.
6151f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performPoll(FLAG_PERSIST_ALL);
6168e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6178e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            // verify that we're watching global alert
6188e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            registerGlobalAlert();
61975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
62075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
62175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
622b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
623b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        @Override
624b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        public void onReceive(Context context, Intent intent) {
625b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // on background handler thread, and UID_REMOVED is protected
626b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // broadcast.
627b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            final int uid = intent.getIntExtra(EXTRA_UID, 0);
628b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            synchronized (mStatsLock) {
6296248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                mWakeLock.acquire();
6306248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                try {
6316248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                    removeUidLocked(uid);
6326248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                } finally {
6336248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                    mWakeLock.release();
6346248926e199dca9bde3c76c5f82c486c293cdcddJeff Sharkey                }
635b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
636b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
637b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    };
638b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
63975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
64075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        @Override
64175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        public void onReceive(Context context, Intent intent) {
642b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            // SHUTDOWN is protected broadcast.
64375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            synchronized (mStatsLock) {
6443f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                shutdownLocked();
64575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
64675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
64775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    };
64875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
649d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    /**
6508e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Observer that watches for {@link INetworkManagementService} alerts.
6518e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
6528e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() {
6538e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        @Override
6548e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        public void limitReached(String limitName, String iface) {
6558e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            // only someone like NMS should be calling us
6568e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
6578e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6588e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
6598e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // kick off background poll to collect network stats; UID stats
6608e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // are handled during normal polling interval.
6611f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                final int flags = FLAG_PERSIST_NETWORK;
662b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
6638e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
6648e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                // re-arm global alert for next update
6658e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                registerGlobalAlert();
6668e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
6678e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
6688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    };
6698e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
670367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
671367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
672367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
673367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    /**
674367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     * Receiver that watches for {@link TelephonyManager} changes, such as
675367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     * transitioning between network types.
676367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey     */
677367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private PhoneStateListener mPhoneListener = new PhoneStateListener() {
678367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        @Override
679367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        public void onDataConnectionStateChanged(int state, int networkType) {
680367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean stateChanged = state != mLastPhoneState;
681367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
682367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
683367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            if (networkTypeChanged && !stateChanged) {
684367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // networkType changed without a state change, which means we
685367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // need to roll our own update. delay long enough for
686367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // ConnectivityManager to process.
687367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // TODO: add direct event to ConnectivityService instead of
688367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                // relying on this delay.
689367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
690367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mHandler.sendMessageDelayed(
691367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                        mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
692367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
693367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
694367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mLastPhoneState = state;
695367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mLastPhoneNetworkType = networkType;
696367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        }
697367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    };
698367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
699367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    private void updateIfaces() {
700367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        synchronized (mStatsLock) {
701367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            mWakeLock.acquire();
702367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            try {
703367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                updateIfacesLocked();
704367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            } finally {
705367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                mWakeLock.release();
706367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey            }
707367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey        }
708367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey    }
709367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
7108e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
711d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * Inspect all current {@link NetworkState} to derive mapping from {@code
712d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
713d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     * are active on a single {@code iface}, they are combined under a single
7141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * {@link NetworkIdentitySet}.
715d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey     */
716d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    private void updateIfacesLocked() {
71739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
718d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
719d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // take one last stats snapshot before updating iface mapping. this
720d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // isn't perfect, since the kernel may already be counting traffic from
721d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // the updated network.
722b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
7231f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // poll, but only persist network stats to keep codepath fast. UID stats
7241f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // will be persisted during next alarm poll event.
7251f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        performPollLocked(FLAG_PERSIST_NETWORK);
726d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
727d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        final NetworkState[] states;
728d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        try {
729d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            states = mConnManager.getAllNetworkState();
730d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        } catch (RemoteException e) {
731b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
732d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            return;
733d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
734d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
735d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // rebuild active interfaces based on connected networks
7361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        mActiveIfaces.clear();
737d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
738d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        for (NetworkState state : states) {
739d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (state.networkInfo.isConnected()) {
740d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                // collect networks under their parent interfaces
741d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                final String iface = state.linkProperties.getInterfaceName();
7421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
7431b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                NetworkIdentitySet ident = mActiveIfaces.get(iface);
7441b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                if (ident == null) {
7451b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    ident = new NetworkIdentitySet();
7461b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    mActiveIfaces.put(iface, ident);
7471b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
7481b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
749d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey                ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
750d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            }
751d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
752d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey    }
753d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
75439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
7558e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
7568e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     * so we have baseline values without double-counting.
7578e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey     */
7588e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    private void bootstrapStats() {
7598e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        try {
7608e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
761905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            mLastPollNetworkDevSnapshot = mNetworkManager.getNetworkStatsSummary();
762905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            mLastPollNetworkXtSnapshot = computeNetworkXtSnapshotFromUid(mLastPollUidSnapshot);
7638e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mLastPollOperationsSnapshot = new NetworkStats(0L, 0);
7648e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (IllegalStateException e) {
7658e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.w(TAG, "problem reading network stats: " + e);
7668e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        } catch (RemoteException e) {
767b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
7688e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
7698e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
7708e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
771b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private void performPoll(int flags) {
7728e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        synchronized (mStatsLock) {
7738e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            mWakeLock.acquire();
7748e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            try {
775b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                performPollLocked(flags);
7768e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            } finally {
7778e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                mWakeLock.release();
7788e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            }
7798e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
7808e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    }
7818e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
7828e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey    /**
78339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Periodic poll operation, reading current statistics and recording into
78439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * {@link NetworkStatsHistory}.
78539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
786b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey    private void performPollLocked(int flags) {
787b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
7888e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        final long startRealtime = SystemClock.elapsedRealtime();
78975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
790b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
791b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
7921f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
793b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey
79475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // try refreshing time source when stale
79539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
79675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            mTime.forceRefresh();
79775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
79875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
79975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        // TODO: consider marking "untrusted" times in historical stats
80075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
80175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                : System.currentTimeMillis();
802b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        final long threshold = mSettings.getPersistThreshold();
80375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
804905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats uidSnapshot;
805905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats networkXtSnapshot;
806905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats networkDevSnapshot;
80775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        try {
808905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // collect any tethering stats
809d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            final NetworkStats tetherSnapshot = getNetworkStatsTethering();
8101f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
811905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // record uid stats, folding in tethering stats
812905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
813905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            uidSnapshot.combineAllValues(tetherSnapshot);
8141f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            performUidPollLocked(uidSnapshot, currentTime);
8151f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
816905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // record dev network stats
817905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            networkDevSnapshot = mNetworkManager.getNetworkStatsSummary();
818905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            performNetworkDevPollLocked(networkDevSnapshot, currentTime);
819905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
820905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // record xt network stats
821905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            networkXtSnapshot = computeNetworkXtSnapshotFromUid(uidSnapshot);
822905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            performNetworkXtPollLocked(networkXtSnapshot, currentTime);
823367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey
824b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        } catch (IllegalStateException e) {
825b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
826905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            return;
827b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey        } catch (RemoteException e) {
828b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            // ignored; service lives in system_server
829905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            return;
830905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
831905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
832905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        // persist when enough network data has occurred
833905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final long persistNetworkDevDelta = computeStatsDelta(
8343359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPersistNetworkDevSnapshot, networkDevSnapshot, true, "devp").getTotalBytes();
835905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final long persistNetworkXtDelta = computeStatsDelta(
8363359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPersistNetworkXtSnapshot, networkXtSnapshot, true, "xtp").getTotalBytes();
837905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final boolean networkOverThreshold = persistNetworkDevDelta > threshold
838905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                || persistNetworkXtDelta > threshold;
839905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (persistForce || (persistNetwork && networkOverThreshold)) {
840905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            writeNetworkDevStatsLocked();
841905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            writeNetworkXtStatsLocked();
842905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            mLastPersistNetworkDevSnapshot = networkDevSnapshot;
843905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            mLastPersistNetworkXtSnapshot = networkXtSnapshot;
844905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
845905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
846905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        // persist when enough uid data has occurred
847163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        final long persistUidDelta = computeStatsDelta(
8483359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPersistUidSnapshot, uidSnapshot, true, "uidp").getTotalBytes();
849905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (persistForce || (persistUid && persistUidDelta > threshold)) {
850905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            writeUidStatsLocked();
851905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            mLastPersistUidSnapshot = uidSnapshot;
85261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
853497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey
8548e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        if (LOGV) {
8558e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            final long duration = SystemClock.elapsedRealtime() - startRealtime;
8568e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            Slog.v(TAG, "performPollLocked() took " + duration + "ms");
8578e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey        }
8588e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey
859905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (ENABLE_SAMPLE_AFTER_POLL) {
860905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // sample stats after each full poll
861905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            performSample();
862905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
86307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
864497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        // finally, dispatch updated event to any listeners
865497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
866497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
867497e4437af386930dff3bd55296d128bd4520959Jeff Sharkey        mContext.sendBroadcast(updatedIntent, READ_NETWORK_USAGE_HISTORY);
86861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
86961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
87061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
871905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Update {@link #mNetworkDevStats} historical usage.
87261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
873905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void performNetworkDevPollLocked(NetworkStats networkDevSnapshot, long currentTime) {
8741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        final HashSet<String> unknownIface = Sets.newHashSet();
875d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
876905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats delta = computeStatsDelta(
8773359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPollNetworkDevSnapshot, networkDevSnapshot, false, "dev");
878d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        final long timeStart = currentTime - delta.getElapsedRealtime();
879d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey
880d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        NetworkStats.Entry entry = null;
881d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        for (int i = 0; i < delta.size(); i++) {
882d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            entry = delta.getValues(i, entry);
883d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
884d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey            if (ident == null) {
885d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey                unknownIface.add(entry.iface);
88675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey                continue;
88775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey            }
88875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
889905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            final NetworkStatsHistory history = findOrCreateNetworkDevStatsLocked(ident);
890a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            history.recordData(timeStart, currentTime, entry);
891d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        }
892d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
893905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mLastPollNetworkDevSnapshot = networkDevSnapshot;
89475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
895d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        if (LOGD && unknownIface.size() > 0) {
896905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            Slog.w(TAG, "unknown dev interfaces " + unknownIface + ", ignoring those stats");
897d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        }
89861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
899d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey
90061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
901905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Update {@link #mNetworkXtStats} historical usage.
90261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
903905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void performNetworkXtPollLocked(NetworkStats networkXtSnapshot, long currentTime) {
904905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final HashSet<String> unknownIface = Sets.newHashSet();
90539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
906905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats delta = computeStatsDelta(
9073359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPollNetworkXtSnapshot, networkXtSnapshot, false, "xt");
908d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        final long timeStart = currentTime - delta.getElapsedRealtime();
9091b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
910d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        NetworkStats.Entry entry = null;
911d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        for (int i = 0; i < delta.size(); i++) {
912d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            entry = delta.getValues(i, entry);
913d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
9141b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            if (ident == null) {
915905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                unknownIface.add(entry.iface);
9161b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                continue;
91739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
9181b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
919905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            final NetworkStatsHistory history = findOrCreateNetworkXtStatsLocked(ident);
920a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            history.recordData(timeStart, currentTime, entry);
92161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
9221b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
923905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mLastPollNetworkXtSnapshot = networkXtSnapshot;
924905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
925905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (LOGD && unknownIface.size() > 0) {
926905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            Slog.w(TAG, "unknown xt interfaces " + unknownIface + ", ignoring those stats");
927905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        }
92861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
92975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
930b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    /**
931905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey     * Update {@link #mUidStats} historical usage.
932cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey     */
933905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
934cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        ensureUidStatsLoadedLocked();
935cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
936163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        final NetworkStats delta = computeStatsDelta(
9373359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPollUidSnapshot, uidSnapshot, false, "uid");
938905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStats operationsDelta = computeStatsDelta(
9393359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                mLastPollOperationsSnapshot, mOperations, false, "uidop");
940cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        final long timeStart = currentTime - delta.getElapsedRealtime();
941cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
942cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        NetworkStats.Entry entry = null;
943905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        NetworkStats.Entry operationsEntry = null;
944cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        for (int i = 0; i < delta.size(); i++) {
945cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            entry = delta.getValues(i, entry);
946cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface);
947cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            if (ident == null) {
948cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0
949cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                        || entry.txPackets > 0) {
950905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                    Log.w(TAG, "dropping UID delta from unknown iface: " + entry);
951cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                }
952cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey                continue;
953cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            }
954cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
955905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            // splice in operation counts since last poll
956905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.set, entry.tag);
957905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            if (j != -1) {
958905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                operationsEntry = operationsDelta.getValues(j, operationsEntry);
959905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                entry.operations = operationsEntry.operations;
960905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            }
961905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
962cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            final NetworkStatsHistory history = findOrCreateUidStatsLocked(
963905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                    ident, entry.uid, entry.set, entry.tag);
964cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey            history.recordData(timeStart, currentTime, entry);
965cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey        }
966cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
967905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mLastPollUidSnapshot = uidSnapshot;
9684abb1b8ef64dc4cd71966b59dc5d72a15055bf13Jeff Sharkey        mLastPollOperationsSnapshot = mOperations.clone();
969cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    }
970cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey
971cdd02c5d76d3dd4e21b5bb922d7fcfb86efec85fJeff Sharkey    /**
97207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     * Sample recent statistics summary into {@link EventLog}.
97307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey     */
97407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    private void performSample() {
9751f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long largestBucketSize = Math.max(
9761f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                mSettings.getNetworkBucketDuration(), mSettings.getUidBucketDuration());
9771f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
9781f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // take sample as atomic buckets
9791f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long now = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis();
9801f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long end = now - (now % largestBucketSize) + largestBucketSize;
9811f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        final long start = end - largestBucketSize;
98207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
983905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
984905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
98507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        NetworkTemplate template = null;
986905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        NetworkStats.Entry devTotal = null;
987905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        NetworkStats.Entry xtTotal = null;
98807b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        NetworkStats.Entry uidTotal = null;
98907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
99007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        // collect mobile sample
99107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
992905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
993905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
99407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
995905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        EventLogTags.writeNetstatsMobileSample(
996905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
997905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
998905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
999905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                trustedTime);
100007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
100107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        // collect wifi sample
100207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        template = buildTemplateWifi();
1003905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal);
1004905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal);
100507b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal);
1006905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        EventLogTags.writeNetstatsWifiSample(
1007905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1008905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1009905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1010905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                trustedTime);
101107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
101207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
101307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    /**
1014b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey     * Clean up {@link #mUidStats} after UID is removed.
1015b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey     */
1016b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    private void removeUidLocked(int uid) {
1017b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        ensureUidStatsLoadedLocked();
1018b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
1019163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        // perform one last poll before removing
1020163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        performPollLocked(FLAG_PERSIST_ALL);
1021163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
1022b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final ArrayList<UidStatsKey> knownKeys = Lists.newArrayList();
1023b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        knownKeys.addAll(mUidStats.keySet());
1024b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1025b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // migrate all UID stats into special "removed" bucket
1026b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        for (UidStatsKey key : knownKeys) {
1027b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (key.uid == uid) {
1028b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                // only migrate combined TAG_NONE history
1029b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                if (key.tag == TAG_NONE) {
1030b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory uidHistory = mUidStats.get(key);
1031b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked(
1032b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE);
1033b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    removedHistory.recordEntireHistory(uidHistory);
1034d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                }
1035b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                mUidStats.remove(key);
1036b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            }
1037b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
1038b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
1039163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        // clear UID from current stats snapshot
1040163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        mLastPollUidSnapshot = mLastPollUidSnapshot.withoutUid(uid);
1041163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey        mLastPollNetworkXtSnapshot = computeNetworkXtSnapshotFromUid(mLastPollUidSnapshot);
1042163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
1043b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        // clear kernel stats associated with UID
1044b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        resetKernelUidStats(uid);
1045b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
1046b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        // since this was radical rewrite, push to disk
1047b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        writeUidStatsLocked();
1048b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey    }
1049b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
1050905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStatsHistory findOrCreateNetworkXtStatsLocked(NetworkIdentitySet ident) {
1051905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return findOrCreateNetworkStatsLocked(ident, mNetworkXtStats);
1052905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
1053905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
1054905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStatsHistory findOrCreateNetworkDevStatsLocked(NetworkIdentitySet ident) {
1055905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return findOrCreateNetworkStatsLocked(ident, mNetworkDevStats);
1056905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
1057905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
1058905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private NetworkStatsHistory findOrCreateNetworkStatsLocked(
1059905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            NetworkIdentitySet ident, HashMap<NetworkIdentitySet, NetworkStatsHistory> source) {
1060905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        final NetworkStatsHistory existing = source.get(ident);
106139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
106239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // update when no existing, or when bucket duration changed
1063d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        final long bucketDuration = mSettings.getNetworkBucketDuration();
106439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        NetworkStatsHistory updated = null;
106539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (existing == null) {
10664a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration, 10);
1067d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        } else if (existing.getBucketDuration() != bucketDuration) {
10684a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(
10694a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey                    bucketDuration, estimateResizeBuckets(existing, bucketDuration));
107039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated.recordEntireHistory(existing);
107139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
107239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
107339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (updated != null) {
1074905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            source.put(ident, updated);
107539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return updated;
107639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else {
107739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return existing;
107875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
107975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
108075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1081d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey    private NetworkStatsHistory findOrCreateUidStatsLocked(
1082b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            NetworkIdentitySet ident, int uid, int set, int tag) {
1083b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        ensureUidStatsLoadedLocked();
1084b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
1085b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final UidStatsKey key = new UidStatsKey(ident, uid, set, tag);
1086b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final NetworkStatsHistory existing = mUidStats.get(key);
108739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
108839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // update when no existing, or when bucket duration changed
1089d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        final long bucketDuration = mSettings.getUidBucketDuration();
109039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        NetworkStatsHistory updated = null;
109139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (existing == null) {
10924a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(bucketDuration, 10);
1093d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        } else if (existing.getBucketDuration() != bucketDuration) {
10944a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey            updated = new NetworkStatsHistory(
10954a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey                    bucketDuration, estimateResizeBuckets(existing, bucketDuration));
109639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            updated.recordEntireHistory(existing);
109739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
109839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
109939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (updated != null) {
1100b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            mUidStats.put(key, updated);
110139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return updated;
110239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } else {
110339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return existing;
110475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
110575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
110675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1107905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void readNetworkDevStatsLocked() {
1108905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (LOGV) Slog.v(TAG, "readNetworkDevStatsLocked()");
1109905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        readNetworkStats(mNetworkDevFile, mNetworkDevStats);
1110905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
1111905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
1112905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void readNetworkXtStatsLocked() {
1113905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (LOGV) Slog.v(TAG, "readNetworkXtStatsLocked()");
1114905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        readNetworkStats(mNetworkXtFile, mNetworkXtStats);
1115905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
11163f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
1117905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static void readNetworkStats(
1118905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            AtomicFile inputFile, HashMap<NetworkIdentitySet, NetworkStatsHistory> output) {
11193f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        // clear any existing stats and read from disk
1120905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        output.clear();
11213f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11224e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        DataInputStream in = null;
11233f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        try {
1124905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            in = new DataInputStream(new BufferedInputStream(inputFile.openRead()));
11253f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11263f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            // verify file magic header intact
11273f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final int magic = in.readInt();
11283f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (magic != FILE_MAGIC) {
11293f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                throw new ProtocolException("unexpected magic: " + magic);
11303f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
11313f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
11323f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            final int version = in.readInt();
11333f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            switch (version) {
11341b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case VERSION_NETWORK_INIT: {
11351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // network := size *(NetworkIdentitySet NetworkStatsHistory)
11363f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    final int size = in.readInt();
11373f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    for (int i = 0; i < size; i++) {
11381b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        final NetworkIdentitySet ident = new NetworkIdentitySet(in);
11393f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                        final NetworkStatsHistory history = new NetworkStatsHistory(in);
1140905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                        output.put(ident, history);
11413f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    }
11423f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    break;
11433f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
11443f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                default: {
11453f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                    throw new ProtocolException("unexpected version: " + version);
11463f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                }
11473f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
11483f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (FileNotFoundException e) {
11493f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            // missing stats is okay, probably first boot
11503f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (IOException e) {
1151b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
11523f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } finally {
11534e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            IoUtils.closeQuietly(in);
11543f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
115575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
115675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
115739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void ensureUidStatsLoadedLocked() {
115839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (!mUidStatsLoaded) {
115939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            readUidStatsLocked();
116039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidStatsLoaded = true;
116139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
116239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
116339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
116439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void readUidStatsLocked() {
116539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "readUidStatsLocked()");
116639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
116739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // clear any existing stats and read from disk
116839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
116939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
11704e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey        DataInputStream in = null;
117139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        try {
11724e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            in = new DataInputStream(new BufferedInputStream(mUidFile.openRead()));
117339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
117439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // verify file magic header intact
117539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int magic = in.readInt();
117639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (magic != FILE_MAGIC) {
117739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                throw new ProtocolException("unexpected magic: " + magic);
117839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
117939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
118039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            final int version = in.readInt();
118139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            switch (version) {
11821b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case VERSION_UID_INIT: {
118339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    // uid := size *(UID NetworkStatsHistory)
118439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
11851b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // drop this data version, since we don't have a good
11861b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // mapping into NetworkIdentitySet.
11871b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    break;
11881b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
11891b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                case VERSION_UID_WITH_IDENT: {
11901b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory))
1191d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
1192d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    // drop this data version, since this version only existed
1193d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    // for a short time.
1194d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                    break;
1195d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                }
1196b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                case VERSION_UID_WITH_TAG:
1197b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                case VERSION_UID_WITH_SET: {
1198b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory))
1199b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final int identSize = in.readInt();
1200b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    for (int i = 0; i < identSize; i++) {
12011b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        final NetworkIdentitySet ident = new NetworkIdentitySet(in);
12021b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1203b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        final int size = in.readInt();
1204b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        for (int j = 0; j < size; j++) {
12051b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                            final int uid = in.readInt();
1206b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt()
1207b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                                    : SET_DEFAULT;
1208d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey                            final int tag = in.readInt();
1209d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey
1210b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            final UidStatsKey key = new UidStatsKey(ident, uid, set, tag);
12111b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                            final NetworkStatsHistory history = new NetworkStatsHistory(in);
1212b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                            mUidStats.put(key, history);
12131b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                        }
121439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    }
121539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    break;
121639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                }
121739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                default: {
121839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                    throw new ProtocolException("unexpected version: " + version);
121939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                }
122039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
122139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (FileNotFoundException e) {
122239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // missing stats is okay, probably first boot
122339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (IOException e) {
1224b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem reading uid stats", e);
122539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } finally {
12264e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            IoUtils.closeQuietly(in);
122739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
122839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
122939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1230905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void writeNetworkDevStatsLocked() {
1231905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (LOGV) Slog.v(TAG, "writeNetworkDevStatsLocked()");
1232905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        writeNetworkStats(mNetworkDevStats, mNetworkDevFile);
1233905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
1234905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
1235905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void writeNetworkXtStatsLocked() {
1236905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        if (LOGV) Slog.v(TAG, "writeNetworkXtStatsLocked()");
1237905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        writeNetworkStats(mNetworkXtStats, mNetworkXtFile);
1238905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
12393f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
1240905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private void writeNetworkStats(
1241905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            HashMap<NetworkIdentitySet, NetworkStatsHistory> input, AtomicFile outputFile) {
1242d2a458750e5a3d490af09cecb5c28370baf0a913Jeff Sharkey        // TODO: consider duplicating stats and releasing lock while writing
12433f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
12441f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // trim any history beyond max
12451f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        if (mTime.hasCache()) {
12461f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long currentTime = mTime.currentTimeMillis();
12471f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long maxHistory = mSettings.getNetworkMaxHistory();
1248905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            for (NetworkStatsHistory history : input.values()) {
12491f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                history.removeBucketsBefore(currentTime - maxHistory);
12501f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            }
12511f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        }
12521f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
12533f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        FileOutputStream fos = null;
12543f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        try {
1255905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            fos = outputFile.startWrite();
12564e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
12573f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
12583f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            out.writeInt(FILE_MAGIC);
12591b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            out.writeInt(VERSION_NETWORK_INIT);
12603f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
1261905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            out.writeInt(input.size());
1262905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            for (NetworkIdentitySet ident : input.keySet()) {
1263905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                final NetworkStatsHistory history = input.get(ident);
12643f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                ident.writeToStream(out);
12653f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                history.writeToStream(out);
12663f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
12673f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
12684e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            out.flush();
1269905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            outputFile.finishWrite(fos);
127039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        } catch (IOException e) {
1271b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem writing stats", e);
127239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            if (fos != null) {
1273905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                outputFile.failWrite(fos);
127439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
127539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
127639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
127739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
127839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private void writeUidStatsLocked() {
127939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        if (LOGV) Slog.v(TAG, "writeUidStatsLocked()");
128039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1281b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        if (!mUidStatsLoaded) {
1282b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            Slog.w(TAG, "asked to write UID stats when not loaded; skipping");
1283b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey            return;
1284b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey        }
1285b09540f33a6cabe50edec0ef32d0b1d0b0d96fffJeff Sharkey
128639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        // TODO: consider duplicating stats and releasing lock while writing
128739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
12881f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        // trim any history beyond max
12891f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        if (mTime.hasCache()) {
12901f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long currentTime = mTime.currentTimeMillis();
12911f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long maxUidHistory = mSettings.getUidMaxHistory();
12921f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            final long maxTagHistory = mSettings.getTagMaxHistory();
12931f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            for (UidStatsKey key : mUidStats.keySet()) {
12941f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                final NetworkStatsHistory history = mUidStats.get(key);
12951f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
12961f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                // detailed tags are trimmed sooner than summary in TAG_NONE
12971f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                if (key.tag == TAG_NONE) {
12981f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                    history.removeBucketsBefore(currentTime - maxUidHistory);
12991f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                } else {
13001f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                    history.removeBucketsBefore(currentTime - maxTagHistory);
13011f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                }
13021f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey            }
13031f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey        }
13041f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey
1305b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        // build UidStatsKey lists grouped by ident
1306b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        final HashMap<NetworkIdentitySet, ArrayList<UidStatsKey>> keysByIdent = Maps.newHashMap();
1307b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        for (UidStatsKey key : mUidStats.keySet()) {
1308b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            ArrayList<UidStatsKey> keys = keysByIdent.get(key.ident);
1309b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (keys == null) {
1310b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                keys = Lists.newArrayList();
1311b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                keysByIdent.put(key.ident, keys);
1312b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
1313b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            keys.add(key);
1314b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1315b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
131639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        FileOutputStream fos = null;
131739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        try {
131839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            fos = mUidFile.startWrite();
13194e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos));
132039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
132139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            out.writeInt(FILE_MAGIC);
1322b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            out.writeInt(VERSION_UID_WITH_SET);
132339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1324b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            out.writeInt(keysByIdent.size());
1325b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            for (NetworkIdentitySet ident : keysByIdent.keySet()) {
1326b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final ArrayList<UidStatsKey> keys = keysByIdent.get(ident);
13271b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                ident.writeToStream(out);
132839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
1329b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                out.writeInt(keys.size());
1330b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                for (UidStatsKey key : keys) {
1331b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory history = mUidStats.get(key);
1332b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    out.writeInt(key.uid);
1333b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    out.writeInt(key.set);
1334b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    out.writeInt(key.tag);
13351b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                    history.writeToStream(out);
13361b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                }
133739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            }
133839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
13394e814c348ce205fcc1a273427f95ef1d100ed60cJeff Sharkey            out.flush();
134039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mUidFile.finishWrite(fos);
13413f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        } catch (IOException e) {
1342b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            Log.wtf(TAG, "problem writing stats", e);
13433f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (fos != null) {
134439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                mUidFile.failWrite(fos);
13453f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
13463f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey        }
134775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
134875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
134975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    @Override
135075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
135175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        mContext.enforceCallingOrSelfPermission(DUMP, TAG);
135275279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
135361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        final HashSet<String> argSet = new HashSet<String>();
135461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        for (String arg : args) {
135561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            argSet.add(arg);
135661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
135761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
1358350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey        final boolean fullHistory = argSet.contains("full");
1359350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey
136061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        synchronized (mStatsLock) {
136161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            // TODO: remove this testing code, since it corrupts stats
136261ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (argSet.contains("generate")) {
1363293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                generateRandomLocked(args);
136461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.println("Generated stub stats");
136561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                return;
136661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
136761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
13683f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            if (argSet.contains("poll")) {
13691f0b13b9d64085dd8342ba942f39b6063b6d534dJeff Sharkey                performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
13703f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                pw.println("Forced poll");
13713f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey                return;
13723f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey            }
13733f3913550c10792edb8aecf66cc83c3db5c8b311Jeff Sharkey
137461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            pw.println("Active interfaces:");
13751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            for (String iface : mActiveIfaces.keySet()) {
13761b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                final NetworkIdentitySet ident = mActiveIfaces.get(iface);
137761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print("  iface="); pw.print(iface);
137861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print(" ident="); pw.println(ident.toString());
137961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
138061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
1381905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            pw.println("Known historical dev stats:");
1382905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            for (NetworkIdentitySet ident : mNetworkDevStats.keySet()) {
1383905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                final NetworkStatsHistory history = mNetworkDevStats.get(ident);
1384905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                pw.print("  ident="); pw.println(ident.toString());
1385905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                history.dump("  ", pw, fullHistory);
1386905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            }
1387905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
1388905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            pw.println("Known historical xt stats:");
1389905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey            for (NetworkIdentitySet ident : mNetworkXtStats.keySet()) {
1390905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey                final NetworkStatsHistory history = mNetworkXtStats.get(ident);
139161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                pw.print("  ident="); pw.println(ident.toString());
1392350083e36b9db6062e165954403ef921ff3dfdadJeff Sharkey                history.dump("  ", pw, fullHistory);
139361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
139461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
139561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            if (argSet.contains("detail")) {
139639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                // since explicitly requested with argument, we're okay to load
139739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                // from disk if not already in memory.
139839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey                ensureUidStatsLoadedLocked();
13991b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1400b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final ArrayList<UidStatsKey> keys = Lists.newArrayList();
1401b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                keys.addAll(mUidStats.keySet());
1402b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                Collections.sort(keys);
1403b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
14041b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                pw.println("Detailed UID stats:");
1405b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                for (UidStatsKey key : keys) {
1406b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print("  ident="); pw.print(key.ident.toString());
1407b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print(" uid="); pw.print(key.uid);
1408b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print(" set="); pw.print(NetworkStats.setToString(key.set));
1409b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag));
1410b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1411b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    final NetworkStatsHistory history = mUidStats.get(key);
1412b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    history.dump("    ", pw, fullHistory);
141361ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey                }
141461ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey            }
141575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
141661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
141775279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
141861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    /**
141961ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     * @deprecated only for temporary testing
142061ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey     */
142161ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    @Deprecated
1422293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey    private void generateRandomLocked(String[] args) {
1423293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final long totalBytes = Long.parseLong(args[1]);
1424293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final long totalTime = Long.parseLong(args[2]);
1425293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1426293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final PackageManager pm = mContext.getPackageManager();
1427293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final ArrayList<Integer> specialUidList = Lists.newArrayList();
1428293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        for (int i = 3; i < args.length; i++) {
1429293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            try {
1430293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                specialUidList.add(pm.getApplicationInfo(args[i], 0).uid);
1431293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            } catch (NameNotFoundException e) {
1432293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                throw new RuntimeException(e);
1433293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            }
1434293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        }
1435293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1436293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final HashSet<Integer> otherUidSet = Sets.newHashSet();
1437293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        for (ApplicationInfo info : pm.getInstalledApplications(0)) {
1438293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            if (pm.checkPermission(android.Manifest.permission.INTERNET, info.packageName)
1439293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                    == PackageManager.PERMISSION_GRANTED && !specialUidList.contains(info.uid)) {
1440293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                otherUidSet.add(info.uid);
1441293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            }
1442293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        }
1443293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1444293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final ArrayList<Integer> otherUidList = new ArrayList<Integer>(otherUidSet);
1445293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1446293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final long end = System.currentTimeMillis();
1447293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final long start = end - totalTime;
144861ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
1449905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mNetworkDevStats.clear();
1450905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        mNetworkXtStats.clear();
145139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        mUidStats.clear();
1452293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1453293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey        final Random r = new Random();
14541b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        for (NetworkIdentitySet ident : mActiveIfaces.values()) {
1455293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            final NetworkStatsHistory devHistory = findOrCreateNetworkDevStatsLocked(ident);
1456293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            final NetworkStatsHistory xtHistory = findOrCreateNetworkXtStatsLocked(ident);
1457293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1458293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            final ArrayList<Integer> uidList = new ArrayList<Integer>();
1459293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            uidList.addAll(specialUidList);
1460293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1461293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            if (uidList.size() == 0) {
1462293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                Collections.shuffle(otherUidList);
1463293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                uidList.addAll(otherUidList);
1464293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            }
1465293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1466293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            boolean first = true;
1467293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            long remainingBytes = totalBytes;
1468293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey            for (int uid : uidList) {
1469293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                final NetworkStatsHistory defaultHistory = findOrCreateUidStatsLocked(
1470293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                        ident, uid, SET_DEFAULT, TAG_NONE);
1471293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                final NetworkStatsHistory foregroundHistory = findOrCreateUidStatsLocked(
1472293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                        ident, uid, SET_FOREGROUND, TAG_NONE);
1473293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1474293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                final long uidBytes = totalBytes / uidList.size();
1475293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1476293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                final float fractionDefault = r.nextFloat();
1477293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                final long defaultBytes = (long) (uidBytes * fractionDefault);
1478293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                final long foregroundBytes = (long) (uidBytes * (1 - fractionDefault));
1479293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1480293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                defaultHistory.generateRandom(start, end, defaultBytes);
1481293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                foregroundHistory.generateRandom(start, end, foregroundBytes);
1482293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1483293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                if (first) {
1484293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                    final long bumpTime = (start + end) / 2;
1485293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                    defaultHistory.recordData(
1486293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                            bumpTime, bumpTime + DAY_IN_MILLIS, 200 * MB_IN_BYTES, 0);
1487293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                    first = false;
1488293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                }
1489293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey
1490293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                devHistory.recordEntireHistory(defaultHistory);
1491293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                devHistory.recordEntireHistory(foregroundHistory);
1492293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                xtHistory.recordEntireHistory(defaultHistory);
1493293779f9c63cbae0dde564449f0270b595593b0dJeff Sharkey                xtHistory.recordEntireHistory(foregroundHistory);
14941b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
149561ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey        }
149661ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey    }
149761ee0bbb5b87fb5c4c3dc219868d52743def3d2bJeff Sharkey
149875279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    /**
149975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * Return the delta between two {@link NetworkStats} snapshots, where {@code
150075279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     * before} can be {@code null}.
150175279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey     */
1502163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey    private NetworkStats computeStatsDelta(
1503163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            NetworkStats before, NetworkStats current, boolean collectStale, String type) {
150475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        if (before != null) {
1505163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            try {
1506d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                return current.subtract(before, false);
1507163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            } catch (NonMonotonicException e) {
1508163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                Log.w(TAG, "found non-monotonic values; saving to dropbox");
1509163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
1510163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                // record error for debugging
1511163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                final StringBuilder builder = new StringBuilder();
15123359aca7655a7d18615c1ada6cbabeff403947d1Jeff Sharkey                builder.append("found non-monotonic " + type + " values at left[" + e.leftIndex
1513163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                        + "] - right[" + e.rightIndex + "]\n");
1514163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                builder.append("left=").append(e.left).append('\n');
1515163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                builder.append("right=").append(e.right).append('\n');
1516163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey                mDropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
1517163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey
1518d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                try {
1519d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                    // return clamped delta to help recover
1520d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                    return current.subtract(before, true);
1521d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                } catch (NonMonotonicException e1) {
1522d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                    Log.wtf(TAG, "found non-monotonic values; returning empty delta", e1);
1523d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                    return new NetworkStats(0L, 10);
1524d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey                }
1525163e6443f27884a9bfcb9a48ef606dc635852c23Jeff Sharkey            }
152663d27a9233fed934340231f438493746084a681dJeff Sharkey        } else if (collectStale) {
152763d27a9233fed934340231f438493746084a681dJeff Sharkey            // caller is okay collecting stale stats for first call.
152863d27a9233fed934340231f438493746084a681dJeff Sharkey            return current;
152975279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        } else {
1530a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // this is first snapshot; to prevent from double-counting we only
1531a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            // observe traffic occuring between known snapshots.
1532a63ba59260cd1bb3f5c16e395ace45a61f1d4461Jeff Sharkey            return new NetworkStats(0L, 10);
153375279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey        }
153475279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey    }
153575279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey
1536d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    /**
1537d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     * Return snapshot of current tethering statistics. Will return empty
1538d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     * {@link NetworkStats} if any problems are encountered.
1539d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey     */
1540d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    private NetworkStats getNetworkStatsTethering() throws RemoteException {
1541d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey        try {
1542d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs();
1543d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs);
1544d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey        } catch (IllegalStateException e) {
1545d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            Log.wtf(TAG, "problem reading network stats", e);
1546d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey            return new NetworkStats(0L, 10);
1547d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey        }
1548d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey    }
1549d4ef8c8fc9ea70448e5d8138bf8bc96f4e69903fJeff Sharkey
1550905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) {
1551905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey        return uidSnapshot.groupedByIface();
1552905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey    }
1553905b5891d2aa802f447ac2ce5d77b6c5ba06277aJeff Sharkey
15544a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    private int estimateNetworkBuckets() {
15554a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration());
15564a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
15574a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
15584a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    private int estimateUidBuckets() {
15594a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey        return (int) (mSettings.getUidMaxHistory() / mSettings.getUidBucketDuration());
15604a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
15614a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
15624a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    private static int estimateResizeBuckets(NetworkStatsHistory existing, long newBucketDuration) {
1563d37948f6ed1667d077e0e3a38808f42f981ddcc2Jeff Sharkey        return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration);
15644a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey    }
15654a97122ebf4d92a3f94402041729d77905e6c0c0Jeff Sharkey
156639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    /**
15671b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity}
15681b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     * in the given {@link NetworkIdentitySet}.
15691b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey     */
15701b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) {
15711b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        for (NetworkIdentity ident : identSet) {
15721b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            if (template.matches(ident)) {
15731b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey                return true;
15741b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey            }
15751b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        }
15761b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey        return false;
15771b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    }
15781b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey
1579b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private Handler.Callback mHandlerCallback = new Handler.Callback() {
1580b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        /** {@inheritDoc} */
1581b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public boolean handleMessage(Message msg) {
1582b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            switch (msg.what) {
15838e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey                case MSG_PERFORM_POLL: {
1584b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    final int flags = msg.arg1;
1585b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey                    performPoll(flags);
1586b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    return true;
1587b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                }
1588367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                case MSG_UPDATE_IFACES: {
1589367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    updateIfaces();
1590367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                    return true;
1591367d15ab1a33b6159447fa8542d4fa8ff148371cJeff Sharkey                }
1592b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                default: {
1593b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                    return false;
1594b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                }
1595b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
1596b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1597b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    };
1598b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
159907b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    private static String getActiveSubscriberId(Context context) {
160007b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
160107b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey                Context.TELEPHONY_SERVICE);
160207b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey        return telephony.getSubscriberId();
160307b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey    }
160407b0dd9a092273f0451cd9881312cb9b22a7af3fJeff Sharkey
1605b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    /**
1606b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     * Key uniquely identifying a {@link NetworkStatsHistory} for a UID.
1607b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey     */
1608b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    private static class UidStatsKey implements Comparable<UidStatsKey> {
1609b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final NetworkIdentitySet ident;
1610b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final int uid;
1611b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final int set;
1612b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public final int tag;
1613b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1614b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public UidStatsKey(NetworkIdentitySet ident, int uid, int set, int tag) {
1615b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.ident = ident;
1616b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.uid = uid;
1617b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.set = set;
1618b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            this.tag = tag;
1619b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1620b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1621b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        @Override
1622b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public int hashCode() {
1623b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            return Objects.hashCode(ident, uid, set, tag);
1624b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1625b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1626b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        @Override
1627b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public boolean equals(Object obj) {
1628b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            if (obj instanceof UidStatsKey) {
1629b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                final UidStatsKey key = (UidStatsKey) obj;
1630b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                return Objects.equal(ident, key.ident) && uid == key.uid && set == key.set
1631b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey                        && tag == key.tag;
1632b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            }
1633b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            return false;
1634b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1635b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
1636b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        /** {@inheritDoc} */
1637b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        public int compareTo(UidStatsKey another) {
1638b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey            return Integer.compare(uid, another.uid);
1639b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey        }
1640b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey    }
1641b5d55e302d2253e4bfb233ea705caf258cdc4cb9Jeff Sharkey
16421b5a2a96f793211bfbd39aa29cc41031dfa23950Jeff Sharkey    /**
164339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     * Default external settings that read from {@link Settings.Secure}.
164439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey     */
164539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
164639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private final ContentResolver mResolver;
164739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
164839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public DefaultNetworkStatsSettings(Context context) {
164939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            mResolver = checkNotNull(context.getContentResolver());
165039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            // TODO: adjust these timings for production builds
165139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
165239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
165339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        private long getSecureLong(String name, long def) {
165439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return Settings.Secure.getLong(mResolver, name, def);
165539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
1656991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey        private boolean getSecureBoolean(String name, boolean def) {
1657991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey            final int defInt = def ? 1 : 0;
1658991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey            return Settings.Secure.getInt(mResolver, name, defInt) != 0;
1659991d1b1b3f303ad247a959881b1d5b57766f678bJeff Sharkey        }
166039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey
166139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPollInterval() {
16628e9992ae5053a3ac52d28a5a892aed0a0798c7abJeff Sharkey            return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
166339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
166439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getPersistThreshold() {
1665b3d5957604f8fcaafe72bd76052bc76b682bf443Jeff Sharkey            return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 2 * MB_IN_BYTES);
166639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
166739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkBucketDuration() {
166839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS);
166939ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
167039ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getNetworkMaxHistory() {
167139ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_NETWORK_MAX_HISTORY, 90 * DAY_IN_MILLIS);
167239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
167339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidBucketDuration() {
167439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS);
167539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
167639ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getUidMaxHistory() {
167739ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return getSecureLong(NETSTATS_UID_MAX_HISTORY, 90 * DAY_IN_MILLIS);
167839ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
1679d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        public long getTagMaxHistory() {
1680d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey            return getSecureLong(NETSTATS_TAG_MAX_HISTORY, 30 * DAY_IN_MILLIS);
1681d03fd3f004e3ba8aaa1692ee0e92e8ae171d2a04Jeff Sharkey        }
168239ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        public long getTimeCacheMaxAge() {
168339ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey            return DAY_IN_MILLIS;
168439ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey        }
168539ebc2195ed16b9e955dd57f5c95212bb7b934b6Jeff Sharkey    }
168675279904202357565cf5a1cb11148d01f42b4569Jeff Sharkey}
1687