From 987f5ff357a7527aa99dbd334d85a071cb898863 Mon Sep 17 00:00:00 2001 From: Jeff Sharkey Date: Fri, 16 Sep 2011 01:52:49 -0700 Subject: [PATCH] Collect and persist tethering stats. Use new "gettetherstats" netd command to retrieve statistics for active tethering connections. Keep tethering poll events separate from UID poll, even though they end up same historical structures. Bug: 5244846 Change-Id: Ia0c5165f6712c12b51586f86c331a2aad4ad6afb --- core/java/android/net/TrafficStats.java | 18 ++++- .../server/net/NetworkStatsService.java | 69 ++++++++++++++++++- 2 files changed, 82 insertions(+), 5 deletions(-) diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 47cfa73de0..18eb9f69da 100644 --- a/core/java/android/net/TrafficStats.java +++ b/core/java/android/net/TrafficStats.java @@ -52,26 +52,34 @@ public class TrafficStats { */ public static final int UID_REMOVED = -4; + /** + * Special UID value used when collecting {@link NetworkStatsHistory} for + * tethering traffic. + * + * @hide + */ + public static final int UID_TETHERING = -5; + /** * Default tag value for {@link DownloadManager} traffic. * * @hide */ - public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001; + public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01; /** * Default tag value for {@link MediaPlayer} traffic. * * @hide */ - public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002; + public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02; /** * Default tag value for {@link BackupManager} traffic. * * @hide */ - public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003; + public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03; /** * Snapshot of {@link NetworkStats} when the currently active profiling @@ -90,6 +98,10 @@ public class TrafficStats { *

* Changes only take effect during subsequent calls to * {@link #tagSocket(Socket)}. + *

+ * Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and + * used internally by system services like {@link DownloadManager} when + * performing traffic on behalf of an application. */ public static void setThreadStatsTag(int tag) { NetworkManagementSocketTagger.setThreadSocketStatsTag(tag); diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java index a2b097ecb4..bb5f015de6 100644 --- a/services/java/com/android/server/net/NetworkStatsService.java +++ b/services/java/com/android/server/net/NetworkStatsService.java @@ -25,6 +25,7 @@ import static android.content.Intent.ACTION_SHUTDOWN; import static android.content.Intent.ACTION_UID_REMOVED; import static android.content.Intent.EXTRA_UID; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; +import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; import static android.net.NetworkStats.IFACE_ALL; import static android.net.NetworkStats.SET_ALL; import static android.net.NetworkStats.SET_DEFAULT; @@ -34,6 +35,7 @@ import static android.net.NetworkStats.UID_ALL; import static android.net.NetworkTemplate.buildTemplateMobileAll; import static android.net.NetworkTemplate.buildTemplateWifi; import static android.net.TrafficStats.UID_REMOVED; +import static android.net.TrafficStats.UID_TETHERING; import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL; import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; @@ -68,6 +70,7 @@ import android.net.NetworkState; import android.net.NetworkStats; import android.net.NetworkStatsHistory; import android.net.NetworkTemplate; +import android.net.TrafficStats; import android.os.Binder; import android.os.Environment; import android.os.Handler; @@ -89,6 +92,7 @@ import android.util.TrustedTime; import com.android.internal.os.AtomicFile; import com.android.internal.util.Objects; import com.android.server.EventLogTags; +import com.android.server.connectivity.Tethering; import com.google.android.collect.Lists; import com.google.android.collect.Maps; import com.google.android.collect.Sets; @@ -134,11 +138,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { /** Flags to control detail level of poll event. */ private static final int FLAG_POLL_NETWORK = 0x1; private static final int FLAG_POLL_UID = 0x2; + private static final int FLAG_POLL_TETHER = 0x3; private static final int FLAG_PERSIST_NETWORK = 0x10; private static final int FLAG_PERSIST_UID = 0x20; private static final int FLAG_FORCE_PERSIST = 0x100; - private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID; + private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID | FLAG_POLL_TETHER; private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; private final Context mContext; @@ -195,6 +200,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub { private NetworkStats mLastPollNetworkSnapshot; private NetworkStats mLastPollUidSnapshot; private NetworkStats mLastPollOperationsSnapshot; + private NetworkStats mLastPollTetherSnapshot; private NetworkStats mLastPersistNetworkSnapshot; private NetworkStats mLastPersistUidSnapshot; @@ -258,6 +264,10 @@ public class NetworkStatsService extends INetworkStatsService.Stub { final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); + // watch for tethering changes + final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED); + mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler); + // listen for periodic polling events final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler); @@ -543,6 +553,18 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } }; + /** + * Receiver that watches for {@link Tethering} to claim interface pairs. + */ + private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + // on background handler thread, and verified CONNECTIVITY_INTERNAL + // permission above. + performPoll(FLAG_POLL_TETHER); + } + }; + private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -686,12 +708,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub { boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0; boolean pollUid = (flags & FLAG_POLL_UID) != 0; + boolean pollTether = (flags & FLAG_POLL_TETHER) != 0; // when complete poll requested, any partial poll enables everything final boolean forceCompletePoll = mSettings.getForceCompletePoll(); - if (forceCompletePoll && (pollNetwork || pollUid)) { + if (forceCompletePoll && (pollNetwork || pollUid || pollTether)) { pollNetwork = true; pollUid = true; + pollTether = true; } final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; @@ -723,6 +747,15 @@ public class NetworkStatsService extends INetworkStatsService.Stub { } } + if (pollTether) { + final String[] ifacePairs = mConnManager.getTetheredIfacePairs(); + final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( + ifacePairs); + performTetherPollLocked(tetherSnapshot, currentTime); + + // persisted during normal UID cycle below + } + if (pollUid) { final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); performUidPollLocked(uidSnapshot, currentTime); @@ -848,6 +881,38 @@ public class NetworkStatsService extends INetworkStatsService.Stub { mOperations = new NetworkStats(0L, 10); } + /** + * Update {@link #mUidStats} historical usage for + * {@link TrafficStats#UID_TETHERING} based on tethering statistics. + */ + private void performTetherPollLocked(NetworkStats tetherSnapshot, long currentTime) { + ensureUidStatsLoadedLocked(); + + final NetworkStats delta = computeStatsDelta( + mLastPollTetherSnapshot, tetherSnapshot, false); + final long timeStart = currentTime - delta.getElapsedRealtime(); + + NetworkStats.Entry entry = null; + for (int i = 0; i < delta.size(); i++) { + entry = delta.getValues(i, entry); + final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); + if (ident == null) { + if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 + || entry.txPackets > 0) { + Log.w(TAG, "dropping tether delta from unknown iface: " + entry); + } + continue; + } + + final NetworkStatsHistory history = findOrCreateUidStatsLocked( + ident, UID_TETHERING, SET_DEFAULT, TAG_NONE); + history.recordData(timeStart, currentTime, entry); + } + + // normal UID poll will trim any history beyond max + mLastPollTetherSnapshot = tetherSnapshot; + } + /** * Sample recent statistics summary into {@link EventLog}. */