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.NETWORK_STATS_PROVIDER; 20 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; 21 import static android.Manifest.permission.UPDATE_DEVICE_STATS; 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.content.pm.PackageManager.PERMISSION_GRANTED; 27 import static android.net.NetworkIdentity.SUBTYPE_COMBINED; 28 import static android.net.NetworkStack.checkNetworkStackPermission; 29 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL; 30 import static android.net.NetworkStats.IFACE_ALL; 31 import static android.net.NetworkStats.IFACE_VT; 32 import static android.net.NetworkStats.INTERFACES_ALL; 33 import static android.net.NetworkStats.METERED_ALL; 34 import static android.net.NetworkStats.ROAMING_ALL; 35 import static android.net.NetworkStats.SET_ALL; 36 import static android.net.NetworkStats.SET_DEFAULT; 37 import static android.net.NetworkStats.SET_FOREGROUND; 38 import static android.net.NetworkStats.STATS_PER_IFACE; 39 import static android.net.NetworkStats.STATS_PER_UID; 40 import static android.net.NetworkStats.TAG_ALL; 41 import static android.net.NetworkStats.TAG_NONE; 42 import static android.net.NetworkStats.UID_ALL; 43 import static android.net.NetworkStatsHistory.FIELD_ALL; 44 import static android.net.NetworkTemplate.buildTemplateMobileWildcard; 45 import static android.net.NetworkTemplate.buildTemplateWifiWildcard; 46 import static android.net.TetheringManager.ACTION_TETHER_STATE_CHANGED; 47 import static android.net.TrafficStats.KB_IN_BYTES; 48 import static android.net.TrafficStats.MB_IN_BYTES; 49 import static android.net.TrafficStats.UNSUPPORTED; 50 import static android.os.Trace.TRACE_TAG_NETWORK; 51 import static android.provider.Settings.Global.NETSTATS_AUGMENT_ENABLED; 52 import static android.provider.Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED; 53 import static android.provider.Settings.Global.NETSTATS_DEV_BUCKET_DURATION; 54 import static android.provider.Settings.Global.NETSTATS_DEV_DELETE_AGE; 55 import static android.provider.Settings.Global.NETSTATS_DEV_PERSIST_BYTES; 56 import static android.provider.Settings.Global.NETSTATS_DEV_ROTATE_AGE; 57 import static android.provider.Settings.Global.NETSTATS_GLOBAL_ALERT_BYTES; 58 import static android.provider.Settings.Global.NETSTATS_POLL_INTERVAL; 59 import static android.provider.Settings.Global.NETSTATS_SAMPLE_ENABLED; 60 import static android.provider.Settings.Global.NETSTATS_UID_BUCKET_DURATION; 61 import static android.provider.Settings.Global.NETSTATS_UID_DELETE_AGE; 62 import static android.provider.Settings.Global.NETSTATS_UID_PERSIST_BYTES; 63 import static android.provider.Settings.Global.NETSTATS_UID_ROTATE_AGE; 64 import static android.provider.Settings.Global.NETSTATS_UID_TAG_BUCKET_DURATION; 65 import static android.provider.Settings.Global.NETSTATS_UID_TAG_DELETE_AGE; 66 import static android.provider.Settings.Global.NETSTATS_UID_TAG_PERSIST_BYTES; 67 import static android.provider.Settings.Global.NETSTATS_UID_TAG_ROTATE_AGE; 68 import static android.telephony.SubscriptionManager.INVALID_SUBSCRIPTION_ID; 69 import static android.text.format.DateUtils.DAY_IN_MILLIS; 70 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 71 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 72 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 73 74 import static com.android.net.module.util.NetworkCapabilitiesUtils.getDisplayTransport; 75 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; 76 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; 77 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; 78 79 import android.annotation.NonNull; 80 import android.annotation.Nullable; 81 import android.app.AlarmManager; 82 import android.app.PendingIntent; 83 import android.app.usage.NetworkStatsManager; 84 import android.content.BroadcastReceiver; 85 import android.content.ContentResolver; 86 import android.content.Context; 87 import android.content.Intent; 88 import android.content.IntentFilter; 89 import android.content.pm.ApplicationInfo; 90 import android.content.pm.PackageManager; 91 import android.database.ContentObserver; 92 import android.net.DataUsageRequest; 93 import android.net.INetworkManagementEventObserver; 94 import android.net.INetworkStatsService; 95 import android.net.INetworkStatsSession; 96 import android.net.Network; 97 import android.net.NetworkCapabilities; 98 import android.net.NetworkIdentity; 99 import android.net.NetworkSpecifier; 100 import android.net.NetworkStack; 101 import android.net.NetworkStateSnapshot; 102 import android.net.NetworkStats; 103 import android.net.NetworkStats.NonMonotonicObserver; 104 import android.net.NetworkStatsHistory; 105 import android.net.NetworkTemplate; 106 import android.net.TelephonyNetworkSpecifier; 107 import android.net.TrafficStats; 108 import android.net.UnderlyingNetworkInfo; 109 import android.net.Uri; 110 import android.net.netstats.provider.INetworkStatsProvider; 111 import android.net.netstats.provider.INetworkStatsProviderCallback; 112 import android.net.netstats.provider.NetworkStatsProvider; 113 import android.os.BestClock; 114 import android.os.Binder; 115 import android.os.DropBoxManager; 116 import android.os.Environment; 117 import android.os.Handler; 118 import android.os.HandlerExecutor; 119 import android.os.HandlerThread; 120 import android.os.IBinder; 121 import android.os.INetworkManagementService; 122 import android.os.Looper; 123 import android.os.Message; 124 import android.os.Messenger; 125 import android.os.PowerManager; 126 import android.os.RemoteException; 127 import android.os.SystemClock; 128 import android.os.Trace; 129 import android.os.UserHandle; 130 import android.provider.Settings; 131 import android.provider.Settings.Global; 132 import android.service.NetworkInterfaceProto; 133 import android.service.NetworkStatsServiceDumpProto; 134 import android.telephony.PhoneStateListener; 135 import android.telephony.SubscriptionPlan; 136 import android.text.TextUtils; 137 import android.text.format.DateUtils; 138 import android.util.ArrayMap; 139 import android.util.ArraySet; 140 import android.util.EventLog; 141 import android.util.Log; 142 import android.util.MathUtils; 143 import android.util.Slog; 144 import android.util.SparseIntArray; 145 import android.util.proto.ProtoOutputStream; 146 147 import com.android.internal.annotations.GuardedBy; 148 import com.android.internal.annotations.VisibleForTesting; 149 import com.android.internal.util.ArrayUtils; 150 import com.android.internal.util.DumpUtils; 151 import com.android.internal.util.FileRotator; 152 import com.android.internal.util.IndentingPrintWriter; 153 import com.android.server.EventLogTags; 154 import com.android.server.LocalServices; 155 156 import java.io.File; 157 import java.io.FileDescriptor; 158 import java.io.IOException; 159 import java.io.PrintWriter; 160 import java.time.Clock; 161 import java.time.ZoneOffset; 162 import java.util.Arrays; 163 import java.util.HashSet; 164 import java.util.List; 165 import java.util.Objects; 166 import java.util.concurrent.CopyOnWriteArrayList; 167 import java.util.concurrent.Executor; 168 import java.util.concurrent.Semaphore; 169 import java.util.concurrent.TimeUnit; 170 171 /** 172 * Collect and persist detailed network statistics, and provide this data to 173 * other system services. 174 */ 175 public class NetworkStatsService extends INetworkStatsService.Stub { 176 static final String TAG = "NetworkStats"; 177 static final boolean LOGD = Log.isLoggable(TAG, Log.DEBUG); 178 static final boolean LOGV = Log.isLoggable(TAG, Log.VERBOSE); 179 180 // Perform polling and persist all (FLAG_PERSIST_ALL). 181 private static final int MSG_PERFORM_POLL = 1; 182 // Perform polling, persist network, and register the global alert again. 183 private static final int MSG_PERFORM_POLL_REGISTER_ALERT = 2; 184 private static final int MSG_NOTIFY_NETWORK_STATUS = 3; 185 // A message for broadcasting ACTION_NETWORK_STATS_UPDATED in handler thread to prevent 186 // deadlock. 187 private static final int MSG_BROADCAST_NETWORK_STATS_UPDATED = 4; 188 189 /** Flags to control detail level of poll event. */ 190 private static final int FLAG_PERSIST_NETWORK = 0x1; 191 private static final int FLAG_PERSIST_UID = 0x2; 192 private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; 193 private static final int FLAG_PERSIST_FORCE = 0x100; 194 195 /** 196 * When global alert quota is high, wait for this delay before processing each polling, 197 * and do not schedule further polls once there is already one queued. 198 * This avoids firing the global alert too often on devices with high transfer speeds and 199 * high quota. 200 */ 201 private static final int DEFAULT_PERFORM_POLL_DELAY_MS = 1000; 202 203 private static final String TAG_NETSTATS_ERROR = "netstats_error"; 204 205 private final Context mContext; 206 private final INetworkManagementService mNetworkManager; 207 private final NetworkStatsFactory mStatsFactory; 208 private final AlarmManager mAlarmManager; 209 private final Clock mClock; 210 private final NetworkStatsSettings mSettings; 211 private final NetworkStatsObservers mStatsObservers; 212 213 private final File mSystemDir; 214 private final File mBaseDir; 215 216 private final PowerManager.WakeLock mWakeLock; 217 218 private final boolean mUseBpfTrafficStats; 219 220 private final ContentObserver mContentObserver; 221 private final ContentResolver mContentResolver; 222 223 @VisibleForTesting 224 public static final String ACTION_NETWORK_STATS_POLL = 225 "com.android.server.action.NETWORK_STATS_POLL"; 226 public static final String ACTION_NETWORK_STATS_UPDATED = 227 "com.android.server.action.NETWORK_STATS_UPDATED"; 228 229 private PendingIntent mPollIntent; 230 231 private static final String PREFIX_DEV = "dev"; 232 private static final String PREFIX_XT = "xt"; 233 private static final String PREFIX_UID = "uid"; 234 private static final String PREFIX_UID_TAG = "uid_tag"; 235 236 /** 237 * Settings that can be changed externally. 238 */ 239 public interface NetworkStatsSettings { getPollInterval()240 long getPollInterval(); getPollDelay()241 long getPollDelay(); getSampleEnabled()242 boolean getSampleEnabled(); getAugmentEnabled()243 boolean getAugmentEnabled(); 244 /** 245 * When enabled, all mobile data is reported under {@link NetworkIdentity#SUBTYPE_COMBINED}. 246 * When disabled, mobile data is broken down by a granular subtype representative of the 247 * actual subtype. {@see NetworkTemplate#getCollapsedRatType}. 248 * Enabling this decreases the level of detail but saves performance, disk space and 249 * amount of data logged. 250 */ getCombineSubtypeEnabled()251 boolean getCombineSubtypeEnabled(); 252 253 class Config { 254 public final long bucketDuration; 255 public final long rotateAgeMillis; 256 public final long deleteAgeMillis; 257 Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis)258 public Config(long bucketDuration, long rotateAgeMillis, long deleteAgeMillis) { 259 this.bucketDuration = bucketDuration; 260 this.rotateAgeMillis = rotateAgeMillis; 261 this.deleteAgeMillis = deleteAgeMillis; 262 } 263 } 264 getDevConfig()265 Config getDevConfig(); getXtConfig()266 Config getXtConfig(); getUidConfig()267 Config getUidConfig(); getUidTagConfig()268 Config getUidTagConfig(); 269 getGlobalAlertBytes(long def)270 long getGlobalAlertBytes(long def); getDevPersistBytes(long def)271 long getDevPersistBytes(long def); getXtPersistBytes(long def)272 long getXtPersistBytes(long def); getUidPersistBytes(long def)273 long getUidPersistBytes(long def); getUidTagPersistBytes(long def)274 long getUidTagPersistBytes(long def); 275 } 276 277 private final Object mStatsLock = new Object(); 278 279 /** Set of currently active ifaces. */ 280 @GuardedBy("mStatsLock") 281 private final ArrayMap<String, NetworkIdentitySet> mActiveIfaces = new ArrayMap<>(); 282 283 /** Set of currently active ifaces for UID stats. */ 284 @GuardedBy("mStatsLock") 285 private final ArrayMap<String, NetworkIdentitySet> mActiveUidIfaces = new ArrayMap<>(); 286 287 /** Current default active iface. */ 288 @GuardedBy("mStatsLock") 289 private String mActiveIface; 290 291 /** Set of any ifaces associated with mobile networks since boot. */ 292 private volatile String[] mMobileIfaces = new String[0]; 293 294 /** Set of all ifaces currently used by traffic that does not explicitly specify a Network. */ 295 @GuardedBy("mStatsLock") 296 private Network[] mDefaultNetworks = new Network[0]; 297 298 /** Last states of all networks sent from ConnectivityService. */ 299 @GuardedBy("mStatsLock") 300 @Nullable 301 private NetworkStateSnapshot[] mLastNetworkStateSnapshots = null; 302 303 private final DropBoxNonMonotonicObserver mNonMonotonicObserver = 304 new DropBoxNonMonotonicObserver(); 305 306 private static final int MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS = 100; 307 private final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList = 308 new CopyOnWriteArrayList<>(); 309 /** Semaphore used to wait for stats provider to respond to request stats update. */ 310 private final Semaphore mStatsProviderSem = new Semaphore(0, true); 311 312 @GuardedBy("mStatsLock") 313 private NetworkStatsRecorder mDevRecorder; 314 @GuardedBy("mStatsLock") 315 private NetworkStatsRecorder mXtRecorder; 316 @GuardedBy("mStatsLock") 317 private NetworkStatsRecorder mUidRecorder; 318 @GuardedBy("mStatsLock") 319 private NetworkStatsRecorder mUidTagRecorder; 320 321 /** Cached {@link #mXtRecorder} stats. */ 322 @GuardedBy("mStatsLock") 323 private NetworkStatsCollection mXtStatsCached; 324 325 /** Current counter sets for each UID. */ 326 private SparseIntArray mActiveUidCounterSet = new SparseIntArray(); 327 328 /** Data layer operation counters for splicing into other structures. */ 329 private NetworkStats mUidOperations = new NetworkStats(0L, 10); 330 331 @NonNull 332 private final Handler mHandler; 333 334 private volatile boolean mSystemReady; 335 private long mPersistThreshold = 2 * MB_IN_BYTES; 336 private long mGlobalAlertBytes; 337 338 private static final long POLL_RATE_LIMIT_MS = 15_000; 339 340 private long mLastStatsSessionPoll; 341 342 /** Map from UID to number of opened sessions */ 343 @GuardedBy("mOpenSessionCallsPerUid") 344 private final SparseIntArray mOpenSessionCallsPerUid = new SparseIntArray(); 345 346 private final static int DUMP_STATS_SESSION_COUNT = 20; 347 348 @NonNull 349 private final Dependencies mDeps; 350 351 @NonNull 352 private final NetworkStatsSubscriptionsMonitor mNetworkStatsSubscriptionsMonitor; 353 getDefaultSystemDir()354 private static @NonNull File getDefaultSystemDir() { 355 return new File(Environment.getDataDirectory(), "system"); 356 } 357 getDefaultBaseDir()358 private static @NonNull File getDefaultBaseDir() { 359 File baseDir = new File(getDefaultSystemDir(), "netstats"); 360 baseDir.mkdirs(); 361 return baseDir; 362 } 363 getDefaultClock()364 private static @NonNull Clock getDefaultClock() { 365 return new BestClock(ZoneOffset.UTC, SystemClock.currentNetworkTimeClock(), 366 Clock.systemUTC()); 367 } 368 369 private final class NetworkStatsHandler extends Handler { NetworkStatsHandler(@onNull Looper looper)370 NetworkStatsHandler(@NonNull Looper looper) { 371 super(looper); 372 } 373 374 @Override handleMessage(Message msg)375 public void handleMessage(Message msg) { 376 switch (msg.what) { 377 case MSG_PERFORM_POLL: { 378 performPoll(FLAG_PERSIST_ALL); 379 break; 380 } 381 case MSG_NOTIFY_NETWORK_STATUS: { 382 // If no cached states, ignore. 383 if (mLastNetworkStateSnapshots == null) break; 384 // TODO (b/181642673): Protect mDefaultNetworks from concurrent accessing. 385 handleNotifyNetworkStatus( 386 mDefaultNetworks, mLastNetworkStateSnapshots, mActiveIface); 387 break; 388 } 389 case MSG_PERFORM_POLL_REGISTER_ALERT: { 390 performPoll(FLAG_PERSIST_NETWORK); 391 registerGlobalAlert(); 392 break; 393 } 394 case MSG_BROADCAST_NETWORK_STATS_UPDATED: { 395 final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); 396 updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 397 mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL, 398 READ_NETWORK_USAGE_HISTORY); 399 break; 400 } 401 } 402 } 403 } 404 create(Context context, INetworkManagementService networkManager)405 public static NetworkStatsService create(Context context, 406 INetworkManagementService networkManager) { 407 AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE); 408 PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); 409 PowerManager.WakeLock wakeLock = 410 powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 411 412 final NetworkStatsService service = new NetworkStatsService(context, networkManager, 413 alarmManager, wakeLock, getDefaultClock(), 414 new DefaultNetworkStatsSettings(context), new NetworkStatsFactory(), 415 new NetworkStatsObservers(), getDefaultSystemDir(), getDefaultBaseDir(), 416 new Dependencies()); 417 service.registerLocalService(); 418 419 return service; 420 } 421 422 // This must not be called outside of tests, even within the same package, as this constructor 423 // does not register the local service. Use the create() helper above. 424 @VisibleForTesting NetworkStatsService(Context context, INetworkManagementService networkManager, AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, NetworkStatsSettings settings, NetworkStatsFactory factory, NetworkStatsObservers statsObservers, File systemDir, File baseDir, @NonNull Dependencies deps)425 NetworkStatsService(Context context, INetworkManagementService networkManager, 426 AlarmManager alarmManager, PowerManager.WakeLock wakeLock, Clock clock, 427 NetworkStatsSettings settings, NetworkStatsFactory factory, 428 NetworkStatsObservers statsObservers, File systemDir, File baseDir, 429 @NonNull Dependencies deps) { 430 mContext = Objects.requireNonNull(context, "missing Context"); 431 mNetworkManager = Objects.requireNonNull(networkManager, 432 "missing INetworkManagementService"); 433 mAlarmManager = Objects.requireNonNull(alarmManager, "missing AlarmManager"); 434 mClock = Objects.requireNonNull(clock, "missing Clock"); 435 mSettings = Objects.requireNonNull(settings, "missing NetworkStatsSettings"); 436 mWakeLock = Objects.requireNonNull(wakeLock, "missing WakeLock"); 437 mStatsFactory = Objects.requireNonNull(factory, "missing factory"); 438 mStatsObservers = Objects.requireNonNull(statsObservers, "missing NetworkStatsObservers"); 439 mSystemDir = Objects.requireNonNull(systemDir, "missing systemDir"); 440 mBaseDir = Objects.requireNonNull(baseDir, "missing baseDir"); 441 mUseBpfTrafficStats = new File("/sys/fs/bpf/map_netd_app_uid_stats_map").exists(); 442 mDeps = Objects.requireNonNull(deps, "missing Dependencies"); 443 444 final HandlerThread handlerThread = mDeps.makeHandlerThread(); 445 handlerThread.start(); 446 mHandler = new NetworkStatsHandler(handlerThread.getLooper()); 447 mNetworkStatsSubscriptionsMonitor = deps.makeSubscriptionsMonitor(mContext, 448 mHandler.getLooper(), new HandlerExecutor(mHandler), this); 449 mContentResolver = mContext.getContentResolver(); 450 mContentObserver = mDeps.makeContentObserver(mHandler, mSettings, 451 mNetworkStatsSubscriptionsMonitor); 452 } 453 454 /** 455 * Dependencies of NetworkStatsService, for injection in tests. 456 */ 457 // TODO: Move more stuff into dependencies object. 458 @VisibleForTesting 459 public static class Dependencies { 460 /** 461 * Create a HandlerThread to use in NetworkStatsService. 462 */ 463 @NonNull makeHandlerThread()464 public HandlerThread makeHandlerThread() { 465 return new HandlerThread(TAG); 466 } 467 468 /** 469 * Create a {@link NetworkStatsSubscriptionsMonitor}, can be used to monitor RAT change 470 * event in NetworkStatsService. 471 */ 472 @NonNull makeSubscriptionsMonitor(@onNull Context context, @NonNull Looper looper, @NonNull Executor executor, @NonNull NetworkStatsService service)473 public NetworkStatsSubscriptionsMonitor makeSubscriptionsMonitor(@NonNull Context context, 474 @NonNull Looper looper, @NonNull Executor executor, 475 @NonNull NetworkStatsService service) { 476 // TODO: Update RatType passively in NSS, instead of querying into the monitor 477 // when notifyNetworkStatus. 478 return new NetworkStatsSubscriptionsMonitor(context, looper, executor, 479 (subscriberId, type) -> service.handleOnCollapsedRatTypeChanged()); 480 } 481 482 /** 483 * Create a ContentObserver instance which is used to observe settings changes, 484 * and dispatch onChange events on handler thread. 485 */ makeContentObserver(@onNull Handler handler, @NonNull NetworkStatsSettings settings, @NonNull NetworkStatsSubscriptionsMonitor monitor)486 public @NonNull ContentObserver makeContentObserver(@NonNull Handler handler, 487 @NonNull NetworkStatsSettings settings, 488 @NonNull NetworkStatsSubscriptionsMonitor monitor) { 489 return new ContentObserver(handler) { 490 @Override 491 public void onChange(boolean selfChange, @NonNull Uri uri) { 492 if (!settings.getCombineSubtypeEnabled()) { 493 monitor.start(); 494 } else { 495 monitor.stop(); 496 } 497 } 498 }; 499 } 500 } 501 502 private void registerLocalService() { 503 LocalServices.addService(NetworkStatsManagerInternal.class, 504 new NetworkStatsManagerInternalImpl()); 505 } 506 507 public void systemReady() { 508 synchronized (mStatsLock) { 509 mSystemReady = true; 510 511 // create data recorders along with historical rotators 512 mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false); 513 mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false); 514 mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false); 515 mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true); 516 517 updatePersistThresholdsLocked(); 518 519 // upgrade any legacy stats, migrating them to rotated files 520 maybeUpgradeLegacyStatsLocked(); 521 522 // read historical network stats from disk, since policy service 523 // might need them right away. 524 mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked(); 525 526 // bootstrap initial stats to prevent double-counting later 527 bootstrapStatsLocked(); 528 } 529 530 // watch for tethering changes 531 final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED); 532 mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler); 533 534 // listen for periodic polling events 535 final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); 536 mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 537 538 // listen for uid removal to clean stats 539 final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED); 540 mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler); 541 542 // listen for user changes to clean stats 543 final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED); 544 mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler); 545 546 // persist stats during clean shutdown 547 final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN); 548 mContext.registerReceiver(mShutdownReceiver, shutdownFilter); 549 550 try { 551 mNetworkManager.registerObserver(mAlertObserver); 552 } catch (RemoteException e) { 553 // ignored; service lives in system_server 554 } 555 556 // schedule periodic pall alarm based on {@link NetworkStatsSettings#getPollInterval()}. 557 final PendingIntent pollIntent = 558 PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 559 PendingIntent.FLAG_IMMUTABLE); 560 561 final long currentRealtime = SystemClock.elapsedRealtime(); 562 mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, 563 mSettings.getPollInterval(), pollIntent); 564 565 mContentResolver.registerContentObserver(Settings.Global 566 .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED), 567 false /* notifyForDescendants */, mContentObserver); 568 569 // Post a runnable on handler thread to call onChange(). It's for getting current value of 570 // NETSTATS_COMBINE_SUBTYPE_ENABLED to decide start or stop monitoring RAT type changes. 571 mHandler.post(() -> mContentObserver.onChange(false, Settings.Global 572 .getUriFor(Settings.Global.NETSTATS_COMBINE_SUBTYPE_ENABLED))); 573 574 registerGlobalAlert(); 575 } 576 577 private NetworkStatsRecorder buildRecorder( 578 String prefix, NetworkStatsSettings.Config config, boolean includeTags) { 579 final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService( 580 Context.DROPBOX_SERVICE); 581 return new NetworkStatsRecorder(new FileRotator( 582 mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis), 583 mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags); 584 } 585 586 @GuardedBy("mStatsLock") 587 private void shutdownLocked() { 588 mContext.unregisterReceiver(mTetherReceiver); 589 mContext.unregisterReceiver(mPollReceiver); 590 mContext.unregisterReceiver(mRemovedReceiver); 591 mContext.unregisterReceiver(mUserReceiver); 592 mContext.unregisterReceiver(mShutdownReceiver); 593 594 if (!mSettings.getCombineSubtypeEnabled()) { 595 mNetworkStatsSubscriptionsMonitor.stop(); 596 } 597 598 mContentResolver.unregisterContentObserver(mContentObserver); 599 600 final long currentTime = mClock.millis(); 601 602 // persist any pending stats 603 mDevRecorder.forcePersistLocked(currentTime); 604 mXtRecorder.forcePersistLocked(currentTime); 605 mUidRecorder.forcePersistLocked(currentTime); 606 mUidTagRecorder.forcePersistLocked(currentTime); 607 608 mSystemReady = false; 609 } 610 611 @GuardedBy("mStatsLock") 612 private void maybeUpgradeLegacyStatsLocked() { 613 File file; 614 try { 615 file = new File(mSystemDir, "netstats.bin"); 616 if (file.exists()) { 617 mDevRecorder.importLegacyNetworkLocked(file); 618 file.delete(); 619 } 620 621 file = new File(mSystemDir, "netstats_xt.bin"); 622 if (file.exists()) { 623 file.delete(); 624 } 625 626 file = new File(mSystemDir, "netstats_uid.bin"); 627 if (file.exists()) { 628 mUidRecorder.importLegacyUidLocked(file); 629 mUidTagRecorder.importLegacyUidLocked(file); 630 file.delete(); 631 } 632 } catch (IOException e) { 633 Log.wtf(TAG, "problem during legacy upgrade", e); 634 } catch (OutOfMemoryError e) { 635 Log.wtf(TAG, "problem during legacy upgrade", e); 636 } 637 } 638 639 /** 640 * Register for a global alert that is delivered through {@link INetworkManagementEventObserver} 641 * or {@link NetworkStatsProviderCallback#onAlertReached()} once a threshold amount of data has 642 * been transferred. 643 */ 644 private void registerGlobalAlert() { 645 try { 646 mNetworkManager.setGlobalAlert(mGlobalAlertBytes); 647 } catch (IllegalStateException e) { 648 Slog.w(TAG, "problem registering for global alert: " + e); 649 } catch (RemoteException e) { 650 // ignored; service lives in system_server 651 } 652 invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetAlert(mGlobalAlertBytes)); 653 } 654 655 @Override 656 public INetworkStatsSession openSession() { 657 // NOTE: if callers want to get non-augmented data, they should go 658 // through the public API 659 return openSessionInternal(NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, null); 660 } 661 662 @Override 663 public INetworkStatsSession openSessionForUsageStats(int flags, String callingPackage) { 664 return openSessionInternal(flags, callingPackage); 665 } 666 667 private boolean isRateLimitedForPoll(int callingUid) { 668 if (callingUid == android.os.Process.SYSTEM_UID) { 669 return false; 670 } 671 672 final long lastCallTime; 673 final long now = SystemClock.elapsedRealtime(); 674 synchronized (mOpenSessionCallsPerUid) { 675 int calls = mOpenSessionCallsPerUid.get(callingUid, 0); 676 mOpenSessionCallsPerUid.put(callingUid, calls + 1); 677 lastCallTime = mLastStatsSessionPoll; 678 mLastStatsSessionPoll = now; 679 } 680 681 return now - lastCallTime < POLL_RATE_LIMIT_MS; 682 } 683 684 private INetworkStatsSession openSessionInternal(final int flags, final String callingPackage) { 685 final int callingUid = Binder.getCallingUid(); 686 final int usedFlags = isRateLimitedForPoll(callingUid) 687 ? flags & (~NetworkStatsManager.FLAG_POLL_ON_OPEN) 688 : flags; 689 if ((usedFlags & (NetworkStatsManager.FLAG_POLL_ON_OPEN 690 | NetworkStatsManager.FLAG_POLL_FORCE)) != 0) { 691 final long ident = Binder.clearCallingIdentity(); 692 try { 693 performPoll(FLAG_PERSIST_ALL); 694 } finally { 695 Binder.restoreCallingIdentity(ident); 696 } 697 } 698 699 // return an IBinder which holds strong references to any loaded stats 700 // for its lifetime; when caller closes only weak references remain. 701 702 return new INetworkStatsSession.Stub() { 703 private final int mCallingUid = callingUid; 704 private final String mCallingPackage = callingPackage; 705 private final @NetworkStatsAccess.Level int mAccessLevel = checkAccessLevel( 706 callingPackage); 707 708 private NetworkStatsCollection mUidComplete; 709 private NetworkStatsCollection mUidTagComplete; 710 711 private NetworkStatsCollection getUidComplete() { 712 synchronized (mStatsLock) { 713 if (mUidComplete == null) { 714 mUidComplete = mUidRecorder.getOrLoadCompleteLocked(); 715 } 716 return mUidComplete; 717 } 718 } 719 720 private NetworkStatsCollection getUidTagComplete() { 721 synchronized (mStatsLock) { 722 if (mUidTagComplete == null) { 723 mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked(); 724 } 725 return mUidTagComplete; 726 } 727 } 728 729 @Override 730 public int[] getRelevantUids() { 731 return getUidComplete().getRelevantUids(mAccessLevel); 732 } 733 734 @Override 735 public NetworkStats getDeviceSummaryForNetwork( 736 NetworkTemplate template, long start, long end) { 737 return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel, 738 mCallingUid); 739 } 740 741 @Override 742 public NetworkStats getSummaryForNetwork( 743 NetworkTemplate template, long start, long end) { 744 return internalGetSummaryForNetwork(template, usedFlags, start, end, mAccessLevel, 745 mCallingUid); 746 } 747 748 @Override 749 public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { 750 return internalGetHistoryForNetwork(template, usedFlags, fields, mAccessLevel, 751 mCallingUid); 752 } 753 754 @Override 755 public NetworkStats getSummaryForAllUid( 756 NetworkTemplate template, long start, long end, boolean includeTags) { 757 try { 758 final NetworkStats stats = getUidComplete() 759 .getSummary(template, start, end, mAccessLevel, mCallingUid); 760 if (includeTags) { 761 final NetworkStats tagStats = getUidTagComplete() 762 .getSummary(template, start, end, mAccessLevel, mCallingUid); 763 stats.combineAllValues(tagStats); 764 } 765 return stats; 766 } catch (NullPointerException e) { 767 // TODO: Track down and fix the cause of this crash and remove this catch block. 768 Slog.wtf(TAG, "NullPointerException in getSummaryForAllUid", e); 769 throw e; 770 } 771 } 772 773 @Override 774 public NetworkStatsHistory getHistoryForUid( 775 NetworkTemplate template, int uid, int set, int tag, int fields) { 776 // NOTE: We don't augment UID-level statistics 777 if (tag == TAG_NONE) { 778 return getUidComplete().getHistory(template, null, uid, set, tag, fields, 779 Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid); 780 } else { 781 return getUidTagComplete().getHistory(template, null, uid, set, tag, fields, 782 Long.MIN_VALUE, Long.MAX_VALUE, mAccessLevel, mCallingUid); 783 } 784 } 785 786 @Override 787 public NetworkStatsHistory getHistoryIntervalForUid( 788 NetworkTemplate template, int uid, int set, int tag, int fields, 789 long start, long end) { 790 // NOTE: We don't augment UID-level statistics 791 if (tag == TAG_NONE) { 792 return getUidComplete().getHistory(template, null, uid, set, tag, fields, 793 start, end, mAccessLevel, mCallingUid); 794 } else if (uid == Binder.getCallingUid()) { 795 return getUidTagComplete().getHistory(template, null, uid, set, tag, fields, 796 start, end, mAccessLevel, mCallingUid); 797 } else { 798 throw new SecurityException("Calling package " + mCallingPackage 799 + " cannot access tag information from a different uid"); 800 } 801 } 802 803 @Override 804 public void close() { 805 mUidComplete = null; 806 mUidTagComplete = null; 807 } 808 }; 809 } 810 811 private @NetworkStatsAccess.Level int checkAccessLevel(String callingPackage) { 812 return NetworkStatsAccess.checkAccessLevel( 813 mContext, Binder.getCallingUid(), callingPackage); 814 } 815 816 /** 817 * Find the most relevant {@link SubscriptionPlan} for the given 818 * {@link NetworkTemplate} and flags. This is typically used to augment 819 * local measurement results to match a known anchor from the carrier. 820 */ 821 private SubscriptionPlan resolveSubscriptionPlan(NetworkTemplate template, int flags) { 822 SubscriptionPlan plan = null; 823 if ((flags & NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN) != 0 824 && mSettings.getAugmentEnabled()) { 825 if (LOGD) Slog.d(TAG, "Resolving plan for " + template); 826 final long token = Binder.clearCallingIdentity(); 827 try { 828 plan = LocalServices.getService(NetworkPolicyManagerInternal.class) 829 .getSubscriptionPlan(template); 830 } finally { 831 Binder.restoreCallingIdentity(token); 832 } 833 if (LOGD) Slog.d(TAG, "Resolved to plan " + plan); 834 } 835 return plan; 836 } 837 838 /** 839 * Return network summary, splicing between DEV and XT stats when 840 * appropriate. 841 */ 842 private NetworkStats internalGetSummaryForNetwork(NetworkTemplate template, int flags, 843 long start, long end, @NetworkStatsAccess.Level int accessLevel, int callingUid) { 844 // We've been using pure XT stats long enough that we no longer need to 845 // splice DEV and XT together. 846 final NetworkStatsHistory history = internalGetHistoryForNetwork(template, flags, FIELD_ALL, 847 accessLevel, callingUid); 848 849 final long now = System.currentTimeMillis(); 850 final NetworkStatsHistory.Entry entry = history.getValues(start, end, now, null); 851 852 final NetworkStats stats = new NetworkStats(end - start, 1); 853 stats.insertEntry(new NetworkStats.Entry(IFACE_ALL, UID_ALL, SET_ALL, TAG_NONE, 854 METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, entry.rxBytes, entry.rxPackets, 855 entry.txBytes, entry.txPackets, entry.operations)); 856 return stats; 857 } 858 859 /** 860 * Return network history, splicing between DEV and XT stats when 861 * appropriate. 862 */ 863 private NetworkStatsHistory internalGetHistoryForNetwork(NetworkTemplate template, 864 int flags, int fields, @NetworkStatsAccess.Level int accessLevel, int callingUid) { 865 // We've been using pure XT stats long enough that we no longer need to 866 // splice DEV and XT together. 867 final SubscriptionPlan augmentPlan = resolveSubscriptionPlan(template, flags); 868 synchronized (mStatsLock) { 869 return mXtStatsCached.getHistory(template, augmentPlan, 870 UID_ALL, SET_ALL, TAG_NONE, fields, Long.MIN_VALUE, Long.MAX_VALUE, 871 accessLevel, callingUid); 872 } 873 } 874 875 private long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { 876 assertSystemReady(); 877 878 // NOTE: if callers want to get non-augmented data, they should go 879 // through the public API 880 return internalGetSummaryForNetwork(template, 881 NetworkStatsManager.FLAG_AUGMENT_WITH_SUBSCRIPTION_PLAN, start, end, 882 NetworkStatsAccess.Level.DEVICE, Binder.getCallingUid()).getTotalBytes(); 883 } 884 885 private NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { 886 assertSystemReady(); 887 888 final NetworkStatsCollection uidComplete; 889 synchronized (mStatsLock) { 890 uidComplete = mUidRecorder.getOrLoadCompleteLocked(); 891 } 892 return uidComplete.getSummary(template, start, end, NetworkStatsAccess.Level.DEVICE, 893 android.os.Process.SYSTEM_UID); 894 } 895 896 @Override 897 public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { 898 if (Binder.getCallingUid() != uid) { 899 Log.w(TAG, "Snapshots only available for calling UID"); 900 return new NetworkStats(SystemClock.elapsedRealtime(), 0); 901 } 902 903 // TODO: switch to data layer stats once kernel exports 904 // for now, read network layer stats and flatten across all ifaces 905 final NetworkStats networkLayer = readNetworkStatsUidDetail(uid, INTERFACES_ALL, TAG_ALL); 906 907 // splice in operation counts 908 networkLayer.spliceOperationsFrom(mUidOperations); 909 910 final NetworkStats dataLayer = new NetworkStats( 911 networkLayer.getElapsedRealtime(), networkLayer.size()); 912 913 NetworkStats.Entry entry = null; 914 for (int i = 0; i < networkLayer.size(); i++) { 915 entry = networkLayer.getValues(i, entry); 916 entry.iface = IFACE_ALL; 917 dataLayer.combineValues(entry); 918 } 919 920 return dataLayer; 921 } 922 923 @Override 924 public NetworkStats getDetailedUidStats(String[] requiredIfaces) { 925 try { 926 final String[] ifacesToQuery = 927 mStatsFactory.augmentWithStackedInterfaces(requiredIfaces); 928 return getNetworkStatsUidDetail(ifacesToQuery); 929 } catch (RemoteException e) { 930 Log.wtf(TAG, "Error compiling UID stats", e); 931 return new NetworkStats(0L, 0); 932 } 933 } 934 935 @Override 936 public String[] getMobileIfaces() { 937 // TODO (b/192758557): Remove debug log. 938 if (ArrayUtils.contains(mMobileIfaces, null)) { 939 throw new NullPointerException( 940 "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); 941 } 942 return mMobileIfaces.clone(); 943 } 944 945 @Override 946 public void incrementOperationCount(int uid, int tag, int operationCount) { 947 if (Binder.getCallingUid() != uid) { 948 mContext.enforceCallingOrSelfPermission(UPDATE_DEVICE_STATS, TAG); 949 } 950 951 if (operationCount < 0) { 952 throw new IllegalArgumentException("operation count can only be incremented"); 953 } 954 if (tag == TAG_NONE) { 955 throw new IllegalArgumentException("operation count must have specific tag"); 956 } 957 958 synchronized (mStatsLock) { 959 final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT); 960 mUidOperations.combineValues( 961 mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount); 962 mUidOperations.combineValues( 963 mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount); 964 } 965 } 966 967 @VisibleForTesting 968 void setUidForeground(int uid, boolean uidForeground) { 969 synchronized (mStatsLock) { 970 final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT; 971 final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT); 972 if (oldSet != set) { 973 mActiveUidCounterSet.put(uid, set); 974 setKernelCounterSet(uid, set); 975 } 976 } 977 } 978 979 /** 980 * Notify {@code NetworkStatsService} about network status changed. 981 */ 982 public void notifyNetworkStatus( 983 @NonNull Network[] defaultNetworks, 984 @NonNull NetworkStateSnapshot[] networkStates, 985 @Nullable String activeIface, 986 @NonNull UnderlyingNetworkInfo[] underlyingNetworkInfos) { 987 checkNetworkStackPermission(mContext); 988 989 final long token = Binder.clearCallingIdentity(); 990 try { 991 handleNotifyNetworkStatus(defaultNetworks, networkStates, activeIface); 992 } finally { 993 Binder.restoreCallingIdentity(token); 994 } 995 996 // Update the VPN underlying interfaces only after the poll is made and tun data has been 997 // migrated. Otherwise the migration would use the new interfaces instead of the ones that 998 // were current when the polled data was transferred. 999 mStatsFactory.updateUnderlyingNetworkInfos(underlyingNetworkInfos); 1000 } 1001 1002 @Override 1003 public void forceUpdate() { 1004 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); 1005 1006 final long token = Binder.clearCallingIdentity(); 1007 try { 1008 performPoll(FLAG_PERSIST_ALL); 1009 } finally { 1010 Binder.restoreCallingIdentity(token); 1011 } 1012 } 1013 1014 private void advisePersistThreshold(long thresholdBytes) { 1015 // clamp threshold into safe range 1016 mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES); 1017 if (LOGV) { 1018 Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to " 1019 + mPersistThreshold); 1020 } 1021 1022 final long oldGlobalAlertBytes = mGlobalAlertBytes; 1023 1024 // update and persist if beyond new thresholds 1025 final long currentTime = mClock.millis(); 1026 synchronized (mStatsLock) { 1027 if (!mSystemReady) return; 1028 1029 updatePersistThresholdsLocked(); 1030 1031 mDevRecorder.maybePersistLocked(currentTime); 1032 mXtRecorder.maybePersistLocked(currentTime); 1033 mUidRecorder.maybePersistLocked(currentTime); 1034 mUidTagRecorder.maybePersistLocked(currentTime); 1035 } 1036 1037 if (oldGlobalAlertBytes != mGlobalAlertBytes) { 1038 registerGlobalAlert(); 1039 } 1040 } 1041 1042 @Override 1043 public DataUsageRequest registerUsageCallback(String callingPackage, 1044 DataUsageRequest request, Messenger messenger, IBinder binder) { 1045 Objects.requireNonNull(callingPackage, "calling package is null"); 1046 Objects.requireNonNull(request, "DataUsageRequest is null"); 1047 Objects.requireNonNull(request.template, "NetworkTemplate is null"); 1048 Objects.requireNonNull(messenger, "messenger is null"); 1049 Objects.requireNonNull(binder, "binder is null"); 1050 1051 int callingUid = Binder.getCallingUid(); 1052 @NetworkStatsAccess.Level int accessLevel = checkAccessLevel(callingPackage); 1053 DataUsageRequest normalizedRequest; 1054 final long token = Binder.clearCallingIdentity(); 1055 try { 1056 normalizedRequest = mStatsObservers.register(request, messenger, binder, 1057 callingUid, accessLevel); 1058 } finally { 1059 Binder.restoreCallingIdentity(token); 1060 } 1061 1062 // Create baseline stats 1063 mHandler.sendMessage(mHandler.obtainMessage(MSG_PERFORM_POLL)); 1064 1065 return normalizedRequest; 1066 } 1067 1068 @Override 1069 public void unregisterUsageRequest(DataUsageRequest request) { 1070 Objects.requireNonNull(request, "DataUsageRequest is null"); 1071 1072 int callingUid = Binder.getCallingUid(); 1073 final long token = Binder.clearCallingIdentity(); 1074 try { 1075 mStatsObservers.unregister(request, callingUid); 1076 } finally { 1077 Binder.restoreCallingIdentity(token); 1078 } 1079 } 1080 1081 @Override 1082 public long getUidStats(int uid, int type) { 1083 final int callingUid = Binder.getCallingUid(); 1084 if (callingUid != android.os.Process.SYSTEM_UID && callingUid != uid) { 1085 return UNSUPPORTED; 1086 } 1087 return nativeGetUidStat(uid, type, checkBpfStatsEnable()); 1088 } 1089 1090 @Override 1091 public long getIfaceStats(@NonNull String iface, int type) { 1092 Objects.requireNonNull(iface); 1093 long nativeIfaceStats = nativeGetIfaceStat(iface, type, checkBpfStatsEnable()); 1094 if (nativeIfaceStats == -1) { 1095 return nativeIfaceStats; 1096 } else { 1097 // When tethering offload is in use, nativeIfaceStats does not contain usage from 1098 // offload, add it back here. Note that the included statistics might be stale 1099 // since polling newest stats from hardware might impact system health and not 1100 // suitable for TrafficStats API use cases. 1101 return nativeIfaceStats + getProviderIfaceStats(iface, type); 1102 } 1103 } 1104 1105 @Override 1106 public long getTotalStats(int type) { 1107 long nativeTotalStats = nativeGetTotalStat(type, checkBpfStatsEnable()); 1108 if (nativeTotalStats == -1) { 1109 return nativeTotalStats; 1110 } else { 1111 // Refer to comment in getIfaceStats 1112 return nativeTotalStats + getProviderIfaceStats(IFACE_ALL, type); 1113 } 1114 } 1115 1116 private long getProviderIfaceStats(@Nullable String iface, int type) { 1117 final NetworkStats providerSnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE); 1118 final HashSet<String> limitIfaces; 1119 if (iface == IFACE_ALL) { 1120 limitIfaces = null; 1121 } else { 1122 limitIfaces = new HashSet<>(); 1123 limitIfaces.add(iface); 1124 } 1125 final NetworkStats.Entry entry = providerSnapshot.getTotal(null, limitIfaces); 1126 switch (type) { 1127 case TrafficStats.TYPE_RX_BYTES: 1128 return entry.rxBytes; 1129 case TrafficStats.TYPE_RX_PACKETS: 1130 return entry.rxPackets; 1131 case TrafficStats.TYPE_TX_BYTES: 1132 return entry.txBytes; 1133 case TrafficStats.TYPE_TX_PACKETS: 1134 return entry.txPackets; 1135 default: 1136 return 0; 1137 } 1138 } 1139 1140 private boolean checkBpfStatsEnable() { 1141 return mUseBpfTrafficStats; 1142 } 1143 1144 /** 1145 * Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to 1146 * reflect current {@link #mPersistThreshold} value. Always defers to 1147 * {@link Global} values when defined. 1148 */ 1149 @GuardedBy("mStatsLock") 1150 private void updatePersistThresholdsLocked() { 1151 mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold)); 1152 mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold)); 1153 mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold)); 1154 mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold)); 1155 mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold); 1156 } 1157 1158 /** 1159 * Receiver that watches for {@link Tethering} to claim interface pairs. 1160 */ 1161 private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() { 1162 @Override 1163 public void onReceive(Context context, Intent intent) { 1164 performPoll(FLAG_PERSIST_NETWORK); 1165 } 1166 }; 1167 1168 private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { 1169 @Override 1170 public void onReceive(Context context, Intent intent) { 1171 // on background handler thread, and verified UPDATE_DEVICE_STATS 1172 // permission above. 1173 performPoll(FLAG_PERSIST_ALL); 1174 1175 // verify that we're watching global alert 1176 registerGlobalAlert(); 1177 } 1178 }; 1179 1180 private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() { 1181 @Override 1182 public void onReceive(Context context, Intent intent) { 1183 // on background handler thread, and UID_REMOVED is protected 1184 // broadcast. 1185 1186 final int uid = intent.getIntExtra(EXTRA_UID, -1); 1187 if (uid == -1) return; 1188 1189 synchronized (mStatsLock) { 1190 mWakeLock.acquire(); 1191 try { 1192 removeUidsLocked(uid); 1193 } finally { 1194 mWakeLock.release(); 1195 } 1196 } 1197 } 1198 }; 1199 1200 private BroadcastReceiver mUserReceiver = new BroadcastReceiver() { 1201 @Override 1202 public void onReceive(Context context, Intent intent) { 1203 // On background handler thread, and USER_REMOVED is protected 1204 // broadcast. 1205 1206 final int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1); 1207 if (userId == -1) return; 1208 1209 synchronized (mStatsLock) { 1210 mWakeLock.acquire(); 1211 try { 1212 removeUserLocked(userId); 1213 } finally { 1214 mWakeLock.release(); 1215 } 1216 } 1217 } 1218 }; 1219 1220 private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() { 1221 @Override 1222 public void onReceive(Context context, Intent intent) { 1223 // SHUTDOWN is protected broadcast. 1224 synchronized (mStatsLock) { 1225 shutdownLocked(); 1226 } 1227 } 1228 }; 1229 1230 /** 1231 * Observer that watches for {@link INetworkManagementService} alerts. 1232 */ 1233 private final INetworkManagementEventObserver mAlertObserver = new BaseNetworkObserver() { 1234 @Override 1235 public void limitReached(String limitName, String iface) { 1236 // only someone like NMS should be calling us 1237 NetworkStack.checkNetworkStackPermission(mContext); 1238 1239 if (LIMIT_GLOBAL_ALERT.equals(limitName)) { 1240 // kick off background poll to collect network stats unless there is already 1241 // such a call pending; UID stats are handled during normal polling interval. 1242 if (!mHandler.hasMessages(MSG_PERFORM_POLL_REGISTER_ALERT)) { 1243 mHandler.sendEmptyMessageDelayed(MSG_PERFORM_POLL_REGISTER_ALERT, 1244 mSettings.getPollDelay()); 1245 } 1246 } 1247 } 1248 }; 1249 1250 /** 1251 * Handle collapsed RAT type changed event. 1252 */ 1253 @VisibleForTesting 1254 public void handleOnCollapsedRatTypeChanged() { 1255 // Protect service from frequently updating. Remove pending messages if any. 1256 mHandler.removeMessages(MSG_NOTIFY_NETWORK_STATUS); 1257 mHandler.sendMessageDelayed( 1258 mHandler.obtainMessage(MSG_NOTIFY_NETWORK_STATUS), mSettings.getPollDelay()); 1259 } 1260 1261 private void handleNotifyNetworkStatus( 1262 Network[] defaultNetworks, 1263 NetworkStateSnapshot[] snapshots, 1264 String activeIface) { 1265 synchronized (mStatsLock) { 1266 mWakeLock.acquire(); 1267 try { 1268 mActiveIface = activeIface; 1269 handleNotifyNetworkStatusLocked(defaultNetworks, snapshots); 1270 } finally { 1271 mWakeLock.release(); 1272 } 1273 } 1274 } 1275 1276 /** 1277 * Inspect all current {@link NetworkStateSnapshot}s to derive mapping from {@code iface} to 1278 * {@link NetworkStatsHistory}. When multiple networks are active on a single {@code iface}, 1279 * they are combined under a single {@link NetworkIdentitySet}. 1280 */ 1281 @GuardedBy("mStatsLock") 1282 private void handleNotifyNetworkStatusLocked(@NonNull Network[] defaultNetworks, 1283 @NonNull NetworkStateSnapshot[] snapshots) { 1284 if (!mSystemReady) return; 1285 if (LOGV) Slog.v(TAG, "handleNotifyNetworkStatusLocked()"); 1286 1287 // take one last stats snapshot before updating iface mapping. this 1288 // isn't perfect, since the kernel may already be counting traffic from 1289 // the updated network. 1290 1291 // poll, but only persist network stats to keep codepath fast. UID stats 1292 // will be persisted during next alarm poll event. 1293 performPollLocked(FLAG_PERSIST_NETWORK); 1294 1295 // Rebuild active interfaces based on connected networks 1296 mActiveIfaces.clear(); 1297 mActiveUidIfaces.clear(); 1298 // Update the list of default networks. 1299 mDefaultNetworks = defaultNetworks; 1300 1301 mLastNetworkStateSnapshots = snapshots; 1302 1303 final boolean combineSubtypeEnabled = mSettings.getCombineSubtypeEnabled(); 1304 final ArraySet<String> mobileIfaces = new ArraySet<>(); 1305 for (NetworkStateSnapshot snapshot : snapshots) { 1306 final int displayTransport = 1307 getDisplayTransport(snapshot.getNetworkCapabilities().getTransportTypes()); 1308 final boolean isMobile = (NetworkCapabilities.TRANSPORT_CELLULAR == displayTransport); 1309 final boolean isDefault = ArrayUtils.contains(mDefaultNetworks, snapshot.getNetwork()); 1310 final int subType = combineSubtypeEnabled ? SUBTYPE_COMBINED 1311 : getSubTypeForStateSnapshot(snapshot); 1312 final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, snapshot, 1313 isDefault, subType); 1314 1315 // Traffic occurring on the base interface is always counted for 1316 // both total usage and UID details. 1317 final String baseIface = snapshot.getLinkProperties().getInterfaceName(); 1318 if (baseIface != null) { 1319 findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident); 1320 findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident); 1321 1322 // Build a separate virtual interface for VT (Video Telephony) data usage. 1323 // Only do this when IMS is not metered, but VT is metered. 1324 // If IMS is metered, then the IMS network usage has already included VT usage. 1325 // VT is considered always metered in framework's layer. If VT is not metered 1326 // per carrier's policy, modem will report 0 usage for VT calls. 1327 if (snapshot.getNetworkCapabilities().hasCapability( 1328 NetworkCapabilities.NET_CAPABILITY_IMS) && !ident.getMetered()) { 1329 1330 // Copy the identify from IMS one but mark it as metered. 1331 NetworkIdentity vtIdent = new NetworkIdentity(ident.getType(), 1332 ident.getSubType(), ident.getSubscriberId(), ident.getNetworkId(), 1333 ident.getRoaming(), true /* metered */, 1334 true /* onDefaultNetwork */, ident.getOemManaged()); 1335 final String ifaceVt = IFACE_VT + getSubIdForMobile(snapshot); 1336 findOrCreateNetworkIdentitySet(mActiveIfaces, ifaceVt).add(vtIdent); 1337 findOrCreateNetworkIdentitySet(mActiveUidIfaces, ifaceVt).add(vtIdent); 1338 } 1339 1340 if (isMobile) { 1341 mobileIfaces.add(baseIface); 1342 } 1343 } 1344 1345 // Traffic occurring on stacked interfaces is usually clatd. 1346 // 1347 // UID stats are always counted on the stacked interface and never on the base 1348 // interface, because the packets on the base interface do not actually match 1349 // application sockets (they're not IPv4) and thus the app uid is not known. 1350 // For receive this is obvious: packets must be translated from IPv6 to IPv4 1351 // before the application socket can be found. 1352 // For transmit: either they go through the clat daemon which by virtue of going 1353 // through userspace strips the original socket association during the IPv4 to 1354 // IPv6 translation process, or they are offloaded by eBPF, which doesn't: 1355 // However, on an ebpf device the accounting is done in cgroup ebpf hooks, 1356 // which don't trigger again post ebpf translation. 1357 // (as such stats accounted to the clat uid are ignored) 1358 // 1359 // Interface stats are more complicated. 1360 // 1361 // eBPF offloaded 464xlat'ed packets never hit base interface ip6tables, and thus 1362 // *all* statistics are collected by iptables on the stacked v4-* interface. 1363 // 1364 // Additionally for ingress all packets bound for the clat IPv6 address are dropped 1365 // in ip6tables raw prerouting and thus even non-offloaded packets are only 1366 // accounted for on the stacked interface. 1367 // 1368 // For egress, packets subject to eBPF offload never appear on the base interface 1369 // and only appear on the stacked interface. Thus to ensure packets increment 1370 // interface stats, we must collate data from stacked interfaces. For xt_qtaguid 1371 // (or non eBPF offloaded) TX they would appear on both, however egress interface 1372 // accounting is explicitly bypassed for traffic from the clat uid. 1373 // 1374 // TODO: This code might be combined to above code. 1375 for (String iface : snapshot.getLinkProperties().getAllInterfaceNames()) { 1376 // baseIface has been handled, so ignore it. 1377 if (TextUtils.equals(baseIface, iface)) continue; 1378 if (iface != null) { 1379 findOrCreateNetworkIdentitySet(mActiveIfaces, iface).add(ident); 1380 findOrCreateNetworkIdentitySet(mActiveUidIfaces, iface).add(ident); 1381 if (isMobile) { 1382 mobileIfaces.add(iface); 1383 } 1384 1385 mStatsFactory.noteStackedIface(iface, baseIface); 1386 } 1387 } 1388 } 1389 1390 mMobileIfaces = mobileIfaces.toArray(new String[0]); 1391 // TODO (b/192758557): Remove debug log. 1392 if (ArrayUtils.contains(mMobileIfaces, null)) { 1393 throw new NullPointerException( 1394 "null element in mMobileIfaces: " + Arrays.toString(mMobileIfaces)); 1395 } 1396 } 1397 1398 private static int getSubIdForMobile(@NonNull NetworkStateSnapshot state) { 1399 if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 1400 throw new IllegalArgumentException("Mobile state need capability TRANSPORT_CELLULAR"); 1401 } 1402 1403 final NetworkSpecifier spec = state.getNetworkCapabilities().getNetworkSpecifier(); 1404 if (spec instanceof TelephonyNetworkSpecifier) { 1405 return ((TelephonyNetworkSpecifier) spec).getSubscriptionId(); 1406 } else { 1407 Slog.wtf(TAG, "getSubIdForState invalid NetworkSpecifier"); 1408 return INVALID_SUBSCRIPTION_ID; 1409 } 1410 } 1411 1412 /** 1413 * For networks with {@code TRANSPORT_CELLULAR}, get subType that was obtained through 1414 * {@link PhoneStateListener}. Otherwise, return 0 given that other networks with different 1415 * transport types do not actually fill this value. 1416 */ 1417 private int getSubTypeForStateSnapshot(@NonNull NetworkStateSnapshot state) { 1418 if (!state.getNetworkCapabilities().hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) { 1419 return 0; 1420 } 1421 1422 return mNetworkStatsSubscriptionsMonitor.getRatTypeForSubscriberId(state.getSubscriberId()); 1423 } 1424 1425 private static <K> NetworkIdentitySet findOrCreateNetworkIdentitySet( 1426 ArrayMap<K, NetworkIdentitySet> map, K key) { 1427 NetworkIdentitySet ident = map.get(key); 1428 if (ident == null) { 1429 ident = new NetworkIdentitySet(); 1430 map.put(key, ident); 1431 } 1432 return ident; 1433 } 1434 1435 @GuardedBy("mStatsLock") 1436 private void recordSnapshotLocked(long currentTime) throws RemoteException { 1437 // snapshot and record current counters; read UID stats first to 1438 // avoid over counting dev stats. 1439 Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotUid"); 1440 final NetworkStats uidSnapshot = getNetworkStatsUidDetail(INTERFACES_ALL); 1441 Trace.traceEnd(TRACE_TAG_NETWORK); 1442 Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotXt"); 1443 final NetworkStats xtSnapshot = readNetworkStatsSummaryXt(); 1444 Trace.traceEnd(TRACE_TAG_NETWORK); 1445 Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotDev"); 1446 final NetworkStats devSnapshot = readNetworkStatsSummaryDev(); 1447 Trace.traceEnd(TRACE_TAG_NETWORK); 1448 1449 // Snapshot for dev/xt stats from all custom stats providers. Counts per-interface data 1450 // from stats providers that isn't already counted by dev and XT stats. 1451 Trace.traceBegin(TRACE_TAG_NETWORK, "snapshotStatsProvider"); 1452 final NetworkStats providersnapshot = getNetworkStatsFromProviders(STATS_PER_IFACE); 1453 Trace.traceEnd(TRACE_TAG_NETWORK); 1454 xtSnapshot.combineAllValues(providersnapshot); 1455 devSnapshot.combineAllValues(providersnapshot); 1456 1457 // For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic 1458 // can't be reattributed to responsible apps. 1459 Trace.traceBegin(TRACE_TAG_NETWORK, "recordDev"); 1460 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime); 1461 Trace.traceEnd(TRACE_TAG_NETWORK); 1462 Trace.traceBegin(TRACE_TAG_NETWORK, "recordXt"); 1463 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime); 1464 Trace.traceEnd(TRACE_TAG_NETWORK); 1465 1466 // For per-UID stats, pass the VPN info so VPN traffic is reattributed to responsible apps. 1467 Trace.traceBegin(TRACE_TAG_NETWORK, "recordUid"); 1468 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime); 1469 Trace.traceEnd(TRACE_TAG_NETWORK); 1470 Trace.traceBegin(TRACE_TAG_NETWORK, "recordUidTag"); 1471 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime); 1472 Trace.traceEnd(TRACE_TAG_NETWORK); 1473 1474 // We need to make copies of member fields that are sent to the observer to avoid 1475 // a race condition between the service handler thread and the observer's 1476 mStatsObservers.updateStats(xtSnapshot, uidSnapshot, new ArrayMap<>(mActiveIfaces), 1477 new ArrayMap<>(mActiveUidIfaces), currentTime); 1478 } 1479 1480 /** 1481 * Bootstrap initial stats snapshot, usually during {@link #systemReady()} 1482 * so we have baseline values without double-counting. 1483 */ 1484 @GuardedBy("mStatsLock") 1485 private void bootstrapStatsLocked() { 1486 final long currentTime = mClock.millis(); 1487 1488 try { 1489 recordSnapshotLocked(currentTime); 1490 } catch (IllegalStateException e) { 1491 Slog.w(TAG, "problem reading network stats: " + e); 1492 } catch (RemoteException e) { 1493 // ignored; service lives in system_server 1494 } 1495 } 1496 1497 private void performPoll(int flags) { 1498 synchronized (mStatsLock) { 1499 mWakeLock.acquire(); 1500 1501 try { 1502 performPollLocked(flags); 1503 } finally { 1504 mWakeLock.release(); 1505 } 1506 } 1507 } 1508 1509 /** 1510 * Periodic poll operation, reading current statistics and recording into 1511 * {@link NetworkStatsHistory}. 1512 */ 1513 @GuardedBy("mStatsLock") 1514 private void performPollLocked(int flags) { 1515 if (!mSystemReady) return; 1516 if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); 1517 Trace.traceBegin(TRACE_TAG_NETWORK, "performPollLocked"); 1518 1519 final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; 1520 final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; 1521 final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; 1522 1523 performPollFromProvidersLocked(); 1524 1525 // TODO: consider marking "untrusted" times in historical stats 1526 final long currentTime = mClock.millis(); 1527 1528 try { 1529 recordSnapshotLocked(currentTime); 1530 } catch (IllegalStateException e) { 1531 Log.wtf(TAG, "problem reading network stats", e); 1532 return; 1533 } catch (RemoteException e) { 1534 // ignored; service lives in system_server 1535 return; 1536 } 1537 1538 // persist any pending data depending on requested flags 1539 Trace.traceBegin(TRACE_TAG_NETWORK, "[persisting]"); 1540 if (persistForce) { 1541 mDevRecorder.forcePersistLocked(currentTime); 1542 mXtRecorder.forcePersistLocked(currentTime); 1543 mUidRecorder.forcePersistLocked(currentTime); 1544 mUidTagRecorder.forcePersistLocked(currentTime); 1545 } else { 1546 if (persistNetwork) { 1547 mDevRecorder.maybePersistLocked(currentTime); 1548 mXtRecorder.maybePersistLocked(currentTime); 1549 } 1550 if (persistUid) { 1551 mUidRecorder.maybePersistLocked(currentTime); 1552 mUidTagRecorder.maybePersistLocked(currentTime); 1553 } 1554 } 1555 Trace.traceEnd(TRACE_TAG_NETWORK); 1556 1557 if (mSettings.getSampleEnabled()) { 1558 // sample stats after each full poll 1559 performSampleLocked(); 1560 } 1561 1562 // finally, dispatch updated event to any listeners 1563 mHandler.sendMessage(mHandler.obtainMessage(MSG_BROADCAST_NETWORK_STATS_UPDATED)); 1564 1565 Trace.traceEnd(TRACE_TAG_NETWORK); 1566 } 1567 1568 @GuardedBy("mStatsLock") 1569 private void performPollFromProvidersLocked() { 1570 // Request asynchronous stats update from all providers for next poll. And wait a bit of 1571 // time to allow providers report-in given that normally binder call should be fast. Note 1572 // that size of list might be changed because addition/removing at the same time. For 1573 // addition, the stats of the missed provider can only be collected in next poll; 1574 // for removal, wait might take up to MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS 1575 // once that happened. 1576 // TODO: request with a valid token. 1577 Trace.traceBegin(TRACE_TAG_NETWORK, "provider.requestStatsUpdate"); 1578 final int registeredCallbackCount = mStatsProviderCbList.size(); 1579 mStatsProviderSem.drainPermits(); 1580 invokeForAllStatsProviderCallbacks( 1581 (cb) -> cb.mProvider.onRequestStatsUpdate(0 /* unused */)); 1582 try { 1583 mStatsProviderSem.tryAcquire(registeredCallbackCount, 1584 MAX_STATS_PROVIDER_POLL_WAIT_TIME_MS, TimeUnit.MILLISECONDS); 1585 } catch (InterruptedException e) { 1586 // Strictly speaking it's possible a provider happened to deliver between the timeout 1587 // and the log, and that doesn't matter too much as this is just a debug log. 1588 Log.d(TAG, "requestStatsUpdate - providers responded " 1589 + mStatsProviderSem.availablePermits() 1590 + "/" + registeredCallbackCount + " : " + e); 1591 } 1592 Trace.traceEnd(TRACE_TAG_NETWORK); 1593 } 1594 1595 /** 1596 * Sample recent statistics summary into {@link EventLog}. 1597 */ 1598 @GuardedBy("mStatsLock") 1599 private void performSampleLocked() { 1600 // TODO: migrate trustedtime fixes to separate binary log events 1601 final long currentTime = mClock.millis(); 1602 1603 NetworkTemplate template; 1604 NetworkStats.Entry devTotal; 1605 NetworkStats.Entry xtTotal; 1606 NetworkStats.Entry uidTotal; 1607 1608 // collect mobile sample 1609 template = buildTemplateMobileWildcard(); 1610 devTotal = mDevRecorder.getTotalSinceBootLocked(template); 1611 xtTotal = mXtRecorder.getTotalSinceBootLocked(template); 1612 uidTotal = mUidRecorder.getTotalSinceBootLocked(template); 1613 1614 EventLogTags.writeNetstatsMobileSample( 1615 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, 1616 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, 1617 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, 1618 currentTime); 1619 1620 // collect wifi sample 1621 template = buildTemplateWifiWildcard(); 1622 devTotal = mDevRecorder.getTotalSinceBootLocked(template); 1623 xtTotal = mXtRecorder.getTotalSinceBootLocked(template); 1624 uidTotal = mUidRecorder.getTotalSinceBootLocked(template); 1625 1626 EventLogTags.writeNetstatsWifiSample( 1627 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, 1628 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, 1629 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, 1630 currentTime); 1631 } 1632 1633 /** 1634 * Clean up {@link #mUidRecorder} after UID is removed. 1635 */ 1636 @GuardedBy("mStatsLock") 1637 private void removeUidsLocked(int... uids) { 1638 if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids)); 1639 1640 // Perform one last poll before removing 1641 performPollLocked(FLAG_PERSIST_ALL); 1642 1643 mUidRecorder.removeUidsLocked(uids); 1644 mUidTagRecorder.removeUidsLocked(uids); 1645 1646 // Clear kernel stats associated with UID 1647 for (int uid : uids) { 1648 resetKernelUidStats(uid); 1649 } 1650 } 1651 1652 /** 1653 * Clean up {@link #mUidRecorder} after user is removed. 1654 */ 1655 @GuardedBy("mStatsLock") 1656 private void removeUserLocked(int userId) { 1657 if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId); 1658 1659 // Build list of UIDs that we should clean up 1660 int[] uids = new int[0]; 1661 final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications( 1662 PackageManager.MATCH_ANY_USER 1663 | PackageManager.MATCH_DISABLED_COMPONENTS); 1664 for (ApplicationInfo app : apps) { 1665 final int uid = UserHandle.getUid(userId, app.uid); 1666 uids = ArrayUtils.appendInt(uids, uid); 1667 } 1668 1669 removeUidsLocked(uids); 1670 } 1671 1672 private class NetworkStatsManagerInternalImpl extends NetworkStatsManagerInternal { 1673 @Override 1674 public long getNetworkTotalBytes(NetworkTemplate template, long start, long end) { 1675 Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkTotalBytes"); 1676 try { 1677 return NetworkStatsService.this.getNetworkTotalBytes(template, start, end); 1678 } finally { 1679 Trace.traceEnd(TRACE_TAG_NETWORK); 1680 } 1681 } 1682 1683 @Override 1684 public NetworkStats getNetworkUidBytes(NetworkTemplate template, long start, long end) { 1685 Trace.traceBegin(TRACE_TAG_NETWORK, "getNetworkUidBytes"); 1686 try { 1687 return NetworkStatsService.this.getNetworkUidBytes(template, start, end); 1688 } finally { 1689 Trace.traceEnd(TRACE_TAG_NETWORK); 1690 } 1691 } 1692 1693 @Override 1694 public void setUidForeground(int uid, boolean uidForeground) { 1695 NetworkStatsService.this.setUidForeground(uid, uidForeground); 1696 } 1697 1698 @Override 1699 public void advisePersistThreshold(long thresholdBytes) { 1700 NetworkStatsService.this.advisePersistThreshold(thresholdBytes); 1701 } 1702 1703 @Override 1704 public void forceUpdate() { 1705 NetworkStatsService.this.forceUpdate(); 1706 } 1707 1708 @Override 1709 public void setStatsProviderWarningAndLimitAsync( 1710 @NonNull String iface, long warning, long limit) { 1711 if (LOGV) { 1712 Slog.v(TAG, "setStatsProviderWarningAndLimitAsync(" 1713 + iface + "," + warning + "," + limit + ")"); 1714 } 1715 invokeForAllStatsProviderCallbacks((cb) -> cb.mProvider.onSetWarningAndLimit(iface, 1716 warning, limit)); 1717 } 1718 } 1719 1720 @Override 1721 protected void dump(FileDescriptor fd, PrintWriter rawWriter, String[] args) { 1722 if (!DumpUtils.checkDumpPermission(mContext, TAG, rawWriter)) return; 1723 1724 long duration = DateUtils.DAY_IN_MILLIS; 1725 final HashSet<String> argSet = new HashSet<String>(); 1726 for (String arg : args) { 1727 argSet.add(arg); 1728 1729 if (arg.startsWith("--duration=")) { 1730 try { 1731 duration = Long.parseLong(arg.substring(11)); 1732 } catch (NumberFormatException ignored) { 1733 } 1734 } 1735 } 1736 1737 // usage: dumpsys netstats --full --uid --tag --poll --checkin 1738 final boolean poll = argSet.contains("--poll") || argSet.contains("poll"); 1739 final boolean checkin = argSet.contains("--checkin"); 1740 final boolean fullHistory = argSet.contains("--full") || argSet.contains("full"); 1741 final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail"); 1742 final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail"); 1743 1744 final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " "); 1745 1746 synchronized (mStatsLock) { 1747 if (args.length > 0 && "--proto".equals(args[0])) { 1748 // In this case ignore all other arguments. 1749 dumpProtoLocked(fd); 1750 return; 1751 } 1752 1753 if (poll) { 1754 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE); 1755 pw.println("Forced poll"); 1756 return; 1757 } 1758 1759 if (checkin) { 1760 final long end = System.currentTimeMillis(); 1761 final long start = end - duration; 1762 1763 pw.print("v1,"); 1764 pw.print(start / SECOND_IN_MILLIS); pw.print(','); 1765 pw.print(end / SECOND_IN_MILLIS); pw.println(); 1766 1767 pw.println("xt"); 1768 mXtRecorder.dumpCheckin(rawWriter, start, end); 1769 1770 if (includeUid) { 1771 pw.println("uid"); 1772 mUidRecorder.dumpCheckin(rawWriter, start, end); 1773 } 1774 if (includeTag) { 1775 pw.println("tag"); 1776 mUidTagRecorder.dumpCheckin(rawWriter, start, end); 1777 } 1778 return; 1779 } 1780 1781 pw.println("Configs:"); 1782 pw.increaseIndent(); 1783 pw.printPair(NETSTATS_COMBINE_SUBTYPE_ENABLED, mSettings.getCombineSubtypeEnabled()); 1784 pw.println(); 1785 pw.decreaseIndent(); 1786 1787 pw.println("Active interfaces:"); 1788 pw.increaseIndent(); 1789 for (int i = 0; i < mActiveIfaces.size(); i++) { 1790 pw.printPair("iface", mActiveIfaces.keyAt(i)); 1791 pw.printPair("ident", mActiveIfaces.valueAt(i)); 1792 pw.println(); 1793 } 1794 pw.decreaseIndent(); 1795 1796 pw.println("Active UID interfaces:"); 1797 pw.increaseIndent(); 1798 for (int i = 0; i < mActiveUidIfaces.size(); i++) { 1799 pw.printPair("iface", mActiveUidIfaces.keyAt(i)); 1800 pw.printPair("ident", mActiveUidIfaces.valueAt(i)); 1801 pw.println(); 1802 } 1803 pw.decreaseIndent(); 1804 1805 // Get the top openSession callers 1806 final SparseIntArray calls; 1807 synchronized (mOpenSessionCallsPerUid) { 1808 calls = mOpenSessionCallsPerUid.clone(); 1809 } 1810 1811 final int N = calls.size(); 1812 final long[] values = new long[N]; 1813 for (int j = 0; j < N; j++) { 1814 values[j] = ((long) calls.valueAt(j) << 32) | calls.keyAt(j); 1815 } 1816 Arrays.sort(values); 1817 1818 pw.println("Top openSession callers (uid=count):"); 1819 pw.increaseIndent(); 1820 final int end = Math.max(0, N - DUMP_STATS_SESSION_COUNT); 1821 for (int j = N - 1; j >= end; j--) { 1822 final int uid = (int) (values[j] & 0xffffffff); 1823 final int count = (int) (values[j] >> 32); 1824 pw.print(uid); pw.print("="); pw.println(count); 1825 } 1826 pw.decreaseIndent(); 1827 pw.println(); 1828 1829 pw.println("Stats Providers:"); 1830 pw.increaseIndent(); 1831 invokeForAllStatsProviderCallbacks((cb) -> { 1832 pw.println(cb.mTag + " Xt:"); 1833 pw.increaseIndent(); 1834 pw.print(cb.getCachedStats(STATS_PER_IFACE).toString()); 1835 pw.decreaseIndent(); 1836 if (includeUid) { 1837 pw.println(cb.mTag + " Uid:"); 1838 pw.increaseIndent(); 1839 pw.print(cb.getCachedStats(STATS_PER_UID).toString()); 1840 pw.decreaseIndent(); 1841 } 1842 }); 1843 pw.decreaseIndent(); 1844 1845 pw.println("Dev stats:"); 1846 pw.increaseIndent(); 1847 mDevRecorder.dumpLocked(pw, fullHistory); 1848 pw.decreaseIndent(); 1849 1850 pw.println("Xt stats:"); 1851 pw.increaseIndent(); 1852 mXtRecorder.dumpLocked(pw, fullHistory); 1853 pw.decreaseIndent(); 1854 1855 if (includeUid) { 1856 pw.println("UID stats:"); 1857 pw.increaseIndent(); 1858 mUidRecorder.dumpLocked(pw, fullHistory); 1859 pw.decreaseIndent(); 1860 } 1861 1862 if (includeTag) { 1863 pw.println("UID tag stats:"); 1864 pw.increaseIndent(); 1865 mUidTagRecorder.dumpLocked(pw, fullHistory); 1866 pw.decreaseIndent(); 1867 } 1868 } 1869 } 1870 1871 @GuardedBy("mStatsLock") 1872 private void dumpProtoLocked(FileDescriptor fd) { 1873 final ProtoOutputStream proto = new ProtoOutputStream(fd); 1874 1875 // TODO Right now it writes all history. Should it limit to the "since-boot" log? 1876 1877 dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_INTERFACES, mActiveIfaces); 1878 dumpInterfaces(proto, NetworkStatsServiceDumpProto.ACTIVE_UID_INTERFACES, mActiveUidIfaces); 1879 mDevRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.DEV_STATS); 1880 mXtRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.XT_STATS); 1881 mUidRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_STATS); 1882 mUidTagRecorder.dumpDebugLocked(proto, NetworkStatsServiceDumpProto.UID_TAG_STATS); 1883 1884 proto.flush(); 1885 } 1886 1887 private static void dumpInterfaces(ProtoOutputStream proto, long tag, 1888 ArrayMap<String, NetworkIdentitySet> ifaces) { 1889 for (int i = 0; i < ifaces.size(); i++) { 1890 final long start = proto.start(tag); 1891 1892 proto.write(NetworkInterfaceProto.INTERFACE, ifaces.keyAt(i)); 1893 ifaces.valueAt(i).dumpDebug(proto, NetworkInterfaceProto.IDENTITIES); 1894 1895 proto.end(start); 1896 } 1897 } 1898 1899 private NetworkStats readNetworkStatsSummaryDev() { 1900 try { 1901 return mStatsFactory.readNetworkStatsSummaryDev(); 1902 } catch (IOException e) { 1903 throw new IllegalStateException(e); 1904 } 1905 } 1906 1907 private NetworkStats readNetworkStatsSummaryXt() { 1908 try { 1909 return mStatsFactory.readNetworkStatsSummaryXt(); 1910 } catch (IOException e) { 1911 throw new IllegalStateException(e); 1912 } 1913 } 1914 1915 private NetworkStats readNetworkStatsUidDetail(int uid, String[] ifaces, int tag) { 1916 try { 1917 return mStatsFactory.readNetworkStatsDetail(uid, ifaces, tag); 1918 } catch (IOException e) { 1919 throw new IllegalStateException(e); 1920 } 1921 } 1922 1923 /** 1924 * Return snapshot of current UID statistics, including any 1925 * {@link TrafficStats#UID_TETHERING}, video calling data usage, and {@link #mUidOperations} 1926 * values. 1927 * 1928 * @param ifaces A list of interfaces the stats should be restricted to, or 1929 * {@link NetworkStats#INTERFACES_ALL}. 1930 */ 1931 private NetworkStats getNetworkStatsUidDetail(String[] ifaces) 1932 throws RemoteException { 1933 final NetworkStats uidSnapshot = readNetworkStatsUidDetail(UID_ALL, ifaces, TAG_ALL); 1934 1935 // fold tethering stats and operations into uid snapshot 1936 final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID); 1937 tetherSnapshot.filter(UID_ALL, ifaces, TAG_ALL); 1938 mStatsFactory.apply464xlatAdjustments(uidSnapshot, tetherSnapshot); 1939 uidSnapshot.combineAllValues(tetherSnapshot); 1940 1941 // get a stale copy of uid stats snapshot provided by providers. 1942 final NetworkStats providerStats = getNetworkStatsFromProviders(STATS_PER_UID); 1943 providerStats.filter(UID_ALL, ifaces, TAG_ALL); 1944 mStatsFactory.apply464xlatAdjustments(uidSnapshot, providerStats); 1945 uidSnapshot.combineAllValues(providerStats); 1946 1947 uidSnapshot.combineAllValues(mUidOperations); 1948 1949 return uidSnapshot; 1950 } 1951 1952 /** 1953 * Return snapshot of current non-offloaded tethering statistics. Will return empty 1954 * {@link NetworkStats} if any problems are encountered, or queried by {@code STATS_PER_IFACE} 1955 * since it is already included by {@link #nativeGetIfaceStat}. 1956 * See {@code OffloadTetheringStatsProvider} for offloaded tethering stats. 1957 */ 1958 // TODO: Remove this by implementing {@link NetworkStatsProvider} for non-offloaded 1959 // tethering stats. 1960 private NetworkStats getNetworkStatsTethering(int how) throws RemoteException { 1961 try { 1962 return mNetworkManager.getNetworkStatsTethering(how); 1963 } catch (IllegalStateException e) { 1964 Log.wtf(TAG, "problem reading network stats", e); 1965 return new NetworkStats(0L, 10); 1966 } 1967 } 1968 1969 // TODO: It is copied from ConnectivityService, consider refactor these check permission 1970 // functions to a proper util. 1971 private boolean checkAnyPermissionOf(String... permissions) { 1972 for (String permission : permissions) { 1973 if (mContext.checkCallingOrSelfPermission(permission) == PERMISSION_GRANTED) { 1974 return true; 1975 } 1976 } 1977 return false; 1978 } 1979 1980 private void enforceAnyPermissionOf(String... permissions) { 1981 if (!checkAnyPermissionOf(permissions)) { 1982 throw new SecurityException("Requires one of the following permissions: " 1983 + String.join(", ", permissions) + "."); 1984 } 1985 } 1986 1987 /** 1988 * Registers a custom provider of {@link android.net.NetworkStats} to combine the network 1989 * statistics that cannot be seen by the kernel to system. To unregister, invoke the 1990 * {@code unregister()} of the returned callback. 1991 * 1992 * @param tag a human readable identifier of the custom network stats provider. 1993 * @param provider the {@link INetworkStatsProvider} binder corresponding to the 1994 * {@link NetworkStatsProvider} to be registered. 1995 * 1996 * @return a {@link INetworkStatsProviderCallback} binder 1997 * interface, which can be used to report events to the system. 1998 */ 1999 public @NonNull INetworkStatsProviderCallback registerNetworkStatsProvider( 2000 @NonNull String tag, @NonNull INetworkStatsProvider provider) { 2001 enforceAnyPermissionOf(NETWORK_STATS_PROVIDER, 2002 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK); 2003 Objects.requireNonNull(provider, "provider is null"); 2004 Objects.requireNonNull(tag, "tag is null"); 2005 try { 2006 NetworkStatsProviderCallbackImpl callback = new NetworkStatsProviderCallbackImpl( 2007 tag, provider, mStatsProviderSem, mAlertObserver, 2008 mStatsProviderCbList); 2009 mStatsProviderCbList.add(callback); 2010 Log.d(TAG, "registerNetworkStatsProvider from " + callback.mTag + " uid/pid=" 2011 + getCallingUid() + "/" + getCallingPid()); 2012 return callback; 2013 } catch (RemoteException e) { 2014 Log.e(TAG, "registerNetworkStatsProvider failed", e); 2015 } 2016 return null; 2017 } 2018 2019 // Collect stats from local cache of providers. 2020 private @NonNull NetworkStats getNetworkStatsFromProviders(int how) { 2021 final NetworkStats ret = new NetworkStats(0L, 0); 2022 invokeForAllStatsProviderCallbacks((cb) -> ret.combineAllValues(cb.getCachedStats(how))); 2023 return ret; 2024 } 2025 2026 @FunctionalInterface 2027 private interface ThrowingConsumer<S, T extends Throwable> { 2028 void accept(S s) throws T; 2029 } 2030 2031 private void invokeForAllStatsProviderCallbacks( 2032 @NonNull ThrowingConsumer<NetworkStatsProviderCallbackImpl, RemoteException> task) { 2033 for (final NetworkStatsProviderCallbackImpl cb : mStatsProviderCbList) { 2034 try { 2035 task.accept(cb); 2036 } catch (RemoteException e) { 2037 Log.e(TAG, "Fail to broadcast to provider: " + cb.mTag, e); 2038 } 2039 } 2040 } 2041 2042 private static class NetworkStatsProviderCallbackImpl extends INetworkStatsProviderCallback.Stub 2043 implements IBinder.DeathRecipient { 2044 @NonNull final String mTag; 2045 2046 @NonNull final INetworkStatsProvider mProvider; 2047 @NonNull private final Semaphore mSemaphore; 2048 @NonNull final INetworkManagementEventObserver mAlertObserver; 2049 @NonNull final CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> mStatsProviderCbList; 2050 2051 @NonNull private final Object mProviderStatsLock = new Object(); 2052 2053 @GuardedBy("mProviderStatsLock") 2054 // Track STATS_PER_IFACE and STATS_PER_UID separately. 2055 private final NetworkStats mIfaceStats = new NetworkStats(0L, 0); 2056 @GuardedBy("mProviderStatsLock") 2057 private final NetworkStats mUidStats = new NetworkStats(0L, 0); 2058 2059 NetworkStatsProviderCallbackImpl( 2060 @NonNull String tag, @NonNull INetworkStatsProvider provider, 2061 @NonNull Semaphore semaphore, 2062 @NonNull INetworkManagementEventObserver alertObserver, 2063 @NonNull CopyOnWriteArrayList<NetworkStatsProviderCallbackImpl> cbList) 2064 throws RemoteException { 2065 mTag = tag; 2066 mProvider = provider; 2067 mProvider.asBinder().linkToDeath(this, 0); 2068 mSemaphore = semaphore; 2069 mAlertObserver = alertObserver; 2070 mStatsProviderCbList = cbList; 2071 } 2072 2073 @NonNull 2074 public NetworkStats getCachedStats(int how) { 2075 synchronized (mProviderStatsLock) { 2076 NetworkStats stats; 2077 switch (how) { 2078 case STATS_PER_IFACE: 2079 stats = mIfaceStats; 2080 break; 2081 case STATS_PER_UID: 2082 stats = mUidStats; 2083 break; 2084 default: 2085 throw new IllegalArgumentException("Invalid type: " + how); 2086 } 2087 // Callers might be able to mutate the returned object. Return a defensive copy 2088 // instead of local reference. 2089 return stats.clone(); 2090 } 2091 } 2092 2093 @Override 2094 public void notifyStatsUpdated(int token, @Nullable NetworkStats ifaceStats, 2095 @Nullable NetworkStats uidStats) { 2096 // TODO: 1. Use token to map ifaces to correct NetworkIdentity. 2097 // 2. Store the difference and store it directly to the recorder. 2098 synchronized (mProviderStatsLock) { 2099 if (ifaceStats != null) mIfaceStats.combineAllValues(ifaceStats); 2100 if (uidStats != null) mUidStats.combineAllValues(uidStats); 2101 } 2102 mSemaphore.release(); 2103 } 2104 2105 @Override 2106 public void notifyAlertReached() throws RemoteException { 2107 mAlertObserver.limitReached(LIMIT_GLOBAL_ALERT, null /* unused */); 2108 } 2109 2110 @Override 2111 public void notifyWarningOrLimitReached() { 2112 Log.d(TAG, mTag + ": notifyWarningOrLimitReached"); 2113 LocalServices.getService(NetworkPolicyManagerInternal.class) 2114 .onStatsProviderWarningOrLimitReached(mTag); 2115 } 2116 2117 @Override 2118 public void binderDied() { 2119 Log.d(TAG, mTag + ": binderDied"); 2120 mStatsProviderCbList.remove(this); 2121 } 2122 2123 @Override 2124 public void unregister() { 2125 Log.d(TAG, mTag + ": unregister"); 2126 mStatsProviderCbList.remove(this); 2127 } 2128 2129 } 2130 2131 private void assertSystemReady() { 2132 if (!mSystemReady) { 2133 throw new IllegalStateException("System not ready"); 2134 } 2135 } 2136 2137 private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> { 2138 @Override 2139 public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, 2140 int rightIndex, String cookie) { 2141 Log.w(TAG, "Found non-monotonic values; saving to dropbox"); 2142 2143 // record error for debugging 2144 final StringBuilder builder = new StringBuilder(); 2145 builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex 2146 + "] - right[" + rightIndex + "]\n"); 2147 builder.append("left=").append(left).append('\n'); 2148 builder.append("right=").append(right).append('\n'); 2149 2150 mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR, 2151 builder.toString()); 2152 } 2153 2154 @Override 2155 public void foundNonMonotonic( 2156 NetworkStats stats, int statsIndex, String cookie) { 2157 Log.w(TAG, "Found non-monotonic values; saving to dropbox"); 2158 2159 final StringBuilder builder = new StringBuilder(); 2160 builder.append("Found non-monotonic " + cookie + " values at [" + statsIndex + "]\n"); 2161 builder.append("stats=").append(stats).append('\n'); 2162 2163 mContext.getSystemService(DropBoxManager.class).addText(TAG_NETSTATS_ERROR, 2164 builder.toString()); 2165 } 2166 } 2167 2168 /** 2169 * Default external settings that read from 2170 * {@link android.provider.Settings.Global}. 2171 */ 2172 private static class DefaultNetworkStatsSettings implements NetworkStatsSettings { 2173 private final ContentResolver mResolver; 2174 2175 public DefaultNetworkStatsSettings(Context context) { 2176 mResolver = Objects.requireNonNull(context.getContentResolver()); 2177 // TODO: adjust these timings for production builds 2178 } 2179 2180 private long getGlobalLong(String name, long def) { 2181 return Settings.Global.getLong(mResolver, name, def); 2182 } 2183 private boolean getGlobalBoolean(String name, boolean def) { 2184 final int defInt = def ? 1 : 0; 2185 return Settings.Global.getInt(mResolver, name, defInt) != 0; 2186 } 2187 2188 @Override 2189 public long getPollInterval() { 2190 return getGlobalLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); 2191 } 2192 @Override 2193 public long getPollDelay() { 2194 return DEFAULT_PERFORM_POLL_DELAY_MS; 2195 } 2196 @Override 2197 public long getGlobalAlertBytes(long def) { 2198 return getGlobalLong(NETSTATS_GLOBAL_ALERT_BYTES, def); 2199 } 2200 @Override 2201 public boolean getSampleEnabled() { 2202 return getGlobalBoolean(NETSTATS_SAMPLE_ENABLED, true); 2203 } 2204 @Override 2205 public boolean getAugmentEnabled() { 2206 return getGlobalBoolean(NETSTATS_AUGMENT_ENABLED, true); 2207 } 2208 @Override 2209 public boolean getCombineSubtypeEnabled() { 2210 return getGlobalBoolean(NETSTATS_COMBINE_SUBTYPE_ENABLED, false); 2211 } 2212 @Override 2213 public Config getDevConfig() { 2214 return new Config(getGlobalLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), 2215 getGlobalLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), 2216 getGlobalLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); 2217 } 2218 @Override 2219 public Config getXtConfig() { 2220 return getDevConfig(); 2221 } 2222 @Override 2223 public Config getUidConfig() { 2224 return new Config(getGlobalLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), 2225 getGlobalLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS), 2226 getGlobalLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); 2227 } 2228 @Override 2229 public Config getUidTagConfig() { 2230 return new Config(getGlobalLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), 2231 getGlobalLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS), 2232 getGlobalLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS)); 2233 } 2234 @Override 2235 public long getDevPersistBytes(long def) { 2236 return getGlobalLong(NETSTATS_DEV_PERSIST_BYTES, def); 2237 } 2238 @Override 2239 public long getXtPersistBytes(long def) { 2240 return getDevPersistBytes(def); 2241 } 2242 @Override 2243 public long getUidPersistBytes(long def) { 2244 return getGlobalLong(NETSTATS_UID_PERSIST_BYTES, def); 2245 } 2246 @Override 2247 public long getUidTagPersistBytes(long def) { 2248 return getGlobalLong(NETSTATS_UID_TAG_PERSIST_BYTES, def); 2249 } 2250 } 2251 2252 private static native long nativeGetTotalStat(int type, boolean useBpfStats); 2253 private static native long nativeGetIfaceStat(String iface, int type, boolean useBpfStats); 2254 private static native long nativeGetUidStat(int uid, int type, boolean useBpfStats); 2255 } 2256