NetworkStatsServicepublic class NetworkStatsService extends INetworkStatsService.Stub Collect and persist detailed network statistics, and provide this data to
other system services. |
Fields Summary |
---|
private static final String | TAG | private static final boolean | LOGV | private static final int | MSG_PERFORM_POLL | private static final int | MSG_UPDATE_IFACES | private static final int | MSG_REGISTER_GLOBAL_ALERT | private static final int | FLAG_PERSIST_NETWORKFlags to control detail level of poll event. | private static final int | FLAG_PERSIST_UID | private static final int | FLAG_PERSIST_ALL | private static final int | FLAG_PERSIST_FORCE | private static final String | TAG_NETSTATS_ERROR | private final android.content.Context | mContext | private final android.os.INetworkManagementService | mNetworkManager | private final android.app.AlarmManager | mAlarmManager | private final android.util.TrustedTime | mTime | private final android.telephony.TelephonyManager | mTeleManager | private final NetworkStatsSettings | mSettings | private final File | mSystemDir | private final File | mBaseDir | private final PowerManager.WakeLock | mWakeLock | private android.net.IConnectivityManager | mConnManager | public static final String | ACTION_NETWORK_STATS_POLL | public static final String | ACTION_NETWORK_STATS_UPDATED | private android.app.PendingIntent | mPollIntent | private static final String | PREFIX_DEV | private static final String | PREFIX_XT | private static final String | PREFIX_UID | private static final String | PREFIX_UID_TAG | private final Object | mStatsLock | private final android.util.ArrayMap | mActiveIfacesSet of currently active ifaces. | private final android.util.ArrayMap | mActiveUidIfacesSet of currently active ifaces for UID stats. | private String | mActiveIfaceCurrent default active iface. | private String[] | mMobileIfacesSet of any ifaces associated with mobile networks since boot. | private final DropBoxNonMonotonicObserver | mNonMonotonicObserver | private NetworkStatsRecorder | mDevRecorder | private NetworkStatsRecorder | mXtRecorder | private NetworkStatsRecorder | mUidRecorder | private NetworkStatsRecorder | mUidTagRecorder | private NetworkStatsCollection | mXtStatsCachedCached {@link #mXtRecorder} stats. | private android.util.SparseIntArray | mActiveUidCounterSetCurrent counter sets for each UID. | private android.net.NetworkStats | mUidOperationsData layer operation counters for splicing into other structures. | private final android.os.Handler | mHandler | private boolean | mSystemReady | private long | mPersistThreshold | private long | mGlobalAlertBytes | private android.content.BroadcastReceiver | mTetherReceiverReceiver that watches for {@link Tethering} to claim interface pairs. | private android.content.BroadcastReceiver | mPollReceiver | private android.content.BroadcastReceiver | mRemovedReceiver | private android.content.BroadcastReceiver | mUserReceiver | private android.content.BroadcastReceiver | mShutdownReceiver | private android.net.INetworkManagementEventObserver | mAlertObserverObserver that watches for {@link INetworkManagementService} alerts. | private Handler.Callback | mHandlerCallback |
Constructors Summary |
---|
public NetworkStatsService(android.content.Context context, android.os.INetworkManagementService networkManager, android.app.IAlarmManager alarmManager)
this(context, networkManager, alarmManager, NtpTrustedTime.getInstance(context),
getDefaultSystemDir(), new DefaultNetworkStatsSettings(context));
| public NetworkStatsService(android.content.Context context, android.os.INetworkManagementService networkManager, android.app.IAlarmManager alarmManager, android.util.TrustedTime time, File systemDir, NetworkStatsSettings settings)
mContext = checkNotNull(context, "missing Context");
mNetworkManager = checkNotNull(networkManager, "missing INetworkManagementService");
mTime = checkNotNull(time, "missing TrustedTime");
mTeleManager = checkNotNull(TelephonyManager.getDefault(), "missing TelephonyManager");
mSettings = checkNotNull(settings, "missing NetworkStatsSettings");
mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
final PowerManager powerManager = (PowerManager) context.getSystemService(
Context.POWER_SERVICE);
mWakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, TAG);
HandlerThread thread = new HandlerThread(TAG);
thread.start();
mHandler = new Handler(thread.getLooper(), mHandlerCallback);
mSystemDir = checkNotNull(systemDir);
mBaseDir = new File(systemDir, "netstats");
mBaseDir.mkdirs();
|
Methods Summary |
---|
public void | advisePersistThreshold(long thresholdBytes)
mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
assertBandwidthControlEnabled();
// clamp threshold into safe range
mPersistThreshold = MathUtils.constrain(thresholdBytes, 128 * KB_IN_BYTES, 2 * MB_IN_BYTES);
if (LOGV) {
Slog.v(TAG, "advisePersistThreshold() given " + thresholdBytes + ", clamped to "
+ mPersistThreshold);
}
// update and persist if beyond new thresholds
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
synchronized (mStatsLock) {
if (!mSystemReady) return;
updatePersistThresholds();
mDevRecorder.maybePersistLocked(currentTime);
mXtRecorder.maybePersistLocked(currentTime);
mUidRecorder.maybePersistLocked(currentTime);
mUidTagRecorder.maybePersistLocked(currentTime);
}
// re-arm global alert
registerGlobalAlert();
| private void | assertBandwidthControlEnabled()
if (!isBandwidthControlEnabled()) {
throw new IllegalStateException("Bandwidth module disabled");
}
| public void | bindConnectivityManager(android.net.IConnectivityManager connManager)
mConnManager = checkNotNull(connManager, "missing IConnectivityManager");
| private void | bootstrapStatsLocked()Bootstrap initial stats snapshot, usually during {@link #systemReady()}
so we have baseline values without double-counting.
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
try {
// snapshot and record current counters; read UID stats first to
// avoid overcounting dev stats.
final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
} catch (IllegalStateException e) {
Slog.w(TAG, "problem reading network stats: " + e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
| private NetworkStatsRecorder | buildRecorder(java.lang.String prefix, NetworkStatsSettings.Config config, boolean includeTags)
final DropBoxManager dropBox = (DropBoxManager) mContext.getSystemService(
Context.DROPBOX_SERVICE);
return new NetworkStatsRecorder(new FileRotator(
mBaseDir, prefix, config.rotateAgeMillis, config.deleteAgeMillis),
mNonMonotonicObserver, dropBox, prefix, config.bucketDuration, includeTags);
| protected void | dump(java.io.FileDescriptor fd, java.io.PrintWriter rawWriter, java.lang.String[] args)
mContext.enforceCallingOrSelfPermission(DUMP, TAG);
long duration = DateUtils.DAY_IN_MILLIS;
final HashSet<String> argSet = new HashSet<String>();
for (String arg : args) {
argSet.add(arg);
if (arg.startsWith("--duration=")) {
try {
duration = Long.parseLong(arg.substring(11));
} catch (NumberFormatException ignored) {
}
}
}
// usage: dumpsys netstats --full --uid --tag --poll --checkin
final boolean poll = argSet.contains("--poll") || argSet.contains("poll");
final boolean checkin = argSet.contains("--checkin");
final boolean fullHistory = argSet.contains("--full") || argSet.contains("full");
final boolean includeUid = argSet.contains("--uid") || argSet.contains("detail");
final boolean includeTag = argSet.contains("--tag") || argSet.contains("detail");
final IndentingPrintWriter pw = new IndentingPrintWriter(rawWriter, " ");
synchronized (mStatsLock) {
if (poll) {
performPollLocked(FLAG_PERSIST_ALL | FLAG_PERSIST_FORCE);
pw.println("Forced poll");
return;
}
if (checkin) {
final long end = System.currentTimeMillis();
final long start = end - duration;
pw.print("v1,");
pw.print(start / SECOND_IN_MILLIS); pw.print(',");
pw.print(end / SECOND_IN_MILLIS); pw.println();
pw.println("xt");
mXtRecorder.dumpCheckin(rawWriter, start, end);
if (includeUid) {
pw.println("uid");
mUidRecorder.dumpCheckin(rawWriter, start, end);
}
if (includeTag) {
pw.println("tag");
mUidTagRecorder.dumpCheckin(rawWriter, start, end);
}
return;
}
pw.println("Active interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveIfaces.size(); i++) {
pw.printPair("iface", mActiveIfaces.keyAt(i));
pw.printPair("ident", mActiveIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
pw.println("Active UID interfaces:");
pw.increaseIndent();
for (int i = 0; i < mActiveUidIfaces.size(); i++) {
pw.printPair("iface", mActiveUidIfaces.keyAt(i));
pw.printPair("ident", mActiveUidIfaces.valueAt(i));
pw.println();
}
pw.decreaseIndent();
pw.println("Dev stats:");
pw.increaseIndent();
mDevRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
pw.println("Xt stats:");
pw.increaseIndent();
mXtRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
if (includeUid) {
pw.println("UID stats:");
pw.increaseIndent();
mUidRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
}
if (includeTag) {
pw.println("UID tag stats:");
pw.increaseIndent();
mUidTagRecorder.dumpLocked(pw, fullHistory);
pw.decreaseIndent();
}
}
| private static NetworkIdentitySet | findOrCreateNetworkIdentitySet(android.util.ArrayMap map, K key)
NetworkIdentitySet ident = map.get(key);
if (ident == null) {
ident = new NetworkIdentitySet();
map.put(key, ident);
}
return ident;
| public void | forceUpdate()
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
assertBandwidthControlEnabled();
final long token = Binder.clearCallingIdentity();
try {
performPoll(FLAG_PERSIST_ALL);
} finally {
Binder.restoreCallingIdentity(token);
}
| public void | forceUpdateIfaces()
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
assertBandwidthControlEnabled();
final long token = Binder.clearCallingIdentity();
try {
updateIfaces();
} finally {
Binder.restoreCallingIdentity(token);
}
| public android.net.NetworkStats | getDataLayerSnapshotForUid(int uid)
if (Binder.getCallingUid() != uid) {
mContext.enforceCallingOrSelfPermission(ACCESS_NETWORK_STATE, TAG);
}
assertBandwidthControlEnabled();
// TODO: switch to data layer stats once kernel exports
// for now, read network layer stats and flatten across all ifaces
final long token = Binder.clearCallingIdentity();
final NetworkStats networkLayer;
try {
networkLayer = mNetworkManager.getNetworkStatsUidDetail(uid);
} finally {
Binder.restoreCallingIdentity(token);
}
// splice in operation counts
networkLayer.spliceOperationsFrom(mUidOperations);
final NetworkStats dataLayer = new NetworkStats(
networkLayer.getElapsedRealtime(), networkLayer.size());
NetworkStats.Entry entry = null;
for (int i = 0; i < networkLayer.size(); i++) {
entry = networkLayer.getValues(i, entry);
entry.iface = IFACE_ALL;
dataLayer.combineValues(entry);
}
return dataLayer;
| private static java.io.File | getDefaultSystemDir()
return new File(Environment.getDataDirectory(), "system");
| public java.lang.String[] | getMobileIfaces()
return mMobileIfaces;
| private android.net.NetworkStats | getNetworkStatsTethering()Return snapshot of current tethering statistics. Will return empty
{@link NetworkStats} if any problems are encountered.
try {
return mNetworkManager.getNetworkStatsTethering();
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
return new NetworkStats(0L, 10);
}
| private android.net.NetworkStats | getNetworkStatsUidDetail()Return snapshot of current UID statistics, including any
{@link TrafficStats#UID_TETHERING} and {@link #mUidOperations} values.
final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
// fold tethering stats and operations into uid snapshot
final NetworkStats tetherSnapshot = getNetworkStatsTethering();
uidSnapshot.combineAllValues(tetherSnapshot);
uidSnapshot.combineAllValues(mUidOperations);
return uidSnapshot;
| public long | getNetworkTotalBytes(android.net.NetworkTemplate template, long start, long end)
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
assertBandwidthControlEnabled();
return internalGetSummaryForNetwork(template, start, end).getTotalBytes();
| public void | incrementOperationCount(int uid, int tag, int operationCount)
if (Binder.getCallingUid() != uid) {
mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
}
if (operationCount < 0) {
throw new IllegalArgumentException("operation count can only be incremented");
}
if (tag == TAG_NONE) {
throw new IllegalArgumentException("operation count must have specific tag");
}
synchronized (mStatsLock) {
final int set = mActiveUidCounterSet.get(uid, SET_DEFAULT);
mUidOperations.combineValues(
mActiveIface, uid, set, tag, 0L, 0L, 0L, 0L, operationCount);
mUidOperations.combineValues(
mActiveIface, uid, set, TAG_NONE, 0L, 0L, 0L, 0L, operationCount);
}
| private android.net.NetworkStatsHistory | internalGetHistoryForNetwork(android.net.NetworkTemplate template, int fields)Return network history, splicing between DEV and XT stats when
appropriate.
// We've been using pure XT stats long enough that we no longer need to
// splice DEV and XT together.
return mXtStatsCached.getHistory(template, UID_ALL, SET_ALL, TAG_NONE, fields);
| private android.net.NetworkStats | internalGetSummaryForNetwork(android.net.NetworkTemplate template, long start, long end)Return network summary, splicing between DEV and XT stats when
appropriate.
// We've been using pure XT stats long enough that we no longer need to
// splice DEV and XT together.
return mXtStatsCached.getSummary(template, start, end);
| private boolean | isBandwidthControlEnabled()
final long token = Binder.clearCallingIdentity();
try {
return mNetworkManager.isBandwidthControlEnabled();
} catch (RemoteException e) {
// ignored; service lives in system_server
return false;
} finally {
Binder.restoreCallingIdentity(token);
}
| private void | maybeUpgradeLegacyStatsLocked()
File file;
try {
file = new File(mSystemDir, "netstats.bin");
if (file.exists()) {
mDevRecorder.importLegacyNetworkLocked(file);
file.delete();
}
file = new File(mSystemDir, "netstats_xt.bin");
if (file.exists()) {
file.delete();
}
file = new File(mSystemDir, "netstats_uid.bin");
if (file.exists()) {
mUidRecorder.importLegacyUidLocked(file);
mUidTagRecorder.importLegacyUidLocked(file);
file.delete();
}
} catch (IOException e) {
Log.wtf(TAG, "problem during legacy upgrade", e);
} catch (OutOfMemoryError e) {
Log.wtf(TAG, "problem during legacy upgrade", e);
}
| public android.net.INetworkStatsSession | openSession()
mContext.enforceCallingOrSelfPermission(READ_NETWORK_USAGE_HISTORY, TAG);
assertBandwidthControlEnabled();
// return an IBinder which holds strong references to any loaded stats
// for its lifetime; when caller closes only weak references remain.
return new INetworkStatsSession.Stub() {
private NetworkStatsCollection mUidComplete;
private NetworkStatsCollection mUidTagComplete;
private NetworkStatsCollection getUidComplete() {
synchronized (mStatsLock) {
if (mUidComplete == null) {
mUidComplete = mUidRecorder.getOrLoadCompleteLocked();
}
return mUidComplete;
}
}
private NetworkStatsCollection getUidTagComplete() {
synchronized (mStatsLock) {
if (mUidTagComplete == null) {
mUidTagComplete = mUidTagRecorder.getOrLoadCompleteLocked();
}
return mUidTagComplete;
}
}
@Override
public NetworkStats getSummaryForNetwork(
NetworkTemplate template, long start, long end) {
return internalGetSummaryForNetwork(template, start, end);
}
@Override
public NetworkStatsHistory getHistoryForNetwork(NetworkTemplate template, int fields) {
return internalGetHistoryForNetwork(template, fields);
}
@Override
public NetworkStats getSummaryForAllUid(
NetworkTemplate template, long start, long end, boolean includeTags) {
final NetworkStats stats = getUidComplete().getSummary(template, start, end);
if (includeTags) {
final NetworkStats tagStats = getUidTagComplete()
.getSummary(template, start, end);
stats.combineAllValues(tagStats);
}
return stats;
}
@Override
public NetworkStatsHistory getHistoryForUid(
NetworkTemplate template, int uid, int set, int tag, int fields) {
if (tag == TAG_NONE) {
return getUidComplete().getHistory(template, uid, set, tag, fields);
} else {
return getUidTagComplete().getHistory(template, uid, set, tag, fields);
}
}
@Override
public void close() {
mUidComplete = null;
mUidTagComplete = null;
}
};
| private void | performPoll(int flags)
// try refreshing time source when stale
if (mTime.getCacheAge() > mSettings.getTimeCacheMaxAge()) {
mTime.forceRefresh();
}
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
performPollLocked(flags);
} finally {
mWakeLock.release();
}
}
| private void | performPollLocked(int flags)Periodic poll operation, reading current statistics and recording into
{@link NetworkStatsHistory}.
if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
final long startRealtime = SystemClock.elapsedRealtime();
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
final boolean persistForce = (flags & FLAG_PERSIST_FORCE) != 0;
// TODO: consider marking "untrusted" times in historical stats
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
try {
// snapshot and record current counters; read UID stats first to
// avoid overcounting dev stats.
final NetworkStats uidSnapshot = getNetworkStatsUidDetail();
final NetworkStats xtSnapshot = mNetworkManager.getNetworkStatsSummaryXt();
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
mDevRecorder.recordSnapshotLocked(devSnapshot, mActiveIfaces, currentTime);
mXtRecorder.recordSnapshotLocked(xtSnapshot, mActiveIfaces, currentTime);
mUidRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
mUidTagRecorder.recordSnapshotLocked(uidSnapshot, mActiveUidIfaces, currentTime);
} catch (IllegalStateException e) {
Log.wtf(TAG, "problem reading network stats", e);
return;
} catch (RemoteException e) {
// ignored; service lives in system_server
return;
}
// persist any pending data depending on requested flags
if (persistForce) {
mDevRecorder.forcePersistLocked(currentTime);
mXtRecorder.forcePersistLocked(currentTime);
mUidRecorder.forcePersistLocked(currentTime);
mUidTagRecorder.forcePersistLocked(currentTime);
} else {
if (persistNetwork) {
mDevRecorder.maybePersistLocked(currentTime);
mXtRecorder.maybePersistLocked(currentTime);
}
if (persistUid) {
mUidRecorder.maybePersistLocked(currentTime);
mUidTagRecorder.maybePersistLocked(currentTime);
}
}
if (LOGV) {
final long duration = SystemClock.elapsedRealtime() - startRealtime;
Slog.v(TAG, "performPollLocked() took " + duration + "ms");
}
if (mSettings.getSampleEnabled()) {
// sample stats after each full poll
performSampleLocked();
}
// finally, dispatch updated event to any listeners
final Intent updatedIntent = new Intent(ACTION_NETWORK_STATS_UPDATED);
updatedIntent.setFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
mContext.sendBroadcastAsUser(updatedIntent, UserHandle.ALL,
READ_NETWORK_USAGE_HISTORY);
| private void | performSampleLocked()Sample recent statistics summary into {@link EventLog}.
// TODO: migrate trustedtime fixes to separate binary log events
final long trustedTime = mTime.hasCache() ? mTime.currentTimeMillis() : -1;
NetworkTemplate template;
NetworkStats.Entry devTotal;
NetworkStats.Entry xtTotal;
NetworkStats.Entry uidTotal;
// collect mobile sample
template = buildTemplateMobileWildcard();
devTotal = mDevRecorder.getTotalSinceBootLocked(template);
xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
EventLogTags.writeNetstatsMobileSample(
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
trustedTime);
// collect wifi sample
template = buildTemplateWifiWildcard();
devTotal = mDevRecorder.getTotalSinceBootLocked(template);
xtTotal = mXtRecorder.getTotalSinceBootLocked(template);
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
EventLogTags.writeNetstatsWifiSample(
devTotal.rxBytes, devTotal.rxPackets, devTotal.txBytes, devTotal.txPackets,
xtTotal.rxBytes, xtTotal.rxPackets, xtTotal.txBytes, xtTotal.txPackets,
uidTotal.rxBytes, uidTotal.rxPackets, uidTotal.txBytes, uidTotal.txPackets,
trustedTime);
| private void | registerGlobalAlert()Register for a global alert that is delivered through
{@link INetworkManagementEventObserver} once a threshold amount of data
has been transferred.
try {
mNetworkManager.setGlobalAlert(mGlobalAlertBytes);
} catch (IllegalStateException e) {
Slog.w(TAG, "problem registering for global alert: " + e);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
| private void | registerPollAlarmLocked()Clear any existing {@link #ACTION_NETWORK_STATS_POLL} alarms, and
reschedule based on current {@link NetworkStatsSettings#getPollInterval()}.
if (mPollIntent != null) {
mAlarmManager.cancel(mPollIntent);
}
mPollIntent = PendingIntent.getBroadcast(
mContext, 0, new Intent(ACTION_NETWORK_STATS_POLL), 0);
final long currentRealtime = SystemClock.elapsedRealtime();
mAlarmManager.setInexactRepeating(AlarmManager.ELAPSED_REALTIME, currentRealtime,
mSettings.getPollInterval(), mPollIntent);
| private void | removeUidsLocked(int uids)Clean up {@link #mUidRecorder} after UID is removed.
if (LOGV) Slog.v(TAG, "removeUidsLocked() for UIDs " + Arrays.toString(uids));
// Perform one last poll before removing
performPollLocked(FLAG_PERSIST_ALL);
mUidRecorder.removeUidsLocked(uids);
mUidTagRecorder.removeUidsLocked(uids);
// Clear kernel stats associated with UID
for (int uid : uids) {
resetKernelUidStats(uid);
}
| private void | removeUserLocked(int userId)Clean up {@link #mUidRecorder} after user is removed.
if (LOGV) Slog.v(TAG, "removeUserLocked() for userId=" + userId);
// Build list of UIDs that we should clean up
int[] uids = new int[0];
final List<ApplicationInfo> apps = mContext.getPackageManager().getInstalledApplications(
PackageManager.GET_UNINSTALLED_PACKAGES | PackageManager.GET_DISABLED_COMPONENTS);
for (ApplicationInfo app : apps) {
final int uid = UserHandle.getUid(userId, app.uid);
uids = ArrayUtils.appendInt(uids, uid);
}
removeUidsLocked(uids);
| public void | setUidForeground(int uid, boolean uidForeground)
mContext.enforceCallingOrSelfPermission(MODIFY_NETWORK_ACCOUNTING, TAG);
synchronized (mStatsLock) {
final int set = uidForeground ? SET_FOREGROUND : SET_DEFAULT;
final int oldSet = mActiveUidCounterSet.get(uid, SET_DEFAULT);
if (oldSet != set) {
mActiveUidCounterSet.put(uid, set);
setKernelCounterSet(uid, set);
}
}
| private void | shutdownLocked()
mContext.unregisterReceiver(mTetherReceiver);
mContext.unregisterReceiver(mPollReceiver);
mContext.unregisterReceiver(mRemovedReceiver);
mContext.unregisterReceiver(mShutdownReceiver);
final long currentTime = mTime.hasCache() ? mTime.currentTimeMillis()
: System.currentTimeMillis();
// persist any pending stats
mDevRecorder.forcePersistLocked(currentTime);
mXtRecorder.forcePersistLocked(currentTime);
mUidRecorder.forcePersistLocked(currentTime);
mUidTagRecorder.forcePersistLocked(currentTime);
mDevRecorder = null;
mXtRecorder = null;
mUidRecorder = null;
mUidTagRecorder = null;
mXtStatsCached = null;
mSystemReady = false;
| public void | systemReady()
mSystemReady = true;
if (!isBandwidthControlEnabled()) {
Slog.w(TAG, "bandwidth controls disabled, unable to track stats");
return;
}
// create data recorders along with historical rotators
mDevRecorder = buildRecorder(PREFIX_DEV, mSettings.getDevConfig(), false);
mXtRecorder = buildRecorder(PREFIX_XT, mSettings.getXtConfig(), false);
mUidRecorder = buildRecorder(PREFIX_UID, mSettings.getUidConfig(), false);
mUidTagRecorder = buildRecorder(PREFIX_UID_TAG, mSettings.getUidTagConfig(), true);
updatePersistThresholds();
synchronized (mStatsLock) {
// upgrade any legacy stats, migrating them to rotated files
maybeUpgradeLegacyStatsLocked();
// read historical network stats from disk, since policy service
// might need them right away.
mXtStatsCached = mXtRecorder.getOrLoadCompleteLocked();
// bootstrap initial stats to prevent double-counting later
bootstrapStatsLocked();
}
// watch for tethering changes
final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
mContext.registerReceiver(mTetherReceiver, tetherFilter, null, mHandler);
// listen for periodic polling events
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
// listen for uid removal to clean stats
final IntentFilter removedFilter = new IntentFilter(ACTION_UID_REMOVED);
mContext.registerReceiver(mRemovedReceiver, removedFilter, null, mHandler);
// listen for user changes to clean stats
final IntentFilter userFilter = new IntentFilter(ACTION_USER_REMOVED);
mContext.registerReceiver(mUserReceiver, userFilter, null, mHandler);
// persist stats during clean shutdown
final IntentFilter shutdownFilter = new IntentFilter(ACTION_SHUTDOWN);
mContext.registerReceiver(mShutdownReceiver, shutdownFilter);
try {
mNetworkManager.registerObserver(mAlertObserver);
} catch (RemoteException e) {
// ignored; service lives in system_server
}
registerPollAlarmLocked();
registerGlobalAlert();
| private void | updateIfaces()
synchronized (mStatsLock) {
mWakeLock.acquire();
try {
updateIfacesLocked();
} finally {
mWakeLock.release();
}
}
| private void | updateIfacesLocked()Inspect all current {@link NetworkState} to derive mapping from {@code
iface} to {@link NetworkStatsHistory}. When multiple {@link NetworkInfo}
are active on a single {@code iface}, they are combined under a single
{@link NetworkIdentitySet}.
if (!mSystemReady) return;
if (LOGV) Slog.v(TAG, "updateIfacesLocked()");
// take one last stats snapshot before updating iface mapping. this
// isn't perfect, since the kernel may already be counting traffic from
// the updated network.
// poll, but only persist network stats to keep codepath fast. UID stats
// will be persisted during next alarm poll event.
performPollLocked(FLAG_PERSIST_NETWORK);
final NetworkState[] states;
final LinkProperties activeLink;
try {
states = mConnManager.getAllNetworkState();
activeLink = mConnManager.getActiveLinkProperties();
} catch (RemoteException e) {
// ignored; service lives in system_server
return;
}
mActiveIface = activeLink != null ? activeLink.getInterfaceName() : null;
// Rebuild active interfaces based on connected networks
mActiveIfaces.clear();
mActiveUidIfaces.clear();
final ArraySet<String> mobileIfaces = new ArraySet<>();
for (NetworkState state : states) {
if (state.networkInfo.isConnected()) {
final boolean isMobile = isNetworkTypeMobile(state.networkInfo.getType());
final NetworkIdentity ident = NetworkIdentity.buildNetworkIdentity(mContext, state);
// Traffic occurring on the base interface is always counted for
// both total usage and UID details.
final String baseIface = state.linkProperties.getInterfaceName();
if (baseIface != null) {
findOrCreateNetworkIdentitySet(mActiveIfaces, baseIface).add(ident);
findOrCreateNetworkIdentitySet(mActiveUidIfaces, baseIface).add(ident);
if (isMobile) {
mobileIfaces.add(baseIface);
}
}
// Traffic occurring on stacked interfaces is usually clatd,
// which is already accounted against its final egress interface
// by the kernel. Thus, we only need to collect stacked
// interface stats at the UID level.
final List<LinkProperties> stackedLinks = state.linkProperties.getStackedLinks();
for (LinkProperties stackedLink : stackedLinks) {
final String stackedIface = stackedLink.getInterfaceName();
if (stackedIface != null) {
findOrCreateNetworkIdentitySet(mActiveUidIfaces, stackedIface).add(ident);
if (isMobile) {
mobileIfaces.add(stackedIface);
}
}
}
}
}
mMobileIfaces = mobileIfaces.toArray(new String[mobileIfaces.size()]);
| private void | updatePersistThresholds()Update {@link NetworkStatsRecorder} and {@link #mGlobalAlertBytes} to
reflect current {@link #mPersistThreshold} value. Always defers to
{@link Global} values when defined.
mDevRecorder.setPersistThreshold(mSettings.getDevPersistBytes(mPersistThreshold));
mXtRecorder.setPersistThreshold(mSettings.getXtPersistBytes(mPersistThreshold));
mUidRecorder.setPersistThreshold(mSettings.getUidPersistBytes(mPersistThreshold));
mUidTagRecorder.setPersistThreshold(mSettings.getUidTagPersistBytes(mPersistThreshold));
mGlobalAlertBytes = mSettings.getGlobalAlertBytes(mPersistThreshold);
|
|