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