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.EXTRA_UID; 27 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; 28 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 29 import static android.net.ConnectivityManager.isNetworkTypeMobile; 30 import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED; 31 import static android.net.NetworkStats.IFACE_ALL; 32 import static android.net.NetworkStats.SET_ALL; 33 import static android.net.NetworkStats.SET_DEFAULT; 34 import static android.net.NetworkStats.SET_FOREGROUND; 35 import static android.net.NetworkStats.TAG_NONE; 36 import static android.net.NetworkStats.UID_ALL; 37 import static android.net.NetworkTemplate.buildTemplateMobileWildcard; 38 import static android.net.NetworkTemplate.buildTemplateWifiWildcard; 39 import static android.net.TrafficStats.KB_IN_BYTES; 40 import static android.net.TrafficStats.MB_IN_BYTES; 41 import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION; 42 import static android.provider.Settings.Secure.NETSTATS_DEV_DELETE_AGE; 43 import static android.provider.Settings.Secure.NETSTATS_DEV_PERSIST_BYTES; 44 import static android.provider.Settings.Secure.NETSTATS_DEV_ROTATE_AGE; 45 import static android.provider.Settings.Secure.NETSTATS_GLOBAL_ALERT_BYTES; 46 import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL; 47 import static android.provider.Settings.Secure.NETSTATS_REPORT_XT_OVER_DEV; 48 import static android.provider.Settings.Secure.NETSTATS_SAMPLE_ENABLED; 49 import static android.provider.Settings.Secure.NETSTATS_TIME_CACHE_MAX_AGE; 50 import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION; 51 import static android.provider.Settings.Secure.NETSTATS_UID_DELETE_AGE; 52 import static android.provider.Settings.Secure.NETSTATS_UID_PERSIST_BYTES; 53 import static android.provider.Settings.Secure.NETSTATS_UID_ROTATE_AGE; 54 import static android.provider.Settings.Secure.NETSTATS_UID_TAG_BUCKET_DURATION; 55 import static android.provider.Settings.Secure.NETSTATS_UID_TAG_DELETE_AGE; 56 import static android.provider.Settings.Secure.NETSTATS_UID_TAG_PERSIST_BYTES; 57 import static android.provider.Settings.Secure.NETSTATS_UID_TAG_ROTATE_AGE; 58 import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE; 59 import static android.telephony.PhoneStateListener.LISTEN_NONE; 60 import static android.text.format.DateUtils.DAY_IN_MILLIS; 61 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 62 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 63 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 64 import static com.android.internal.util.ArrayUtils.appendElement; 65 import static com.android.internal.util.ArrayUtils.contains; 66 import static com.android.internal.util.Preconditions.checkNotNull; 67 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; 68 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; 69 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; 70 71 import android.app.AlarmManager; 72 import android.app.IAlarmManager; 73 import android.app.PendingIntent; 74 import android.content.BroadcastReceiver; 75 import android.content.ContentResolver; 76 import android.content.Context; 77 import android.content.Intent; 78 import android.content.IntentFilter; 79 import android.net.IConnectivityManager; 80 import android.net.INetworkManagementEventObserver; 81 import android.net.INetworkStatsService; 82 import android.net.INetworkStatsSession; 83 import android.net.LinkProperties; 84 import android.net.NetworkIdentity; 85 import android.net.NetworkInfo; 86 import android.net.NetworkState; 87 import android.net.NetworkStats; 88 import android.net.NetworkStats.NonMonotonicObserver; 89 import android.net.NetworkStatsHistory; 90 import android.net.NetworkTemplate; 91 import android.net.TrafficStats; 92 import android.os.Binder; 93 import android.os.DropBoxManager; 94 import android.os.Environment; 95 import android.os.Handler; 96 import android.os.HandlerThread; 97 import android.os.INetworkManagementService; 98 import android.os.Message; 99 import android.os.PowerManager; 100 import android.os.RemoteException; 101 import android.os.SystemClock; 102 import android.provider.Settings; 103 import android.provider.Settings.Secure; 104 import android.telephony.PhoneStateListener; 105 import android.telephony.TelephonyManager; 106 import android.util.EventLog; 107 import android.util.Log; 108 import android.util.MathUtils; 109 import android.util.NtpTrustedTime; 110 import android.util.Slog; 111 import android.util.SparseIntArray; 112 import android.util.TrustedTime; 113 114 import com.android.internal.util.FileRotator; 115 import com.android.internal.util.IndentingPrintWriter; 116 import com.android.server.EventLogTags; 117 import com.android.server.connectivity.Tethering; 118 import com.google.android.collect.Maps; 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.HashMap; 125 import java.util.HashSet; 126 127 /** 128 * Collect and persist detailed network statistics, and provide this data to 129 * other system services. 130 */ 131 public 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 /** 699 * Receiver that watches for {@link IConnectivityManager} to claim network 700 * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()} 701 * with mobile interfaces. 702 */ 703 private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 704 @Override 705 public void onReceive(Context context, Intent intent) { 706 // on background handler thread, and verified CONNECTIVITY_INTERNAL 707 // permission above. 708 updateIfaces(); 709 } 710 }; 711 712 /** 713 * Receiver that watches for {@link Tethering} to claim interface pairs. 714 */ 715 private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() { 716 @Override 717 public void onReceive(Context context, Intent intent) { 718 // on background handler thread, and verified CONNECTIVITY_INTERNAL 719 // permission above. 720 performPoll(FLAG_PERSIST_NETWORK); 721 } 722 }; 723 724 private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { 725 @Override 726 public void onReceive(Context context, Intent intent) { 727 // on background handler thread, and verified UPDATE_DEVICE_STATS 728 // permission above. 729 performPoll(FLAG_PERSIST_ALL); 730 731 // verify that we're watching global alert 732 registerGlobalAlert(); 733 } 734 }; 735 736 private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() { 737 @Override 738 public void onReceive(Context context, Intent intent) { 739 // on background handler thread, and UID_REMOVED is protected 740 // broadcast. 741 final int uid = intent.getIntExtra(EXTRA_UID, 0); 742 synchronized (mStatsLock) { 743 mWakeLock.acquire(); 744 try { 745 removeUidLocked(uid); 746 } finally { 747 mWakeLock.release(); 748 } 749 } 750 } 751 }; 752 753 private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() { 754 @Override 755 public void onReceive(Context context, Intent intent) { 756 // SHUTDOWN is protected broadcast. 757 synchronized (mStatsLock) { 758 shutdownLocked(); 759 } 760 } 761 }; 762 763 /** 764 * Observer that watches for {@link INetworkManagementService} alerts. 765 */ 766 private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { 767 @Override 768 public void limitReached(String limitName, String iface) { 769 // only someone like NMS should be calling us 770 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 771 772 if (LIMIT_GLOBAL_ALERT.equals(limitName)) { 773 // kick off background poll to collect network stats; UID stats 774 // are handled during normal polling interval. 775 final int flags = FLAG_PERSIST_NETWORK; 776 mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget(); 777 778 // re-arm global alert for next update 779 mHandler.obtainMessage(MSG_REGISTER_GLOBAL_ALERT).sendToTarget(); 780 } 781 } 782 }; 783 784 private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN; 785 private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 786 787 /** 788 * Receiver that watches for {@link TelephonyManager} changes, such as 789 * transitioning between network types. 790 */ 791 private PhoneStateListener mPhoneListener = new PhoneStateListener() { 792 @Override 793 public void onDataConnectionStateChanged(int state, int networkType) { 794 final boolean stateChanged = state != mLastPhoneState; 795 final boolean networkTypeChanged = networkType != mLastPhoneNetworkType; 796 797 if (networkTypeChanged && !stateChanged) { 798 // networkType changed without a state change, which means we 799 // need to roll our own update. delay long enough for 800 // ConnectivityManager to process. 801 // TODO: add direct event to ConnectivityService instead of 802 // relying on this delay. 803 if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()"); 804 mHandler.sendMessageDelayed( 805 mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); 806 } 807 808 mLastPhoneState = state; 809 mLastPhoneNetworkType = networkType; 810 } 811 }; 812 813 private void updateIfaces() { 814 synchronized (mStatsLock) { 815 mWakeLock.acquire(); 816 try { 817 updateIfacesLocked(); 818 } finally { 819 mWakeLock.release(); 820 } 821 } 822 } 823 824 /** 825 * Inspect all current {@link NetworkState} to derive mapping from {@code 826 * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo} 827 * are active on a single {@code iface}, they are combined under a single 828 * {@link NetworkIdentitySet}. 829 */ 830 private void updateIfacesLocked() { 831 if (!mSystemReady) return; 832 if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 833 834 // take one last stats snapshot before updating iface mapping. this 835 // isn't perfect, since the kernel may already be counting traffic from 836 // the updated network. 837 838 // poll, but only persist network stats to keep codepath fast. UID stats 839 // will be persisted during next alarm poll event. 840 performPollLocked(FLAG_PERSIST_NETWORK); 841 842 final NetworkState[] states; 843 final LinkProperties activeLink; 844 try { 845 states = mConnManager.getAllNetworkState(); 846 activeLink = mConnManager.getActiveLinkProperties(); 847 } catch (RemoteException e) { 848 // ignored; service lives in system_server 849 return; 850 } 851 852 mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null; 853 854 // rebuild active interfaces based on connected networks 855 mActiveIfaces.clear(); 856 857 for (NetworkState state : states) { 858 if (state.networkInfo.isConnected()) { 859 // collect networks under their parent interfaces 860 final String iface = state.linkProperties.getInterfaceName(); 861 862 NetworkIdentitySet ident = mActiveIfaces.get(iface); 863 if (ident == null) { 864 ident = new NetworkIdentitySet(); 865 mActiveIfaces.put(iface, ident); 866 } 867 868 ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state)); 869 870 // remember any ifaces associated with mobile networks 871 if (isNetworkTypeMobile(state.networkInfo.getType())) { 872 if (!contains(mMobileIfaces, iface)) { 873 mMobileIfaces = appendElement(String.class, mMobileIfaces, iface); 874 } 875 } 876 } 877 } 878 } 879 880 /** 881 * Bootstrap initial stats snapshot, usually during {@link #systemReady()} 882 * so we have baseline values without double-counting. 883 */ 884 private void bootstrapStatsLocked() { 885 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() 886 : System.currentTimeMillis(); 887 888 try { 889 // snapshot and record current counters; read UID stats first to 890 // avoid overcounting dev stats. 891 final NetworkStats uidSnapshot = getNetworkStatsUidDetail(); 892 final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt(); 893 final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); 894 895 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime); 896 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime); 897 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime); 898 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime); 899 900 } catch (IllegalStateException e) { 901 Slog.w(TAG, "problem reading network stats: " + e); 902 } catch (RemoteException e) { 903 // ignored; service lives in system_server 904 } 905 } 906 907 private void performPoll(int flags) { 908 synchronized (mStatsLock) { 909 mWakeLock.acquire(); 910 911 // try refreshing time source when stale 912 if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) { 913 mTime.forceRefresh(); 914 } 915 916 try { 917 performPollLocked(flags); 918 } finally { 919 mWakeLock.release(); 920 } 921 } 922 } 923 924 /** 925 * Periodic poll operation, reading current statistics and recording into 926 * {@link NetworkStatsHistory}. 927 */ 928 private void performPollLocked(int flags) { 929 if (!mSystemReady) return; 930 if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); 931 932 final long startRealtime = SystemClock.elapsedRealtime(); 933 934 final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; 935 final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; 936 final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; 937 938 // TODO: consider marking "untrusted" times in historical stats 939 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() 940 : System.currentTimeMillis(); 941 942 try { 943 // snapshot and record current counters; read UID stats first to 944 // avoid overcounting dev stats. 945 final NetworkStats uidSnapshot = getNetworkStatsUidDetail(); 946 final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt(); 947 final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev(); 948 949 mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime); 950 mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime); 951 mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime); 952 mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveIfaces, currentTime); 953 954 } catch (IllegalStateException e) { 955 Log.wtf(TAG, "problem reading network stats", e); 956 return; 957 } catch (RemoteException e) { 958 // ignored; service lives in system_server 959 return; 960 } 961 962 // persist any pending data depending on requested flags 963 if (persistForce) { 964 mDevRecorder.forcePersistLocked(currentTime); 965 mXtRecorder.forcePersistLocked(currentTime); 966 mUidRecorder.forcePersistLocked(currentTime); 967 mUidTagRecorder.forcePersistLocked(currentTime); 968 } else { 969 if (persistNetwork) { 970 mDevRecorder.maybePersistLocked(currentTime); 971 mXtRecorder.maybePersistLocked(currentTime); 972 } 973 if (persistUid) { 974 mUidRecorder.maybePersistLocked(currentTime); 975 mUidTagRecorder.maybePersistLocked(currentTime); 976 } 977 } 978 979 if (LOGV) { 980 final long duration = SystemClock.elapsedRealtime() - startRealtime; 981 Slog.v(TAG, "performPollLocked() took " + duration + "ms"); 982 } 983 984 if (mSettings.getSampleEnabled()) { 985 // sample stats after each full poll 986 performSampleLocked(); 987 } 988 989 // finally, dispatch updated event to any listeners 990 final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); 991 updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 992 mContext.sendBroadcast(updatedIntent, READ_NETWORK_USAGE_HISTORY); 993 } 994 995 /** 996 * Sample recent statistics summary into {@link EventLog}. 997 */ 998 private void performSampleLocked() { 999 // TODO: migrate trustedtime fixes to separate binary log events 1000 final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1; 1001 1002 NetworkTemplate template; 1003 NetworkStats.Entry devTotal; 1004 NetworkStats.Entry xtTotal; 1005 NetworkStats.Entry uidTotal; 1006 1007 // collect mobile sample 1008 template = buildTemplateMobileWildcard(); 1009 devTotal = mDevRecorder.getTotalSinceBootLocked(template); 1010 xtTotal = mXtRecorder.getTotalSinceBootLocked(template); 1011 uidTotal = mUidRecorder.getTotalSinceBootLocked(template); 1012 1013 EventLogTags.writeNetstatsMobileSample( 1014 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, 1015 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, 1016 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, 1017 trustedTime); 1018 1019 // collect wifi sample 1020 template = buildTemplateWifiWildcard(); 1021 devTotal = mDevRecorder.getTotalSinceBootLocked(template); 1022 xtTotal = mXtRecorder.getTotalSinceBootLocked(template); 1023 uidTotal = mUidRecorder.getTotalSinceBootLocked(template); 1024 1025 EventLogTags.writeNetstatsWifiSample( 1026 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, 1027 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, 1028 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, 1029 trustedTime); 1030 } 1031 1032 /** 1033 * Clean up {@link #mUidRecorder} after UID is removed. 1034 */ 1035 private void removeUidLocked(int uid) { 1036 // perform one last poll before removing 1037 performPollLocked(FLAG_PERSIST_ALL); 1038 1039 mUidRecorder.removeUidLocked(uid); 1040 mUidTagRecorder.removeUidLocked(uid); 1041 1042 // clear kernel stats associated with UID 1043 resetKernelUidStats(uid); 1044 } 1045 1046 @Override 1047 protected void dump(FileDescriptor fd, PrintWriter writer, String[] args) { 1048 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1049 1050 final HashSet<String> argSet = new HashSet<String>(); 1051 for (String arg : args) { 1052 argSet.add(arg); 1053 } 1054 1055 // usage: dumpsys netstats --full --uid --tag --poll --checkin 1056 final boolean poll = argSet.contains("--poll") || argSet.contains("poll"); 1057 final boolean checkin = argSet.contains("--checkin"); 1058 final boolean fullHistory = argSet.contains("--full") || argSet.contains("full"); 1059 final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail"); 1060 final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail"); 1061 1062 final IndentingPrintWriter pw = new IndentingPrintWriter(writer, " "); 1063 1064 synchronized (mStatsLock) { 1065 if (poll) { 1066 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE); 1067 pw.println("Forced poll"); 1068 return; 1069 } 1070 1071 if (checkin) { 1072 // list current stats files to verify rotation 1073 pw.println("Current files:"); 1074 pw.increaseIndent(); 1075 for (String file : mBaseDir.list()) { 1076 pw.println(file); 1077 } 1078 pw.decreaseIndent(); 1079 return; 1080 } 1081 1082 pw.println("Active interfaces:"); 1083 pw.increaseIndent(); 1084 for (String iface : mActiveIfaces.keySet()) { 1085 final NetworkIdentitySet ident = mActiveIfaces.get(iface); 1086 pw.print("iface="); pw.print(iface); 1087 pw.print(" ident="); pw.println(ident.toString()); 1088 } 1089 pw.decreaseIndent(); 1090 1091 pw.println("Dev stats:"); 1092 pw.increaseIndent(); 1093 mDevRecorder.dumpLocked(pw, fullHistory); 1094 pw.decreaseIndent(); 1095 1096 pw.println("Xt stats:"); 1097 pw.increaseIndent(); 1098 mXtRecorder.dumpLocked(pw, fullHistory); 1099 pw.decreaseIndent(); 1100 1101 if (includeUid) { 1102 pw.println("UID stats:"); 1103 pw.increaseIndent(); 1104 mUidRecorder.dumpLocked(pw, fullHistory); 1105 pw.decreaseIndent(); 1106 } 1107 1108 if (includeTag) { 1109 pw.println("UID tag stats:"); 1110 pw.increaseIndent(); 1111 mUidTagRecorder.dumpLocked(pw, fullHistory); 1112 pw.decreaseIndent(); 1113 } 1114 } 1115 } 1116 1117 /** 1118 * Return snapshot of current UID statistics, including any 1119 * {@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values. 1120 */ 1121 private NetworkStats getNetworkStatsUidDetail() throws RemoteException { 1122 final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); 1123 1124 // fold tethering stats and operations into uid snapshot 1125 final NetworkStats tetherSnapshot = getNetworkStatsTethering(); 1126 uidSnapshot.combineAllValues(tetherSnapshot); 1127 uidSnapshot.combineAllValues(mUidOperations); 1128 1129 return uidSnapshot; 1130 } 1131 1132 /** 1133 * Return snapshot of current tethering statistics. Will return empty 1134 * {@link NetworkStats} if any problems are encountered. 1135 */ 1136 private NetworkStats getNetworkStatsTethering() throws RemoteException { 1137 try { 1138 final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs(); 1139 return mNetworkManager.getNetworkStatsTethering(tetheredIfacePairs); 1140 } catch (IllegalStateException e) { 1141 Log.wtf(TAG, "problem reading network stats", e); 1142 return new NetworkStats(0L, 10); 1143 } 1144 } 1145 1146 private Handler.Callback mHandlerCallback = new Handler.Callback() { 1147 @Override 1148 public boolean handleMessage(Message msg) { 1149 switch (msg.what) { 1150 case MSG_PERFORM_POLL: { 1151 final int flags = msg.arg1; 1152 performPoll(flags); 1153 return true; 1154 } 1155 case MSG_UPDATE_IFACES: { 1156 updateIfaces(); 1157 return true; 1158 } 1159 case MSG_REGISTER_GLOBAL_ALERT: { 1160 registerGlobalAlert(); 1161 return true; 1162 } 1163 default: { 1164 return false; 1165 } 1166 } 1167 } 1168 }; 1169 1170 private void assertBandwidthControlEnabled() { 1171 if (!isBandwidthControlEnabled()) { 1172 throw new IllegalStateException("Bandwidth module disabled"); 1173 } 1174 } 1175 1176 private boolean isBandwidthControlEnabled() { 1177 final long token = Binder.clearCallingIdentity(); 1178 try { 1179 return mNetworkManager.isBandwidthControlEnabled(); 1180 } catch (RemoteException e) { 1181 // ignored; service lives in system_server 1182 return false; 1183 } finally { 1184 Binder.restoreCallingIdentity(token); 1185 } 1186 } 1187 1188 private class DropBoxNonMonotonicObserver implements NonMonotonicObserver<String> { 1189 @Override 1190 public void foundNonMonotonic(NetworkStats left, int leftIndex, NetworkStats right, 1191 int rightIndex, String cookie) { 1192 Log.w(TAG, "found non-monotonic values; saving to dropbox"); 1193 1194 // record error for debugging 1195 final StringBuilder builder = new StringBuilder(); 1196 builder.append("found non-monotonic " + cookie + " values at left[" + leftIndex 1197 + "] - right[" + rightIndex + "]\n"); 1198 builder.append("left=").append(left).append('\n'); 1199 builder.append("right=").append(right).append('\n'); 1200 1201 final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService( 1202 Context.DROPBOX_SERVICE); 1203 dropBox.addText(TAG_NETSTATS_ERROR, builder.toString()); 1204 } 1205 } 1206 1207 /** 1208 * Default external settings that read from 1209 * {@link android.provider.Settings.Secure}. 1210 */ 1211 private static class DefaultNetworkStatsSettings implements NetworkStatsSettings { 1212 private final ContentResolver mResolver; 1213 1214 public DefaultNetworkStatsSettings(Context context) { 1215 mResolver = checkNotNull(context.getContentResolver()); 1216 // TODO: adjust these timings for production builds 1217 } 1218 1219 private long getSecureLong(String name, long def) { 1220 return Settings.Secure.getLong(mResolver, name, def); 1221 } 1222 private boolean getSecureBoolean(String name, boolean def) { 1223 final int defInt = def ? 1 : 0; 1224 return Settings.Secure.getInt(mResolver, name, defInt) != 0; 1225 } 1226 1227 @Override 1228 public long getPollInterval() { 1229 return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); 1230 } 1231 @Override 1232 public long getTimeCacheMaxAge() { 1233 return getSecureLong(NETSTATS_TIME_CACHE_MAX_AGE, DAY_IN_MILLIS); 1234 } 1235 @Override 1236 public long getGlobalAlertBytes(long def) { 1237 return getSecureLong(NETSTATS_GLOBAL_ALERT_BYTES, def); 1238 } 1239 @Override 1240 public boolean getSampleEnabled() { 1241 return getSecureBoolean(NETSTATS_SAMPLE_ENABLED, true); 1242 } 1243 @Override 1244 public boolean getReportXtOverDev() { 1245 return getSecureBoolean(NETSTATS_REPORT_XT_OVER_DEV, true); 1246 } 1247 @Override 1248 public Config getDevConfig() { 1249 return new Config(getSecureLong(NETSTATS_DEV_BUCKET_DURATION, HOUR_IN_MILLIS), 1250 getSecureLong(NETSTATS_DEV_ROTATE_AGE, 15 * DAY_IN_MILLIS), 1251 getSecureLong(NETSTATS_DEV_DELETE_AGE, 90 * DAY_IN_MILLIS)); 1252 } 1253 @Override 1254 public Config getXtConfig() { 1255 return getDevConfig(); 1256 } 1257 @Override 1258 public Config getUidConfig() { 1259 return new Config(getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), 1260 getSecureLong(NETSTATS_UID_ROTATE_AGE, 15 * DAY_IN_MILLIS), 1261 getSecureLong(NETSTATS_UID_DELETE_AGE, 90 * DAY_IN_MILLIS)); 1262 } 1263 @Override 1264 public Config getUidTagConfig() { 1265 return new Config(getSecureLong(NETSTATS_UID_TAG_BUCKET_DURATION, 2 * HOUR_IN_MILLIS), 1266 getSecureLong(NETSTATS_UID_TAG_ROTATE_AGE, 5 * DAY_IN_MILLIS), 1267 getSecureLong(NETSTATS_UID_TAG_DELETE_AGE, 15 * DAY_IN_MILLIS)); 1268 } 1269 @Override 1270 public long getDevPersistBytes(long def) { 1271 return getSecureLong(NETSTATS_DEV_PERSIST_BYTES, def); 1272 } 1273 @Override 1274 public long getXtPersistBytes(long def) { 1275 return getDevPersistBytes(def); 1276 } 1277 @Override 1278 public long getUidPersistBytes(long def) { 1279 return getSecureLong(NETSTATS_UID_PERSIST_BYTES, def); 1280 } 1281 @Override 1282 public long getUidTagPersistBytes(long def) { 1283 return getSecureLong(NETSTATS_UID_TAG_PERSIST_BYTES, def); 1284 } 1285 } 1286 } 1287