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