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