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