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