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