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