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