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