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