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