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.READ_NETWORK_USAGE_HISTORY;
22import static android.content.Intent.ACTION_SHUTDOWN;
23import static android.content.Intent.ACTION_UID_REMOVED;
24import static android.content.Intent.ACTION_USER_REMOVED;
25import static android.content.Intent.EXTRA_UID;
26import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
27import static android.net.ConnectivityManager.isNetworkTypeMobile;
28import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
29import static android.net.NetworkStats.IFACE_ALL;
30import static android.net.NetworkStats.INTERFACES_ALL;
31import static android.net.NetworkStats.METERED_ALL;
32import static android.net.NetworkStats.ROAMING_ALL;
33import static android.net.NetworkStats.SET_ALL;
34import static android.net.NetworkStats.SET_DEFAULT;
35import static android.net.NetworkStats.SET_FOREGROUND;
36import static android.net.NetworkStats.STATS_PER_IFACE;
37import static android.net.NetworkStats.STATS_PER_UID;
38import static android.net.NetworkStats.TAG_ALL;
39import static android.net.NetworkStats.TAG_NONE;
40import static android.net.NetworkStats.UID_ALL;
41import static android.net.NetworkStatsHistory.FIELD_ALL;
42import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
43import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
44import static android.net.TrafficStats.KB_IN_BYTES;
45import static android.net.TrafficStats.MB_IN_BYTES;
46import static android.os.Trace.TRACE_TAG_NETWORK;
47import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
48import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
49import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
50import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
51import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
52import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
53import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
54import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
55import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
56import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
57import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
58import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
59import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
60import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
61import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
62import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
63import static android.text.format.DateUtils.DAY_IN_MILLIS;
64import static android.text.format.DateUtils.HOUR_IN_MILLIS;
65import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
66import static android.text.format.DateUtils.SECOND_IN_MILLIS;
67
68import static com.android.internal.util.Preconditions.checkNotNull;
69import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
70import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
71import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
72
73import android.annotation.NonNull;
74import android.app.AlarmManager;
75import android.app.PendingIntent;
76import android.app.usage.NetworkStatsManager;
77import android.content.BroadcastReceiver;
78import android.content.ContentResolver;
79import android.content.Context;
80import android.content.Intent;
81import android.content.IntentFilter;
82import android.content.pm.ApplicationInfo;
83import android.content.pm.PackageManager;
84import android.net.DataUsageRequest;
85import android.net.IConnectivityManager;
86import android.net.INetworkManagementEventObserver;
87import android.net.INetworkStatsService;
88import android.net.INetworkStatsSession;
89import android.net.LinkProperties;
90import android.net.Network;
91import android.net.NetworkCapabilities;
92import android.net.NetworkIdentity;
93import android.net.NetworkInfo;
94import android.net.NetworkState;
95import android.net.NetworkStats;
96import android.net.NetworkStats.NonMonotonicObserver;
97import android.net.NetworkStatsHistory;
98import android.net.NetworkTemplate;
99import android.net.TrafficStats;
100import android.os.BestClock;
101import android.os.Binder;
102import android.os.DropBoxManager;
103import android.os.Environment;
104import android.os.Handler;
105import android.os.HandlerThread;
106import android.os.IBinder;
107import android.os.INetworkManagementService;
108import android.os.Message;
109import android.os.Messenger;
110import android.os.PowerManager;
111import android.os.RemoteException;
112import android.os.SystemClock;
113import android.os.Trace;
114import android.os.UserHandle;
115import android.provider.Settings;
116import android.provider.Settings.Global;
117import android.service.NetworkInterfaceProto;
118import android.service.NetworkStatsServiceDumpProto;
119import android.telephony.SubscriptionPlan;
120import android.telephony.TelephonyManager;
121import android.text.format.DateUtils;
122import android.util.ArrayMap;
123import android.util.ArraySet;
124import android.util.EventLog;
125import android.util.Log;
126import android.util.MathUtils;
127import android.util.Slog;
128import android.util.SparseIntArray;
129import android.util.proto.ProtoOutputStream;
130
131import com.android.internal.annotations.GuardedBy;
132import com.android.internal.annotations.VisibleForTesting;
133import com.android.internal.net.NetworkStatsFactory;
134import com.android.internal.net.VpnInfo;
135import com.android.internal.util.ArrayUtils;
136import com.android.internal.util.DumpUtils;
137import com.android.internal.util.FileRotator;
138import com.android.internal.util.IndentingPrintWriter;
139import com.android.server.EventLogTags;
140import com.android.server.LocalServices;
141import com.android.server.connectivity.Tethering;
142
143import java.io.File;
144import java.io.FileDescriptor;
145import java.io.IOException;
146import java.io.PrintWriter;
147import java.time.Clock;
148import java.time.ZoneOffset;
149import java.util.Arrays;
150import java.util.HashSet;
151import java.util.List;
152
153/**
154 * Collect and persist detailed network statistics, and provide this data to
155 * other system services.
156 */
157public class NetworkStatsService extends INetworkStatsService.Stub {
158    static final String TAG = "NetworkStats";
159    static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
160    static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
161
162    private static final int MSG_PERFORM_POLL = 1;
163    private static final int MSG_UPDATE_IFACES = 2;
164    private static final int MSG_REGISTER_GLOBAL_ALERT = 3;
165
166    /** Flags to control detail level of poll event. */
167    private static final int FLAG_PERSIST_NETWORK = 0x1;
168    private static final int FLAG_PERSIST_UID = 0x2;
169    private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
170    private static final int FLAG_PERSIST_FORCE = 0x100;
171
172    private static final String TAG_NETSTATS_ERROR = "netstats_error";
173
174    private final Context mContext;
175    private final INetworkManagementService mNetworkManager;
176    private final AlarmManager mAlarmManager;
177    private final Clock mClock;
178    private final TelephonyManager mTeleManager;
179    private final NetworkStatsSettings mSettings;
180    private final NetworkStatsObservers mStatsObservers;
181
182    private final File mSystemDir;
183    private final File mBaseDir;
184
185    private final PowerManager.WakeLock mWakeLock;
186
187    private final boolean mUseBpfTrafficStats;
188
189    private IConnectivityManager mConnManager;
190
191    @VisibleForTesting
192    public static final String ACTION_NETWORK_STATS_POLL =
193            "com.android.server.action.NETWORK_STATS_POLL";
194    public static final String ACTION_NETWORK_STATS_UPDATED =
195            "com.android.server.action.NETWORK_STATS_UPDATED";
196
197    private PendingIntent mPollIntent;
198
199    private static final String PREFIX_DEV = "dev";
200    private static final String PREFIX_XT = "xt";
201    private static final String PREFIX_UID = "uid";
202    private static final String PREFIX_UID_TAG = "uid_tag";
203
204    /**
205     * Virtual network interface for video telephony. This is for VT data usage counting purpose.
206     */
207    public static final String VT_INTERFACE = "vt_data0";
208
209    /**
210     * Settings that can be changed externally.
211     */
212    public interface NetworkStatsSettings {
213        public long getPollInterval();
214        public boolean getSampleEnabled();
215        public boolean getAugmentEnabled();
216
217        public static class Config {
218            public final long bucketDuration;
219            public final long rotateAgeMillis;
220            public final long deleteAgeMillis;
221
222            public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
223                this.bucketDuration = bucketDuration;
224                this.rotateAgeMillis = rotateAgeMillis;
225                this.deleteAgeMillis = deleteAgeMillis;
226            }
227        }
228
229        public Config getDevConfig();
230        public Config getXtConfig();
231        public Config getUidConfig();
232        public Config getUidTagConfig();
233
234        public long getGlobalAlertBytes(long def);
235        public long getDevPersistBytes(long def);
236        public long getXtPersistBytes(long def);
237        public long getUidPersistBytes(long def);
238        public long getUidTagPersistBytes(long def);
239    }
240
241    private final Object mStatsLock = new Object();
242
243    /** Set of currently active ifaces. */
244    @GuardedBy("mStatsLock")
245    private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
246
247    /** Set of currently active ifaces for UID stats. */
248    @GuardedBy("mStatsLock")
249    private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
250
251    /** Current default active iface. */
252    private String mActiveIface;
253
254    /** Set of any ifaces associated with mobile networks since boot. */
255    @GuardedBy("mStatsLock")
256    private String[] mMobileIfaces = new String[0];
257
258    /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
259    @GuardedBy("mStatsLock")
260    private Network[] mDefaultNetworks = new Network[0];
261
262    private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
263            new DropBoxNonMonotonicObserver();
264
265    @GuardedBy("mStatsLock")
266    private NetworkStatsRecorder mDevRecorder;
267    @GuardedBy("mStatsLock")
268    private NetworkStatsRecorder mXtRecorder;
269    @GuardedBy("mStatsLock")
270    private NetworkStatsRecorder mUidRecorder;
271    @GuardedBy("mStatsLock")
272    private NetworkStatsRecorder mUidTagRecorder;
273
274    /** Cached {@link #mXtRecorder} stats. */
275    @GuardedBy("mStatsLock")
276    private NetworkStatsCollection mXtStatsCached;
277
278    /** Current counter sets for each UID. */
279    private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
280
281    /** Data layer operation counters for splicing into other structures. */
282    private NetworkStats mUidOperations = new NetworkStats(0L, 10);
283
284    /** Must be set in factory by calling #setHandler. */
285    private Handler mHandler;
286    private Handler.Callback mHandlerCallback;
287
288    private volatile boolean mSystemReady;
289    private long mPersistThreshold = 2 * MB_IN_BYTES;
290    private long mGlobalAlertBytes;
291
292    private static final long POLL_RATE_LIMIT_MS = 15_000;
293
294    private long mLastStatsSessionPoll;
295
296    /** Map from UID to number of opened sessions */
297    @GuardedBy("mOpenSessionCallsPerUid")
298    private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
299
300    private final static int DUMP_STATS_SESSION_COUNT = 20;
301
302    private static @NonNull File getDefaultSystemDir() {
303        return new File(Environment.getDataDirectory(), "system");
304    }
305
306    private static @NonNull File getDefaultBaseDir() {
307        File baseDir = new File(getDefaultSystemDir(), "netstats");
308        baseDir.mkdirs();
309        return baseDir;
310    }
311
312    private static @NonNull Clock getDefaultClock() {
313        return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
314                Clock.systemUTC());
315    }
316
317    public static NetworkStatsService create(Context context,
318                INetworkManagementService networkManager) {
319        AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
320        PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
321        PowerManager.WakeLock wakeLock =
322                powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
323
324        NetworkStatsService service = new NetworkStatsService(context, networkManager, alarmManager,
325                wakeLock, getDefaultClock(), TelephonyManager.getDefault(),
326                new DefaultNetworkStatsSettings(context), new NetworkStatsObservers(),
327                getDefaultSystemDir(), getDefaultBaseDir());
328
329        HandlerThread handlerThread = new HandlerThread(TAG);
330        Handler.Callback callback = new HandlerCallback(service);
331        handlerThread.start();
332        Handler handler = new Handler(handlerThread.getLooper(), callback);
333        service.setHandler(handler, callback);
334        return service;
335    }
336
337    @VisibleForTesting
338    NetworkStatsService(Context context, INetworkManagementService networkManager,
339            AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
340            TelephonyManager teleManager, NetworkStatsSettings settings,
341            NetworkStatsObservers statsObservers, File systemDir, File baseDir) {
342        mContext = checkNotNull(context, "missing Context");
343        mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
344        mAlarmManager = checkNotNull(alarmManager, "missing AlarmManager");
345        mClock = checkNotNull(clock, "missing Clock");
346        mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
347        mTeleManager = checkNotNull(teleManager, "missing TelephonyManager");
348        mWakeLock = checkNotNull(wakeLock, "missing WakeLock");
349        mStatsObservers = checkNotNull(statsObservers, "missing NetworkStatsObservers");
350        mSystemDir = checkNotNull(systemDir, "missing systemDir");
351        mBaseDir = checkNotNull(baseDir, "missing baseDir");
352        mUseBpfTrafficStats = new File("/sys/fs/bpf/traffic_uid_stats_map").exists();
353
354        LocalServices.addService(NetworkStatsManagerInternal.class,
355                new NetworkStatsManagerInternalImpl());
356    }
357
358    @VisibleForTesting
359    void setHandler(Handler handler, Handler.Callback callback) {
360        mHandler = handler;
361        mHandlerCallback = callback;
362    }
363
364    public void bindConnectivityManager(IConnectivityManager connManager) {
365        mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
366    }
367
368    public void systemReady() {
369        mSystemReady = true;
370
371        if (!isBandwidthControlEnabled()) {
372            Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
373            return;
374        }
375
376        synchronized (mStatsLock) {
377            // create data recorders along with historical rotators
378            mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
379            mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
380            mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
381            mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
382
383            updatePersistThresholdsLocked();
384
385            // upgrade any legacy stats, migrating them to rotated files
386            maybeUpgradeLegacyStatsLocked();
387
388            // read historical network stats from disk, since policy service
389            // might need them right away.
390            mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
391
392            // bootstrap initial stats to prevent double-counting later
393            bootstrapStatsLocked();
394        }
395
396        // watch for tethering changes
397        final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
398        mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
399
400        // listen for periodic polling events
401        final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
402        mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
403
404        // listen for uid removal to clean stats
405        final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
406        mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
407
408        // listen for user changes to clean stats
409        final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
410        mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
411
412        // persist stats during clean shutdown
413        final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
414        mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
415
416        try {
417            mNetworkManager.registerObserver(mAlertObserver);
418        } catch (RemoteException e) {
419            // ignored; service lives in system_server
420        }
421
422        registerPollAlarmLocked();
423        registerGlobalAlert();
424    }
425
426    private NetworkStatsRecorder buildRecorder(
427            String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
428        final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
429                Context.DROPBOX_SERVICE);
430        return new NetworkStatsRecorder(new FileRotator(
431                mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
432                mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
433    }
434
435    @GuardedBy("mStatsLock")
436    private void shutdownLocked() {
437        mContext.unregisterReceiver(mTetherReceiver);
438        mContext.unregisterReceiver(mPollReceiver);
439        mContext.unregisterReceiver(mRemovedReceiver);
440        mContext.unregisterReceiver(mUserReceiver);
441        mContext.unregisterReceiver(mShutdownReceiver);
442
443        final long currentTime = mClock.millis();
444
445        // persist any pending stats
446        mDevRecorder.forcePersistLocked(currentTime);
447        mXtRecorder.forcePersistLocked(currentTime);
448        mUidRecorder.forcePersistLocked(currentTime);
449        mUidTagRecorder.forcePersistLocked(currentTime);
450
451        mSystemReady = false;
452    }
453
454    @GuardedBy("mStatsLock")
455    private void maybeUpgradeLegacyStatsLocked() {
456        File file;
457        try {
458            file = new File(mSystemDir, "netstats.bin");
459            if (file.exists()) {
460                mDevRecorder.importLegacyNetworkLocked(file);
461                file.delete();
462            }
463
464            file = new File(mSystemDir, "netstats_xt.bin");
465            if (file.exists()) {
466                file.delete();
467            }
468
469            file = new File(mSystemDir, "netstats_uid.bin");
470            if (file.exists()) {
471                mUidRecorder.importLegacyUidLocked(file);
472                mUidTagRecorder.importLegacyUidLocked(file);
473                file.delete();
474            }
475        } catch (IOException e) {
476            Log.wtf(TAG, "problem during legacy upgrade", e);
477        } catch (OutOfMemoryError e) {
478            Log.wtf(TAG, "problem during legacy upgrade", e);
479        }
480    }
481
482    /**
483     * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
484     * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
485     */
486    private void registerPollAlarmLocked() {
487        if (mPollIntent != null) {
488            mAlarmManager.cancel(mPollIntent);
489        }
490
491        mPollIntent = PendingIntent.getBroadcast(
492                mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
493
494        final long currentRealtime = SystemClock.elapsedRealtime();
495        mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
496                mSettings.getPollInterval(), mPollIntent);
497    }
498
499    /**
500     * Register for a global alert that is delivered through
501     * {@link INetworkManagementEventObserver} once a threshold amount of data
502     * has been transferred.
503     */
504    private void registerGlobalAlert() {
505        try {
506            mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
507        } catch (IllegalStateException e) {
508            Slog.w(TAG, "problem registering for global alert: " + e);
509        } catch (RemoteException e) {
510            // ignored; service lives in system_server
511        }
512    }
513
514    @Override
515    public INetworkStatsSession openSession() {
516        // NOTE: if callers want to get non-augmented data, they should go
517        // through the public API
518        return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
519    }
520
521    @Override
522    public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) {
523        return openSessionInternal(flags, callingPackage);
524    }
525
526    private boolean isRateLimitedForPoll(int callingUid) {
527        if (callingUid == android.os.Process.SYSTEM_UID) {
528            return false;
529        }
530
531        final long lastCallTime;
532        final long now = SystemClock.elapsedRealtime();
533        synchronized (mOpenSessionCallsPerUid) {
534            int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
535            mOpenSessionCallsPerUid.put(callingUid, calls + 1);
536            lastCallTime = mLastStatsSessionPoll;
537            mLastStatsSessionPoll = now;
538        }
539
540        return now - lastCallTime < POLL_RATE_LIMIT_MS;
541    }
542
543    private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
544        assertBandwidthControlEnabled();
545
546        final int callingUid = Binder.getCallingUid();
547        final int usedFlags = isRateLimitedForPoll(callingUid)
548                ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
549                : flags;
550        if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
551                | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
552            final long ident = Binder.clearCallingIdentity();
553            try {
554                performPoll(FLAG_PERSIST_ALL);
555            } finally {
556                Binder.restoreCallingIdentity(ident);
557            }
558        }
559
560        // return an IBinder which holds strong references to any loaded stats
561        // for its lifetime; when caller closes only weak references remain.
562
563        return new INetworkStatsSession.Stub() {
564            private final int mCallingUid = callingUid;
565            private final String mCallingPackage = callingPackage;
566            private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
567                    callingPackage);
568
569            private NetworkStatsCollection mUidComplete;
570            private NetworkStatsCollection mUidTagComplete;
571
572            private NetworkStatsCollection getUidComplete() {
573                synchronized (mStatsLock) {
574                    if (mUidComplete == null) {
575                        mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
576                    }
577                    return mUidComplete;
578                }
579            }
580
581            private NetworkStatsCollection getUidTagComplete() {
582                synchronized (mStatsLock) {
583                    if (mUidTagComplete == null) {
584                        mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
585                    }
586                    return mUidTagComplete;
587                }
588            }
589
590            @Override
591            public int[] getRelevantUids() {
592                return getUidComplete().getRelevantUids(mAccessLevel);
593            }
594
595            @Override
596            public NetworkStats getDeviceSummaryForNetwork(
597                    NetworkTemplate template, long start, long end) {
598                return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
599                        mCallingUid);
600            }
601
602            @Override
603            public NetworkStats getSummaryForNetwork(
604                    NetworkTemplate template, long start, long end) {
605                return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
606                        mCallingUid);
607            }
608
609            @Override
610            public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
611                return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
612                        mCallingUid);
613            }
614
615            @Override
616            public NetworkStats getSummaryForAllUid(
617                    NetworkTemplate template, long start, long end, boolean includeTags) {
618                try {
619                    final NetworkStats stats = getUidComplete()
620                            .getSummary(template, start, end, mAccessLevel, mCallingUid);
621                    if (includeTags) {
622                        final NetworkStats tagStats = getUidTagComplete()
623                                .getSummary(template, start, end, mAccessLevel, mCallingUid);
624                        stats.combineAllValues(tagStats);
625                    }
626                    return stats;
627                } catch (NullPointerException e) {
628                    // TODO: Track down and fix the cause of this crash and remove this catch block.
629                    Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
630                    throw e;
631                }
632            }
633
634            @Override
635            public NetworkStatsHistory getHistoryForUid(
636                    NetworkTemplate template, int uid, int set, int tag, int fields) {
637                // NOTE: We don't augment UID-level statistics
638                if (tag == TAG_NONE) {
639                    return getUidComplete().getHistory(template, null, uid, set, tag, fields,
640                            Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
641                } else {
642                    return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
643                            Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
644                }
645            }
646
647            @Override
648            public NetworkStatsHistory getHistoryIntervalForUid(
649                    NetworkTemplate template, int uid, int set, int tag, int fields,
650                    long start, long end) {
651                // NOTE: We don't augment UID-level statistics
652                if (tag == TAG_NONE) {
653                    return getUidComplete().getHistory(template, null, uid, set, tag, fields,
654                            start, end, mAccessLevel, mCallingUid);
655                } else if (uid == Binder.getCallingUid()) {
656                    return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
657                            start, end, mAccessLevel, mCallingUid);
658                } else {
659                    throw new SecurityException("Calling package " + mCallingPackage
660                            + " cannot access tag information from a different uid");
661                }
662            }
663
664            @Override
665            public void close() {
666                mUidComplete = null;
667                mUidTagComplete = null;
668            }
669        };
670    }
671
672    private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
673        return NetworkStatsAccess.checkAccessLevel(
674                mContext, Binder.getCallingUid(), callingPackage);
675    }
676
677    /**
678     * Find the most relevant {@link SubscriptionPlan} for the given
679     * {@link NetworkTemplate} and flags. This is typically used to augment
680     * local measurement results to match a known anchor from the carrier.
681     */
682    private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) {
683        SubscriptionPlan plan = null;
684        if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
685                && mSettings.getAugmentEnabled()) {
686            if (LOGD) Slog.d(TAG, "Resolving plan for " + template);
687            final long token = Binder.clearCallingIdentity();
688            try {
689                plan = LocalServices.getService(NetworkPolicyManagerInternal.class)
690                        .getSubscriptionPlan(template);
691            } finally {
692                Binder.restoreCallingIdentity(token);
693            }
694            if (LOGD) Slog.d(TAG, "Resolved to plan " + plan);
695        }
696        return plan;
697    }
698
699    /**
700     * Return network summary, splicing between DEV and XT stats when
701     * appropriate.
702     */
703    private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags,
704            long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
705        // We've been using pure XT stats long enough that we no longer need to
706        // splice DEV and XT together.
707        final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
708                accessLevel, callingUid);
709
710        final long now = System.currentTimeMillis();
711        final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
712
713        final NetworkStats stats = new NetworkStats(end - start, 1);
714        stats.addValues(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
715                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
716                entry.txBytes, entry.txPackets, entry.operations));
717        return stats;
718    }
719
720    /**
721     * Return network history, splicing between DEV and XT stats when
722     * appropriate.
723     */
724    private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
725            int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
726        // We've been using pure XT stats long enough that we no longer need to
727        // splice DEV and XT together.
728        final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
729        synchronized (mStatsLock) {
730            return mXtStatsCached.getHistory(template, augmentPlan,
731                    UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
732                    accessLevel, callingUid);
733        }
734    }
735
736    private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
737        assertSystemReady();
738        assertBandwidthControlEnabled();
739
740        // NOTE: if callers want to get non-augmented data, they should go
741        // through the public API
742        return internalGetSummaryForNetwork(template,
743                NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
744                NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
745    }
746
747    private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
748        assertSystemReady();
749        assertBandwidthControlEnabled();
750
751        final NetworkStatsCollection uidComplete;
752        synchronized (mStatsLock) {
753            uidComplete = mUidRecorder.getOrLoadCompleteLocked();
754        }
755        return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE,
756                android.os.Process.SYSTEM_UID);
757    }
758
759    @Override
760    public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
761        if (Binder.getCallingUid() != uid) {
762            mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
763        }
764        assertBandwidthControlEnabled();
765
766        // TODO: switch to data layer stats once kernel exports
767        // for now, read network layer stats and flatten across all ifaces
768        final long token = Binder.clearCallingIdentity();
769        final NetworkStats networkLayer;
770        try {
771            networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid,
772                    NetworkStats.INTERFACES_ALL);
773        } finally {
774            Binder.restoreCallingIdentity(token);
775        }
776
777        // splice in operation counts
778        networkLayer.spliceOperationsFrom(mUidOperations);
779
780        final NetworkStats dataLayer = new NetworkStats(
781                networkLayer.getElapsedRealtime(), networkLayer.size());
782
783        NetworkStats.Entry entry = null;
784        for (int i = 0; i < networkLayer.size(); i++) {
785            entry = networkLayer.getValues(i, entry);
786            entry.iface = IFACE_ALL;
787            dataLayer.combineValues(entry);
788        }
789
790        return dataLayer;
791    }
792
793    @Override
794    public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
795        try {
796            final String[] ifacesToQuery =
797                    NetworkStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
798            return getNetworkStatsUidDetail(ifacesToQuery);
799        } catch (RemoteException e) {
800            Log.wtf(TAG, "Error compiling UID stats", e);
801            return new NetworkStats(0L, 0);
802        }
803    }
804
805    @Override
806    public String[] getMobileIfaces() {
807        return mMobileIfaces;
808    }
809
810    @Override
811    public void incrementOperationCount(int uid, int tag, int operationCount) {
812        if (Binder.getCallingUid() != uid) {
813            mContext.enforceCallingOrSelfPermission(
814                    android.Manifest.permission.UPDATE_DEVICE_STATS, TAG);
815        }
816
817        if (operationCount < 0) {
818            throw new IllegalArgumentException("operation count can only be incremented");
819        }
820        if (tag == TAG_NONE) {
821            throw new IllegalArgumentException("operation count must have specific tag");
822        }
823
824        synchronized (mStatsLock) {
825            final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
826            mUidOperations.combineValues(
827                    mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
828            mUidOperations.combineValues(
829                    mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
830        }
831    }
832
833    @VisibleForTesting
834    void setUidForeground(int uid, boolean uidForeground) {
835        synchronized (mStatsLock) {
836            final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
837            final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
838            if (oldSet != set) {
839                mActiveUidCounterSet.put(uid, set);
840                setKernelCounterSet(uid, set);
841            }
842        }
843    }
844
845    @Override
846    public void forceUpdateIfaces(Network[] defaultNetworks) {
847        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
848        assertBandwidthControlEnabled();
849
850        final long token = Binder.clearCallingIdentity();
851        try {
852            updateIfaces(defaultNetworks);
853        } finally {
854            Binder.restoreCallingIdentity(token);
855        }
856    }
857
858    @Override
859    public void forceUpdate() {
860        mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
861        assertBandwidthControlEnabled();
862
863        final long token = Binder.clearCallingIdentity();
864        try {
865            performPoll(FLAG_PERSIST_ALL);
866        } finally {
867            Binder.restoreCallingIdentity(token);
868        }
869    }
870
871    private void advisePersistThreshold(long thresholdBytes) {
872        assertBandwidthControlEnabled();
873
874        // clamp threshold into safe range
875        mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
876        if (LOGV) {
877            Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
878                    + mPersistThreshold);
879        }
880
881        // update and persist if beyond new thresholds
882        final long currentTime = mClock.millis();
883        synchronized (mStatsLock) {
884            if (!mSystemReady) return;
885
886            updatePersistThresholdsLocked();
887
888            mDevRecorder.maybePersistLocked(currentTime);
889            mXtRecorder.maybePersistLocked(currentTime);
890            mUidRecorder.maybePersistLocked(currentTime);
891            mUidTagRecorder.maybePersistLocked(currentTime);
892        }
893
894        // re-arm global alert
895        registerGlobalAlert();
896    }
897
898    @Override
899    public DataUsageRequest registerUsageCallback(String callingPackage,
900                DataUsageRequest request, Messenger messenger, IBinder binder) {
901        checkNotNull(callingPackage, "calling package is null");
902        checkNotNull(request, "DataUsageRequest is null");
903        checkNotNull(request.template, "NetworkTemplate is null");
904        checkNotNull(messenger, "messenger is null");
905        checkNotNull(binder, "binder is null");
906
907        int callingUid = Binder.getCallingUid();
908        @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
909        DataUsageRequest normalizedRequest;
910        final long token = Binder.clearCallingIdentity();
911        try {
912            normalizedRequest = mStatsObservers.register(request, messenger, binder,
913                    callingUid, accessLevel);
914        } finally {
915            Binder.restoreCallingIdentity(token);
916        }
917
918        // Create baseline stats
919        mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL, FLAG_PERSIST_ALL));
920
921        return normalizedRequest;
922   }
923
924    @Override
925    public void unregisterUsageRequest(DataUsageRequest request) {
926        checkNotNull(request, "DataUsageRequest is null");
927
928        int callingUid = Binder.getCallingUid();
929        final long token = Binder.clearCallingIdentity();
930        try {
931            mStatsObservers.unregister(request, callingUid);
932        } finally {
933            Binder.restoreCallingIdentity(token);
934        }
935    }
936
937    @Override
938    public long getUidStats(int uid, int type) {
939        return nativeGetUidStat(uid, type, checkBpfStatsEnable());
940    }
941
942    @Override
943    public long getIfaceStats(String iface, int type) {
944        return nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
945    }
946
947    @Override
948    public long getTotalStats(int type) {
949        return nativeGetTotalStat(type, checkBpfStatsEnable());
950    }
951
952    private boolean checkBpfStatsEnable() {
953        return mUseBpfTrafficStats;
954    }
955
956    /**
957     * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
958     * reflect current {@link #mPersistThreshold} value. Always defers to
959     * {@link Global} values when defined.
960     */
961    @GuardedBy("mStatsLock")
962    private void updatePersistThresholdsLocked() {
963        mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
964        mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
965        mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
966        mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
967        mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
968    }
969
970    /**
971     * Receiver that watches for {@link Tethering} to claim interface pairs.
972     */
973    private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
974        @Override
975        public void onReceive(Context context, Intent intent) {
976            // on background handler thread, and verified CONNECTIVITY_INTERNAL
977            // permission above.
978            performPoll(FLAG_PERSIST_NETWORK);
979        }
980    };
981
982    private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
983        @Override
984        public void onReceive(Context context, Intent intent) {
985            // on background handler thread, and verified UPDATE_DEVICE_STATS
986            // permission above.
987            performPoll(FLAG_PERSIST_ALL);
988
989            // verify that we're watching global alert
990            registerGlobalAlert();
991        }
992    };
993
994    private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
995        @Override
996        public void onReceive(Context context, Intent intent) {
997            // on background handler thread, and UID_REMOVED is protected
998            // broadcast.
999
1000            final int uid = intent.getIntExtra(EXTRA_UID, -1);
1001            if (uid == -1) return;
1002
1003            synchronized (mStatsLock) {
1004                mWakeLock.acquire();
1005                try {
1006                    removeUidsLocked(uid);
1007                } finally {
1008                    mWakeLock.release();
1009                }
1010            }
1011        }
1012    };
1013
1014    private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
1015        @Override
1016        public void onReceive(Context context, Intent intent) {
1017            // On background handler thread, and USER_REMOVED is protected
1018            // broadcast.
1019
1020            final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
1021            if (userId == -1) return;
1022
1023            synchronized (mStatsLock) {
1024                mWakeLock.acquire();
1025                try {
1026                    removeUserLocked(userId);
1027                } finally {
1028                    mWakeLock.release();
1029                }
1030            }
1031        }
1032    };
1033
1034    private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
1035        @Override
1036        public void onReceive(Context context, Intent intent) {
1037            // SHUTDOWN is protected broadcast.
1038            synchronized (mStatsLock) {
1039                shutdownLocked();
1040            }
1041        }
1042    };
1043
1044    /**
1045     * Observer that watches for {@link INetworkManagementService} alerts.
1046     */
1047    private INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
1048        @Override
1049        public void limitReached(String limitName, String iface) {
1050            // only someone like NMS should be calling us
1051            mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
1052
1053            if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
1054                // kick off background poll to collect network stats; UID stats
1055                // are handled during normal polling interval.
1056                final int flags = FLAG_PERSIST_NETWORK;
1057                mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget();
1058
1059                // re-arm global alert for next update
1060                mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget();
1061            }
1062        }
1063    };
1064
1065    private void updateIfaces(Network[] defaultNetworks) {
1066        synchronized (mStatsLock) {
1067            mWakeLock.acquire();
1068            try {
1069                updateIfacesLocked(defaultNetworks);
1070            } finally {
1071                mWakeLock.release();
1072            }
1073        }
1074    }
1075
1076    /**
1077     * Inspect all current {@link NetworkState} to derive mapping from {@code
1078     * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
1079     * are active on a single {@code iface}, they are combined under a single
1080     * {@link NetworkIdentitySet}.
1081     */
1082    @GuardedBy("mStatsLock")
1083    private void updateIfacesLocked(Network[] defaultNetworks) {
1084        if (!mSystemReady) return;
1085        if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
1086
1087        // take one last stats snapshot before updating iface mapping. this
1088        // isn't perfect, since the kernel may already be counting traffic from
1089        // the updated network.
1090
1091        // poll, but only persist network stats to keep codepath fast. UID stats
1092        // will be persisted during next alarm poll event.
1093        performPollLocked(FLAG_PERSIST_NETWORK);
1094
1095        final NetworkState[] states;
1096        final LinkProperties activeLink;
1097        try {
1098            states = mConnManager.getAllNetworkState();
1099            activeLink = mConnManager.getActiveLinkProperties();
1100        } catch (RemoteException e) {
1101            // ignored; service lives in system_server
1102            return;
1103        }
1104
1105        mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
1106
1107        // Rebuild active interfaces based on connected networks
1108        mActiveIfaces.clear();
1109        mActiveUidIfaces.clear();
1110        if (defaultNetworks != null) {
1111            // Caller is ConnectivityService. Update the list of default networks.
1112            mDefaultNetworks = defaultNetworks;
1113        }
1114
1115        final ArraySet<String> mobileIfaces = new ArraySet<>();
1116        for (NetworkState state : states) {
1117            if (state.networkInfo.isConnected()) {
1118                final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
1119                final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, state.network);
1120                final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state,
1121                        isDefault);
1122
1123                // Traffic occurring on the base interface is always counted for
1124                // both total usage and UID details.
1125                final String baseIface = state.linkProperties.getInterfaceName();
1126                if (baseIface != null) {
1127                    findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
1128                    findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
1129
1130                    // Build a separate virtual interface for VT (Video Telephony) data usage.
1131                    // Only do this when IMS is not metered, but VT is metered.
1132                    // If IMS is metered, then the IMS network usage has already included VT usage.
1133                    // VT is considered always metered in framework's layer. If VT is not metered
1134                    // per carrier's policy, modem will report 0 usage for VT calls.
1135                    if (state.networkCapabilities.hasCapability(
1136                            NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) {
1137
1138                        // Copy the identify from IMS one but mark it as metered.
1139                        NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
1140                                ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
1141                                ident.getRoaming(), true /* metered */,
1142                                true /* onDefaultNetwork */);
1143                        findOrCreateNetworkIdentitySet(mActiveIfaces, VT_INTERFACE).add(vtIdent);
1144                        findOrCreateNetworkIdentitySet(mActiveUidIfaces, VT_INTERFACE).add(vtIdent);
1145                    }
1146
1147                    if (isMobile) {
1148                        mobileIfaces.add(baseIface);
1149                    }
1150                }
1151
1152                // Traffic occurring on stacked interfaces is usually clatd,
1153                // which is already accounted against its final egress interface
1154                // by the kernel. Thus, we only need to collect stacked
1155                // interface stats at the UID level.
1156                final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
1157                for (LinkProperties stackedLink : stackedLinks) {
1158                    final String stackedIface = stackedLink.getInterfaceName();
1159                    if (stackedIface != null) {
1160                        findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
1161                        if (isMobile) {
1162                            mobileIfaces.add(stackedIface);
1163                        }
1164
1165                        NetworkStatsFactory.noteStackedIface(stackedIface, baseIface);
1166                    }
1167                }
1168            }
1169        }
1170
1171        mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
1172    }
1173
1174    private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
1175            ArrayMap<K, NetworkIdentitySet> map, K key) {
1176        NetworkIdentitySet ident = map.get(key);
1177        if (ident == null) {
1178            ident = new NetworkIdentitySet();
1179            map.put(key, ident);
1180        }
1181        return ident;
1182    }
1183
1184    @GuardedBy("mStatsLock")
1185    private void recordSnapshotLocked(long currentTime) throws RemoteException {
1186        // snapshot and record current counters; read UID stats first to
1187        // avoid over counting dev stats.
1188        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
1189        final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
1190        Trace.traceEnd(TRACE_TAG_NETWORK);
1191        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
1192        final NetworkStats xtSnapshot = getNetworkStatsXt();
1193        Trace.traceEnd(TRACE_TAG_NETWORK);
1194        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
1195        final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
1196        Trace.traceEnd(TRACE_TAG_NETWORK);
1197
1198        // Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats
1199        // providers that isn't already counted by dev and XT stats.
1200        Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotTether");
1201        final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
1202        Trace.traceEnd(TRACE_TAG_NETWORK);
1203        xtSnapshot.combineAllValues(tetherSnapshot);
1204        devSnapshot.combineAllValues(tetherSnapshot);
1205
1206        // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
1207        // can't be reattributed to responsible apps.
1208        Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
1209        mDevRecorder.recordSnapshotLocked(
1210                devSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
1211        Trace.traceEnd(TRACE_TAG_NETWORK);
1212        Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
1213        mXtRecorder.recordSnapshotLocked(
1214                xtSnapshot, mActiveIfaces, null /* vpnArray */, currentTime);
1215        Trace.traceEnd(TRACE_TAG_NETWORK);
1216
1217        // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
1218        VpnInfo[] vpnArray = mConnManager.getAllVpnInfo();
1219        Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
1220        mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
1221        Trace.traceEnd(TRACE_TAG_NETWORK);
1222        Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
1223        mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, vpnArray, currentTime);
1224        Trace.traceEnd(TRACE_TAG_NETWORK);
1225
1226        // We need to make copies of member fields that are sent to the observer to avoid
1227        // a race condition between the service handler thread and the observer's
1228        mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
1229                new ArrayMap<>(mActiveUidIfaces), vpnArray, currentTime);
1230    }
1231
1232    /**
1233     * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
1234     * so we have baseline values without double-counting.
1235     */
1236    @GuardedBy("mStatsLock")
1237    private void bootstrapStatsLocked() {
1238        final long currentTime = mClock.millis();
1239
1240        try {
1241            recordSnapshotLocked(currentTime);
1242        } catch (IllegalStateException e) {
1243            Slog.w(TAG, "problem reading network stats: " + e);
1244        } catch (RemoteException e) {
1245            // ignored; service lives in system_server
1246        }
1247    }
1248
1249    private void performPoll(int flags) {
1250        synchronized (mStatsLock) {
1251            mWakeLock.acquire();
1252
1253            try {
1254                performPollLocked(flags);
1255            } finally {
1256                mWakeLock.release();
1257            }
1258        }
1259    }
1260
1261    /**
1262     * Periodic poll operation, reading current statistics and recording into
1263     * {@link NetworkStatsHistory}.
1264     */
1265    @GuardedBy("mStatsLock")
1266    private void performPollLocked(int flags) {
1267        if (!mSystemReady) return;
1268        if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
1269        Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
1270
1271        final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
1272        final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
1273        final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
1274
1275        // TODO: consider marking "untrusted" times in historical stats
1276        final long currentTime = mClock.millis();
1277
1278        try {
1279            recordSnapshotLocked(currentTime);
1280        } catch (IllegalStateException e) {
1281            Log.wtf(TAG, "problem reading network stats", e);
1282            return;
1283        } catch (RemoteException e) {
1284            // ignored; service lives in system_server
1285            return;
1286        }
1287
1288        // persist any pending data depending on requested flags
1289        Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
1290        if (persistForce) {
1291            mDevRecorder.forcePersistLocked(currentTime);
1292            mXtRecorder.forcePersistLocked(currentTime);
1293            mUidRecorder.forcePersistLocked(currentTime);
1294            mUidTagRecorder.forcePersistLocked(currentTime);
1295        } else {
1296            if (persistNetwork) {
1297                mDevRecorder.maybePersistLocked(currentTime);
1298                mXtRecorder.maybePersistLocked(currentTime);
1299            }
1300            if (persistUid) {
1301                mUidRecorder.maybePersistLocked(currentTime);
1302                mUidTagRecorder.maybePersistLocked(currentTime);
1303            }
1304        }
1305        Trace.traceEnd(TRACE_TAG_NETWORK);
1306
1307        if (mSettings.getSampleEnabled()) {
1308            // sample stats after each full poll
1309            performSampleLocked();
1310        }
1311
1312        // finally, dispatch updated event to any listeners
1313        final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
1314        updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
1315        mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
1316                READ_NETWORK_USAGE_HISTORY);
1317
1318        Trace.traceEnd(TRACE_TAG_NETWORK);
1319    }
1320
1321    /**
1322     * Sample recent statistics summary into {@link EventLog}.
1323     */
1324    @GuardedBy("mStatsLock")
1325    private void performSampleLocked() {
1326        // TODO: migrate trustedtime fixes to separate binary log events
1327        final long currentTime = mClock.millis();
1328
1329        NetworkTemplate template;
1330        NetworkStats.Entry devTotal;
1331        NetworkStats.Entry xtTotal;
1332        NetworkStats.Entry uidTotal;
1333
1334        // collect mobile sample
1335        template = buildTemplateMobileWildcard();
1336        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
1337        xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
1338        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1339
1340        EventLogTags.writeNetstatsMobileSample(
1341                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1342                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1343                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1344                currentTime);
1345
1346        // collect wifi sample
1347        template = buildTemplateWifiWildcard();
1348        devTotal = mDevRecorder.getTotalSinceBootLocked(template);
1349        xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
1350        uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1351
1352        EventLogTags.writeNetstatsWifiSample(
1353                devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1354                xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1355                uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1356                currentTime);
1357    }
1358
1359    /**
1360     * Clean up {@link #mUidRecorder} after UID is removed.
1361     */
1362    @GuardedBy("mStatsLock")
1363    private void removeUidsLocked(int... uids) {
1364        if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
1365
1366        // Perform one last poll before removing
1367        performPollLocked(FLAG_PERSIST_ALL);
1368
1369        mUidRecorder.removeUidsLocked(uids);
1370        mUidTagRecorder.removeUidsLocked(uids);
1371
1372        // Clear kernel stats associated with UID
1373        for (int uid : uids) {
1374            resetKernelUidStats(uid);
1375        }
1376    }
1377
1378    /**
1379     * Clean up {@link #mUidRecorder} after user is removed.
1380     */
1381    @GuardedBy("mStatsLock")
1382    private void removeUserLocked(int userId) {
1383        if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
1384
1385        // Build list of UIDs that we should clean up
1386        int[] uids = new int[0];
1387        final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1388                PackageManager.MATCH_ANY_USER
1389                | PackageManager.MATCH_DISABLED_COMPONENTS);
1390        for (ApplicationInfo app : apps) {
1391            final int uid = UserHandle.getUid(userId, app.uid);
1392            uids = ArrayUtils.appendInt(uids, uid);
1393        }
1394
1395        removeUidsLocked(uids);
1396    }
1397
1398    private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal {
1399        @Override
1400        public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
1401            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes");
1402            try {
1403                return NetworkStatsService.this.getNetworkTotalBytes(template, start, end);
1404            } finally {
1405                Trace.traceEnd(TRACE_TAG_NETWORK);
1406            }
1407        }
1408
1409        @Override
1410        public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
1411            Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes");
1412            try {
1413                return NetworkStatsService.this.getNetworkUidBytes(template, start, end);
1414            } finally {
1415                Trace.traceEnd(TRACE_TAG_NETWORK);
1416            }
1417        }
1418
1419        @Override
1420        public void setUidForeground(int uid, boolean uidForeground) {
1421            NetworkStatsService.this.setUidForeground(uid, uidForeground);
1422        }
1423
1424        @Override
1425        public void advisePersistThreshold(long thresholdBytes) {
1426            NetworkStatsService.this.advisePersistThreshold(thresholdBytes);
1427        }
1428
1429        @Override
1430        public void forceUpdate() {
1431            NetworkStatsService.this.forceUpdate();
1432        }
1433    }
1434
1435    @Override
1436    protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
1437        if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
1438
1439        long duration = DateUtils.DAY_IN_MILLIS;
1440        final HashSet<String> argSet = new HashSet<String>();
1441        for (String arg : args) {
1442            argSet.add(arg);
1443
1444            if (arg.startsWith("--duration=")) {
1445                try {
1446                    duration = Long.parseLong(arg.substring(11));
1447                } catch (NumberFormatException ignored) {
1448                }
1449            }
1450        }
1451
1452        // usage: dumpsys netstats --full --uid --tag --poll --checkin
1453        final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
1454        final boolean checkin = argSet.contains("--checkin");
1455        final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
1456        final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
1457        final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
1458
1459        final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, "  ");
1460
1461        synchronized (mStatsLock) {
1462            if (args.length > 0 && "--proto".equals(args[0])) {
1463                // In this case ignore all other arguments.
1464                dumpProtoLocked(fd);
1465                return;
1466            }
1467
1468            if (poll) {
1469                performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
1470                pw.println("Forced poll");
1471                return;
1472            }
1473
1474            if (checkin) {
1475                final long end = System.currentTimeMillis();
1476                final long start = end - duration;
1477
1478                pw.print("v1,");
1479                pw.print(start / SECOND_IN_MILLIS); pw.print(',');
1480                pw.print(end / SECOND_IN_MILLIS); pw.println();
1481
1482                pw.println("xt");
1483                mXtRecorder.dumpCheckin(rawWriter, start, end);
1484
1485                if (includeUid) {
1486                    pw.println("uid");
1487                    mUidRecorder.dumpCheckin(rawWriter, start, end);
1488                }
1489                if (includeTag) {
1490                    pw.println("tag");
1491                    mUidTagRecorder.dumpCheckin(rawWriter, start, end);
1492                }
1493                return;
1494            }
1495
1496            pw.println("Active interfaces:");
1497            pw.increaseIndent();
1498            for (int i = 0; i < mActiveIfaces.size(); i++) {
1499                pw.printPair("iface", mActiveIfaces.keyAt(i));
1500                pw.printPair("ident", mActiveIfaces.valueAt(i));
1501                pw.println();
1502            }
1503            pw.decreaseIndent();
1504
1505            pw.println("Active UID interfaces:");
1506            pw.increaseIndent();
1507            for (int i = 0; i < mActiveUidIfaces.size(); i++) {
1508                pw.printPair("iface", mActiveUidIfaces.keyAt(i));
1509                pw.printPair("ident", mActiveUidIfaces.valueAt(i));
1510                pw.println();
1511            }
1512            pw.decreaseIndent();
1513
1514            // Get the top openSession callers
1515            final SparseIntArray calls;
1516            synchronized (mOpenSessionCallsPerUid) {
1517                calls = mOpenSessionCallsPerUid.clone();
1518            }
1519
1520            final int N = calls.size();
1521            final long[] values = new long[N];
1522            for (int j = 0; j < N; j++) {
1523                values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
1524            }
1525            Arrays.sort(values);
1526
1527            pw.println("Top openSession callers (uid=count):");
1528            pw.increaseIndent();
1529            final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
1530            for (int j = N - 1; j >= end; j--) {
1531                final int uid = (int) (values[j] & 0xffffffff);
1532                final int count = (int) (values[j] >> 32);
1533                pw.print(uid); pw.print("="); pw.println(count);
1534            }
1535            pw.decreaseIndent();
1536            pw.println();
1537
1538            pw.println("Dev stats:");
1539            pw.increaseIndent();
1540            mDevRecorder.dumpLocked(pw, fullHistory);
1541            pw.decreaseIndent();
1542
1543            pw.println("Xt stats:");
1544            pw.increaseIndent();
1545            mXtRecorder.dumpLocked(pw, fullHistory);
1546            pw.decreaseIndent();
1547
1548            if (includeUid) {
1549                pw.println("UID stats:");
1550                pw.increaseIndent();
1551                mUidRecorder.dumpLocked(pw, fullHistory);
1552                pw.decreaseIndent();
1553            }
1554
1555            if (includeTag) {
1556                pw.println("UID tag stats:");
1557                pw.increaseIndent();
1558                mUidTagRecorder.dumpLocked(pw, fullHistory);
1559                pw.decreaseIndent();
1560            }
1561        }
1562    }
1563
1564    @GuardedBy("mStatsLock")
1565    private void dumpProtoLocked(FileDescriptor fd) {
1566        final ProtoOutputStream proto = new ProtoOutputStream(fd);
1567
1568        // TODO Right now it writes all history.  Should it limit to the "since-boot" log?
1569
1570        dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces);
1571        dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces);
1572        mDevRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
1573        mXtRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
1574        mUidRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
1575        mUidTagRecorder.writeToProtoLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS);
1576
1577        proto.flush();
1578    }
1579
1580    private static void dumpInterfaces(ProtoOutputStream proto, long tag,
1581            ArrayMap<String, NetworkIdentitySet> ifaces) {
1582        for (int i = 0; i < ifaces.size(); i++) {
1583            final long start = proto.start(tag);
1584
1585            proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i));
1586            ifaces.valueAt(i).writeToProto(proto, NetworkInterfaceProto.IDENTITIES);
1587
1588            proto.end(start);
1589        }
1590    }
1591
1592    /**
1593     * Return snapshot of current UID statistics, including any
1594     * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations}
1595     * values.
1596     *
1597     * @param ifaces A list of interfaces the stats should be restricted to, or
1598     *               {@link NetworkStats#INTERFACES_ALL}.
1599     */
1600    private NetworkStats getNetworkStatsUidDetail(String[] ifaces)
1601            throws RemoteException {
1602
1603        // TODO: remove 464xlat adjustments from NetworkStatsFactory and apply all at once here.
1604        final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL,
1605                ifaces);
1606
1607        // fold tethering stats and operations into uid snapshot
1608        final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
1609        tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
1610        NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
1611        uidSnapshot.combineAllValues(tetherSnapshot);
1612
1613        final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
1614                Context.TELEPHONY_SERVICE);
1615
1616        // fold video calling data usage stats into uid snapshot
1617        final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID);
1618        if (vtStats != null) {
1619            vtStats.filter(UID_ALL, ifaces, TAG_ALL);
1620            NetworkStatsFactory.apply464xlatAdjustments(uidSnapshot, vtStats);
1621            uidSnapshot.combineAllValues(vtStats);
1622        }
1623
1624        uidSnapshot.combineAllValues(mUidOperations);
1625
1626        return uidSnapshot;
1627    }
1628
1629    /**
1630     * Return snapshot of current XT statistics with video calling data usage statistics.
1631     */
1632    private NetworkStats getNetworkStatsXt() throws RemoteException {
1633        final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
1634
1635        final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
1636                Context.TELEPHONY_SERVICE);
1637
1638        // Merge video calling data usage into XT
1639        final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE);
1640        if (vtSnapshot != null) {
1641            xtSnapshot.combineAllValues(vtSnapshot);
1642        }
1643
1644        return xtSnapshot;
1645    }
1646
1647    /**
1648     * Return snapshot of current tethering statistics. Will return empty
1649     * {@link NetworkStats} if any problems are encountered.
1650     */
1651    private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
1652        try {
1653            return mNetworkManager.getNetworkStatsTethering(how);
1654        } catch (IllegalStateException e) {
1655            Log.wtf(TAG, "problem reading network stats", e);
1656            return new NetworkStats(0L, 10);
1657        }
1658    }
1659
1660    @VisibleForTesting
1661    static class HandlerCallback implements Handler.Callback {
1662        private final NetworkStatsService mService;
1663
1664        HandlerCallback(NetworkStatsService service) {
1665            this.mService = service;
1666        }
1667
1668        @Override
1669        public boolean handleMessage(Message msg) {
1670            switch (msg.what) {
1671                case MSG_PERFORM_POLL: {
1672                    final int flags = msg.arg1;
1673                    mService.performPoll(flags);
1674                    return true;
1675                }
1676                case MSG_UPDATE_IFACES: {
1677                    mService.updateIfaces(null);
1678                    return true;
1679                }
1680                case MSG_REGISTER_GLOBAL_ALERT: {
1681                    mService.registerGlobalAlert();
1682                    return true;
1683                }
1684                default: {
1685                    return false;
1686                }
1687            }
1688        }
1689    }
1690
1691    private void assertSystemReady() {
1692        if (!mSystemReady) {
1693            throw new IllegalStateException("System not ready");
1694        }
1695    }
1696
1697    private void assertBandwidthControlEnabled() {
1698        if (!isBandwidthControlEnabled()) {
1699            throw new IllegalStateException("Bandwidth module disabled");
1700        }
1701    }
1702
1703    private boolean isBandwidthControlEnabled() {
1704        final long token = Binder.clearCallingIdentity();
1705        try {
1706            return mNetworkManager.isBandwidthControlEnabled();
1707        } catch (RemoteException e) {
1708            // ignored; service lives in system_server
1709            return false;
1710        } finally {
1711            Binder.restoreCallingIdentity(token);
1712        }
1713    }
1714
1715    private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
1716        @Override
1717        public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
1718                int rightIndex, String cookie) {
1719            Log.w(TAG, "Found non-monotonic values; saving to dropbox");
1720
1721            // record error for debugging
1722            final StringBuilder builder = new StringBuilder();
1723            builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
1724                    + "] - right[" + rightIndex + "]\n");
1725            builder.append("left=").append(left).append('\n');
1726            builder.append("right=").append(right).append('\n');
1727
1728            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
1729                    builder.toString());
1730        }
1731
1732        @Override
1733        public void foundNonMonotonic(
1734                NetworkStats stats, int statsIndex, String cookie) {
1735            Log.w(TAG, "Found non-monotonic values; saving to dropbox");
1736
1737            final StringBuilder builder = new StringBuilder();
1738            builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
1739            builder.append("stats=").append(stats).append('\n');
1740
1741            mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
1742                    builder.toString());
1743        }
1744    }
1745
1746    /**
1747     * Default external settings that read from
1748     * {@link android.provider.Settings.Global}.
1749     */
1750    private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
1751        private final ContentResolver mResolver;
1752
1753        public DefaultNetworkStatsSettings(Context context) {
1754            mResolver = checkNotNull(context.getContentResolver());
1755            // TODO: adjust these timings for production builds
1756        }
1757
1758        private long getGlobalLong(String name, long def) {
1759            return Settings.Global.getLong(mResolver, name, def);
1760        }
1761        private boolean getGlobalBoolean(String name, boolean def) {
1762            final int defInt = def ? 1 : 0;
1763            return Settings.Global.getInt(mResolver, name, defInt) != 0;
1764        }
1765
1766        @Override
1767        public long getPollInterval() {
1768            return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
1769        }
1770        @Override
1771        public long getGlobalAlertBytes(long def) {
1772            return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
1773        }
1774        @Override
1775        public boolean getSampleEnabled() {
1776            return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
1777        }
1778        @Override
1779        public boolean getAugmentEnabled() {
1780            return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
1781        }
1782        @Override
1783        public Config getDevConfig() {
1784            return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
1785                    getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1786                    getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
1787        }
1788        @Override
1789        public Config getXtConfig() {
1790            return getDevConfig();
1791        }
1792        @Override
1793        public Config getUidConfig() {
1794            return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1795                    getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
1796                    getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
1797        }
1798        @Override
1799        public Config getUidTagConfig() {
1800            return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
1801                    getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
1802                    getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
1803        }
1804        @Override
1805        public long getDevPersistBytes(long def) {
1806            return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
1807        }
1808        @Override
1809        public long getXtPersistBytes(long def) {
1810            return getDevPersistBytes(def);
1811        }
1812        @Override
1813        public long getUidPersistBytes(long def) {
1814            return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
1815        }
1816        @Override
1817        public long getUidTagPersistBytes(long def) {
1818            return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
1819        }
1820    }
1821
1822    private static int TYPE_RX_BYTES;
1823    private static int TYPE_RX_PACKETS;
1824    private static int TYPE_TX_BYTES;
1825    private static int TYPE_TX_PACKETS;
1826    private static int TYPE_TCP_RX_PACKETS;
1827    private static int TYPE_TCP_TX_PACKETS;
1828
1829    private static native long nativeGetTotalStat(int type, boolean useBpfStats);
1830    private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
1831    private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
1832}
1833