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