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