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