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