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