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