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.EXTRA_UID; 27 import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; 28 import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; 29 import static android.net.NetworkStats.IFACE_ALL; 30 import static android.net.NetworkStats.SET_ALL; 31 import static android.net.NetworkStats.SET_DEFAULT; 32 import static android.net.NetworkStats.SET_FOREGROUND; 33 import static android.net.NetworkStats.TAG_NONE; 34 import static android.net.NetworkStats.UID_ALL; 35 import static android.net.NetworkStatsHistory.randomLong; 36 import static android.net.NetworkTemplate.buildTemplateMobileAll; 37 import static android.net.NetworkTemplate.buildTemplateWifi; 38 import static android.net.TrafficStats.UID_REMOVED; 39 import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; 40 import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; 41 import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD; 42 import static android.provider.Settings.Secure.NETSTATS_POLL_INTERVAL; 43 import static android.provider.Settings.Secure.NETSTATS_TAG_MAX_HISTORY; 44 import static android.provider.Settings.Secure.NETSTATS_UID_BUCKET_DURATION; 45 import static android.provider.Settings.Secure.NETSTATS_UID_MAX_HISTORY; 46 import static android.telephony.PhoneStateListener.LISTEN_DATA_CONNECTION_STATE; 47 import static android.telephony.PhoneStateListener.LISTEN_NONE; 48 import static android.text.format.DateUtils.DAY_IN_MILLIS; 49 import static android.text.format.DateUtils.HOUR_IN_MILLIS; 50 import static android.text.format.DateUtils.MINUTE_IN_MILLIS; 51 import static android.text.format.DateUtils.SECOND_IN_MILLIS; 52 import static android.text.format.DateUtils.WEEK_IN_MILLIS; 53 import static com.android.internal.util.Preconditions.checkNotNull; 54 import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT; 55 import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats; 56 import static com.android.server.NetworkManagementSocketTagger.setKernelCounterSet; 57 58 import android.app.AlarmManager; 59 import android.app.IAlarmManager; 60 import android.app.PendingIntent; 61 import android.content.BroadcastReceiver; 62 import android.content.ContentResolver; 63 import android.content.Context; 64 import android.content.Intent; 65 import android.content.IntentFilter; 66 import android.content.pm.ApplicationInfo; 67 import android.content.pm.PackageManager; 68 import android.content.pm.PackageManager.NameNotFoundException; 69 import android.net.IConnectivityManager; 70 import android.net.INetworkManagementEventObserver; 71 import android.net.INetworkStatsService; 72 import android.net.NetworkIdentity; 73 import android.net.NetworkInfo; 74 import android.net.NetworkState; 75 import android.net.NetworkStats; 76 import android.net.NetworkStatsHistory; 77 import android.net.NetworkTemplate; 78 import android.os.Binder; 79 import android.os.Environment; 80 import android.os.Handler; 81 import android.os.HandlerThread; 82 import android.os.INetworkManagementService; 83 import android.os.Message; 84 import android.os.PowerManager; 85 import android.os.RemoteException; 86 import android.os.SystemClock; 87 import android.provider.Settings; 88 import android.telephony.PhoneStateListener; 89 import android.telephony.TelephonyManager; 90 import android.util.EventLog; 91 import android.util.Log; 92 import android.util.NtpTrustedTime; 93 import android.util.Slog; 94 import android.util.SparseIntArray; 95 import android.util.TrustedTime; 96 97 import com.android.internal.os.AtomicFile; 98 import com.android.internal.util.Objects; 99 import com.android.server.EventLogTags; 100 import com.android.server.connectivity.Tethering; 101 import com.google.android.collect.Lists; 102 import com.google.android.collect.Maps; 103 import com.google.android.collect.Sets; 104 105 import java.io.BufferedInputStream; 106 import java.io.BufferedOutputStream; 107 import java.io.DataInputStream; 108 import java.io.DataOutputStream; 109 import java.io.File; 110 import java.io.FileDescriptor; 111 import java.io.FileNotFoundException; 112 import java.io.FileOutputStream; 113 import java.io.IOException; 114 import java.io.PrintWriter; 115 import java.net.ProtocolException; 116 import java.util.ArrayList; 117 import java.util.Collections; 118 import java.util.HashMap; 119 import java.util.HashSet; 120 import java.util.Random; 121 122 import libcore.io.IoUtils; 123 124 /** 125 * Collect and persist detailed network statistics, and provide this data to 126 * other system services. 127 */ 128 public class NetworkStatsService extends INetworkStatsService.Stub { 129 private static final String TAG = "NetworkStats"; 130 private static final boolean LOGD = false; 131 private static final boolean LOGV = false; 132 133 /** File header magic number: "ANET" */ 134 private static final int FILE_MAGIC = 0x414E4554; 135 private static final int VERSION_NETWORK_INIT = 1; 136 private static final int VERSION_UID_INIT = 1; 137 private static final int VERSION_UID_WITH_IDENT = 2; 138 private static final int VERSION_UID_WITH_TAG = 3; 139 private static final int VERSION_UID_WITH_SET = 4; 140 141 private static final int MSG_PERFORM_POLL = 1; 142 private static final int MSG_UPDATE_IFACES = 2; 143 144 /** Flags to control detail level of poll event. */ 145 private static final int FLAG_PERSIST_NETWORK = 0x1; 146 private static final int FLAG_PERSIST_UID = 0x2; 147 private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; 148 private static final int FLAG_PERSIST_FORCE = 0x100; 149 150 /** Sample recent usage after each poll event. */ 151 private static final boolean ENABLE_SAMPLE_AFTER_POLL = true; 152 153 private final Context mContext; 154 private final INetworkManagementService mNetworkManager; 155 private final IAlarmManager mAlarmManager; 156 private final TrustedTime mTime; 157 private final TelephonyManager mTeleManager; 158 private final NetworkStatsSettings mSettings; 159 160 private final PowerManager.WakeLock mWakeLock; 161 162 private IConnectivityManager mConnManager; 163 164 // @VisibleForTesting 165 public static final String ACTION_NETWORK_STATS_POLL = 166 "com.android.server.action.NETWORK_STATS_POLL"; 167 public static final String ACTION_NETWORK_STATS_UPDATED = 168 "com.android.server.action.NETWORK_STATS_UPDATED"; 169 170 private PendingIntent mPollIntent; 171 172 // TODO: trim empty history objects entirely 173 174 private static final long KB_IN_BYTES = 1024; 175 private static final long MB_IN_BYTES = 1024 * KB_IN_BYTES; 176 private static final long GB_IN_BYTES = 1024 * MB_IN_BYTES; 177 178 /** 179 * Settings that can be changed externally. 180 */ 181 public interface NetworkStatsSettings { 182 public long getPollInterval(); 183 public long getPersistThreshold(); 184 public long getNetworkBucketDuration(); 185 public long getNetworkMaxHistory(); 186 public long getUidBucketDuration(); 187 public long getUidMaxHistory(); 188 public long getTagMaxHistory(); 189 public long getTimeCacheMaxAge(); 190 } 191 192 private final Object mStatsLock = new Object(); 193 194 /** Set of currently active ifaces. */ 195 private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap(); 196 /** Set of historical {@code dev} stats for known networks. */ 197 private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkDevStats = Maps.newHashMap(); 198 /** Set of historical {@code xtables} stats for known networks. */ 199 private HashMap<NetworkIdentitySet, NetworkStatsHistory> mNetworkXtStats = Maps.newHashMap(); 200 /** Set of historical {@code xtables} stats for known UIDs. */ 201 private HashMap<UidStatsKey, NetworkStatsHistory> mUidStats = Maps.newHashMap(); 202 203 /** Flag if {@link #mUidStats} have been loaded from disk. */ 204 private boolean mUidStatsLoaded = false; 205 206 private NetworkStats mLastPollNetworkDevSnapshot; 207 private NetworkStats mLastPollNetworkXtSnapshot; 208 private NetworkStats mLastPollUidSnapshot; 209 private NetworkStats mLastPollOperationsSnapshot; 210 211 private NetworkStats mLastPersistNetworkDevSnapshot; 212 private NetworkStats mLastPersistNetworkXtSnapshot; 213 private NetworkStats mLastPersistUidSnapshot; 214 215 /** Current counter sets for each UID. */ 216 private SparseIntArray mActiveUidCounterSet = new SparseIntArray(); 217 218 /** Data layer operation counters for splicing into other structures. */ 219 private NetworkStats mOperations = new NetworkStats(0L, 10); 220 221 private final HandlerThread mHandlerThread; 222 private final Handler mHandler; 223 224 private final AtomicFile mNetworkDevFile; 225 private final AtomicFile mNetworkXtFile; 226 private final AtomicFile mUidFile; 227 228 public NetworkStatsService( 229 Context context, INetworkManagementService networkManager, IAlarmManager alarmManager) { 230 this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context), 231 getSystemDir(), new DefaultNetworkStatsSettings(context)); 232 } 233 234 private static File getSystemDir() { 235 return new File(Environment.getDataDirectory(), "system"); 236 } 237 238 public NetworkStatsService(Context context, INetworkManagementService networkManager, 239 IAlarmManager alarmManager, TrustedTime time, File systemDir, 240 NetworkStatsSettings settings) { 241 mContext = checkNotNull(context, "missing Context"); 242 mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService"); 243 mAlarmManager = checkNotNull(alarmManager, "missing IAlarmManager"); 244 mTime = checkNotNull(time, "missing TrustedTime"); 245 mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager"); 246 mSettings = checkNotNull(settings, "missing NetworkStatsSettings"); 247 248 final PowerManager powerManager = (PowerManager) context.getSystemService( 249 Context.POWER_SERVICE); 250 mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG); 251 252 mHandlerThread = new HandlerThread(TAG); 253 mHandlerThread.start(); 254 mHandler = new Handler(mHandlerThread.getLooper(), mHandlerCallback); 255 256 mNetworkDevFile = new AtomicFile(new File(systemDir, "netstats.bin")); 257 mNetworkXtFile = new AtomicFile(new File(systemDir, "netstats_xt.bin")); 258 mUidFile = new AtomicFile(new File(systemDir, "netstats_uid.bin")); 259 } 260 261 public void bindConnectivityManager(IConnectivityManager connManager) { 262 mConnManager = checkNotNull(connManager, "missing IConnectivityManager"); 263 } 264 265 public void systemReady() { 266 synchronized (mStatsLock) { 267 // read historical network stats from disk, since policy service 268 // might need them right away. we delay loading detailed UID stats 269 // until actually needed. 270 readNetworkDevStatsLocked(); 271 readNetworkXtStatsLocked(); 272 } 273 274 // watch for network interfaces to be claimed 275 final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); 276 mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); 277 278 // watch for tethering changes 279 final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED); 280 mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler); 281 282 // listen for periodic polling events 283 final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); 284 mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler); 285 286 // listen for uid removal to clean stats 287 final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED); 288 mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler); 289 290 // persist stats during clean shutdown 291 final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN); 292 mContext.registerReceiver(mShutdownReceiver, shutdownFilter); 293 294 try { 295 mNetworkManager.registerObserver(mAlertObserver); 296 } catch (RemoteException e) { 297 // ignored; service lives in system_server 298 } 299 300 // watch for networkType changes that aren't broadcast through 301 // CONNECTIVITY_ACTION_IMMEDIATE above. 302 mTeleManager.listen(mPhoneListener, LISTEN_DATA_CONNECTION_STATE); 303 304 registerPollAlarmLocked(); 305 registerGlobalAlert(); 306 307 // bootstrap initial stats to prevent double-counting later 308 bootstrapStats(); 309 } 310 311 private void shutdownLocked() { 312 mContext.unregisterReceiver(mConnReceiver); 313 mContext.unregisterReceiver(mTetherReceiver); 314 mContext.unregisterReceiver(mPollReceiver); 315 mContext.unregisterReceiver(mRemovedReceiver); 316 mContext.unregisterReceiver(mShutdownReceiver); 317 318 mTeleManager.listen(mPhoneListener, LISTEN_NONE); 319 320 writeNetworkDevStatsLocked(); 321 writeNetworkXtStatsLocked(); 322 if (mUidStatsLoaded) { 323 writeUidStatsLocked(); 324 } 325 mNetworkDevStats.clear(); 326 mNetworkXtStats.clear(); 327 mUidStats.clear(); 328 mUidStatsLoaded = false; 329 } 330 331 /** 332 * Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and 333 * reschedule based on current {@link NetworkStatsSettings#getPollInterval()}. 334 */ 335 private void registerPollAlarmLocked() { 336 try { 337 if (mPollIntent != null) { 338 mAlarmManager.remove(mPollIntent); 339 } 340 341 mPollIntent = PendingIntent.getBroadcast( 342 mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0); 343 344 final long currentRealtime = SystemClock.elapsedRealtime(); 345 mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime, 346 mSettings.getPollInterval(), mPollIntent); 347 } catch (RemoteException e) { 348 // ignored; service lives in system_server 349 } 350 } 351 352 /** 353 * Register for a global alert that is delivered through 354 * {@link INetworkManagementEventObserver} once a threshold amount of data 355 * has been transferred. 356 */ 357 private void registerGlobalAlert() { 358 try { 359 final long alertBytes = mSettings.getPersistThreshold(); 360 mNetworkManager.setGlobalAlert(alertBytes); 361 } catch (IllegalStateException e) { 362 Slog.w(TAG, "problem registering for global alert: " + e); 363 } catch (RemoteException e) { 364 // ignored; service lives in system_server 365 } 366 } 367 368 @Override 369 public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) { 370 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); 371 return getHistoryForNetworkDev(template, fields); 372 } 373 374 private NetworkStatsHistory getHistoryForNetworkDev(NetworkTemplate template, int fields) { 375 return getHistoryForNetwork(template, fields, mNetworkDevStats); 376 } 377 378 private NetworkStatsHistory getHistoryForNetworkXt(NetworkTemplate template, int fields) { 379 return getHistoryForNetwork(template, fields, mNetworkXtStats); 380 } 381 382 private NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields, 383 HashMap<NetworkIdentitySet, NetworkStatsHistory> source) { 384 synchronized (mStatsLock) { 385 // combine all interfaces that match template 386 final NetworkStatsHistory combined = new NetworkStatsHistory( 387 mSettings.getNetworkBucketDuration(), estimateNetworkBuckets(), fields); 388 for (NetworkIdentitySet ident : source.keySet()) { 389 if (templateMatches(template, ident)) { 390 final NetworkStatsHistory history = source.get(ident); 391 if (history != null) { 392 combined.recordEntireHistory(history); 393 } 394 } 395 } 396 return combined; 397 } 398 } 399 400 @Override 401 public NetworkStatsHistory getHistoryForUid( 402 NetworkTemplate template, int uid, int set, int tag, int fields) { 403 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); 404 405 synchronized (mStatsLock) { 406 ensureUidStatsLoadedLocked(); 407 408 // combine all interfaces that match template 409 final NetworkStatsHistory combined = new NetworkStatsHistory( 410 mSettings.getUidBucketDuration(), estimateUidBuckets(), fields); 411 for (UidStatsKey key : mUidStats.keySet()) { 412 final boolean setMatches = set == SET_ALL || key.set == set; 413 if (templateMatches(template, key.ident) && key.uid == uid && setMatches 414 && key.tag == tag) { 415 final NetworkStatsHistory history = mUidStats.get(key); 416 combined.recordEntireHistory(history); 417 } 418 } 419 420 return combined; 421 } 422 } 423 424 @Override 425 public NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end) { 426 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); 427 return getSummaryForNetworkDev(template, start, end); 428 } 429 430 private NetworkStats getSummaryForNetworkDev(NetworkTemplate template, long start, long end) { 431 return getSummaryForNetwork(template, start, end, mNetworkDevStats); 432 } 433 434 private NetworkStats getSummaryForNetworkXt(NetworkTemplate template, long start, long end) { 435 return getSummaryForNetwork(template, start, end, mNetworkXtStats); 436 } 437 438 private NetworkStats getSummaryForNetwork(NetworkTemplate template, long start, long end, 439 HashMap<NetworkIdentitySet, NetworkStatsHistory> source) { 440 synchronized (mStatsLock) { 441 // use system clock to be externally consistent 442 final long now = System.currentTimeMillis(); 443 444 final NetworkStats stats = new NetworkStats(end - start, 1); 445 final NetworkStats.Entry entry = new NetworkStats.Entry(); 446 NetworkStatsHistory.Entry historyEntry = null; 447 448 // combine total from all interfaces that match template 449 for (NetworkIdentitySet ident : source.keySet()) { 450 if (templateMatches(template, ident)) { 451 final NetworkStatsHistory history = source.get(ident); 452 historyEntry = history.getValues(start, end, now, historyEntry); 453 454 entry.iface = IFACE_ALL; 455 entry.uid = UID_ALL; 456 entry.tag = TAG_NONE; 457 entry.rxBytes = historyEntry.rxBytes; 458 entry.rxPackets = historyEntry.rxPackets; 459 entry.txBytes = historyEntry.txBytes; 460 entry.txPackets = historyEntry.txPackets; 461 462 stats.combineValues(entry); 463 } 464 } 465 466 return stats; 467 } 468 } 469 470 @Override 471 public NetworkStats getSummaryForAllUid( 472 NetworkTemplate template, long start, long end, boolean includeTags) { 473 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); 474 475 synchronized (mStatsLock) { 476 ensureUidStatsLoadedLocked(); 477 478 // use system clock to be externally consistent 479 final long now = System.currentTimeMillis(); 480 481 final NetworkStats stats = new NetworkStats(end - start, 24); 482 final NetworkStats.Entry entry = new NetworkStats.Entry(); 483 NetworkStatsHistory.Entry historyEntry = null; 484 485 for (UidStatsKey key : mUidStats.keySet()) { 486 if (templateMatches(template, key.ident)) { 487 // always include summary under TAG_NONE, and include 488 // other tags when requested. 489 if (key.tag == TAG_NONE || includeTags) { 490 final NetworkStatsHistory history = mUidStats.get(key); 491 historyEntry = history.getValues(start, end, now, historyEntry); 492 493 entry.iface = IFACE_ALL; 494 entry.uid = key.uid; 495 entry.set = key.set; 496 entry.tag = key.tag; 497 entry.rxBytes = historyEntry.rxBytes; 498 entry.rxPackets = historyEntry.rxPackets; 499 entry.txBytes = historyEntry.txBytes; 500 entry.txPackets = historyEntry.txPackets; 501 entry.operations = historyEntry.operations; 502 503 if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 504 || entry.txPackets > 0 || entry.operations > 0) { 505 stats.combineValues(entry); 506 } 507 } 508 } 509 } 510 511 return stats; 512 } 513 } 514 515 @Override 516 public NetworkStats getDataLayerSnapshotForUid(int uid) throws RemoteException { 517 if (Binder.getCallingUid() != uid) { 518 mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG); 519 } 520 521 // TODO: switch to data layer stats once kernel exports 522 // for now, read network layer stats and flatten across all ifaces 523 final NetworkStats networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid); 524 final NetworkStats dataLayer = new NetworkStats( 525 networkLayer.getElapsedRealtime(), networkLayer.size()); 526 527 NetworkStats.Entry entry = null; 528 for (int i = 0; i < networkLayer.size(); i++) { 529 entry = networkLayer.getValues(i, entry); 530 entry.iface = IFACE_ALL; 531 dataLayer.combineValues(entry); 532 } 533 534 // splice in operation counts 535 dataLayer.spliceOperationsFrom(mOperations); 536 return dataLayer; 537 } 538 539 @Override 540 public void incrementOperationCount(int uid, int tag, int operationCount) { 541 if (Binder.getCallingUid() != uid) { 542 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); 543 } 544 545 if (operationCount < 0) { 546 throw new IllegalArgumentException("operation count can only be incremented"); 547 } 548 if (tag == TAG_NONE) { 549 throw new IllegalArgumentException("operation count must have specific tag"); 550 } 551 552 synchronized (mStatsLock) { 553 final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT); 554 mOperations.combineValues(IFACE_ALL, uid, set, tag, 0L, 0L, 0L, 0L, operationCount); 555 mOperations.combineValues(IFACE_ALL, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount); 556 } 557 } 558 559 @Override 560 public void setUidForeground(int uid, boolean uidForeground) { 561 mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG); 562 563 synchronized (mStatsLock) { 564 final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT; 565 final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT); 566 if (oldSet != set) { 567 mActiveUidCounterSet.put(uid, set); 568 setKernelCounterSet(uid, set); 569 } 570 } 571 } 572 573 @Override 574 public void forceUpdate() { 575 mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG); 576 performPoll(FLAG_PERSIST_ALL); 577 } 578 579 /** 580 * Receiver that watches for {@link IConnectivityManager} to claim network 581 * interfaces. Used to associate {@link TelephonyManager#getSubscriberId()} 582 * with mobile interfaces. 583 */ 584 private BroadcastReceiver mConnReceiver = new BroadcastReceiver() { 585 @Override 586 public void onReceive(Context context, Intent intent) { 587 // on background handler thread, and verified CONNECTIVITY_INTERNAL 588 // permission above. 589 updateIfaces(); 590 } 591 }; 592 593 /** 594 * Receiver that watches for {@link Tethering} to claim interface pairs. 595 */ 596 private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() { 597 @Override 598 public void onReceive(Context context, Intent intent) { 599 // on background handler thread, and verified CONNECTIVITY_INTERNAL 600 // permission above. 601 performPoll(FLAG_PERSIST_NETWORK); 602 } 603 }; 604 605 private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { 606 @Override 607 public void onReceive(Context context, Intent intent) { 608 // on background handler thread, and verified UPDATE_DEVICE_STATS 609 // permission above. 610 performPoll(FLAG_PERSIST_ALL); 611 612 // verify that we're watching global alert 613 registerGlobalAlert(); 614 } 615 }; 616 617 private BroadcastReceiver mRemovedReceiver = new BroadcastReceiver() { 618 @Override 619 public void onReceive(Context context, Intent intent) { 620 // on background handler thread, and UID_REMOVED is protected 621 // broadcast. 622 final int uid = intent.getIntExtra(EXTRA_UID, 0); 623 synchronized (mStatsLock) { 624 // TODO: perform one last stats poll for UID 625 mWakeLock.acquire(); 626 try { 627 removeUidLocked(uid); 628 } finally { 629 mWakeLock.release(); 630 } 631 } 632 } 633 }; 634 635 private BroadcastReceiver mShutdownReceiver = new BroadcastReceiver() { 636 @Override 637 public void onReceive(Context context, Intent intent) { 638 // SHUTDOWN is protected broadcast. 639 synchronized (mStatsLock) { 640 shutdownLocked(); 641 } 642 } 643 }; 644 645 /** 646 * Observer that watches for {@link INetworkManagementService} alerts. 647 */ 648 private INetworkManagementEventObserver mAlertObserver = new NetworkAlertObserver() { 649 @Override 650 public void limitReached(String limitName, String iface) { 651 // only someone like NMS should be calling us 652 mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG); 653 654 if (LIMIT_GLOBAL_ALERT.equals(limitName)) { 655 // kick off background poll to collect network stats; UID stats 656 // are handled during normal polling interval. 657 final int flags = FLAG_PERSIST_NETWORK; 658 mHandler.obtainMessage(MSG_PERFORM_POLL, flags, 0).sendToTarget(); 659 660 // re-arm global alert for next update 661 registerGlobalAlert(); 662 } 663 } 664 }; 665 666 private int mLastPhoneState = TelephonyManager.DATA_UNKNOWN; 667 private int mLastPhoneNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN; 668 669 /** 670 * Receiver that watches for {@link TelephonyManager} changes, such as 671 * transitioning between network types. 672 */ 673 private PhoneStateListener mPhoneListener = new PhoneStateListener() { 674 @Override 675 public void onDataConnectionStateChanged(int state, int networkType) { 676 final boolean stateChanged = state != mLastPhoneState; 677 final boolean networkTypeChanged = networkType != mLastPhoneNetworkType; 678 679 if (networkTypeChanged && !stateChanged) { 680 // networkType changed without a state change, which means we 681 // need to roll our own update. delay long enough for 682 // ConnectivityManager to process. 683 // TODO: add direct event to ConnectivityService instead of 684 // relying on this delay. 685 if (LOGV) Slog.v(TAG, "triggering delayed updateIfaces()"); 686 mHandler.sendMessageDelayed( 687 mHandler.obtainMessage(MSG_UPDATE_IFACES), SECOND_IN_MILLIS); 688 } 689 690 mLastPhoneState = state; 691 mLastPhoneNetworkType = networkType; 692 } 693 }; 694 695 private void updateIfaces() { 696 synchronized (mStatsLock) { 697 mWakeLock.acquire(); 698 try { 699 updateIfacesLocked(); 700 } finally { 701 mWakeLock.release(); 702 } 703 } 704 } 705 706 /** 707 * Inspect all current {@link NetworkState} to derive mapping from {@code 708 * iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo} 709 * are active on a single {@code iface}, they are combined under a single 710 * {@link NetworkIdentitySet}. 711 */ 712 private void updateIfacesLocked() { 713 if (LOGV) Slog.v(TAG, "updateIfacesLocked()"); 714 715 // take one last stats snapshot before updating iface mapping. this 716 // isn't perfect, since the kernel may already be counting traffic from 717 // the updated network. 718 719 // poll, but only persist network stats to keep codepath fast. UID stats 720 // will be persisted during next alarm poll event. 721 performPollLocked(FLAG_PERSIST_NETWORK); 722 723 final NetworkState[] states; 724 try { 725 states = mConnManager.getAllNetworkState(); 726 } catch (RemoteException e) { 727 // ignored; service lives in system_server 728 return; 729 } 730 731 // rebuild active interfaces based on connected networks 732 mActiveIfaces.clear(); 733 734 for (NetworkState state : states) { 735 if (state.networkInfo.isConnected()) { 736 // collect networks under their parent interfaces 737 final String iface = state.linkProperties.getInterfaceName(); 738 739 NetworkIdentitySet ident = mActiveIfaces.get(iface); 740 if (ident == null) { 741 ident = new NetworkIdentitySet(); 742 mActiveIfaces.put(iface, ident); 743 } 744 745 ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state)); 746 } 747 } 748 } 749 750 /** 751 * Bootstrap initial stats snapshot, usually during {@link #systemReady()} 752 * so we have baseline values without double-counting. 753 */ 754 private void bootstrapStats() { 755 try { 756 mLastPollUidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); 757 mLastPollNetworkDevSnapshot = mNetworkManager.getNetworkStatsSummary(); 758 mLastPollNetworkXtSnapshot = computeNetworkXtSnapshotFromUid(mLastPollUidSnapshot); 759 mLastPollOperationsSnapshot = new NetworkStats(0L, 0); 760 } catch (IllegalStateException e) { 761 Slog.w(TAG, "problem reading network stats: " + e); 762 } catch (RemoteException e) { 763 // ignored; service lives in system_server 764 } 765 } 766 767 private void performPoll(int flags) { 768 synchronized (mStatsLock) { 769 mWakeLock.acquire(); 770 try { 771 performPollLocked(flags); 772 } finally { 773 mWakeLock.release(); 774 } 775 } 776 } 777 778 /** 779 * Periodic poll operation, reading current statistics and recording into 780 * {@link NetworkStatsHistory}. 781 */ 782 private void performPollLocked(int flags) { 783 if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")"); 784 final long startRealtime = SystemClock.elapsedRealtime(); 785 786 final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; 787 final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0; 788 final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0; 789 790 // try refreshing time source when stale 791 if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) { 792 mTime.forceRefresh(); 793 } 794 795 // TODO: consider marking "untrusted" times in historical stats 796 final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis() 797 : System.currentTimeMillis(); 798 final long threshold = mSettings.getPersistThreshold(); 799 800 final NetworkStats uidSnapshot; 801 final NetworkStats networkXtSnapshot; 802 final NetworkStats networkDevSnapshot; 803 try { 804 // collect any tethering stats 805 final String[] tetheredIfacePairs = mConnManager.getTetheredIfacePairs(); 806 final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( 807 tetheredIfacePairs); 808 809 // record uid stats, folding in tethering stats 810 uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); 811 uidSnapshot.combineAllValues(tetherSnapshot); 812 performUidPollLocked(uidSnapshot, currentTime); 813 814 // record dev network stats 815 networkDevSnapshot = mNetworkManager.getNetworkStatsSummary(); 816 performNetworkDevPollLocked(networkDevSnapshot, currentTime); 817 818 // record xt network stats 819 networkXtSnapshot = computeNetworkXtSnapshotFromUid(uidSnapshot); 820 performNetworkXtPollLocked(networkXtSnapshot, currentTime); 821 822 } catch (IllegalStateException e) { 823 Log.wtf(TAG, "problem reading network stats", e); 824 return; 825 } catch (RemoteException e) { 826 // ignored; service lives in system_server 827 return; 828 } 829 830 // persist when enough network data has occurred 831 final long persistNetworkDevDelta = computeStatsDelta( 832 mLastPersistNetworkDevSnapshot, networkDevSnapshot, true).getTotalBytes(); 833 final long persistNetworkXtDelta = computeStatsDelta( 834 mLastPersistNetworkXtSnapshot, networkXtSnapshot, true).getTotalBytes(); 835 final boolean networkOverThreshold = persistNetworkDevDelta > threshold 836 || persistNetworkXtDelta > threshold; 837 if (persistForce || (persistNetwork && networkOverThreshold)) { 838 writeNetworkDevStatsLocked(); 839 writeNetworkXtStatsLocked(); 840 mLastPersistNetworkDevSnapshot = networkDevSnapshot; 841 mLastPersistNetworkXtSnapshot = networkXtSnapshot; 842 } 843 844 // persist when enough uid data has occurred 845 final long persistUidDelta = computeStatsDelta(mLastPersistUidSnapshot, uidSnapshot, true) 846 .getTotalBytes(); 847 if (persistForce || (persistUid && persistUidDelta > threshold)) { 848 writeUidStatsLocked(); 849 mLastPersistUidSnapshot = uidSnapshot; 850 } 851 852 if (LOGV) { 853 final long duration = SystemClock.elapsedRealtime() - startRealtime; 854 Slog.v(TAG, "performPollLocked() took " + duration + "ms"); 855 } 856 857 if (ENABLE_SAMPLE_AFTER_POLL) { 858 // sample stats after each full poll 859 performSample(); 860 } 861 862 // finally, dispatch updated event to any listeners 863 final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED); 864 updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY); 865 mContext.sendBroadcast(updatedIntent, READ_NETWORK_USAGE_HISTORY); 866 } 867 868 /** 869 * Update {@link #mNetworkDevStats} historical usage. 870 */ 871 private void performNetworkDevPollLocked(NetworkStats networkDevSnapshot, long currentTime) { 872 final HashSet<String> unknownIface = Sets.newHashSet(); 873 874 final NetworkStats delta = computeStatsDelta( 875 mLastPollNetworkDevSnapshot, networkDevSnapshot, false); 876 final long timeStart = currentTime - delta.getElapsedRealtime(); 877 878 NetworkStats.Entry entry = null; 879 for (int i = 0; i < delta.size(); i++) { 880 entry = delta.getValues(i, entry); 881 final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); 882 if (ident == null) { 883 unknownIface.add(entry.iface); 884 continue; 885 } 886 887 final NetworkStatsHistory history = findOrCreateNetworkDevStatsLocked(ident); 888 history.recordData(timeStart, currentTime, entry); 889 } 890 891 mLastPollNetworkDevSnapshot = networkDevSnapshot; 892 893 if (LOGD && unknownIface.size() > 0) { 894 Slog.w(TAG, "unknown dev interfaces " + unknownIface + ", ignoring those stats"); 895 } 896 } 897 898 /** 899 * Update {@link #mNetworkXtStats} historical usage. 900 */ 901 private void performNetworkXtPollLocked(NetworkStats networkXtSnapshot, long currentTime) { 902 final HashSet<String> unknownIface = Sets.newHashSet(); 903 904 final NetworkStats delta = computeStatsDelta( 905 mLastPollNetworkXtSnapshot, networkXtSnapshot, false); 906 final long timeStart = currentTime - delta.getElapsedRealtime(); 907 908 NetworkStats.Entry entry = null; 909 for (int i = 0; i < delta.size(); i++) { 910 entry = delta.getValues(i, entry); 911 final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); 912 if (ident == null) { 913 unknownIface.add(entry.iface); 914 continue; 915 } 916 917 final NetworkStatsHistory history = findOrCreateNetworkXtStatsLocked(ident); 918 history.recordData(timeStart, currentTime, entry); 919 } 920 921 mLastPollNetworkXtSnapshot = networkXtSnapshot; 922 923 if (LOGD && unknownIface.size() > 0) { 924 Slog.w(TAG, "unknown xt interfaces " + unknownIface + ", ignoring those stats"); 925 } 926 } 927 928 /** 929 * Update {@link #mUidStats} historical usage. 930 */ 931 private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) { 932 ensureUidStatsLoadedLocked(); 933 934 final NetworkStats delta = computeStatsDelta(mLastPollUidSnapshot, uidSnapshot, false); 935 final NetworkStats operationsDelta = computeStatsDelta( 936 mLastPollOperationsSnapshot, mOperations, false); 937 final long timeStart = currentTime - delta.getElapsedRealtime(); 938 939 NetworkStats.Entry entry = null; 940 NetworkStats.Entry operationsEntry = null; 941 for (int i = 0; i < delta.size(); i++) { 942 entry = delta.getValues(i, entry); 943 final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); 944 if (ident == null) { 945 if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 946 || entry.txPackets > 0) { 947 Log.w(TAG, "dropping UID delta from unknown iface: " + entry); 948 } 949 continue; 950 } 951 952 // splice in operation counts since last poll 953 final int j = operationsDelta.findIndex(IFACE_ALL, entry.uid, entry.set, entry.tag); 954 if (j != -1) { 955 operationsEntry = operationsDelta.getValues(j, operationsEntry); 956 entry.operations = operationsEntry.operations; 957 } 958 959 final NetworkStatsHistory history = findOrCreateUidStatsLocked( 960 ident, entry.uid, entry.set, entry.tag); 961 history.recordData(timeStart, currentTime, entry); 962 } 963 964 mLastPollUidSnapshot = uidSnapshot; 965 mLastPollOperationsSnapshot = mOperations; 966 mOperations = new NetworkStats(0L, 10); 967 } 968 969 /** 970 * Sample recent statistics summary into {@link EventLog}. 971 */ 972 private void performSample() { 973 final long largestBucketSize = Math.max( 974 mSettings.getNetworkBucketDuration(), mSettings.getUidBucketDuration()); 975 976 // take sample as atomic buckets 977 final long now = mTime.hasCache() ? mTime.currentTimeMillis() : System.currentTimeMillis(); 978 final long end = now - (now % largestBucketSize) + largestBucketSize; 979 final long start = end - largestBucketSize; 980 981 final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1; 982 983 NetworkTemplate template = null; 984 NetworkStats.Entry devTotal = null; 985 NetworkStats.Entry xtTotal = null; 986 NetworkStats.Entry uidTotal = null; 987 988 // collect mobile sample 989 template = buildTemplateMobileAll(getActiveSubscriberId(mContext)); 990 devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal); 991 xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal); 992 uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal); 993 EventLogTags.writeNetstatsMobileSample( 994 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, 995 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, 996 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, 997 trustedTime); 998 999 // collect wifi sample 1000 template = buildTemplateWifi(); 1001 devTotal = getSummaryForNetworkDev(template, start, end).getTotal(devTotal); 1002 xtTotal = getSummaryForNetworkXt(template, start, end).getTotal(xtTotal); 1003 uidTotal = getSummaryForAllUid(template, start, end, false).getTotal(uidTotal); 1004 EventLogTags.writeNetstatsWifiSample( 1005 devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets, 1006 xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets, 1007 uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets, 1008 trustedTime); 1009 } 1010 1011 /** 1012 * Clean up {@link #mUidStats} after UID is removed. 1013 */ 1014 private void removeUidLocked(int uid) { 1015 ensureUidStatsLoadedLocked(); 1016 1017 final ArrayList<UidStatsKey> knownKeys = Lists.newArrayList(); 1018 knownKeys.addAll(mUidStats.keySet()); 1019 1020 // migrate all UID stats into special "removed" bucket 1021 for (UidStatsKey key : knownKeys) { 1022 if (key.uid == uid) { 1023 // only migrate combined TAG_NONE history 1024 if (key.tag == TAG_NONE) { 1025 final NetworkStatsHistory uidHistory = mUidStats.get(key); 1026 final NetworkStatsHistory removedHistory = findOrCreateUidStatsLocked( 1027 key.ident, UID_REMOVED, SET_DEFAULT, TAG_NONE); 1028 removedHistory.recordEntireHistory(uidHistory); 1029 } 1030 mUidStats.remove(key); 1031 } 1032 } 1033 1034 // clear kernel stats associated with UID 1035 resetKernelUidStats(uid); 1036 1037 // since this was radical rewrite, push to disk 1038 writeUidStatsLocked(); 1039 } 1040 1041 private NetworkStatsHistory findOrCreateNetworkXtStatsLocked(NetworkIdentitySet ident) { 1042 return findOrCreateNetworkStatsLocked(ident, mNetworkXtStats); 1043 } 1044 1045 private NetworkStatsHistory findOrCreateNetworkDevStatsLocked(NetworkIdentitySet ident) { 1046 return findOrCreateNetworkStatsLocked(ident, mNetworkDevStats); 1047 } 1048 1049 private NetworkStatsHistory findOrCreateNetworkStatsLocked( 1050 NetworkIdentitySet ident, HashMap<NetworkIdentitySet, NetworkStatsHistory> source) { 1051 final NetworkStatsHistory existing = source.get(ident); 1052 1053 // update when no existing, or when bucket duration changed 1054 final long bucketDuration = mSettings.getNetworkBucketDuration(); 1055 NetworkStatsHistory updated = null; 1056 if (existing == null) { 1057 updated = new NetworkStatsHistory(bucketDuration, 10); 1058 } else if (existing.getBucketDuration() != bucketDuration) { 1059 updated = new NetworkStatsHistory( 1060 bucketDuration, estimateResizeBuckets(existing, bucketDuration)); 1061 updated.recordEntireHistory(existing); 1062 } 1063 1064 if (updated != null) { 1065 source.put(ident, updated); 1066 return updated; 1067 } else { 1068 return existing; 1069 } 1070 } 1071 1072 private NetworkStatsHistory findOrCreateUidStatsLocked( 1073 NetworkIdentitySet ident, int uid, int set, int tag) { 1074 ensureUidStatsLoadedLocked(); 1075 1076 final UidStatsKey key = new UidStatsKey(ident, uid, set, tag); 1077 final NetworkStatsHistory existing = mUidStats.get(key); 1078 1079 // update when no existing, or when bucket duration changed 1080 final long bucketDuration = mSettings.getUidBucketDuration(); 1081 NetworkStatsHistory updated = null; 1082 if (existing == null) { 1083 updated = new NetworkStatsHistory(bucketDuration, 10); 1084 } else if (existing.getBucketDuration() != bucketDuration) { 1085 updated = new NetworkStatsHistory( 1086 bucketDuration, estimateResizeBuckets(existing, bucketDuration)); 1087 updated.recordEntireHistory(existing); 1088 } 1089 1090 if (updated != null) { 1091 mUidStats.put(key, updated); 1092 return updated; 1093 } else { 1094 return existing; 1095 } 1096 } 1097 1098 private void readNetworkDevStatsLocked() { 1099 if (LOGV) Slog.v(TAG, "readNetworkDevStatsLocked()"); 1100 readNetworkStats(mNetworkDevFile, mNetworkDevStats); 1101 } 1102 1103 private void readNetworkXtStatsLocked() { 1104 if (LOGV) Slog.v(TAG, "readNetworkXtStatsLocked()"); 1105 readNetworkStats(mNetworkXtFile, mNetworkXtStats); 1106 } 1107 1108 private static void readNetworkStats( 1109 AtomicFile inputFile, HashMap<NetworkIdentitySet, NetworkStatsHistory> output) { 1110 // clear any existing stats and read from disk 1111 output.clear(); 1112 1113 DataInputStream in = null; 1114 try { 1115 in = new DataInputStream(new BufferedInputStream(inputFile.openRead())); 1116 1117 // verify file magic header intact 1118 final int magic = in.readInt(); 1119 if (magic != FILE_MAGIC) { 1120 throw new ProtocolException("unexpected magic: " + magic); 1121 } 1122 1123 final int version = in.readInt(); 1124 switch (version) { 1125 case VERSION_NETWORK_INIT: { 1126 // network := size *(NetworkIdentitySet NetworkStatsHistory) 1127 final int size = in.readInt(); 1128 for (int i = 0; i < size; i++) { 1129 final NetworkIdentitySet ident = new NetworkIdentitySet(in); 1130 final NetworkStatsHistory history = new NetworkStatsHistory(in); 1131 output.put(ident, history); 1132 } 1133 break; 1134 } 1135 default: { 1136 throw new ProtocolException("unexpected version: " + version); 1137 } 1138 } 1139 } catch (FileNotFoundException e) { 1140 // missing stats is okay, probably first boot 1141 } catch (IOException e) { 1142 Log.wtf(TAG, "problem reading network stats", e); 1143 } finally { 1144 IoUtils.closeQuietly(in); 1145 } 1146 } 1147 1148 private void ensureUidStatsLoadedLocked() { 1149 if (!mUidStatsLoaded) { 1150 readUidStatsLocked(); 1151 mUidStatsLoaded = true; 1152 } 1153 } 1154 1155 private void readUidStatsLocked() { 1156 if (LOGV) Slog.v(TAG, "readUidStatsLocked()"); 1157 1158 // clear any existing stats and read from disk 1159 mUidStats.clear(); 1160 1161 DataInputStream in = null; 1162 try { 1163 in = new DataInputStream(new BufferedInputStream(mUidFile.openRead())); 1164 1165 // verify file magic header intact 1166 final int magic = in.readInt(); 1167 if (magic != FILE_MAGIC) { 1168 throw new ProtocolException("unexpected magic: " + magic); 1169 } 1170 1171 final int version = in.readInt(); 1172 switch (version) { 1173 case VERSION_UID_INIT: { 1174 // uid := size *(UID NetworkStatsHistory) 1175 1176 // drop this data version, since we don't have a good 1177 // mapping into NetworkIdentitySet. 1178 break; 1179 } 1180 case VERSION_UID_WITH_IDENT: { 1181 // uid := size *(NetworkIdentitySet size *(UID NetworkStatsHistory)) 1182 1183 // drop this data version, since this version only existed 1184 // for a short time. 1185 break; 1186 } 1187 case VERSION_UID_WITH_TAG: 1188 case VERSION_UID_WITH_SET: { 1189 // uid := size *(NetworkIdentitySet size *(uid set tag NetworkStatsHistory)) 1190 final int identSize = in.readInt(); 1191 for (int i = 0; i < identSize; i++) { 1192 final NetworkIdentitySet ident = new NetworkIdentitySet(in); 1193 1194 final int size = in.readInt(); 1195 for (int j = 0; j < size; j++) { 1196 final int uid = in.readInt(); 1197 final int set = (version >= VERSION_UID_WITH_SET) ? in.readInt() 1198 : SET_DEFAULT; 1199 final int tag = in.readInt(); 1200 1201 final UidStatsKey key = new UidStatsKey(ident, uid, set, tag); 1202 final NetworkStatsHistory history = new NetworkStatsHistory(in); 1203 mUidStats.put(key, history); 1204 } 1205 } 1206 break; 1207 } 1208 default: { 1209 throw new ProtocolException("unexpected version: " + version); 1210 } 1211 } 1212 } catch (FileNotFoundException e) { 1213 // missing stats is okay, probably first boot 1214 } catch (IOException e) { 1215 Log.wtf(TAG, "problem reading uid stats", e); 1216 } finally { 1217 IoUtils.closeQuietly(in); 1218 } 1219 } 1220 1221 private void writeNetworkDevStatsLocked() { 1222 if (LOGV) Slog.v(TAG, "writeNetworkDevStatsLocked()"); 1223 writeNetworkStats(mNetworkDevStats, mNetworkDevFile); 1224 } 1225 1226 private void writeNetworkXtStatsLocked() { 1227 if (LOGV) Slog.v(TAG, "writeNetworkXtStatsLocked()"); 1228 writeNetworkStats(mNetworkXtStats, mNetworkXtFile); 1229 } 1230 1231 private void writeNetworkStats( 1232 HashMap<NetworkIdentitySet, NetworkStatsHistory> input, AtomicFile outputFile) { 1233 // TODO: consider duplicating stats and releasing lock while writing 1234 1235 // trim any history beyond max 1236 if (mTime.hasCache()) { 1237 final long currentTime = mTime.currentTimeMillis(); 1238 final long maxHistory = mSettings.getNetworkMaxHistory(); 1239 for (NetworkStatsHistory history : input.values()) { 1240 history.removeBucketsBefore(currentTime - maxHistory); 1241 } 1242 } 1243 1244 FileOutputStream fos = null; 1245 try { 1246 fos = outputFile.startWrite(); 1247 final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos)); 1248 1249 out.writeInt(FILE_MAGIC); 1250 out.writeInt(VERSION_NETWORK_INIT); 1251 1252 out.writeInt(input.size()); 1253 for (NetworkIdentitySet ident : input.keySet()) { 1254 final NetworkStatsHistory history = input.get(ident); 1255 ident.writeToStream(out); 1256 history.writeToStream(out); 1257 } 1258 1259 out.flush(); 1260 outputFile.finishWrite(fos); 1261 } catch (IOException e) { 1262 Log.wtf(TAG, "problem writing stats", e); 1263 if (fos != null) { 1264 outputFile.failWrite(fos); 1265 } 1266 } 1267 } 1268 1269 private void writeUidStatsLocked() { 1270 if (LOGV) Slog.v(TAG, "writeUidStatsLocked()"); 1271 1272 if (!mUidStatsLoaded) { 1273 Slog.w(TAG, "asked to write UID stats when not loaded; skipping"); 1274 return; 1275 } 1276 1277 // TODO: consider duplicating stats and releasing lock while writing 1278 1279 // trim any history beyond max 1280 if (mTime.hasCache()) { 1281 final long currentTime = mTime.currentTimeMillis(); 1282 final long maxUidHistory = mSettings.getUidMaxHistory(); 1283 final long maxTagHistory = mSettings.getTagMaxHistory(); 1284 for (UidStatsKey key : mUidStats.keySet()) { 1285 final NetworkStatsHistory history = mUidStats.get(key); 1286 1287 // detailed tags are trimmed sooner than summary in TAG_NONE 1288 if (key.tag == TAG_NONE) { 1289 history.removeBucketsBefore(currentTime - maxUidHistory); 1290 } else { 1291 history.removeBucketsBefore(currentTime - maxTagHistory); 1292 } 1293 } 1294 } 1295 1296 // build UidStatsKey lists grouped by ident 1297 final HashMap<NetworkIdentitySet, ArrayList<UidStatsKey>> keysByIdent = Maps.newHashMap(); 1298 for (UidStatsKey key : mUidStats.keySet()) { 1299 ArrayList<UidStatsKey> keys = keysByIdent.get(key.ident); 1300 if (keys == null) { 1301 keys = Lists.newArrayList(); 1302 keysByIdent.put(key.ident, keys); 1303 } 1304 keys.add(key); 1305 } 1306 1307 FileOutputStream fos = null; 1308 try { 1309 fos = mUidFile.startWrite(); 1310 final DataOutputStream out = new DataOutputStream(new BufferedOutputStream(fos)); 1311 1312 out.writeInt(FILE_MAGIC); 1313 out.writeInt(VERSION_UID_WITH_SET); 1314 1315 out.writeInt(keysByIdent.size()); 1316 for (NetworkIdentitySet ident : keysByIdent.keySet()) { 1317 final ArrayList<UidStatsKey> keys = keysByIdent.get(ident); 1318 ident.writeToStream(out); 1319 1320 out.writeInt(keys.size()); 1321 for (UidStatsKey key : keys) { 1322 final NetworkStatsHistory history = mUidStats.get(key); 1323 out.writeInt(key.uid); 1324 out.writeInt(key.set); 1325 out.writeInt(key.tag); 1326 history.writeToStream(out); 1327 } 1328 } 1329 1330 out.flush(); 1331 mUidFile.finishWrite(fos); 1332 } catch (IOException e) { 1333 Log.wtf(TAG, "problem writing stats", e); 1334 if (fos != null) { 1335 mUidFile.failWrite(fos); 1336 } 1337 } 1338 } 1339 1340 @Override 1341 protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) { 1342 mContext.enforceCallingOrSelfPermission(DUMP, TAG); 1343 1344 final HashSet<String> argSet = new HashSet<String>(); 1345 for (String arg : args) { 1346 argSet.add(arg); 1347 } 1348 1349 final boolean fullHistory = argSet.contains("full"); 1350 1351 synchronized (mStatsLock) { 1352 // TODO: remove this testing code, since it corrupts stats 1353 if (argSet.contains("generate")) { 1354 generateRandomLocked(args); 1355 pw.println("Generated stub stats"); 1356 return; 1357 } 1358 1359 if (argSet.contains("poll")) { 1360 performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE); 1361 pw.println("Forced poll"); 1362 return; 1363 } 1364 1365 pw.println("Active interfaces:"); 1366 for (String iface : mActiveIfaces.keySet()) { 1367 final NetworkIdentitySet ident = mActiveIfaces.get(iface); 1368 pw.print(" iface="); pw.print(iface); 1369 pw.print(" ident="); pw.println(ident.toString()); 1370 } 1371 1372 pw.println("Known historical dev stats:"); 1373 for (NetworkIdentitySet ident : mNetworkDevStats.keySet()) { 1374 final NetworkStatsHistory history = mNetworkDevStats.get(ident); 1375 pw.print(" ident="); pw.println(ident.toString()); 1376 history.dump(" ", pw, fullHistory); 1377 } 1378 1379 pw.println("Known historical xt stats:"); 1380 for (NetworkIdentitySet ident : mNetworkXtStats.keySet()) { 1381 final NetworkStatsHistory history = mNetworkXtStats.get(ident); 1382 pw.print(" ident="); pw.println(ident.toString()); 1383 history.dump(" ", pw, fullHistory); 1384 } 1385 1386 if (argSet.contains("detail")) { 1387 // since explicitly requested with argument, we're okay to load 1388 // from disk if not already in memory. 1389 ensureUidStatsLoadedLocked(); 1390 1391 final ArrayList<UidStatsKey> keys = Lists.newArrayList(); 1392 keys.addAll(mUidStats.keySet()); 1393 Collections.sort(keys); 1394 1395 pw.println("Detailed UID stats:"); 1396 for (UidStatsKey key : keys) { 1397 pw.print(" ident="); pw.print(key.ident.toString()); 1398 pw.print(" uid="); pw.print(key.uid); 1399 pw.print(" set="); pw.print(NetworkStats.setToString(key.set)); 1400 pw.print(" tag="); pw.println(NetworkStats.tagToString(key.tag)); 1401 1402 final NetworkStatsHistory history = mUidStats.get(key); 1403 history.dump(" ", pw, fullHistory); 1404 } 1405 } 1406 } 1407 } 1408 1409 /** 1410 * @deprecated only for temporary testing 1411 */ 1412 @Deprecated 1413 private void generateRandomLocked(String[] args) { 1414 final long totalBytes = Long.parseLong(args[1]); 1415 final long totalTime = Long.parseLong(args[2]); 1416 1417 final PackageManager pm = mContext.getPackageManager(); 1418 final ArrayList<Integer> specialUidList = Lists.newArrayList(); 1419 for (int i = 3; i < args.length; i++) { 1420 try { 1421 specialUidList.add(pm.getApplicationInfo(args[i], 0).uid); 1422 } catch (NameNotFoundException e) { 1423 throw new RuntimeException(e); 1424 } 1425 } 1426 1427 final HashSet<Integer> otherUidSet = Sets.newHashSet(); 1428 for (ApplicationInfo info : pm.getInstalledApplications(0)) { 1429 if (pm.checkPermission(android.Manifest.permission.INTERNET, info.packageName) 1430 == PackageManager.PERMISSION_GRANTED && !specialUidList.contains(info.uid)) { 1431 otherUidSet.add(info.uid); 1432 } 1433 } 1434 1435 final ArrayList<Integer> otherUidList = new ArrayList<Integer>(otherUidSet); 1436 1437 final long end = System.currentTimeMillis(); 1438 final long start = end - totalTime; 1439 1440 mNetworkDevStats.clear(); 1441 mNetworkXtStats.clear(); 1442 mUidStats.clear(); 1443 1444 final Random r = new Random(); 1445 for (NetworkIdentitySet ident : mActiveIfaces.values()) { 1446 final NetworkStatsHistory devHistory = findOrCreateNetworkDevStatsLocked(ident); 1447 final NetworkStatsHistory xtHistory = findOrCreateNetworkXtStatsLocked(ident); 1448 1449 final ArrayList<Integer> uidList = new ArrayList<Integer>(); 1450 uidList.addAll(specialUidList); 1451 1452 if (uidList.size() == 0) { 1453 Collections.shuffle(otherUidList); 1454 uidList.addAll(otherUidList); 1455 } 1456 1457 boolean first = true; 1458 long remainingBytes = totalBytes; 1459 for (int uid : uidList) { 1460 final NetworkStatsHistory defaultHistory = findOrCreateUidStatsLocked( 1461 ident, uid, SET_DEFAULT, TAG_NONE); 1462 final NetworkStatsHistory foregroundHistory = findOrCreateUidStatsLocked( 1463 ident, uid, SET_FOREGROUND, TAG_NONE); 1464 1465 final long uidBytes = totalBytes / uidList.size(); 1466 1467 final float fractionDefault = r.nextFloat(); 1468 final long defaultBytes = (long) (uidBytes * fractionDefault); 1469 final long foregroundBytes = (long) (uidBytes * (1 - fractionDefault)); 1470 1471 defaultHistory.generateRandom(start, end, defaultBytes); 1472 foregroundHistory.generateRandom(start, end, foregroundBytes); 1473 1474 if (first) { 1475 final long bumpTime = (start + end) / 2; 1476 defaultHistory.recordData( 1477 bumpTime, bumpTime + DAY_IN_MILLIS, 200 * MB_IN_BYTES, 0); 1478 first = false; 1479 } 1480 1481 devHistory.recordEntireHistory(defaultHistory); 1482 devHistory.recordEntireHistory(foregroundHistory); 1483 xtHistory.recordEntireHistory(defaultHistory); 1484 xtHistory.recordEntireHistory(foregroundHistory); 1485 } 1486 } 1487 } 1488 1489 /** 1490 * Return the delta between two {@link NetworkStats} snapshots, where {@code 1491 * before} can be {@code null}. 1492 */ 1493 private static NetworkStats computeStatsDelta( 1494 NetworkStats before, NetworkStats current, boolean collectStale) { 1495 if (before != null) { 1496 return current.subtractClamped(before); 1497 } else if (collectStale) { 1498 // caller is okay collecting stale stats for first call. 1499 return current; 1500 } else { 1501 // this is first snapshot; to prevent from double-counting we only 1502 // observe traffic occuring between known snapshots. 1503 return new NetworkStats(0L, 10); 1504 } 1505 } 1506 1507 private static NetworkStats computeNetworkXtSnapshotFromUid(NetworkStats uidSnapshot) { 1508 return uidSnapshot.groupedByIface(); 1509 } 1510 1511 private int estimateNetworkBuckets() { 1512 return (int) (mSettings.getNetworkMaxHistory() / mSettings.getNetworkBucketDuration()); 1513 } 1514 1515 private int estimateUidBuckets() { 1516 return (int) (mSettings.getUidMaxHistory() / mSettings.getUidBucketDuration()); 1517 } 1518 1519 private static int estimateResizeBuckets(NetworkStatsHistory existing, long newBucketDuration) { 1520 return (int) (existing.size() * existing.getBucketDuration() / newBucketDuration); 1521 } 1522 1523 /** 1524 * Test if given {@link NetworkTemplate} matches any {@link NetworkIdentity} 1525 * in the given {@link NetworkIdentitySet}. 1526 */ 1527 private static boolean templateMatches(NetworkTemplate template, NetworkIdentitySet identSet) { 1528 for (NetworkIdentity ident : identSet) { 1529 if (template.matches(ident)) { 1530 return true; 1531 } 1532 } 1533 return false; 1534 } 1535 1536 private Handler.Callback mHandlerCallback = new Handler.Callback() { 1537 /** {@inheritDoc} */ 1538 public boolean handleMessage(Message msg) { 1539 switch (msg.what) { 1540 case MSG_PERFORM_POLL: { 1541 final int flags = msg.arg1; 1542 performPoll(flags); 1543 return true; 1544 } 1545 case MSG_UPDATE_IFACES: { 1546 updateIfaces(); 1547 return true; 1548 } 1549 default: { 1550 return false; 1551 } 1552 } 1553 } 1554 }; 1555 1556 private static String getActiveSubscriberId(Context context) { 1557 final TelephonyManager telephony = (TelephonyManager) context.getSystemService( 1558 Context.TELEPHONY_SERVICE); 1559 return telephony.getSubscriberId(); 1560 } 1561 1562 /** 1563 * Key uniquely identifying a {@link NetworkStatsHistory} for a UID. 1564 */ 1565 private static class UidStatsKey implements Comparable<UidStatsKey> { 1566 public final NetworkIdentitySet ident; 1567 public final int uid; 1568 public final int set; 1569 public final int tag; 1570 1571 public UidStatsKey(NetworkIdentitySet ident, int uid, int set, int tag) { 1572 this.ident = ident; 1573 this.uid = uid; 1574 this.set = set; 1575 this.tag = tag; 1576 } 1577 1578 @Override 1579 public int hashCode() { 1580 return Objects.hashCode(ident, uid, set, tag); 1581 } 1582 1583 @Override 1584 public boolean equals(Object obj) { 1585 if (obj instanceof UidStatsKey) { 1586 final UidStatsKey key = (UidStatsKey) obj; 1587 return Objects.equal(ident, key.ident) && uid == key.uid && set == key.set 1588 && tag == key.tag; 1589 } 1590 return false; 1591 } 1592 1593 /** {@inheritDoc} */ 1594 public int compareTo(UidStatsKey another) { 1595 return Integer.compare(uid, another.uid); 1596 } 1597 } 1598 1599 /** 1600 * Default external settings that read from {@link Settings.Secure}. 1601 */ 1602 private static class DefaultNetworkStatsSettings implements NetworkStatsSettings { 1603 private final ContentResolver mResolver; 1604 1605 public DefaultNetworkStatsSettings(Context context) { 1606 mResolver = checkNotNull(context.getContentResolver()); 1607 // TODO: adjust these timings for production builds 1608 } 1609 1610 private long getSecureLong(String name, long def) { 1611 return Settings.Secure.getLong(mResolver, name, def); 1612 } 1613 private boolean getSecureBoolean(String name, boolean def) { 1614 final int defInt = def ? 1 : 0; 1615 return Settings.Secure.getInt(mResolver, name, defInt) != 0; 1616 } 1617 1618 public long getPollInterval() { 1619 return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS); 1620 } 1621 public long getPersistThreshold() { 1622 return getSecureLong(NETSTATS_PERSIST_THRESHOLD, 2 * MB_IN_BYTES); 1623 } 1624 public long getNetworkBucketDuration() { 1625 return getSecureLong(NETSTATS_NETWORK_BUCKET_DURATION, HOUR_IN_MILLIS); 1626 } 1627 public long getNetworkMaxHistory() { 1628 return getSecureLong(NETSTATS_NETWORK_MAX_HISTORY, 90 * DAY_IN_MILLIS); 1629 } 1630 public long getUidBucketDuration() { 1631 return getSecureLong(NETSTATS_UID_BUCKET_DURATION, 2 * HOUR_IN_MILLIS); 1632 } 1633 public long getUidMaxHistory() { 1634 return getSecureLong(NETSTATS_UID_MAX_HISTORY, 90 * DAY_IN_MILLIS); 1635 } 1636 public long getTagMaxHistory() { 1637 return getSecureLong(NETSTATS_TAG_MAX_HISTORY, 30 * DAY_IN_MILLIS); 1638 } 1639 public long getTimeCacheMaxAge() { 1640 return DAY_IN_MILLIS; 1641 } 1642 } 1643 } 1644