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