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