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