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