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