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