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