Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2011 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.android.server.net;
     18 
     19 import static android.Manifest.permission.ACCESS_NETWORK_STATE;
     20 import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
     21 import static android.Manifest.permission.DUMP;
     22 import static android.Manifest.permission.MODIFY_NETWORK_ACCOUNTING;
     23 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
     24 import static android.content.Intent.ACTION_SHUTDOWN;
     25 import static android.content.Intent.ACTION_UID_REMOVED;
     26 import static android.content.Intent.ACTION_USER_REMOVED;
     27 import static android.content.Intent.EXTRA_UID;
     28 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
     29 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
     30 import static android.net.ConnectivityManager.isNetworkTypeMobile;
     31 import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
     32 import static android.net.NetworkStats.IFACE_ALL;
     33 import static android.net.NetworkStats.SET_ALL;
     34 import static android.net.NetworkStats.SET_DEFAULT;
     35 import static android.net.NetworkStats.SET_FOREGROUND;
     36 import static android.net.NetworkStats.TAG_NONE;
     37 import static android.net.NetworkStats.UID_ALL;
     38 import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
     39 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
     40 import static android.net.TrafficStats.KB_IN_BYTES;
     41 import static android.net.TrafficStats.MB_IN_BYTES;
     42 import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
     43 import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
     44 import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
     45 import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
     46 import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
     47 import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
     48 import static android.provider.Settings.Global.NETSTATS_REPORT_XT_OVER_DEV;
     49 import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
     50 import static android.provider.Settings.Global.NETSTATS_TIME_CACHE_MAX_AGE;
     51 import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
     52 import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
     53 import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
     54 import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
     55 import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
     56 import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
     57 import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
     58 import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
     59 import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE;
     60 import static android.telephony.PhoneStateListener.LISTEN_NONE;
     61 import static android.text.format.DateUtils.DAY_IN_MILLIS;
     62 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
     63 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
     64 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
     65 import static com.android.internal.util.Preconditions.checkNotNull;
     66 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
     67 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
     68 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
     69 
     70 import android.app.AlarmManager;
     71 import android.app.IAlarmManager;
     72 import android.app.PendingIntent;
     73 import android.content.BroadcastReceiver;
     74 import android.content.ContentResolver;
     75 import android.content.Context;
     76 import android.content.Intent;
     77 import android.content.IntentFilter;
     78 import android.content.pm.ApplicationInfo;
     79 import android.content.pm.PackageManager;
     80 import android.net.IConnectivityManager;
     81 import android.net.INetworkManagementEventObserver;
     82 import android.net.INetworkStatsService;
     83 import android.net.INetworkStatsSession;
     84 import android.net.LinkProperties;
     85 import android.net.NetworkIdentity;
     86 import android.net.NetworkInfo;
     87 import android.net.NetworkState;
     88 import android.net.NetworkStats;
     89 import android.net.NetworkStats.NonMonotonicObserver;
     90 import android.net.NetworkStatsHistory;
     91 import android.net.NetworkTemplate;
     92 import android.net.TrafficStats;
     93 import android.os.Binder;
     94 import android.os.DropBoxManager;
     95 import android.os.Environment;
     96 import android.os.Handler;
     97 import android.os.HandlerThread;
     98 import android.os.INetworkManagementService;
     99 import android.os.Message;
    100 import android.os.PowerManager;
    101 import android.os.RemoteException;
    102 import android.os.SystemClock;
    103 import android.os.UserHandle;
    104 import android.provider.Settings;
    105 import android.provider.Settings.Global;
    106 import android.telephony.PhoneStateListener;
    107 import android.telephony.TelephonyManager;
    108 import android.util.ArrayMap;
    109 import android.util.ArraySet;
    110 import android.util.EventLog;
    111 import android.util.Log;
    112 import android.util.MathUtils;
    113 import android.util.NtpTrustedTime;
    114 import android.util.Slog;
    115 import android.util.SparseIntArray;
    116 import android.util.TrustedTime;
    117 
    118 import com.android.internal.annotations.VisibleForTesting;
    119 import com.android.internal.util.ArrayUtils;
    120 import com.android.internal.util.FileRotator;
    121 import com.android.internal.util.IndentingPrintWriter;
    122 import com.android.server.EventLogTags;
    123 import com.android.server.connectivity.Tethering;
    124 
    125 import java.io.File;
    126 import java.io.FileDescriptor;
    127 import java.io.IOException;
    128 import java.io.PrintWriter;
    129 import java.util.Arrays;
    130 import java.util.HashSet;
    131 import java.util.List;
    132 
    133 /**
    134  * Collect and persist detailed network statistics, and provide this data to
    135  * other system services.
    136  */
    137 public class NetworkStatsService extends INetworkStatsService.Stub {
    138     private static final String TAG = "NetworkStats";
    139     private static final boolean LOGV = false;
    140 
    141     private static final int MSG_PERFORM_POLL = 1;
    142     private static final int MSG_UPDATE_IFACES = 2;
    143     private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
    144 
    145     /** Flags to control detail level of poll event. */
    146     private static final int FLAG_PERSIST_NETWORK = 0x1;
    147     private static final int FLAG_PERSIST_UID = 0x2;
    148     private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
    149     private static final int FLAG_PERSIST_FORCE = 0x100;
    150 
    151     private static final String TAG_NETSTATS_ERROR = "netstats_error";
    152 
    153     private final Context mContext;
    154     private final INetworkManagementService mNetworkManager;
    155     private final AlarmManager mAlarmManager;
    156     private final TrustedTime mTime;
    157     private final TelephonyManager mTeleManager;
    158     private final NetworkStatsSettings mSettings;
    159 
    160     private final File mSystemDir;
    161     private final File mBaseDir;
    162 
    163     private final PowerManager.WakeLock mWakeLock;
    164 
    165     private IConnectivityManager mConnManager;
    166 
    167     @VisibleForTesting
    168     public static final String ACTION_NETWORK_STATS_POLL =
    169             "com.android.server.action.NETWORK_STATS_POLL";
    170     public static final String ACTION_NETWORK_STATS_UPDATED =
    171             "com.android.server.action.NETWORK_STATS_UPDATED";
    172 
    173     private PendingIntent mPollIntent;
    174 
    175     private static final String PREFIX_DEV = "dev";
    176     private static final String PREFIX_XT = "xt";
    177     private static final String PREFIX_UID = "uid";
    178     private static final String PREFIX_UID_TAG = "uid_tag";
    179 
    180     /**
    181      * Settings that can be changed externally.
    182      */
    183     public interface NetworkStatsSettings {
    184         public long getPollInterval();
    185         public long getTimeCacheMaxAge();
    186         public boolean getSampleEnabled();
    187         public boolean getReportXtOverDev();
    188 
    189         public static class Config {
    190             public final long bucketDuration;
    191             public final long rotateAgeMillis;
    192             public final long deleteAgeMillis;
    193 
    194             public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
    195                 this.bucketDuration = bucketDuration;
    196                 this.rotateAgeMillis = rotateAgeMillis;
    197                 this.deleteAgeMillis = deleteAgeMillis;
    198             }
    199         }
    200 
    201         public Config getDevConfig();
    202         public Config getXtConfig();
    203         public Config getUidConfig();
    204         public Config getUidTagConfig();
    205 
    206         public long getGlobalAlertBytes(long def);
    207         public long getDevPersistBytes(long def);
    208         public long getXtPersistBytes(long def);
    209         public long getUidPersistBytes(long def);
    210         public long getUidTagPersistBytes(long def);
    211     }
    212 
    213     private final Object mStatsLock = new Object();
    214 
    215     /** Set of currently active ifaces. */
    216     private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
    217     /** Set of currently active ifaces for UID stats. */
    218     private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
    219     /** Current default active iface. */
    220     private String mActiveIface;
    221     /** Set of any ifaces associated with mobile networks since boot. */
    222     private String[] mMobileIfaces = new String[0];
    223 
    224     private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
    225             new DropBoxNonMonotonicObserver();
    226 
    227     private NetworkStatsRecorder mDevRecorder;
    228     private NetworkStatsRecorder mXtRecorder;
    229     private NetworkStatsRecorder mUidRecorder;
    230     private NetworkStatsRecorder mUidTagRecorder;
    231 
    232     /** Cached {@link #mDevRecorder} stats. */
    233     private NetworkStatsCollection mDevStatsCached;
    234     /** Cached {@link #mXtRecorder} stats. */
    235     private NetworkStatsCollection mXtStatsCached;
    236 
    237     /** Current counter sets for each UID. */
    238     private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
    239 
    240     /** Data layer operation counters for splicing into other structures. */
    241     private NetworkStats mUidOperations = new NetworkStats(0L, 10);
    242 
    243     private final Handler mHandler;
    244 
    245     private boolean mSystemReady;
    246     private long mPersistThreshold = 2 * MB_IN_BYTES;
    247     private long mGlobalAlertBytes;
    248 
    249     public NetworkStatsService(
    250             Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) {
    251         this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
    252                 getDefaultSystemDir(), new DefaultNetworkStatsSettings(context));
    253     }
    254 
    255     private static File getDefaultSystemDir() {
    256         return new File(Environment.getDataDirectory(), "system");
    257     }
    258 
    259     public NetworkStatsService(Context context, INetworkManagementService networkManager,
    260             IAlarmManager alarmManager, TrustedTime time, File systemDir,
    261             NetworkStatsSettings settings) {
    262         mContext = checkNotNull(context, "missing Context");
    263         mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
    264         mTime = checkNotNull(time, "missing TrustedTime");
    265         mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
    266         mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
    267         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    268 
    269         final PowerManager powerManager = (PowerManager) context.getSystemService(
    270                 Context.POWER_SERVICE);
    271         mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
    272 
    273         HandlerThread thread = new HandlerThread(TAG);
    274         thread.start();
    275         mHandler = new Handler(thread.getLooper(), mHandlerCallback);
    276 
    277         mSystemDir = checkNotNull(systemDir);
    278         mBaseDir = new File(systemDir, "netstats");
    279         mBaseDir.mkdirs();
    280     }
    281 
    282     public void bindConnectivityManager(IConnectivityManager connManager) {
    283         mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
    284     }
    285 
    286     public void systemReady() {
    287         mSystemReady = true;
    288 
    289         if (!isBandwidthControlEnabled()) {
    290             Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
    291             return;
    292         }
    293 
    294         // create data recorders along with historical rotators
    295         mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
    296         mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
    297         mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
    298         mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
    299 
    300         updatePersistThresholds();
    301 
    302         synchronized (mStatsLock) {
    303             // upgrade any legacy stats, migrating them to rotated files
    304             maybeUpgradeLegacyStatsLocked();
    305 
    306             // read historical network stats from disk, since policy service
    307             // might need them right away.
    308             mDevStatsCached = mDevRecorder.getOrLoadCompleteLocked();
    309             mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
    310 
    311             // bootstrap initial stats to prevent double-counting later
    312             bootstrapStatsLocked();
    313         }
    314 
    315         // watch for network interfaces to be claimed
    316         final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
    317         mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
    318 
    319         // watch for tethering changes
    320         final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
    321         mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
    322 
    323         // listen for periodic polling events
    324         final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
    325         mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
    326 
    327         // listen for uid removal to clean stats
    328         final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
    329         mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
    330 
    331         // listen for user changes to clean stats
    332         final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
    333         mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
    334 
    335         // persist stats during clean shutdown
    336         final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
    337         mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
    338 
    339         try {
    340             mNetworkManager.registerObserver(mAlertObserver);
    341         } catch (RemoteException e) {
    342             // ignored; service lives in system_server
    343         }
    344 
    345         // watch for networkType changes that aren't broadcast through
    346         // CONNECTIVITY_ACTION_IMMEDIATE above.
    347         if (!COMBINE_SUBTYPE_ENABLED) {
    348             mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE);
    349         }
    350 
    351         registerPollAlarmLocked();
    352         registerGlobalAlert();
    353     }
    354 
    355     private NetworkStatsRecorder buildRecorder(
    356             String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
    357         final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
    358                 Context.DROPBOX_SERVICE);
    359         return new NetworkStatsRecorder(new FileRotator(
    360                 mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
    361                 mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
    362     }
    363 
    364     private void shutdownLocked() {
    365         mContext.unregisterReceiver(mConnReceiver);
    366         mContext.unregisterReceiver(mTetherReceiver);
    367         mContext.unregisterReceiver(mPollReceiver);
    368         mContext.unregisterReceiver(mRemovedReceiver);
    369         mContext.unregisterReceiver(mShutdownReceiver);
    370 
    371         if (!COMBINE_SUBTYPE_ENABLED) {
    372             mTeleManager.listen(mPhoneListener, LISTEN_NONE);
    373         }
    374 
    375         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
    376                 : System.currentTimeMillis();
    377 
    378         // persist any pending stats
    379         mDevRecorder.forcePersistLocked(currentTime);
    380         mXtRecorder.forcePersistLocked(currentTime);
    381         mUidRecorder.forcePersistLocked(currentTime);
    382         mUidTagRecorder.forcePersistLocked(currentTime);
    383 
    384         mDevRecorder = null;
    385         mXtRecorder = null;
    386         mUidRecorder = null;
    387         mUidTagRecorder = null;
    388 
    389         mDevStatsCached = null;
    390         mXtStatsCached = null;
    391 
    392         mSystemReady = false;
    393     }
    394 
    395     private void maybeUpgradeLegacyStatsLocked() {
    396         File file;
    397         try {
    398             file = new File(mSystemDir, "netstats.bin");
    399             if (file.exists()) {
    400                 mDevRecorder.importLegacyNetworkLocked(file);
    401                 file.delete();
    402             }
    403 
    404             file = new File(mSystemDir, "netstats_xt.bin");
    405             if (file.exists()) {
    406                 file.delete();
    407             }
    408 
    409             file = new File(mSystemDir, "netstats_uid.bin");
    410             if (file.exists()) {
    411                 mUidRecorder.importLegacyUidLocked(file);
    412                 mUidTagRecorder.importLegacyUidLocked(file);
    413                 file.delete();
    414             }
    415         } catch (IOException e) {
    416             Log.wtf(TAG, "problem during legacy upgrade", e);
    417         } catch (OutOfMemoryError e) {
    418             Log.wtf(TAG, "problem during legacy upgrade", e);
    419         }
    420     }
    421 
    422     /**
    423      * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
    424      * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
    425      */
    426     private void registerPollAlarmLocked() {
    427         if (mPollIntent != null) {
    428             mAlarmManager.cancel(mPollIntent);
    429         }
    430 
    431         mPollIntent = PendingIntent.getBroadcast(
    432                 mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
    433 
    434         final long currentRealtime = SystemClock.elapsedRealtime();
    435         mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
    436                 mSettings.getPollInterval(), mPollIntent);
    437     }
    438 
    439     /**
    440      * Register for a global alert that is delivered through
    441      * {@link INetworkManagementEventObserver} once a threshold amount of data
    442      * has been transferred.
    443      */
    444     private void registerGlobalAlert() {
    445         try {
    446             mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
    447         } catch (IllegalStateException e) {
    448             Slog.w(TAG, "problem registering for global alert: " + e);
    449         } catch (RemoteException e) {
    450             // ignored; service lives in system_server
    451         }
    452     }
    453 
    454     @Override
    455     public INetworkStatsSession openSession() {
    456         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
    457         assertBandwidthControlEnabled();
    458 
    459         // return an IBinder which holds strong references to any loaded stats
    460         // for its lifetime; when caller closes only weak references remain.
    461 
    462         return new INetworkStatsSession.Stub() {
    463             private NetworkStatsCollection mUidComplete;
    464             private NetworkStatsCollection mUidTagComplete;
    465 
    466             private NetworkStatsCollection getUidComplete() {
    467                 synchronized (mStatsLock) {
    468                     if (mUidComplete == null) {
    469                         mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
    470                     }
    471                     return mUidComplete;
    472                 }
    473             }
    474 
    475             private NetworkStatsCollection getUidTagComplete() {
    476                 synchronized (mStatsLock) {
    477                     if (mUidTagComplete == null) {
    478                         mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
    479                     }
    480                     return mUidTagComplete;
    481                 }
    482             }
    483 
    484             @Override
    485             public NetworkStats getSummaryForNetwork(
    486                     NetworkTemplate template, long start, long end) {
    487                 return internalGetSummaryForNetwork(template, start, end);
    488             }
    489 
    490             @Override
    491             public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
    492                 return internalGetHistoryForNetwork(template, fields);
    493             }
    494 
    495             @Override
    496             public NetworkStats getSummaryForAllUid(
    497                     NetworkTemplate template, long start, long end, boolean includeTags) {
    498                 final NetworkStats stats = getUidComplete().getSummary(template, start, end);
    499                 if (includeTags) {
    500                     final NetworkStats tagStats = getUidTagComplete()
    501                             .getSummary(template, start, end);
    502                     stats.combineAllValues(tagStats);
    503                 }
    504                 return stats;
    505             }
    506 
    507             @Override
    508             public NetworkStatsHistory getHistoryForUid(
    509                     NetworkTemplate template, int uid, int set, int tag, int fields) {
    510                 if (tag == TAG_NONE) {
    511                     return getUidComplete().getHistory(template, uid, set, tag, fields);
    512                 } else {
    513                     return getUidTagComplete().getHistory(template, uid, set, tag, fields);
    514                 }
    515             }
    516 
    517             @Override
    518             public void close() {
    519                 mUidComplete = null;
    520                 mUidTagComplete = null;
    521             }
    522         };
    523     }
    524 
    525     /**
    526      * Return network summary, splicing between {@link #mDevStatsCached}
    527      * and {@link #mXtStatsCached} when appropriate.
    528      */
    529     private NetworkStats internalGetSummaryForNetwork(
    530             NetworkTemplate template, long start, long end) {
    531         if (!mSettings.getReportXtOverDev()) {
    532             // shortcut when XT reporting disabled
    533             return mDevStatsCached.getSummary(template, start, end);
    534         }
    535 
    536         // splice stats between DEV and XT, switching over from DEV to XT at
    537         // first atomic bucket.
    538         final long firstAtomicBucket = mXtStatsCached.getFirstAtomicBucketMillis();
    539         final NetworkStats dev = mDevStatsCached.getSummary(
    540                 template, Math.min(start, firstAtomicBucket), Math.min(end, firstAtomicBucket));
    541         final NetworkStats xt = mXtStatsCached.getSummary(
    542                 template, Math.max(start, firstAtomicBucket), Math.max(end, firstAtomicBucket));
    543 
    544         xt.combineAllValues(dev);
    545         return xt;
    546     }
    547 
    548     /**
    549      * Return network history, splicing between {@link #mDevStatsCached}
    550      * and {@link #mXtStatsCached} when appropriate.
    551      */
    552     private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, int fields) {
    553         if (!mSettings.getReportXtOverDev()) {
    554             // shortcut when XT reporting disabled
    555             return mDevStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
    556         }
    557 
    558         // splice stats between DEV and XT, switching over from DEV to XT at
    559         // first atomic bucket.
    560         final long firstAtomicBucket = mXtStatsCached.getFirstAtomicBucketMillis();
    561         final NetworkStatsHistory dev = mDevStatsCached.getHistory(
    562                 template, UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, firstAtomicBucket);
    563         final NetworkStatsHistory xt = mXtStatsCached.getHistory(
    564                 template, UID_ALL, SET_ALL, TAG_NONE, fields, firstAtomicBucket, Long.MAX_VALUE);
    565 
    566         xt.recordEntireHistory(dev);
    567         return xt;
    568     }
    569 
    570     @Override
    571     public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
    572         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
    573         assertBandwidthControlEnabled();
    574         return internalGetSummaryForNetwork(template, start, end).getTotalBytes();
    575     }
    576 
    577     @Override
    578     public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
    579         if (Binder.getCallingUid() != uid) {
    580             mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
    581         }
    582         assertBandwidthControlEnabled();
    583 
    584         // TODO: switch to data layer stats once kernel exports
    585         // for now, read network layer stats and flatten across all ifaces
    586         final long token = Binder.clearCallingIdentity();
    587         final NetworkStats networkLayer;
    588         try {
    589             networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
    590         } finally {
    591             Binder.restoreCallingIdentity(token);
    592         }
    593 
    594         // splice in operation counts
    595         networkLayer.spliceOperationsFrom(mUidOperations);
    596 
    597         final NetworkStats dataLayer = new NetworkStats(
    598                 networkLayer.getElapsedRealtime(), networkLayer.size());
    599 
    600         NetworkStats.Entry entry = null;
    601         for (int i = 0; i < networkLayer.size(); i++) {
    602             entry = networkLayer.getValues(i, entry);
    603             entry.iface = IFACE_ALL;
    604             dataLayer.combineValues(entry);
    605         }
    606 
    607         return dataLayer;
    608     }
    609 
    610     @Override
    611     public String[] getMobileIfaces() {
    612         return mMobileIfaces;
    613     }
    614 
    615     @Override
    616     public void incrementOperationCount(int uid, int tag, int operationCount) {
    617         if (Binder.getCallingUid() != uid) {
    618             mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
    619         }
    620 
    621         if (operationCount < 0) {
    622             throw new IllegalArgumentException("operation count can only be incremented");
    623         }
    624         if (tag == TAG_NONE) {
    625             throw new IllegalArgumentException("operation count must have specific tag");
    626         }
    627 
    628         synchronized (mStatsLock) {
    629             final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
    630             mUidOperations.combineValues(
    631                     mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
    632             mUidOperations.combineValues(
    633                     mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
    634         }
    635     }
    636 
    637     @Override
    638     public void setUidForeground(int uid, boolean uidForeground) {
    639         mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
    640 
    641         synchronized (mStatsLock) {
    642             final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
    643             final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
    644             if (oldSet != set) {
    645                 mActiveUidCounterSet.put(uid, set);
    646                 setKernelCounterSet(uid, set);
    647             }
    648         }
    649     }
    650 
    651     @Override
    652     public void forceUpdate() {
    653         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
    654         assertBandwidthControlEnabled();
    655 
    656         final long token = Binder.clearCallingIdentity();
    657         try {
    658             performPoll(FLAG_PERSIST_ALL);
    659         } finally {
    660             Binder.restoreCallingIdentity(token);
    661         }
    662     }
    663 
    664     @Override
    665     public void advisePersistThreshold(long thresholdBytes) {
    666         mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
    667         assertBandwidthControlEnabled();
    668 
    669         // clamp threshold into safe range
    670         mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
    671         if (LOGV) {
    672             Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
    673                     + mPersistThreshold);
    674         }
    675 
    676         // update and persist if beyond new thresholds
    677         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
    678                 : System.currentTimeMillis();
    679         synchronized (mStatsLock) {
    680             if (!mSystemReady) return;
    681 
    682             updatePersistThresholds();
    683 
    684             mDevRecorder.maybePersistLocked(currentTime);
    685             mXtRecorder.maybePersistLocked(currentTime);
    686             mUidRecorder.maybePersistLocked(currentTime);
    687             mUidTagRecorder.maybePersistLocked(currentTime);
    688         }
    689 
    690         // re-arm global alert
    691         registerGlobalAlert();
    692     }
    693 
    694     /**
    695      * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
    696      * reflect current {@link #mPersistThreshold} value. Always defers to
    697      * {@link Global} values when defined.
    698      */
    699     private void updatePersistThresholds() {
    700         mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
    701         mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
    702         mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
    703         mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
    704         mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
    705     }
    706 
    707     /**
    708      * Receiver that watches for {@link IConnectivityManager} to claim network
    709      * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()}
    710      * with mobile interfaces.
    711      */
    712     private BroadcastReceiver mConnReceiver = new BroadcastReceiver() {
    713         @Override
    714         public void onReceive(Context context, Intent intent) {
    715             // on background handler thread, and verified CONNECTIVITY_INTERNAL
    716             // permission above.
    717             updateIfaces();
    718         }
    719     };
    720 
    721     /**
    722      * Receiver that watches for {@link Tethering} to claim interface pairs.
    723      */
    724     private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
    725         @Override
    726         public void onReceive(Context context, Intent intent) {
    727             // on background handler thread, and verified CONNECTIVITY_INTERNAL
    728             // permission above.
    729             performPoll(FLAG_PERSIST_NETWORK);
    730         }
    731     };
    732 
    733     private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
    734         @Override
    735         public void onReceive(Context context, Intent intent) {
    736             // on background handler thread, and verified UPDATE_DEVICE_STATS
    737             // permission above.
    738             performPoll(FLAG_PERSIST_ALL);
    739 
    740             // verify that we're watching global alert
    741             registerGlobalAlert();
    742         }
    743     };
    744 
    745     private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
    746         @Override
    747         public void onReceive(Context context, Intent intent) {
    748             // on background handler thread, and UID_REMOVED is protected
    749             // broadcast.
    750 
    751             final int uid = intent.getIntExtra(EXTRA_UID, -1);
    752             if (uid == -1) return;
    753 
    754             synchronized (mStatsLock) {
    755                 mWakeLock.acquire();
    756                 try {
    757                     removeUidsLocked(uid);
    758                 } finally {
    759                     mWakeLock.release();
    760                 }
    761             }
    762         }
    763     };
    764 
    765     private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
    766         @Override
    767         public void onReceive(Context context, Intent intent) {
    768             // On background handler thread, and USER_REMOVED is protected
    769             // broadcast.
    770 
    771             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
    772             if (userId == -1) return;
    773 
    774             synchronized (mStatsLock) {
    775                 mWakeLock.acquire();
    776                 try {
    777                     removeUserLocked(userId);
    778                 } finally {
    779                     mWakeLock.release();
    780                 }
    781             }
    782         }
    783     };
    784 
    785     private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
    786         @Override
    787         public void onReceive(Context context, Intent intent) {
    788             // SHUTDOWN is protected broadcast.
    789             synchronized (mStatsLock) {
    790                 shutdownLocked();
    791             }
    792         }
    793     };
    794 
    795     /**
    796      * Observer that watches for {@link INetworkManagementService} alerts.
    797      */
    798     private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
    799         @Override
    800         public void limitReached(String limitName, String iface) {
    801             // only someone like NMS should be calling us
    802             mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
    803 
    804             if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
    805                 // kick off background poll to collect network stats; UID stats
    806                 // are handled during normal polling interval.
    807                 final int flags = FLAG_PERSIST_NETWORK;
    808                 mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
    809 
    810                 // re-arm global alert for next update
    811                 mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
    812             }
    813         }
    814     };
    815 
    816     private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN;
    817     private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
    818 
    819     /**
    820      * Receiver that watches for {@link TelephonyManager} changes, such as
    821      * transitioning between network types.
    822      */
    823     private PhoneStateListener mPhoneListener = new PhoneStateListener() {
    824         @Override
    825         public void onDataConnectionStateChanged(int state, int networkType) {
    826             final boolean stateChanged = state != mLastPhoneState;
    827             final boolean networkTypeChanged = networkType != mLastPhoneNetworkType;
    828 
    829             if (networkTypeChanged && !stateChanged) {
    830                 // networkType changed without a state change, which means we
    831                 // need to roll our own update. delay long enough for
    832                 // ConnectivityManager to process.
    833                 // TODO: add direct event to ConnectivityService instead of
    834                 // relying on this delay.
    835                 if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()");
    836                 mHandler.sendMessageDelayed(
    837                         mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS);
    838             }
    839 
    840             mLastPhoneState = state;
    841             mLastPhoneNetworkType = networkType;
    842         }
    843     };
    844 
    845     private void updateIfaces() {
    846         synchronized (mStatsLock) {
    847             mWakeLock.acquire();
    848             try {
    849                 updateIfacesLocked();
    850             } finally {
    851                 mWakeLock.release();
    852             }
    853         }
    854     }
    855 
    856     /**
    857      * Inspect all current {@link NetworkState} to derive mapping from {@code
    858      * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
    859      * are active on a single {@code iface}, they are combined under a single
    860      * {@link NetworkIdentitySet}.
    861      */
    862     private void updateIfacesLocked() {
    863         if (!mSystemReady) return;
    864         if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
    865 
    866         // take one last stats snapshot before updating iface mapping. this
    867         // isn't perfect, since the kernel may already be counting traffic from
    868         // the updated network.
    869 
    870         // poll, but only persist network stats to keep codepath fast. UID stats
    871         // will be persisted during next alarm poll event.
    872         performPollLocked(FLAG_PERSIST_NETWORK);
    873 
    874         final NetworkState[] states;
    875         final LinkProperties activeLink;
    876         try {
    877             states = mConnManager.getAllNetworkState();
    878             activeLink = mConnManager.getActiveLinkProperties();
    879         } catch (RemoteException e) {
    880             // ignored; service lives in system_server
    881             return;
    882         }
    883 
    884         mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
    885 
    886         // Rebuild active interfaces based on connected networks
    887         mActiveIfaces.clear();
    888         mActiveUidIfaces.clear();
    889 
    890         final ArraySet<String> mobileIfaces = new ArraySet<>();
    891         for (NetworkState state : states) {
    892             if (state.networkInfo.isConnected()) {
    893                 final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
    894                 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
    895 
    896                 // Traffic occurring on the base interface is always counted for
    897                 // both total usage and UID details.
    898                 final String baseIface = state.linkProperties.getInterfaceName();
    899                 if (baseIface != null) {
    900                     findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
    901                     findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
    902                     if (isMobile) {
    903                         mobileIfaces.add(baseIface);
    904                     }
    905                 }
    906 
    907                 // Traffic occurring on stacked interfaces is usually clatd,
    908                 // which is already accounted against its final egress interface
    909                 // by the kernel. Thus, we only need to collect stacked
    910                 // interface stats at the UID level.
    911                 final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
    912                 for (LinkProperties stackedLink : stackedLinks) {
    913                     final String stackedIface = stackedLink.getInterfaceName();
    914                     if (stackedIface != null) {
    915                         findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
    916                         if (isMobile) {
    917                             mobileIfaces.add(stackedIface);
    918                         }
    919                     }
    920                 }
    921             }
    922         }
    923 
    924         mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
    925     }
    926 
    927     private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
    928             ArrayMap<K, NetworkIdentitySet> map, K key) {
    929         NetworkIdentitySet ident = map.get(key);
    930         if (ident == null) {
    931             ident = new NetworkIdentitySet();
    932             map.put(key, ident);
    933         }
    934         return ident;
    935     }
    936 
    937     /**
    938      * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
    939      * so we have baseline values without double-counting.
    940      */
    941     private void bootstrapStatsLocked() {
    942         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
    943                 : System.currentTimeMillis();
    944 
    945         try {
    946             // snapshot and record current counters; read UID stats first to
    947             // avoid overcounting dev stats.
    948             final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
    949             final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
    950             final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
    951 
    952             mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
    953             mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
    954             mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
    955             mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
    956 
    957         } catch (IllegalStateException e) {
    958             Slog.w(TAG, "problem reading network stats: " + e);
    959         } catch (RemoteException e) {
    960             // ignored; service lives in system_server
    961         }
    962     }
    963 
    964     private void performPoll(int flags) {
    965         // try refreshing time source when stale
    966         if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
    967             mTime.forceRefresh();
    968         }
    969 
    970         synchronized (mStatsLock) {
    971             mWakeLock.acquire();
    972 
    973             try {
    974                 performPollLocked(flags);
    975             } finally {
    976                 mWakeLock.release();
    977             }
    978         }
    979     }
    980 
    981     /**
    982      * Periodic poll operation, reading current statistics and recording into
    983      * {@link NetworkStatsHistory}.
    984      */
    985     private void performPollLocked(int flags) {
    986         if (!mSystemReady) return;
    987         if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
    988 
    989         final long startRealtime = SystemClock.elapsedRealtime();
    990 
    991         final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
    992         final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
    993         final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
    994 
    995         // TODO: consider marking "untrusted" times in historical stats
    996         final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
    997                 : System.currentTimeMillis();
    998 
    999         try {
   1000             // snapshot and record current counters; read UID stats first to
   1001             // avoid overcounting dev stats.
   1002             final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
   1003             final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
   1004             final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
   1005 
   1006             mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
   1007             mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
   1008             mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
   1009             mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
   1010 
   1011         } catch (IllegalStateException e) {
   1012             Log.wtf(TAG, "problem reading network stats", e);
   1013             return;
   1014         } catch (RemoteException e) {
   1015             // ignored; service lives in system_server
   1016             return;
   1017         }
   1018 
   1019         // persist any pending data depending on requested flags
   1020         if (persistForce) {
   1021             mDevRecorder.forcePersistLocked(currentTime);
   1022             mXtRecorder.forcePersistLocked(currentTime);
   1023             mUidRecorder.forcePersistLocked(currentTime);
   1024             mUidTagRecorder.forcePersistLocked(currentTime);
   1025         } else {
   1026             if (persistNetwork) {
   1027                 mDevRecorder.maybePersistLocked(currentTime);
   1028                 mXtRecorder.maybePersistLocked(currentTime);
   1029             }
   1030             if (persistUid) {
   1031                 mUidRecorder.maybePersistLocked(currentTime);
   1032                 mUidTagRecorder.maybePersistLocked(currentTime);
   1033             }
   1034         }
   1035 
   1036         if (LOGV) {
   1037             final long duration = SystemClock.elapsedRealtime() - startRealtime;
   1038             Slog.v(TAG, "performPollLocked() took " + duration + "ms");
   1039         }
   1040 
   1041         if (mSettings.getSampleEnabled()) {
   1042             // sample stats after each full poll
   1043             performSampleLocked();
   1044         }
   1045 
   1046         // finally, dispatch updated event to any listeners
   1047         final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
   1048         updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
   1049         mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
   1050                 READ_NETWORK_USAGE_HISTORY);
   1051     }
   1052 
   1053     /**
   1054      * Sample recent statistics summary into {@link EventLog}.
   1055      */
   1056     private void performSampleLocked() {
   1057         // TODO: migrate trustedtime fixes to separate binary log events
   1058         final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
   1059 
   1060         NetworkTemplate template;
   1061         NetworkStats.Entry devTotal;
   1062         NetworkStats.Entry xtTotal;
   1063         NetworkStats.Entry uidTotal;
   1064 
   1065         // collect mobile sample
   1066         template = buildTemplateMobileWildcard();
   1067         devTotal = mDevRecorder.getTotalSinceBootLocked(template);
   1068         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
   1069         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
   1070 
   1071         EventLogTags.writeNetstatsMobileSample(
   1072                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
   1073                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
   1074                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
   1075                 trustedTime);
   1076 
   1077         // collect wifi sample
   1078         template = buildTemplateWifiWildcard();
   1079         devTotal = mDevRecorder.getTotalSinceBootLocked(template);
   1080         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
   1081         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
   1082 
   1083         EventLogTags.writeNetstatsWifiSample(
   1084                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
   1085                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
   1086                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
   1087                 trustedTime);
   1088     }
   1089 
   1090     /**
   1091      * Clean up {@link #mUidRecorder} after UID is removed.
   1092      */
   1093     private void removeUidsLocked(int... uids) {
   1094         if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
   1095 
   1096         // Perform one last poll before removing
   1097         performPollLocked(FLAG_PERSIST_ALL);
   1098 
   1099         mUidRecorder.removeUidsLocked(uids);
   1100         mUidTagRecorder.removeUidsLocked(uids);
   1101 
   1102         // Clear kernel stats associated with UID
   1103         for (int uid : uids) {
   1104             resetKernelUidStats(uid);
   1105         }
   1106     }
   1107 
   1108     /**
   1109      * Clean up {@link #mUidRecorder} after user is removed.
   1110      */
   1111     private void removeUserLocked(int userId) {
   1112         if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
   1113 
   1114         // Build list of UIDs that we should clean up
   1115         int[] uids = new int[0];
   1116         final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
   1117                 PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
   1118         for (ApplicationInfo app : apps) {
   1119             final int uid = UserHandle.getUid(userId, app.uid);
   1120             uids = ArrayUtils.appendInt(uids, uid);
   1121         }
   1122 
   1123         removeUidsLocked(uids);
   1124     }
   1125 
   1126     @Override
   1127     protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
   1128         mContext.enforceCallingOrSelfPermission(DUMP, TAG);
   1129 
   1130         final HashSet<String> argSet = new HashSet<String>();
   1131         for (String arg : args) {
   1132             argSet.add(arg);
   1133         }
   1134 
   1135         // usage: dumpsys netstats --full --uid --tag --poll --checkin
   1136         final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
   1137         final boolean checkin = argSet.contains("--checkin");
   1138         final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
   1139         final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
   1140         final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
   1141 
   1142         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
   1143 
   1144         synchronized (mStatsLock) {
   1145             if (poll) {
   1146                 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
   1147                 pw.println("Forced poll");
   1148                 return;
   1149             }
   1150 
   1151             if (checkin) {
   1152                 // list current stats files to verify rotation
   1153                 pw.println("Current files:");
   1154                 pw.increaseIndent();
   1155                 for (String file : mBaseDir.list()) {
   1156                     pw.println(file);
   1157                 }
   1158                 pw.decreaseIndent();
   1159                 return;
   1160             }
   1161 
   1162             pw.println("Active interfaces:");
   1163             pw.increaseIndent();
   1164             for (int i = 0; i < mActiveIfaces.size(); i++) {
   1165                 pw.printPair("iface", mActiveIfaces.keyAt(i));
   1166                 pw.printPair("ident", mActiveIfaces.valueAt(i));
   1167                 pw.println();
   1168             }
   1169             pw.decreaseIndent();
   1170 
   1171             pw.println("Active UID interfaces:");
   1172             pw.increaseIndent();
   1173             for (int i = 0; i < mActiveUidIfaces.size(); i++) {
   1174                 pw.printPair("iface", mActiveUidIfaces.keyAt(i));
   1175                 pw.printPair("ident", mActiveUidIfaces.valueAt(i));
   1176                 pw.println();
   1177             }
   1178             pw.decreaseIndent();
   1179 
   1180             pw.println("Dev stats:");
   1181             pw.increaseIndent();
   1182             mDevRecorder.dumpLocked(pw, fullHistory);
   1183             pw.decreaseIndent();
   1184 
   1185             pw.println("Xt stats:");
   1186             pw.increaseIndent();
   1187             mXtRecorder.dumpLocked(pw, fullHistory);
   1188             pw.decreaseIndent();
   1189 
   1190             if (includeUid) {
   1191                 pw.println("UID stats:");
   1192                 pw.increaseIndent();
   1193                 mUidRecorder.dumpLocked(pw, fullHistory);
   1194                 pw.decreaseIndent();
   1195             }
   1196 
   1197             if (includeTag) {
   1198                 pw.println("UID tag stats:");
   1199                 pw.increaseIndent();
   1200                 mUidTagRecorder.dumpLocked(pw, fullHistory);
   1201                 pw.decreaseIndent();
   1202             }
   1203         }
   1204     }
   1205 
   1206     /**
   1207      * Return snapshot of current UID statistics, including any
   1208      * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
   1209      */
   1210     private NetworkStats getNetworkStatsUidDetail() throws RemoteException {
   1211         final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
   1212 
   1213         // fold tethering stats and operations into uid snapshot
   1214         final NetworkStats tetherSnapshot = getNetworkStatsTethering();
   1215         uidSnapshot.combineAllValues(tetherSnapshot);
   1216         uidSnapshot.combineAllValues(mUidOperations);
   1217 
   1218         return uidSnapshot;
   1219     }
   1220 
   1221     /**
   1222      * Return snapshot of current tethering statistics. Will return empty
   1223      * {@link NetworkStats} if any problems are encountered.
   1224      */
   1225     private NetworkStats getNetworkStatsTethering() throws RemoteException {
   1226         try {
   1227             return mNetworkManager.getNetworkStatsTethering();
   1228         } catch (IllegalStateException e) {
   1229             Log.wtf(TAG, "problem reading network stats", e);
   1230             return new NetworkStats(0L, 10);
   1231         }
   1232     }
   1233 
   1234     private Handler.Callback mHandlerCallback = new Handler.Callback() {
   1235         @Override
   1236         public boolean handleMessage(Message msg) {
   1237             switch (msg.what) {
   1238                 case MSG_PERFORM_POLL: {
   1239                     final int flags = msg.arg1;
   1240                     performPoll(flags);
   1241                     return true;
   1242                 }
   1243                 case MSG_UPDATE_IFACES: {
   1244                     updateIfaces();
   1245                     return true;
   1246                 }
   1247                 case MSG_REGISTER_GLOBAL_ALERT: {
   1248                     registerGlobalAlert();
   1249                     return true;
   1250                 }
   1251                 default: {
   1252                     return false;
   1253                 }
   1254             }
   1255         }
   1256     };
   1257 
   1258     private void assertBandwidthControlEnabled() {
   1259         if (!isBandwidthControlEnabled()) {
   1260             throw new IllegalStateException("Bandwidth module disabled");
   1261         }
   1262     }
   1263 
   1264     private boolean isBandwidthControlEnabled() {
   1265         final long token = Binder.clearCallingIdentity();
   1266         try {
   1267             return mNetworkManager.isBandwidthControlEnabled();
   1268         } catch (RemoteException e) {
   1269             // ignored; service lives in system_server
   1270             return false;
   1271         } finally {
   1272             Binder.restoreCallingIdentity(token);
   1273         }
   1274     }
   1275 
   1276     private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
   1277         @Override
   1278         public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
   1279                 int rightIndex, String cookie) {
   1280             Log.w(TAG, "found non-monotonic values; saving to dropbox");
   1281 
   1282             // record error for debugging
   1283             final StringBuilder builder = new StringBuilder();
   1284             builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
   1285                     + "] - right[" + rightIndex + "]\n");
   1286             builder.append("left=").append(left).append('\n');
   1287             builder.append("right=").append(right).append('\n');
   1288 
   1289             final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
   1290                     Context.DROPBOX_SERVICE);
   1291             dropBox.addText(TAG_NETSTATS_ERROR, builder.toString());
   1292         }
   1293     }
   1294 
   1295     /**
   1296      * Default external settings that read from
   1297      * {@link android.provider.Settings.Global}.
   1298      */
   1299     private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
   1300         private final ContentResolver mResolver;
   1301 
   1302         public DefaultNetworkStatsSettings(Context context) {
   1303             mResolver = checkNotNull(context.getContentResolver());
   1304             // TODO: adjust these timings for production builds
   1305         }
   1306 
   1307         private long getGlobalLong(String name, long def) {
   1308             return Settings.Global.getLong(mResolver, name, def);
   1309         }
   1310         private boolean getGlobalBoolean(String name, boolean def) {
   1311             final int defInt = def ? 1 : 0;
   1312             return Settings.Global.getInt(mResolver, name, defInt) != 0;
   1313         }
   1314 
   1315         @Override
   1316         public long getPollInterval() {
   1317             return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
   1318         }
   1319         @Override
   1320         public long getTimeCacheMaxAge() {
   1321             return getGlobalLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS);
   1322         }
   1323         @Override
   1324         public long getGlobalAlertBytes(long def) {
   1325             return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
   1326         }
   1327         @Override
   1328         public boolean getSampleEnabled() {
   1329             return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
   1330         }
   1331         @Override
   1332         public boolean getReportXtOverDev() {
   1333             return getGlobalBoolean(NETSTATS_REPORT_XT_OVER_DEV, true);
   1334         }
   1335         @Override
   1336         public Config getDevConfig() {
   1337             return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
   1338                     getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
   1339                     getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
   1340         }
   1341         @Override
   1342         public Config getXtConfig() {
   1343             return getDevConfig();
   1344         }
   1345         @Override
   1346         public Config getUidConfig() {
   1347             return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
   1348                     getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
   1349                     getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
   1350         }
   1351         @Override
   1352         public Config getUidTagConfig() {
   1353             return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
   1354                     getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
   1355                     getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
   1356         }
   1357         @Override
   1358         public long getDevPersistBytes(long def) {
   1359             return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
   1360         }
   1361         @Override
   1362         public long getXtPersistBytes(long def) {
   1363             return getDevPersistBytes(def);
   1364         }
   1365         @Override
   1366         public long getUidPersistBytes(long def) {
   1367             return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
   1368         }
   1369         @Override
   1370         public long getUidTagPersistBytes(long def) {
   1371             return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
   1372         }
   1373     }
   1374 }
   1375