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