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