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