1 /*
2  * Copyright (C) 2011 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.server.net;
18 
19 import static android.Manifest.permission.NETWORK_STATS_PROVIDER;
20 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY;
21 import static android.Manifest.permission.UPDATE_DEVICE_STATS;
22 import static android.content.Intent.ACTION_SHUTDOWN;
23 import static android.content.Intent.ACTION_UID_REMOVED;
24 import static android.content.Intent.ACTION_USER_REMOVED;
25 import static android.content.Intent.EXTRA_UID;
26 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
27 import static android.net.NetworkIdentity.SUBTYPE_COMBINED;
28 import static android.net.NetworkStack.checkNetworkStackPermission;
29 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
30 import static android.net.NetworkStats.IFACE_ALL;
31 import static android.net.NetworkStats.IFACE_VT;
32 import static android.net.NetworkStats.INTERFACES_ALL;
33 import static android.net.NetworkStats.METERED_ALL;
34 import static android.net.NetworkStats.ROAMING_ALL;
35 import static android.net.NetworkStats.SET_ALL;
36 import static android.net.NetworkStats.SET_DEFAULT;
37 import static android.net.NetworkStats.SET_FOREGROUND;
38 import static android.net.NetworkStats.STATS_PER_IFACE;
39 import static android.net.NetworkStats.STATS_PER_UID;
40 import static android.net.NetworkStats.TAG_ALL;
41 import static android.net.NetworkStats.TAG_NONE;
42 import static android.net.NetworkStats.UID_ALL;
43 import static android.net.NetworkStatsHistory.FIELD_ALL;
44 import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
45 import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
46 import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED;
47 import static android.net.TrafficStats.KB_IN_BYTES;
48 import static android.net.TrafficStats.MB_IN_BYTES;
49 import static android.net.TrafficStats.UNSUPPORTED;
50 import static android.os.Trace.TRACE_TAG_NETWORK;
51 import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED;
52 import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED;
53 import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION;
54 import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE;
55 import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES;
56 import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE;
57 import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES;
58 import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL;
59 import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED;
60 import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION;
61 import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE;
62 import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES;
63 import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE;
64 import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION;
65 import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE;
66 import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES;
67 import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE;
68 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID;
69 import static android.text.format.DateUtils.DAY_IN_MILLIS;
70 import static android.text.format.DateUtils.HOUR_IN_MILLIS;
71 import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
72 import static android.text.format.DateUtils.SECOND_IN_MILLIS;
73 
74 import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport;
75 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
76 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
77 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet;
78 
79 import android.annotation.NonNull;
80 import android.annotation.Nullable;
81 import android.app.AlarmManager;
82 import android.app.PendingIntent;
83 import android.app.usage.NetworkStatsManager;
84 import android.content.BroadcastReceiver;
85 import android.content.ContentResolver;
86 import android.content.Context;
87 import android.content.Intent;
88 import android.content.IntentFilter;
89 import android.content.pm.ApplicationInfo;
90 import android.content.pm.PackageManager;
91 import android.database.ContentObserver;
92 import android.net.DataUsageRequest;
93 import android.net.INetworkManagementEventObserver;
94 import android.net.INetworkStatsService;
95 import android.net.INetworkStatsSession;
96 import android.net.Network;
97 import android.net.NetworkCapabilities;
98 import android.net.NetworkIdentity;
99 import android.net.NetworkSpecifier;
100 import android.net.NetworkStack;
101 import android.net.NetworkStateSnapshot;
102 import android.net.NetworkStats;
103 import android.net.NetworkStats.NonMonotonicObserver;
104 import android.net.NetworkStatsHistory;
105 import android.net.NetworkTemplate;
106 import android.net.TelephonyNetworkSpecifier;
107 import android.net.TrafficStats;
108 import android.net.UnderlyingNetworkInfo;
109 import android.net.Uri;
110 import android.net.netstats.provider.INetworkStatsProvider;
111 import android.net.netstats.provider.INetworkStatsProviderCallback;
112 import android.net.netstats.provider.NetworkStatsProvider;
113 import android.os.BestClock;
114 import android.os.Binder;
115 import android.os.DropBoxManager;
116 import android.os.Environment;
117 import android.os.Handler;
118 import android.os.HandlerExecutor;
119 import android.os.HandlerThread;
120 import android.os.IBinder;
121 import android.os.INetworkManagementService;
122 import android.os.Looper;
123 import android.os.Message;
124 import android.os.Messenger;
125 import android.os.PowerManager;
126 import android.os.RemoteException;
127 import android.os.SystemClock;
128 import android.os.Trace;
129 import android.os.UserHandle;
130 import android.provider.Settings;
131 import android.provider.Settings.Global;
132 import android.service.NetworkInterfaceProto;
133 import android.service.NetworkStatsServiceDumpProto;
134 import android.telephony.PhoneStateListener;
135 import android.telephony.SubscriptionPlan;
136 import android.text.TextUtils;
137 import android.text.format.DateUtils;
138 import android.util.ArrayMap;
139 import android.util.ArraySet;
140 import android.util.EventLog;
141 import android.util.Log;
142 import android.util.MathUtils;
143 import android.util.Slog;
144 import android.util.SparseIntArray;
145 import android.util.proto.ProtoOutputStream;
146 
147 import com.android.internal.annotations.GuardedBy;
148 import com.android.internal.annotations.VisibleForTesting;
149 import com.android.internal.util.ArrayUtils;
150 import com.android.internal.util.DumpUtils;
151 import com.android.internal.util.FileRotator;
152 import com.android.internal.util.IndentingPrintWriter;
153 import com.android.server.EventLogTags;
154 import com.android.server.LocalServices;
155 
156 import java.io.File;
157 import java.io.FileDescriptor;
158 import java.io.IOException;
159 import java.io.PrintWriter;
160 import java.time.Clock;
161 import java.time.ZoneOffset;
162 import java.util.Arrays;
163 import java.util.HashSet;
164 import java.util.List;
165 import java.util.Objects;
166 import java.util.concurrent.CopyOnWriteArrayList;
167 import java.util.concurrent.Executor;
168 import java.util.concurrent.Semaphore;
169 import java.util.concurrent.TimeUnit;
170 
171 /**
172  * Collect and persist detailed network statistics, and provide this data to
173  * other system services.
174  */
175 public class NetworkStatsService extends INetworkStatsService.Stub {
176     static final String TAG = "NetworkStats";
177     static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG);
178     static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE);
179 
180     // Perform polling and persist all (FLAG_PERSIST_ALL).
181     private static final int MSG_PERFORM_POLL = 1;
182     // Perform polling, persist network, and register the global alert again.
183     private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2;
184     private static final int MSG_NOTIFY_NETWORK_STATUS = 3;
185     // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent
186     // deadlock.
187     private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4;
188 
189     /** Flags to control detail level of poll event. */
190     private static final int FLAG_PERSIST_NETWORK = 0x1;
191     private static final int FLAG_PERSIST_UID = 0x2;
192     private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
193     private static final int FLAG_PERSIST_FORCE = 0x100;
194 
195     /**
196      * When global alert quota is high, wait for this delay before processing each polling,
197      * and do not schedule further polls once there is already one queued.
198      * This avoids firing the global alert too often on devices with high transfer speeds and
199      * high quota.
200      */
201     private static final int DEFAULT_PERFORM_POLL_DELAY_MS = 1000;
202 
203     private static final String TAG_NETSTATS_ERROR = "netstats_error";
204 
205     private final Context mContext;
206     private final INetworkManagementService mNetworkManager;
207     private final NetworkStatsFactory mStatsFactory;
208     private final AlarmManager mAlarmManager;
209     private final Clock mClock;
210     private final NetworkStatsSettings mSettings;
211     private final NetworkStatsObservers mStatsObservers;
212 
213     private final File mSystemDir;
214     private final File mBaseDir;
215 
216     private final PowerManager.WakeLock mWakeLock;
217 
218     private final boolean mUseBpfTrafficStats;
219 
220     private final ContentObserver mContentObserver;
221     private final ContentResolver mContentResolver;
222 
223     @VisibleForTesting
224     public static final String ACTION_NETWORK_STATS_POLL =
225             "com.android.server.action.NETWORK_STATS_POLL";
226     public static final String ACTION_NETWORK_STATS_UPDATED =
227             "com.android.server.action.NETWORK_STATS_UPDATED";
228 
229     private PendingIntent mPollIntent;
230 
231     private static final String PREFIX_DEV = "dev";
232     private static final String PREFIX_XT = "xt";
233     private static final String PREFIX_UID = "uid";
234     private static final String PREFIX_UID_TAG = "uid_tag";
235 
236     /**
237      * Settings that can be changed externally.
238      */
239     public interface NetworkStatsSettings {
getPollInterval()240         long getPollInterval();
getPollDelay()241         long getPollDelay();
getSampleEnabled()242         boolean getSampleEnabled();
getAugmentEnabled()243         boolean getAugmentEnabled();
244         /**
245          * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}.
246          * When disabled, mobile data is broken down by a granular subtype representative of the
247          * actual subtype. {@see NetworkTemplate#getCollapsedRatType}.
248          * Enabling this decreases the level of detail but saves performance, disk space and
249          * amount of data logged.
250          */
getCombineSubtypeEnabled()251         boolean getCombineSubtypeEnabled();
252 
253         class Config {
254             public final long bucketDuration;
255             public final long rotateAgeMillis;
256             public final long deleteAgeMillis;
257 
Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis)258             public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) {
259                 this.bucketDuration = bucketDuration;
260                 this.rotateAgeMillis = rotateAgeMillis;
261                 this.deleteAgeMillis = deleteAgeMillis;
262             }
263         }
264 
getDevConfig()265         Config getDevConfig();
getXtConfig()266         Config getXtConfig();
getUidConfig()267         Config getUidConfig();
getUidTagConfig()268         Config getUidTagConfig();
269 
getGlobalAlertBytes(long def)270         long getGlobalAlertBytes(long def);
getDevPersistBytes(long def)271         long getDevPersistBytes(long def);
getXtPersistBytes(long def)272         long getXtPersistBytes(long def);
getUidPersistBytes(long def)273         long getUidPersistBytes(long def);
getUidTagPersistBytes(long def)274         long getUidTagPersistBytes(long def);
275     }
276 
277     private final Object mStatsLock = new Object();
278 
279     /** Set of currently active ifaces. */
280     @GuardedBy("mStatsLock")
281     private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>();
282 
283     /** Set of currently active ifaces for UID stats. */
284     @GuardedBy("mStatsLock")
285     private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>();
286 
287     /** Current default active iface. */
288     @GuardedBy("mStatsLock")
289     private String mActiveIface;
290 
291     /** Set of any ifaces associated with mobile networks since boot. */
292     private volatile String[] mMobileIfaces = new String[0];
293 
294     /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */
295     @GuardedBy("mStatsLock")
296     private Network[] mDefaultNetworks = new Network[0];
297 
298     /** Last states of all networks sent from ConnectivityService. */
299     @GuardedBy("mStatsLock")
300     @Nullable
301     private NetworkStateSnapshot[] mLastNetworkStateSnapshots = null;
302 
303     private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
304             new DropBoxNonMonotonicObserver();
305 
306     private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100;
307     private final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList =
308             new CopyOnWriteArrayList<>();
309     /** Semaphore used to wait for stats provider to respond to request stats update. */
310     private final Semaphore mStatsProviderSem = new Semaphore(0, true);
311 
312     @GuardedBy("mStatsLock")
313     private NetworkStatsRecorder mDevRecorder;
314     @GuardedBy("mStatsLock")
315     private NetworkStatsRecorder mXtRecorder;
316     @GuardedBy("mStatsLock")
317     private NetworkStatsRecorder mUidRecorder;
318     @GuardedBy("mStatsLock")
319     private NetworkStatsRecorder mUidTagRecorder;
320 
321     /** Cached {@link #mXtRecorder} stats. */
322     @GuardedBy("mStatsLock")
323     private NetworkStatsCollection mXtStatsCached;
324 
325     /** Current counter sets for each UID. */
326     private SparseIntArray mActiveUidCounterSet = new SparseIntArray();
327 
328     /** Data layer operation counters for splicing into other structures. */
329     private NetworkStats mUidOperations = new NetworkStats(0L, 10);
330 
331     @NonNull
332     private final Handler mHandler;
333 
334     private volatile boolean mSystemReady;
335     private long mPersistThreshold = 2 * MB_IN_BYTES;
336     private long mGlobalAlertBytes;
337 
338     private static final long POLL_RATE_LIMIT_MS = 15_000;
339 
340     private long mLastStatsSessionPoll;
341 
342     /** Map from UID to number of opened sessions */
343     @GuardedBy("mOpenSessionCallsPerUid")
344     private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray();
345 
346     private final static int DUMP_STATS_SESSION_COUNT = 20;
347 
348     @NonNull
349     private final Dependencies mDeps;
350 
351     @NonNull
352     private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor;
353 
getDefaultSystemDir()354     private static @NonNull File getDefaultSystemDir() {
355         return new File(Environment.getDataDirectory(), "system");
356     }
357 
getDefaultBaseDir()358     private static @NonNull File getDefaultBaseDir() {
359         File baseDir = new File(getDefaultSystemDir(), "netstats");
360         baseDir.mkdirs();
361         return baseDir;
362     }
363 
getDefaultClock()364     private static @NonNull Clock getDefaultClock() {
365         return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(),
366                 Clock.systemUTC());
367     }
368 
369     private final class NetworkStatsHandler extends Handler {
NetworkStatsHandler(@onNull Looper looper)370         NetworkStatsHandler(@NonNull Looper looper) {
371             super(looper);
372         }
373 
374         @Override
handleMessage(Message msg)375         public void handleMessage(Message msg) {
376             switch (msg.what) {
377                 case MSG_PERFORM_POLL: {
378                     performPoll(FLAG_PERSIST_ALL);
379                     break;
380                 }
381                 case MSG_NOTIFY_NETWORK_STATUS: {
382                     // If no cached states, ignore.
383                     if (mLastNetworkStateSnapshots == null) break;
384                     // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing.
385                     handleNotifyNetworkStatus(
386                             mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface);
387                     break;
388                 }
389                 case MSG_PERFORM_POLL_REGISTER_ALERT: {
390                     performPoll(FLAG_PERSIST_NETWORK);
391                     registerGlobalAlert();
392                     break;
393                 }
394                 case MSG_BROADCAST_NETWORK_STATS_UPDATED: {
395                     final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
396                     updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
397                     mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
398                             READ_NETWORK_USAGE_HISTORY);
399                     break;
400                 }
401             }
402         }
403     }
404 
create(Context context, INetworkManagementService networkManager)405     public static NetworkStatsService create(Context context,
406                 INetworkManagementService networkManager) {
407         AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
408         PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
409         PowerManager.WakeLock wakeLock =
410                 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
411 
412         final NetworkStatsService service = new NetworkStatsService(context, networkManager,
413                 alarmManager, wakeLock, getDefaultClock(),
414                 new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(),
415                 new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(),
416                 new Dependencies());
417         service.registerLocalService();
418 
419         return service;
420     }
421 
422     // This must not be called outside of tests, even within the same package, as this constructor
423     // does not register the local service. Use the create() helper above.
424     @VisibleForTesting
NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings, NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, File baseDir, @NonNull Dependencies deps)425     NetworkStatsService(Context context, INetworkManagementService networkManager,
426             AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock,
427             NetworkStatsSettings settings, NetworkStatsFactory factory,
428             NetworkStatsObservers statsObservers, File systemDir, File baseDir,
429             @NonNull Dependencies deps) {
430         mContext = Objects.requireNonNull(context, "missing Context");
431         mNetworkManager = Objects.requireNonNull(networkManager,
432                 "missing INetworkManagementService");
433         mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager");
434         mClock = Objects.requireNonNull(clock, "missing Clock");
435         mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings");
436         mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock");
437         mStatsFactory = Objects.requireNonNull(factory, "missing factory");
438         mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers");
439         mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir");
440         mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir");
441         mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists();
442         mDeps = Objects.requireNonNull(deps, "missing Dependencies");
443 
444         final HandlerThread handlerThread = mDeps.makeHandlerThread();
445         handlerThread.start();
446         mHandler = new NetworkStatsHandler(handlerThread.getLooper());
447         mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext,
448                 mHandler.getLooper(), new HandlerExecutor(mHandler), this);
449         mContentResolver = mContext.getContentResolver();
450         mContentObserver = mDeps.makeContentObserver(mHandler, mSettings,
451                 mNetworkStatsSubscriptionsMonitor);
452     }
453 
454     /**
455      * Dependencies of NetworkStatsService, for injection in tests.
456      */
457     // TODO: Move more stuff into dependencies object.
458     @VisibleForTesting
459     public static class Dependencies {
460         /**
461          * Create a HandlerThread to use in NetworkStatsService.
462          */
463         @NonNull
makeHandlerThread()464         public HandlerThread makeHandlerThread() {
465             return new HandlerThread(TAG);
466         }
467 
468         /**
469          * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change
470          * event in NetworkStatsService.
471          */
472         @NonNull
makeSubscriptionsMonitor(@onNull Context context, @NonNull Looper looper, @NonNull Executor executor, @NonNull NetworkStatsService service)473         public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context,
474                 @NonNull Looper looper, @NonNull Executor executor,
475                 @NonNull NetworkStatsService service) {
476             // TODO: Update RatType passively in NSS, instead of querying into the monitor
477             //  when notifyNetworkStatus.
478             return new NetworkStatsSubscriptionsMonitor(context, looper, executor,
479                     (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged());
480         }
481 
482         /**
483          * Create a ContentObserver instance which is used to observe settings changes,
484          * and dispatch onChange events on handler thread.
485          */
makeContentObserver(@onNull Handler handler, @NonNull NetworkStatsSettings settings, @NonNull NetworkStatsSubscriptionsMonitor monitor)486         public @NonNull ContentObserver makeContentObserver(@NonNull Handler handler,
487                 @NonNull NetworkStatsSettings settings,
488                 @NonNull NetworkStatsSubscriptionsMonitor monitor) {
489             return new ContentObserver(handler) {
490                 @Override
491                 public void onChange(boolean selfChange, @NonNull Uri uri) {
492                     if (!settings.getCombineSubtypeEnabled()) {
493                         monitor.start();
494                     } else {
495                         monitor.stop();
496                     }
497                 }
498             };
499         }
500     }
501 
502     private void registerLocalService() {
503         LocalServices.addService(NetworkStatsManagerInternal.class,
504                 new NetworkStatsManagerInternalImpl());
505     }
506 
507     public void systemReady() {
508         synchronized (mStatsLock) {
509             mSystemReady = true;
510 
511             // create data recorders along with historical rotators
512             mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
513             mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
514             mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
515             mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
516 
517             updatePersistThresholdsLocked();
518 
519             // upgrade any legacy stats, migrating them to rotated files
520             maybeUpgradeLegacyStatsLocked();
521 
522             // read historical network stats from disk, since policy service
523             // might need them right away.
524             mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
525 
526             // bootstrap initial stats to prevent double-counting later
527             bootstrapStatsLocked();
528         }
529 
530         // watch for tethering changes
531         final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
532         mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
533 
534         // listen for periodic polling events
535         final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
536         mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
537 
538         // listen for uid removal to clean stats
539         final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
540         mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
541 
542         // listen for user changes to clean stats
543         final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
544         mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
545 
546         // persist stats during clean shutdown
547         final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
548         mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
549 
550         try {
551             mNetworkManager.registerObserver(mAlertObserver);
552         } catch (RemoteException e) {
553             // ignored; service lives in system_server
554         }
555 
556         //  schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}.
557         final PendingIntent pollIntent =
558                 PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL),
559                         PendingIntent.FLAG_IMMUTABLE);
560 
561         final long currentRealtime = SystemClock.elapsedRealtime();
562         mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
563                 mSettings.getPollInterval(), pollIntent);
564 
565         mContentResolver.registerContentObserver(Settings.Global
566                 .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED),
567                         false /* notifyForDescendants */, mContentObserver);
568 
569         // Post a runnable on handler thread to call onChange(). It's for getting current value of
570         // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes.
571         mHandler.post(() -> mContentObserver.onChange(false, Settings.Global
572                 .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED)));
573 
574         registerGlobalAlert();
575     }
576 
577     private NetworkStatsRecorder buildRecorder(
578             String prefix, NetworkStatsSettings.Config config, boolean includeTags) {
579         final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
580                 Context.DROPBOX_SERVICE);
581         return new NetworkStatsRecorder(new FileRotator(
582                 mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
583                 mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
584     }
585 
586     @GuardedBy("mStatsLock")
587     private void shutdownLocked() {
588         mContext.unregisterReceiver(mTetherReceiver);
589         mContext.unregisterReceiver(mPollReceiver);
590         mContext.unregisterReceiver(mRemovedReceiver);
591         mContext.unregisterReceiver(mUserReceiver);
592         mContext.unregisterReceiver(mShutdownReceiver);
593 
594         if (!mSettings.getCombineSubtypeEnabled()) {
595             mNetworkStatsSubscriptionsMonitor.stop();
596         }
597 
598         mContentResolver.unregisterContentObserver(mContentObserver);
599 
600         final long currentTime = mClock.millis();
601 
602         // persist any pending stats
603         mDevRecorder.forcePersistLocked(currentTime);
604         mXtRecorder.forcePersistLocked(currentTime);
605         mUidRecorder.forcePersistLocked(currentTime);
606         mUidTagRecorder.forcePersistLocked(currentTime);
607 
608         mSystemReady = false;
609     }
610 
611     @GuardedBy("mStatsLock")
612     private void maybeUpgradeLegacyStatsLocked() {
613         File file;
614         try {
615             file = new File(mSystemDir, "netstats.bin");
616             if (file.exists()) {
617                 mDevRecorder.importLegacyNetworkLocked(file);
618                 file.delete();
619             }
620 
621             file = new File(mSystemDir, "netstats_xt.bin");
622             if (file.exists()) {
623                 file.delete();
624             }
625 
626             file = new File(mSystemDir, "netstats_uid.bin");
627             if (file.exists()) {
628                 mUidRecorder.importLegacyUidLocked(file);
629                 mUidTagRecorder.importLegacyUidLocked(file);
630                 file.delete();
631             }
632         } catch (IOException e) {
633             Log.wtf(TAG, "problem during legacy upgrade", e);
634         } catch (OutOfMemoryError e) {
635             Log.wtf(TAG, "problem during legacy upgrade", e);
636         }
637     }
638 
639     /**
640      * Register for a global alert that is delivered through {@link INetworkManagementEventObserver}
641      * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has
642      * been transferred.
643      */
644     private void registerGlobalAlert() {
645         try {
646             mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
647         } catch (IllegalStateException e) {
648             Slog.w(TAG, "problem registering for global alert: " + e);
649         } catch (RemoteException e) {
650             // ignored; service lives in system_server
651         }
652         invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes));
653     }
654 
655     @Override
656     public INetworkStatsSession openSession() {
657         // NOTE: if callers want to get non-augmented data, they should go
658         // through the public API
659         return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null);
660     }
661 
662     @Override
663     public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) {
664         return openSessionInternal(flags, callingPackage);
665     }
666 
667     private boolean isRateLimitedForPoll(int callingUid) {
668         if (callingUid == android.os.Process.SYSTEM_UID) {
669             return false;
670         }
671 
672         final long lastCallTime;
673         final long now = SystemClock.elapsedRealtime();
674         synchronized (mOpenSessionCallsPerUid) {
675             int calls = mOpenSessionCallsPerUid.get(callingUid, 0);
676             mOpenSessionCallsPerUid.put(callingUid, calls + 1);
677             lastCallTime = mLastStatsSessionPoll;
678             mLastStatsSessionPoll = now;
679         }
680 
681         return now - lastCallTime < POLL_RATE_LIMIT_MS;
682     }
683 
684     private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) {
685         final int callingUid = Binder.getCallingUid();
686         final int usedFlags = isRateLimitedForPoll(callingUid)
687                 ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN)
688                 : flags;
689         if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN
690                 | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) {
691             final long ident = Binder.clearCallingIdentity();
692             try {
693                 performPoll(FLAG_PERSIST_ALL);
694             } finally {
695                 Binder.restoreCallingIdentity(ident);
696             }
697         }
698 
699         // return an IBinder which holds strong references to any loaded stats
700         // for its lifetime; when caller closes only weak references remain.
701 
702         return new INetworkStatsSession.Stub() {
703             private final int mCallingUid = callingUid;
704             private final String mCallingPackage = callingPackage;
705             private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel(
706                     callingPackage);
707 
708             private NetworkStatsCollection mUidComplete;
709             private NetworkStatsCollection mUidTagComplete;
710 
711             private NetworkStatsCollection getUidComplete() {
712                 synchronized (mStatsLock) {
713                     if (mUidComplete == null) {
714                         mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
715                     }
716                     return mUidComplete;
717                 }
718             }
719 
720             private NetworkStatsCollection getUidTagComplete() {
721                 synchronized (mStatsLock) {
722                     if (mUidTagComplete == null) {
723                         mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
724                     }
725                     return mUidTagComplete;
726                 }
727             }
728 
729             @Override
730             public int[] getRelevantUids() {
731                 return getUidComplete().getRelevantUids(mAccessLevel);
732             }
733 
734             @Override
735             public NetworkStats getDeviceSummaryForNetwork(
736                     NetworkTemplate template, long start, long end) {
737                 return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
738                         mCallingUid);
739             }
740 
741             @Override
742             public NetworkStats getSummaryForNetwork(
743                     NetworkTemplate template, long start, long end) {
744                 return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel,
745                         mCallingUid);
746             }
747 
748             @Override
749             public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
750                 return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel,
751                         mCallingUid);
752             }
753 
754             @Override
755             public NetworkStats getSummaryForAllUid(
756                     NetworkTemplate template, long start, long end, boolean includeTags) {
757                 try {
758                     final NetworkStats stats = getUidComplete()
759                             .getSummary(template, start, end, mAccessLevel, mCallingUid);
760                     if (includeTags) {
761                         final NetworkStats tagStats = getUidTagComplete()
762                                 .getSummary(template, start, end, mAccessLevel, mCallingUid);
763                         stats.combineAllValues(tagStats);
764                     }
765                     return stats;
766                 } catch (NullPointerException e) {
767                     // TODO: Track down and fix the cause of this crash and remove this catch block.
768                     Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e);
769                     throw e;
770                 }
771             }
772 
773             @Override
774             public NetworkStatsHistory getHistoryForUid(
775                     NetworkTemplate template, int uid, int set, int tag, int fields) {
776                 // NOTE: We don't augment UID-level statistics
777                 if (tag == TAG_NONE) {
778                     return getUidComplete().getHistory(template, null, uid, set, tag, fields,
779                             Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
780                 } else {
781                     return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
782                             Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid);
783                 }
784             }
785 
786             @Override
787             public NetworkStatsHistory getHistoryIntervalForUid(
788                     NetworkTemplate template, int uid, int set, int tag, int fields,
789                     long start, long end) {
790                 // NOTE: We don't augment UID-level statistics
791                 if (tag == TAG_NONE) {
792                     return getUidComplete().getHistory(template, null, uid, set, tag, fields,
793                             start, end, mAccessLevel, mCallingUid);
794                 } else if (uid == Binder.getCallingUid()) {
795                     return getUidTagComplete().getHistory(template, null, uid, set, tag, fields,
796                             start, end, mAccessLevel, mCallingUid);
797                 } else {
798                     throw new SecurityException("Calling package " + mCallingPackage
799                             + " cannot access tag information from a different uid");
800                 }
801             }
802 
803             @Override
804             public void close() {
805                 mUidComplete = null;
806                 mUidTagComplete = null;
807             }
808         };
809     }
810 
811     private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) {
812         return NetworkStatsAccess.checkAccessLevel(
813                 mContext, Binder.getCallingUid(), callingPackage);
814     }
815 
816     /**
817      * Find the most relevant {@link SubscriptionPlan} for the given
818      * {@link NetworkTemplate} and flags. This is typically used to augment
819      * local measurement results to match a known anchor from the carrier.
820      */
821     private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) {
822         SubscriptionPlan plan = null;
823         if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0
824                 && mSettings.getAugmentEnabled()) {
825             if (LOGD) Slog.d(TAG, "Resolving plan for " + template);
826             final long token = Binder.clearCallingIdentity();
827             try {
828                 plan = LocalServices.getService(NetworkPolicyManagerInternal.class)
829                         .getSubscriptionPlan(template);
830             } finally {
831                 Binder.restoreCallingIdentity(token);
832             }
833             if (LOGD) Slog.d(TAG, "Resolved to plan " + plan);
834         }
835         return plan;
836     }
837 
838     /**
839      * Return network summary, splicing between DEV and XT stats when
840      * appropriate.
841      */
842     private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags,
843             long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
844         // We've been using pure XT stats long enough that we no longer need to
845         // splice DEV and XT together.
846         final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL,
847                 accessLevel, callingUid);
848 
849         final long now = System.currentTimeMillis();
850         final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null);
851 
852         final NetworkStats stats = new NetworkStats(end - start, 1);
853         stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE,
854                 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets,
855                 entry.txBytes, entry.txPackets, entry.operations));
856         return stats;
857     }
858 
859     /**
860      * Return network history, splicing between DEV and XT stats when
861      * appropriate.
862      */
863     private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template,
864             int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) {
865         // We've been using pure XT stats long enough that we no longer need to
866         // splice DEV and XT together.
867         final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags);
868         synchronized (mStatsLock) {
869             return mXtStatsCached.getHistory(template, augmentPlan,
870                     UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE,
871                     accessLevel, callingUid);
872         }
873     }
874 
875     private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
876         assertSystemReady();
877 
878         // NOTE: if callers want to get non-augmented data, they should go
879         // through the public API
880         return internalGetSummaryForNetwork(template,
881                 NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end,
882                 NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes();
883     }
884 
885     private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
886         assertSystemReady();
887 
888         final NetworkStatsCollection uidComplete;
889         synchronized (mStatsLock) {
890             uidComplete = mUidRecorder.getOrLoadCompleteLocked();
891         }
892         return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE,
893                 android.os.Process.SYSTEM_UID);
894     }
895 
896     @Override
897     public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException {
898         if (Binder.getCallingUid() != uid) {
899             Log.w(TAG, "Snapshots only available for calling UID");
900             return new NetworkStats(SystemClock.elapsedRealtime(), 0);
901         }
902 
903         // TODO: switch to data layer stats once kernel exports
904         // for now, read network layer stats and flatten across all ifaces
905         final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL);
906 
907         // splice in operation counts
908         networkLayer.spliceOperationsFrom(mUidOperations);
909 
910         final NetworkStats dataLayer = new NetworkStats(
911                 networkLayer.getElapsedRealtime(), networkLayer.size());
912 
913         NetworkStats.Entry entry = null;
914         for (int i = 0; i < networkLayer.size(); i++) {
915             entry = networkLayer.getValues(i, entry);
916             entry.iface = IFACE_ALL;
917             dataLayer.combineValues(entry);
918         }
919 
920         return dataLayer;
921     }
922 
923     @Override
924     public NetworkStats getDetailedUidStats(String[] requiredIfaces) {
925         try {
926             final String[] ifacesToQuery =
927                     mStatsFactory.augmentWithStackedInterfaces(requiredIfaces);
928             return getNetworkStatsUidDetail(ifacesToQuery);
929         } catch (RemoteException e) {
930             Log.wtf(TAG, "Error compiling UID stats", e);
931             return new NetworkStats(0L, 0);
932         }
933     }
934 
935     @Override
936     public String[] getMobileIfaces() {
937         // TODO (b/192758557): Remove debug log.
938         if (ArrayUtils.contains(mMobileIfaces, null)) {
939             throw new NullPointerException(
940                     "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
941         }
942         return mMobileIfaces.clone();
943     }
944 
945     @Override
946     public void incrementOperationCount(int uid, int tag, int operationCount) {
947         if (Binder.getCallingUid() != uid) {
948             mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG);
949         }
950 
951         if (operationCount < 0) {
952             throw new IllegalArgumentException("operation count can only be incremented");
953         }
954         if (tag == TAG_NONE) {
955             throw new IllegalArgumentException("operation count must have specific tag");
956         }
957 
958         synchronized (mStatsLock) {
959             final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
960             mUidOperations.combineValues(
961                     mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
962             mUidOperations.combineValues(
963                     mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
964         }
965     }
966 
967     @VisibleForTesting
968     void setUidForeground(int uid, boolean uidForeground) {
969         synchronized (mStatsLock) {
970             final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
971             final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
972             if (oldSet != set) {
973                 mActiveUidCounterSet.put(uid, set);
974                 setKernelCounterSet(uid, set);
975             }
976         }
977     }
978 
979     /**
980      * Notify {@code NetworkStatsService} about network status changed.
981      */
982     public void notifyNetworkStatus(
983             @NonNull Network[] defaultNetworks,
984             @NonNull NetworkStateSnapshot[] networkStates,
985             @Nullable String activeIface,
986             @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) {
987         checkNetworkStackPermission(mContext);
988 
989         final long token = Binder.clearCallingIdentity();
990         try {
991             handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface);
992         } finally {
993             Binder.restoreCallingIdentity(token);
994         }
995 
996         // Update the VPN underlying interfaces only after the poll is made and tun data has been
997         // migrated. Otherwise the migration would use the new interfaces instead of the ones that
998         // were current when the polled data was transferred.
999         mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos);
1000     }
1001 
1002     @Override
1003     public void forceUpdate() {
1004         mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
1005 
1006         final long token = Binder.clearCallingIdentity();
1007         try {
1008             performPoll(FLAG_PERSIST_ALL);
1009         } finally {
1010             Binder.restoreCallingIdentity(token);
1011         }
1012     }
1013 
1014     private void advisePersistThreshold(long thresholdBytes) {
1015         // clamp threshold into safe range
1016         mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
1017         if (LOGV) {
1018             Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
1019                     + mPersistThreshold);
1020         }
1021 
1022         final long oldGlobalAlertBytes = mGlobalAlertBytes;
1023 
1024         // update and persist if beyond new thresholds
1025         final long currentTime = mClock.millis();
1026         synchronized (mStatsLock) {
1027             if (!mSystemReady) return;
1028 
1029             updatePersistThresholdsLocked();
1030 
1031             mDevRecorder.maybePersistLocked(currentTime);
1032             mXtRecorder.maybePersistLocked(currentTime);
1033             mUidRecorder.maybePersistLocked(currentTime);
1034             mUidTagRecorder.maybePersistLocked(currentTime);
1035         }
1036 
1037         if (oldGlobalAlertBytes != mGlobalAlertBytes) {
1038             registerGlobalAlert();
1039         }
1040     }
1041 
1042     @Override
1043     public DataUsageRequest registerUsageCallback(String callingPackage,
1044                 DataUsageRequest request, Messenger messenger, IBinder binder) {
1045         Objects.requireNonNull(callingPackage, "calling package is null");
1046         Objects.requireNonNull(request, "DataUsageRequest is null");
1047         Objects.requireNonNull(request.template, "NetworkTemplate is null");
1048         Objects.requireNonNull(messenger, "messenger is null");
1049         Objects.requireNonNull(binder, "binder is null");
1050 
1051         int callingUid = Binder.getCallingUid();
1052         @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage);
1053         DataUsageRequest normalizedRequest;
1054         final long token = Binder.clearCallingIdentity();
1055         try {
1056             normalizedRequest = mStatsObservers.register(request, messenger, binder,
1057                     callingUid, accessLevel);
1058         } finally {
1059             Binder.restoreCallingIdentity(token);
1060         }
1061 
1062         // Create baseline stats
1063         mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL));
1064 
1065         return normalizedRequest;
1066    }
1067 
1068     @Override
1069     public void unregisterUsageRequest(DataUsageRequest request) {
1070         Objects.requireNonNull(request, "DataUsageRequest is null");
1071 
1072         int callingUid = Binder.getCallingUid();
1073         final long token = Binder.clearCallingIdentity();
1074         try {
1075             mStatsObservers.unregister(request, callingUid);
1076         } finally {
1077             Binder.restoreCallingIdentity(token);
1078         }
1079     }
1080 
1081     @Override
1082     public long getUidStats(int uid, int type) {
1083         final int callingUid = Binder.getCallingUid();
1084         if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) {
1085             return UNSUPPORTED;
1086         }
1087         return nativeGetUidStat(uid, type, checkBpfStatsEnable());
1088     }
1089 
1090     @Override
1091     public long getIfaceStats(@NonNull String iface, int type) {
1092         Objects.requireNonNull(iface);
1093         long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable());
1094         if (nativeIfaceStats == -1) {
1095             return nativeIfaceStats;
1096         } else {
1097             // When tethering offload is in use, nativeIfaceStats does not contain usage from
1098             // offload, add it back here. Note that the included statistics might be stale
1099             // since polling newest stats from hardware might impact system health and not
1100             // suitable for TrafficStats API use cases.
1101             return nativeIfaceStats + getProviderIfaceStats(iface, type);
1102         }
1103     }
1104 
1105     @Override
1106     public long getTotalStats(int type) {
1107         long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable());
1108         if (nativeTotalStats == -1) {
1109             return nativeTotalStats;
1110         } else {
1111             // Refer to comment in getIfaceStats
1112             return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type);
1113         }
1114     }
1115 
1116     private long getProviderIfaceStats(@Nullable String iface, int type) {
1117         final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
1118         final HashSet<String> limitIfaces;
1119         if (iface == IFACE_ALL) {
1120             limitIfaces = null;
1121         } else {
1122             limitIfaces = new HashSet<>();
1123             limitIfaces.add(iface);
1124         }
1125         final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces);
1126         switch (type) {
1127             case TrafficStats.TYPE_RX_BYTES:
1128                 return entry.rxBytes;
1129             case TrafficStats.TYPE_RX_PACKETS:
1130                 return entry.rxPackets;
1131             case TrafficStats.TYPE_TX_BYTES:
1132                 return entry.txBytes;
1133             case TrafficStats.TYPE_TX_PACKETS:
1134                 return entry.txPackets;
1135             default:
1136                 return 0;
1137         }
1138     }
1139 
1140     private boolean checkBpfStatsEnable() {
1141         return mUseBpfTrafficStats;
1142     }
1143 
1144     /**
1145      * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
1146      * reflect current {@link #mPersistThreshold} value. Always defers to
1147      * {@link Global} values when defined.
1148      */
1149     @GuardedBy("mStatsLock")
1150     private void updatePersistThresholdsLocked() {
1151         mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
1152         mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
1153         mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
1154         mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
1155         mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
1156     }
1157 
1158     /**
1159      * Receiver that watches for {@link Tethering} to claim interface pairs.
1160      */
1161     private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() {
1162         @Override
1163         public void onReceive(Context context, Intent intent) {
1164             performPoll(FLAG_PERSIST_NETWORK);
1165         }
1166     };
1167 
1168     private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
1169         @Override
1170         public void onReceive(Context context, Intent intent) {
1171             // on background handler thread, and verified UPDATE_DEVICE_STATS
1172             // permission above.
1173             performPoll(FLAG_PERSIST_ALL);
1174 
1175             // verify that we're watching global alert
1176             registerGlobalAlert();
1177         }
1178     };
1179 
1180     private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() {
1181         @Override
1182         public void onReceive(Context context, Intent intent) {
1183             // on background handler thread, and UID_REMOVED is protected
1184             // broadcast.
1185 
1186             final int uid = intent.getIntExtra(EXTRA_UID, -1);
1187             if (uid == -1) return;
1188 
1189             synchronized (mStatsLock) {
1190                 mWakeLock.acquire();
1191                 try {
1192                     removeUidsLocked(uid);
1193                 } finally {
1194                     mWakeLock.release();
1195                 }
1196             }
1197         }
1198     };
1199 
1200     private BroadcastReceiver mUserReceiver = new BroadcastReceiver() {
1201         @Override
1202         public void onReceive(Context context, Intent intent) {
1203             // On background handler thread, and USER_REMOVED is protected
1204             // broadcast.
1205 
1206             final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
1207             if (userId == -1) return;
1208 
1209             synchronized (mStatsLock) {
1210                 mWakeLock.acquire();
1211                 try {
1212                     removeUserLocked(userId);
1213                 } finally {
1214                     mWakeLock.release();
1215                 }
1216             }
1217         }
1218     };
1219 
1220     private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() {
1221         @Override
1222         public void onReceive(Context context, Intent intent) {
1223             // SHUTDOWN is protected broadcast.
1224             synchronized (mStatsLock) {
1225                 shutdownLocked();
1226             }
1227         }
1228     };
1229 
1230     /**
1231      * Observer that watches for {@link INetworkManagementService} alerts.
1232      */
1233     private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() {
1234         @Override
1235         public void limitReached(String limitName, String iface) {
1236             // only someone like NMS should be calling us
1237             NetworkStack.checkNetworkStackPermission(mContext);
1238 
1239             if (LIMIT_GLOBAL_ALERT.equals(limitName)) {
1240                 // kick off background poll to collect network stats unless there is already
1241                 // such a call pending; UID stats are handled during normal polling interval.
1242                 if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) {
1243                     mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT,
1244                             mSettings.getPollDelay());
1245                 }
1246             }
1247         }
1248     };
1249 
1250     /**
1251      * Handle collapsed RAT type changed event.
1252      */
1253     @VisibleForTesting
1254     public void handleOnCollapsedRatTypeChanged() {
1255         // Protect service from frequently updating. Remove pending messages if any.
1256         mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS);
1257         mHandler.sendMessageDelayed(
1258                 mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay());
1259     }
1260 
1261     private void handleNotifyNetworkStatus(
1262             Network[] defaultNetworks,
1263             NetworkStateSnapshot[] snapshots,
1264             String activeIface) {
1265         synchronized (mStatsLock) {
1266             mWakeLock.acquire();
1267             try {
1268                 mActiveIface = activeIface;
1269                 handleNotifyNetworkStatusLocked(defaultNetworks, snapshots);
1270             } finally {
1271                 mWakeLock.release();
1272             }
1273         }
1274     }
1275 
1276     /**
1277      * Inspect all current {@link NetworkStateSnapshot}s to derive mapping from {@code iface} to
1278      * {@link NetworkStatsHistory}. When multiple networks are active on a single {@code iface},
1279      * they are combined under a single {@link NetworkIdentitySet}.
1280      */
1281     @GuardedBy("mStatsLock")
1282     private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks,
1283             @NonNull NetworkStateSnapshot[] snapshots) {
1284         if (!mSystemReady) return;
1285         if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()");
1286 
1287         // take one last stats snapshot before updating iface mapping. this
1288         // isn't perfect, since the kernel may already be counting traffic from
1289         // the updated network.
1290 
1291         // poll, but only persist network stats to keep codepath fast. UID stats
1292         // will be persisted during next alarm poll event.
1293         performPollLocked(FLAG_PERSIST_NETWORK);
1294 
1295         // Rebuild active interfaces based on connected networks
1296         mActiveIfaces.clear();
1297         mActiveUidIfaces.clear();
1298         // Update the list of default networks.
1299         mDefaultNetworks = defaultNetworks;
1300 
1301         mLastNetworkStateSnapshots = snapshots;
1302 
1303         final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled();
1304         final ArraySet<String> mobileIfaces = new ArraySet<>();
1305         for (NetworkStateSnapshot snapshot : snapshots) {
1306             final int displayTransport =
1307                     getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes());
1308             final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport);
1309             final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork());
1310             final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED
1311                     : getSubTypeForStateSnapshot(snapshot);
1312             final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot,
1313                     isDefault, subType);
1314 
1315             // Traffic occurring on the base interface is always counted for
1316             // both total usage and UID details.
1317             final String baseIface = snapshot.getLinkProperties().getInterfaceName();
1318             if (baseIface != null) {
1319                 findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
1320                 findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
1321 
1322                 // Build a separate virtual interface for VT (Video Telephony) data usage.
1323                 // Only do this when IMS is not metered, but VT is metered.
1324                 // If IMS is metered, then the IMS network usage has already included VT usage.
1325                 // VT is considered always metered in framework's layer. If VT is not metered
1326                 // per carrier's policy, modem will report 0 usage for VT calls.
1327                 if (snapshot.getNetworkCapabilities().hasCapability(
1328                         NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) {
1329 
1330                     // Copy the identify from IMS one but mark it as metered.
1331                     NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(),
1332                             ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(),
1333                             ident.getRoaming(), true /* metered */,
1334                             true /* onDefaultNetwork */, ident.getOemManaged());
1335                     final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot);
1336                     findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent);
1337                     findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent);
1338                 }
1339 
1340                 if (isMobile) {
1341                     mobileIfaces.add(baseIface);
1342                 }
1343             }
1344 
1345             // Traffic occurring on stacked interfaces is usually clatd.
1346             //
1347             // UID stats are always counted on the stacked interface and never on the base
1348             // interface, because the packets on the base interface do not actually match
1349             // application sockets (they're not IPv4) and thus the app uid is not known.
1350             // For receive this is obvious: packets must be translated from IPv6 to IPv4
1351             // before the application socket can be found.
1352             // For transmit: either they go through the clat daemon which by virtue of going
1353             // through userspace strips the original socket association during the IPv4 to
1354             // IPv6 translation process, or they are offloaded by eBPF, which doesn't:
1355             // However, on an ebpf device the accounting is done in cgroup ebpf hooks,
1356             // which don't trigger again post ebpf translation.
1357             // (as such stats accounted to the clat uid are ignored)
1358             //
1359             // Interface stats are more complicated.
1360             //
1361             // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus
1362             // *all* statistics are collected by iptables on the stacked v4-* interface.
1363             //
1364             // Additionally for ingress all packets bound for the clat IPv6 address are dropped
1365             // in ip6tables raw prerouting and thus even non-offloaded packets are only
1366             // accounted for on the stacked interface.
1367             //
1368             // For egress, packets subject to eBPF offload never appear on the base interface
1369             // and only appear on the stacked interface. Thus to ensure packets increment
1370             // interface stats, we must collate data from stacked interfaces. For xt_qtaguid
1371             // (or non eBPF offloaded) TX they would appear on both, however egress interface
1372             // accounting is explicitly bypassed for traffic from the clat uid.
1373             //
1374             // TODO: This code might be combined to above code.
1375             for (String iface : snapshot.getLinkProperties().getAllInterfaceNames()) {
1376                 // baseIface has been handled, so ignore it.
1377                 if (TextUtils.equals(baseIface, iface)) continue;
1378                 if (iface != null) {
1379                     findOrCreateNetworkIdentitySet(mActiveIfaces, iface).add(ident);
1380                     findOrCreateNetworkIdentitySet(mActiveUidIfaces, iface).add(ident);
1381                     if (isMobile) {
1382                         mobileIfaces.add(iface);
1383                     }
1384 
1385                     mStatsFactory.noteStackedIface(iface, baseIface);
1386                 }
1387             }
1388         }
1389 
1390         mMobileIfaces = mobileIfaces.toArray(new String[0]);
1391         // TODO (b/192758557): Remove debug log.
1392         if (ArrayUtils.contains(mMobileIfaces, null)) {
1393             throw new NullPointerException(
1394                     "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces));
1395         }
1396     }
1397 
1398     private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) {
1399         if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
1400             throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR");
1401         }
1402 
1403         final NetworkSpecifier spec = state.getNetworkCapabilities().getNetworkSpecifier();
1404         if (spec instanceof TelephonyNetworkSpecifier) {
1405              return ((TelephonyNetworkSpecifier) spec).getSubscriptionId();
1406         } else {
1407             Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier");
1408             return INVALID_SUBSCRIPTION_ID;
1409         }
1410     }
1411 
1412     /**
1413      * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through
1414      * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different
1415      * transport types do not actually fill this value.
1416      */
1417     private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) {
1418         if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
1419             return 0;
1420         }
1421 
1422         return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.getSubscriberId());
1423     }
1424 
1425     private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet(
1426             ArrayMap<K, NetworkIdentitySet> map, K key) {
1427         NetworkIdentitySet ident = map.get(key);
1428         if (ident == null) {
1429             ident = new NetworkIdentitySet();
1430             map.put(key, ident);
1431         }
1432         return ident;
1433     }
1434 
1435     @GuardedBy("mStatsLock")
1436     private void recordSnapshotLocked(long currentTime) throws RemoteException {
1437         // snapshot and record current counters; read UID stats first to
1438         // avoid over counting dev stats.
1439         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid");
1440         final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL);
1441         Trace.traceEnd(TRACE_TAG_NETWORK);
1442         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt");
1443         final NetworkStats xtSnapshot = readNetworkStatsSummaryXt();
1444         Trace.traceEnd(TRACE_TAG_NETWORK);
1445         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev");
1446         final NetworkStats devSnapshot = readNetworkStatsSummaryDev();
1447         Trace.traceEnd(TRACE_TAG_NETWORK);
1448 
1449         // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data
1450         // from stats providers that isn't already counted by dev and XT stats.
1451         Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider");
1452         final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE);
1453         Trace.traceEnd(TRACE_TAG_NETWORK);
1454         xtSnapshot.combineAllValues(providersnapshot);
1455         devSnapshot.combineAllValues(providersnapshot);
1456 
1457         // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
1458         // can't be reattributed to responsible apps.
1459         Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev");
1460         mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
1461         Trace.traceEnd(TRACE_TAG_NETWORK);
1462         Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt");
1463         mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
1464         Trace.traceEnd(TRACE_TAG_NETWORK);
1465 
1466         // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps.
1467         Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid");
1468         mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
1469         Trace.traceEnd(TRACE_TAG_NETWORK);
1470         Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag");
1471         mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
1472         Trace.traceEnd(TRACE_TAG_NETWORK);
1473 
1474         // We need to make copies of member fields that are sent to the observer to avoid
1475         // a race condition between the service handler thread and the observer's
1476         mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces),
1477                 new ArrayMap<>(mActiveUidIfaces), currentTime);
1478     }
1479 
1480     /**
1481      * Bootstrap initial stats snapshot, usually during {@link #systemReady()}
1482      * so we have baseline values without double-counting.
1483      */
1484     @GuardedBy("mStatsLock")
1485     private void bootstrapStatsLocked() {
1486         final long currentTime = mClock.millis();
1487 
1488         try {
1489             recordSnapshotLocked(currentTime);
1490         } catch (IllegalStateException e) {
1491             Slog.w(TAG, "problem reading network stats: " + e);
1492         } catch (RemoteException e) {
1493             // ignored; service lives in system_server
1494         }
1495     }
1496 
1497     private void performPoll(int flags) {
1498         synchronized (mStatsLock) {
1499             mWakeLock.acquire();
1500 
1501             try {
1502                 performPollLocked(flags);
1503             } finally {
1504                 mWakeLock.release();
1505             }
1506         }
1507     }
1508 
1509     /**
1510      * Periodic poll operation, reading current statistics and recording into
1511      * {@link NetworkStatsHistory}.
1512      */
1513     @GuardedBy("mStatsLock")
1514     private void performPollLocked(int flags) {
1515         if (!mSystemReady) return;
1516         if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
1517         Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked");
1518 
1519         final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
1520         final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
1521         final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
1522 
1523         performPollFromProvidersLocked();
1524 
1525         // TODO: consider marking "untrusted" times in historical stats
1526         final long currentTime = mClock.millis();
1527 
1528         try {
1529             recordSnapshotLocked(currentTime);
1530         } catch (IllegalStateException e) {
1531             Log.wtf(TAG, "problem reading network stats", e);
1532             return;
1533         } catch (RemoteException e) {
1534             // ignored; service lives in system_server
1535             return;
1536         }
1537 
1538         // persist any pending data depending on requested flags
1539         Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]");
1540         if (persistForce) {
1541             mDevRecorder.forcePersistLocked(currentTime);
1542             mXtRecorder.forcePersistLocked(currentTime);
1543             mUidRecorder.forcePersistLocked(currentTime);
1544             mUidTagRecorder.forcePersistLocked(currentTime);
1545         } else {
1546             if (persistNetwork) {
1547                 mDevRecorder.maybePersistLocked(currentTime);
1548                 mXtRecorder.maybePersistLocked(currentTime);
1549             }
1550             if (persistUid) {
1551                 mUidRecorder.maybePersistLocked(currentTime);
1552                 mUidTagRecorder.maybePersistLocked(currentTime);
1553             }
1554         }
1555         Trace.traceEnd(TRACE_TAG_NETWORK);
1556 
1557         if (mSettings.getSampleEnabled()) {
1558             // sample stats after each full poll
1559             performSampleLocked();
1560         }
1561 
1562         // finally, dispatch updated event to any listeners
1563         mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED));
1564 
1565         Trace.traceEnd(TRACE_TAG_NETWORK);
1566     }
1567 
1568     @GuardedBy("mStatsLock")
1569     private void performPollFromProvidersLocked() {
1570         // Request asynchronous stats update from all providers for next poll. And wait a bit of
1571         // time to allow providers report-in given that normally binder call should be fast. Note
1572         // that size of list might be changed because addition/removing at the same time. For
1573         // addition, the stats of the missed provider can only be collected in next poll;
1574         // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS
1575         // once that happened.
1576         // TODO: request with a valid token.
1577         Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate");
1578         final int registeredCallbackCount = mStatsProviderCbList.size();
1579         mStatsProviderSem.drainPermits();
1580         invokeForAllStatsProviderCallbacks(
1581                 (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */));
1582         try {
1583             mStatsProviderSem.tryAcquire(registeredCallbackCount,
1584                     MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS);
1585         } catch (InterruptedException e) {
1586             // Strictly speaking it's possible a provider happened to deliver between the timeout
1587             // and the log, and that doesn't matter too much as this is just a debug log.
1588             Log.d(TAG, "requestStatsUpdate - providers responded "
1589                     + mStatsProviderSem.availablePermits()
1590                     + "/" + registeredCallbackCount + " : " + e);
1591         }
1592         Trace.traceEnd(TRACE_TAG_NETWORK);
1593     }
1594 
1595     /**
1596      * Sample recent statistics summary into {@link EventLog}.
1597      */
1598     @GuardedBy("mStatsLock")
1599     private void performSampleLocked() {
1600         // TODO: migrate trustedtime fixes to separate binary log events
1601         final long currentTime = mClock.millis();
1602 
1603         NetworkTemplate template;
1604         NetworkStats.Entry devTotal;
1605         NetworkStats.Entry xtTotal;
1606         NetworkStats.Entry uidTotal;
1607 
1608         // collect mobile sample
1609         template = buildTemplateMobileWildcard();
1610         devTotal = mDevRecorder.getTotalSinceBootLocked(template);
1611         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
1612         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1613 
1614         EventLogTags.writeNetstatsMobileSample(
1615                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1616                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1617                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1618                 currentTime);
1619 
1620         // collect wifi sample
1621         template = buildTemplateWifiWildcard();
1622         devTotal = mDevRecorder.getTotalSinceBootLocked(template);
1623         xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
1624         uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
1625 
1626         EventLogTags.writeNetstatsWifiSample(
1627                 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
1628                 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
1629                 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
1630                 currentTime);
1631     }
1632 
1633     /**
1634      * Clean up {@link #mUidRecorder} after UID is removed.
1635      */
1636     @GuardedBy("mStatsLock")
1637     private void removeUidsLocked(int... uids) {
1638         if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
1639 
1640         // Perform one last poll before removing
1641         performPollLocked(FLAG_PERSIST_ALL);
1642 
1643         mUidRecorder.removeUidsLocked(uids);
1644         mUidTagRecorder.removeUidsLocked(uids);
1645 
1646         // Clear kernel stats associated with UID
1647         for (int uid : uids) {
1648             resetKernelUidStats(uid);
1649         }
1650     }
1651 
1652     /**
1653      * Clean up {@link #mUidRecorder} after user is removed.
1654      */
1655     @GuardedBy("mStatsLock")
1656     private void removeUserLocked(int userId) {
1657         if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
1658 
1659         // Build list of UIDs that we should clean up
1660         int[] uids = new int[0];
1661         final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
1662                 PackageManager.MATCH_ANY_USER
1663                 | PackageManager.MATCH_DISABLED_COMPONENTS);
1664         for (ApplicationInfo app : apps) {
1665             final int uid = UserHandle.getUid(userId, app.uid);
1666             uids = ArrayUtils.appendInt(uids, uid);
1667         }
1668 
1669         removeUidsLocked(uids);
1670     }
1671 
1672     private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal {
1673         @Override
1674         public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) {
1675             Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes");
1676             try {
1677                 return NetworkStatsService.this.getNetworkTotalBytes(template, start, end);
1678             } finally {
1679                 Trace.traceEnd(TRACE_TAG_NETWORK);
1680             }
1681         }
1682 
1683         @Override
1684         public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) {
1685             Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes");
1686             try {
1687                 return NetworkStatsService.this.getNetworkUidBytes(template, start, end);
1688             } finally {
1689                 Trace.traceEnd(TRACE_TAG_NETWORK);
1690             }
1691         }
1692 
1693         @Override
1694         public void setUidForeground(int uid, boolean uidForeground) {
1695             NetworkStatsService.this.setUidForeground(uid, uidForeground);
1696         }
1697 
1698         @Override
1699         public void advisePersistThreshold(long thresholdBytes) {
1700             NetworkStatsService.this.advisePersistThreshold(thresholdBytes);
1701         }
1702 
1703         @Override
1704         public void forceUpdate() {
1705             NetworkStatsService.this.forceUpdate();
1706         }
1707 
1708         @Override
1709         public void setStatsProviderWarningAndLimitAsync(
1710                 @NonNull String iface, long warning, long limit) {
1711             if (LOGV) {
1712                 Slog.v(TAG, "setStatsProviderWarningAndLimitAsync("
1713                         + iface + "," + warning + "," + limit + ")");
1714             }
1715             invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface,
1716                     warning, limit));
1717         }
1718     }
1719 
1720     @Override
1721     protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) {
1722         if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return;
1723 
1724         long duration = DateUtils.DAY_IN_MILLIS;
1725         final HashSet<String> argSet = new HashSet<String>();
1726         for (String arg : args) {
1727             argSet.add(arg);
1728 
1729             if (arg.startsWith("--duration=")) {
1730                 try {
1731                     duration = Long.parseLong(arg.substring(11));
1732                 } catch (NumberFormatException ignored) {
1733                 }
1734             }
1735         }
1736 
1737         // usage: dumpsys netstats --full --uid --tag --poll --checkin
1738         final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
1739         final boolean checkin = argSet.contains("--checkin");
1740         final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
1741         final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
1742         final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
1743 
1744         final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, "  ");
1745 
1746         synchronized (mStatsLock) {
1747             if (args.length > 0 && "--proto".equals(args[0])) {
1748                 // In this case ignore all other arguments.
1749                 dumpProtoLocked(fd);
1750                 return;
1751             }
1752 
1753             if (poll) {
1754                 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
1755                 pw.println("Forced poll");
1756                 return;
1757             }
1758 
1759             if (checkin) {
1760                 final long end = System.currentTimeMillis();
1761                 final long start = end - duration;
1762 
1763                 pw.print("v1,");
1764                 pw.print(start / SECOND_IN_MILLIS); pw.print(',');
1765                 pw.print(end / SECOND_IN_MILLIS); pw.println();
1766 
1767                 pw.println("xt");
1768                 mXtRecorder.dumpCheckin(rawWriter, start, end);
1769 
1770                 if (includeUid) {
1771                     pw.println("uid");
1772                     mUidRecorder.dumpCheckin(rawWriter, start, end);
1773                 }
1774                 if (includeTag) {
1775                     pw.println("tag");
1776                     mUidTagRecorder.dumpCheckin(rawWriter, start, end);
1777                 }
1778                 return;
1779             }
1780 
1781             pw.println("Configs:");
1782             pw.increaseIndent();
1783             pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled());
1784             pw.println();
1785             pw.decreaseIndent();
1786 
1787             pw.println("Active interfaces:");
1788             pw.increaseIndent();
1789             for (int i = 0; i < mActiveIfaces.size(); i++) {
1790                 pw.printPair("iface", mActiveIfaces.keyAt(i));
1791                 pw.printPair("ident", mActiveIfaces.valueAt(i));
1792                 pw.println();
1793             }
1794             pw.decreaseIndent();
1795 
1796             pw.println("Active UID interfaces:");
1797             pw.increaseIndent();
1798             for (int i = 0; i < mActiveUidIfaces.size(); i++) {
1799                 pw.printPair("iface", mActiveUidIfaces.keyAt(i));
1800                 pw.printPair("ident", mActiveUidIfaces.valueAt(i));
1801                 pw.println();
1802             }
1803             pw.decreaseIndent();
1804 
1805             // Get the top openSession callers
1806             final SparseIntArray calls;
1807             synchronized (mOpenSessionCallsPerUid) {
1808                 calls = mOpenSessionCallsPerUid.clone();
1809             }
1810 
1811             final int N = calls.size();
1812             final long[] values = new long[N];
1813             for (int j = 0; j < N; j++) {
1814                 values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j);
1815             }
1816             Arrays.sort(values);
1817 
1818             pw.println("Top openSession callers (uid=count):");
1819             pw.increaseIndent();
1820             final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT);
1821             for (int j = N - 1; j >= end; j--) {
1822                 final int uid = (int) (values[j] & 0xffffffff);
1823                 final int count = (int) (values[j] >> 32);
1824                 pw.print(uid); pw.print("="); pw.println(count);
1825             }
1826             pw.decreaseIndent();
1827             pw.println();
1828 
1829             pw.println("Stats Providers:");
1830             pw.increaseIndent();
1831             invokeForAllStatsProviderCallbacks((cb) -> {
1832                 pw.println(cb.mTag + " Xt:");
1833                 pw.increaseIndent();
1834                 pw.print(cb.getCachedStats(STATS_PER_IFACE).toString());
1835                 pw.decreaseIndent();
1836                 if (includeUid) {
1837                     pw.println(cb.mTag + " Uid:");
1838                     pw.increaseIndent();
1839                     pw.print(cb.getCachedStats(STATS_PER_UID).toString());
1840                     pw.decreaseIndent();
1841                 }
1842             });
1843             pw.decreaseIndent();
1844 
1845             pw.println("Dev stats:");
1846             pw.increaseIndent();
1847             mDevRecorder.dumpLocked(pw, fullHistory);
1848             pw.decreaseIndent();
1849 
1850             pw.println("Xt stats:");
1851             pw.increaseIndent();
1852             mXtRecorder.dumpLocked(pw, fullHistory);
1853             pw.decreaseIndent();
1854 
1855             if (includeUid) {
1856                 pw.println("UID stats:");
1857                 pw.increaseIndent();
1858                 mUidRecorder.dumpLocked(pw, fullHistory);
1859                 pw.decreaseIndent();
1860             }
1861 
1862             if (includeTag) {
1863                 pw.println("UID tag stats:");
1864                 pw.increaseIndent();
1865                 mUidTagRecorder.dumpLocked(pw, fullHistory);
1866                 pw.decreaseIndent();
1867             }
1868         }
1869     }
1870 
1871     @GuardedBy("mStatsLock")
1872     private void dumpProtoLocked(FileDescriptor fd) {
1873         final ProtoOutputStream proto = new ProtoOutputStream(fd);
1874 
1875         // TODO Right now it writes all history.  Should it limit to the "since-boot" log?
1876 
1877         dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces);
1878         dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces);
1879         mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS);
1880         mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS);
1881         mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS);
1882         mUidTagRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS);
1883 
1884         proto.flush();
1885     }
1886 
1887     private static void dumpInterfaces(ProtoOutputStream proto, long tag,
1888             ArrayMap<String, NetworkIdentitySet> ifaces) {
1889         for (int i = 0; i < ifaces.size(); i++) {
1890             final long start = proto.start(tag);
1891 
1892             proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i));
1893             ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES);
1894 
1895             proto.end(start);
1896         }
1897     }
1898 
1899     private NetworkStats readNetworkStatsSummaryDev() {
1900         try {
1901             return mStatsFactory.readNetworkStatsSummaryDev();
1902         } catch (IOException e) {
1903             throw new IllegalStateException(e);
1904         }
1905     }
1906 
1907     private NetworkStats readNetworkStatsSummaryXt() {
1908         try {
1909             return mStatsFactory.readNetworkStatsSummaryXt();
1910         } catch (IOException e) {
1911             throw new IllegalStateException(e);
1912         }
1913     }
1914 
1915     private NetworkStats readNetworkStatsUidDetail(int uid, String[] ifaces, int tag) {
1916         try {
1917             return mStatsFactory.readNetworkStatsDetail(uid, ifaces, tag);
1918         } catch (IOException e) {
1919             throw new IllegalStateException(e);
1920         }
1921     }
1922 
1923     /**
1924      * Return snapshot of current UID statistics, including any
1925      * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations}
1926      * values.
1927      *
1928      * @param ifaces A list of interfaces the stats should be restricted to, or
1929      *               {@link NetworkStats#INTERFACES_ALL}.
1930      */
1931     private NetworkStats getNetworkStatsUidDetail(String[] ifaces)
1932             throws RemoteException {
1933         final NetworkStats uidSnapshot = readNetworkStatsUidDetail(UID_ALL,  ifaces, TAG_ALL);
1934 
1935         // fold tethering stats and operations into uid snapshot
1936         final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
1937         tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL);
1938         mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot);
1939         uidSnapshot.combineAllValues(tetherSnapshot);
1940 
1941         // get a stale copy of uid stats snapshot provided by providers.
1942         final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID);
1943         providerStats.filter(UID_ALL, ifaces, TAG_ALL);
1944         mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats);
1945         uidSnapshot.combineAllValues(providerStats);
1946 
1947         uidSnapshot.combineAllValues(mUidOperations);
1948 
1949         return uidSnapshot;
1950     }
1951 
1952     /**
1953      * Return snapshot of current non-offloaded tethering statistics. Will return empty
1954      * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE}
1955      * since it is already included by {@link #nativeGetIfaceStat}.
1956      * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats.
1957      */
1958     // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded
1959     //  tethering stats.
1960     private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
1961         try {
1962             return mNetworkManager.getNetworkStatsTethering(how);
1963         } catch (IllegalStateException e) {
1964             Log.wtf(TAG, "problem reading network stats", e);
1965             return new NetworkStats(0L, 10);
1966         }
1967     }
1968 
1969     // TODO: It is copied from ConnectivityService, consider refactor these check permission
1970     //  functions to a proper util.
1971     private boolean checkAnyPermissionOf(String... permissions) {
1972         for (String permission : permissions) {
1973             if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) {
1974                 return true;
1975             }
1976         }
1977         return false;
1978     }
1979 
1980     private void enforceAnyPermissionOf(String... permissions) {
1981         if (!checkAnyPermissionOf(permissions)) {
1982             throw new SecurityException("Requires one of the following permissions: "
1983                     + String.join(", ", permissions) + ".");
1984         }
1985     }
1986 
1987     /**
1988      * Registers a custom provider of {@link android.net.NetworkStats} to combine the network
1989      * statistics that cannot be seen by the kernel to system. To unregister, invoke the
1990      * {@code unregister()} of the returned callback.
1991      *
1992      * @param tag a human readable identifier of the custom network stats provider.
1993      * @param provider the {@link INetworkStatsProvider} binder corresponding to the
1994      *                 {@link NetworkStatsProvider} to be registered.
1995      *
1996      * @return a {@link INetworkStatsProviderCallback} binder
1997      *         interface, which can be used to report events to the system.
1998      */
1999     public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider(
2000             @NonNull String tag, @NonNull INetworkStatsProvider provider) {
2001         enforceAnyPermissionOf(NETWORK_STATS_PROVIDER,
2002                 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
2003         Objects.requireNonNull(provider, "provider is null");
2004         Objects.requireNonNull(tag, "tag is null");
2005         try {
2006             NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl(
2007                     tag, provider, mStatsProviderSem, mAlertObserver,
2008                     mStatsProviderCbList);
2009             mStatsProviderCbList.add(callback);
2010             Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid="
2011                     + getCallingUid() + "/" + getCallingPid());
2012             return callback;
2013         } catch (RemoteException e) {
2014             Log.e(TAG, "registerNetworkStatsProvider failed", e);
2015         }
2016         return null;
2017     }
2018 
2019     // Collect stats from local cache of providers.
2020     private @NonNull NetworkStats getNetworkStatsFromProviders(int how) {
2021         final NetworkStats ret = new NetworkStats(0L, 0);
2022         invokeForAllStatsProviderCallbacks((cb) -> ret.combineAllValues(cb.getCachedStats(how)));
2023         return ret;
2024     }
2025 
2026     @FunctionalInterface
2027     private interface ThrowingConsumer<S, T extends Throwable> {
2028         void accept(S s) throws T;
2029     }
2030 
2031     private void invokeForAllStatsProviderCallbacks(
2032             @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) {
2033         for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) {
2034             try {
2035                 task.accept(cb);
2036             } catch (RemoteException e) {
2037                 Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e);
2038             }
2039         }
2040     }
2041 
2042     private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub
2043             implements IBinder.DeathRecipient {
2044         @NonNull final String mTag;
2045 
2046         @NonNull final INetworkStatsProvider mProvider;
2047         @NonNull private final Semaphore mSemaphore;
2048         @NonNull final INetworkManagementEventObserver mAlertObserver;
2049         @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList;
2050 
2051         @NonNull private final Object mProviderStatsLock = new Object();
2052 
2053         @GuardedBy("mProviderStatsLock")
2054         // Track STATS_PER_IFACE and STATS_PER_UID separately.
2055         private final NetworkStats mIfaceStats = new NetworkStats(0L, 0);
2056         @GuardedBy("mProviderStatsLock")
2057         private final NetworkStats mUidStats = new NetworkStats(0L, 0);
2058 
2059         NetworkStatsProviderCallbackImpl(
2060                 @NonNull String tag, @NonNull INetworkStatsProvider provider,
2061                 @NonNull Semaphore semaphore,
2062                 @NonNull INetworkManagementEventObserver alertObserver,
2063                 @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList)
2064                 throws RemoteException {
2065             mTag = tag;
2066             mProvider = provider;
2067             mProvider.asBinder().linkToDeath(this, 0);
2068             mSemaphore = semaphore;
2069             mAlertObserver = alertObserver;
2070             mStatsProviderCbList = cbList;
2071         }
2072 
2073         @NonNull
2074         public NetworkStats getCachedStats(int how) {
2075             synchronized (mProviderStatsLock) {
2076                 NetworkStats stats;
2077                 switch (how) {
2078                     case STATS_PER_IFACE:
2079                         stats = mIfaceStats;
2080                         break;
2081                     case STATS_PER_UID:
2082                         stats = mUidStats;
2083                         break;
2084                     default:
2085                         throw new IllegalArgumentException("Invalid type: " + how);
2086                 }
2087                 // Callers might be able to mutate the returned object. Return a defensive copy
2088                 // instead of local reference.
2089                 return stats.clone();
2090             }
2091         }
2092 
2093         @Override
2094         public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats,
2095                 @Nullable NetworkStats uidStats) {
2096             // TODO: 1. Use token to map ifaces to correct NetworkIdentity.
2097             //       2. Store the difference and store it directly to the recorder.
2098             synchronized (mProviderStatsLock) {
2099                 if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats);
2100                 if (uidStats != null) mUidStats.combineAllValues(uidStats);
2101             }
2102             mSemaphore.release();
2103         }
2104 
2105         @Override
2106         public void notifyAlertReached() throws RemoteException {
2107             mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */);
2108         }
2109 
2110         @Override
2111         public void notifyWarningOrLimitReached() {
2112             Log.d(TAG, mTag + ": notifyWarningOrLimitReached");
2113             LocalServices.getService(NetworkPolicyManagerInternal.class)
2114                     .onStatsProviderWarningOrLimitReached(mTag);
2115         }
2116 
2117         @Override
2118         public void binderDied() {
2119             Log.d(TAG, mTag + ": binderDied");
2120             mStatsProviderCbList.remove(this);
2121         }
2122 
2123         @Override
2124         public void unregister() {
2125             Log.d(TAG, mTag + ": unregister");
2126             mStatsProviderCbList.remove(this);
2127         }
2128 
2129     }
2130 
2131     private void assertSystemReady() {
2132         if (!mSystemReady) {
2133             throw new IllegalStateException("System not ready");
2134         }
2135     }
2136 
2137     private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> {
2138         @Override
2139         public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right,
2140                 int rightIndex, String cookie) {
2141             Log.w(TAG, "Found non-monotonic values; saving to dropbox");
2142 
2143             // record error for debugging
2144             final StringBuilder builder = new StringBuilder();
2145             builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex
2146                     + "] - right[" + rightIndex + "]\n");
2147             builder.append("left=").append(left).append('\n');
2148             builder.append("right=").append(right).append('\n');
2149 
2150             mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
2151                     builder.toString());
2152         }
2153 
2154         @Override
2155         public void foundNonMonotonic(
2156                 NetworkStats stats, int statsIndex, String cookie) {
2157             Log.w(TAG, "Found non-monotonic values; saving to dropbox");
2158 
2159             final StringBuilder builder = new StringBuilder();
2160             builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n");
2161             builder.append("stats=").append(stats).append('\n');
2162 
2163             mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR,
2164                     builder.toString());
2165         }
2166     }
2167 
2168     /**
2169      * Default external settings that read from
2170      * {@link android.provider.Settings.Global}.
2171      */
2172     private static class DefaultNetworkStatsSettings implements NetworkStatsSettings {
2173         private final ContentResolver mResolver;
2174 
2175         public DefaultNetworkStatsSettings(Context context) {
2176             mResolver = Objects.requireNonNull(context.getContentResolver());
2177             // TODO: adjust these timings for production builds
2178         }
2179 
2180         private long getGlobalLong(String name, long def) {
2181             return Settings.Global.getLong(mResolver, name, def);
2182         }
2183         private boolean getGlobalBoolean(String name, boolean def) {
2184             final int defInt = def ? 1 : 0;
2185             return Settings.Global.getInt(mResolver, name, defInt) != 0;
2186         }
2187 
2188         @Override
2189         public long getPollInterval() {
2190             return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
2191         }
2192         @Override
2193         public long getPollDelay() {
2194             return DEFAULT_PERFORM_POLL_DELAY_MS;
2195         }
2196         @Override
2197         public long getGlobalAlertBytes(long def) {
2198             return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def);
2199         }
2200         @Override
2201         public boolean getSampleEnabled() {
2202             return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true);
2203         }
2204         @Override
2205         public boolean getAugmentEnabled() {
2206             return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true);
2207         }
2208         @Override
2209         public boolean getCombineSubtypeEnabled() {
2210             return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false);
2211         }
2212         @Override
2213         public Config getDevConfig() {
2214             return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS),
2215                     getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS),
2216                     getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS));
2217         }
2218         @Override
2219         public Config getXtConfig() {
2220             return getDevConfig();
2221         }
2222         @Override
2223         public Config getUidConfig() {
2224             return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
2225                     getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS),
2226                     getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS));
2227         }
2228         @Override
2229         public Config getUidTagConfig() {
2230             return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS),
2231                     getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS),
2232                     getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS));
2233         }
2234         @Override
2235         public long getDevPersistBytes(long def) {
2236             return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def);
2237         }
2238         @Override
2239         public long getXtPersistBytes(long def) {
2240             return getDevPersistBytes(def);
2241         }
2242         @Override
2243         public long getUidPersistBytes(long def) {
2244             return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def);
2245         }
2246         @Override
2247         public long getUidTagPersistBytes(long def) {
2248             return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def);
2249         }
2250     }
2251 
2252     private static native long nativeGetTotalStat(int type, boolean useBpfStats);
2253     private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats);
2254     private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats);
2255 }
2256