|
25 | 25 | import static android.content.Intent.ACTION_UID_REMOVED; |
26 | 26 | import static android.content.Intent.EXTRA_UID; |
27 | 27 | import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE; |
| 28 | +import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED; |
28 | 29 | import static android.net.NetworkStats.IFACE_ALL; |
29 | 30 | import static android.net.NetworkStats.SET_ALL; |
30 | 31 | import static android.net.NetworkStats.SET_DEFAULT; |
|
34 | 35 | import static android.net.NetworkTemplate.buildTemplateMobileAll; |
35 | 36 | import static android.net.NetworkTemplate.buildTemplateWifi; |
36 | 37 | import static android.net.TrafficStats.UID_REMOVED; |
| 38 | +import static android.net.TrafficStats.UID_TETHERING; |
37 | 39 | import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL; |
38 | 40 | import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION; |
39 | 41 | import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY; |
|
68 | 70 | import android.net.NetworkStats; |
69 | 71 | import android.net.NetworkStatsHistory; |
70 | 72 | import android.net.NetworkTemplate; |
| 73 | +import android.net.TrafficStats; |
71 | 74 | import android.os.Binder; |
72 | 75 | import android.os.Environment; |
73 | 76 | import android.os.Handler; |
|
89 | 92 | import com.android.internal.os.AtomicFile; |
90 | 93 | import com.android.internal.util.Objects; |
91 | 94 | import com.android.server.EventLogTags; |
| 95 | +import com.android.server.connectivity.Tethering; |
92 | 96 | import com.google.android.collect.Lists; |
93 | 97 | import com.google.android.collect.Maps; |
94 | 98 | import com.google.android.collect.Sets; |
@@ -134,11 +138,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub { |
134 | 138 | /** Flags to control detail level of poll event. */ |
135 | 139 | private static final int FLAG_POLL_NETWORK = 0x1; |
136 | 140 | private static final int FLAG_POLL_UID = 0x2; |
| 141 | + private static final int FLAG_POLL_TETHER = 0x3; |
137 | 142 | private static final int FLAG_PERSIST_NETWORK = 0x10; |
138 | 143 | private static final int FLAG_PERSIST_UID = 0x20; |
139 | 144 | private static final int FLAG_FORCE_PERSIST = 0x100; |
140 | 145 |
|
141 | | - private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID; |
| 146 | + private static final int FLAG_POLL_ALL = FLAG_POLL_NETWORK | FLAG_POLL_UID | FLAG_POLL_TETHER; |
142 | 147 | private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID; |
143 | 148 |
|
144 | 149 | private final Context mContext; |
@@ -195,6 +200,7 @@ public interface NetworkStatsSettings { |
195 | 200 | private NetworkStats mLastPollNetworkSnapshot; |
196 | 201 | private NetworkStats mLastPollUidSnapshot; |
197 | 202 | private NetworkStats mLastPollOperationsSnapshot; |
| 203 | + private NetworkStats mLastPollTetherSnapshot; |
198 | 204 |
|
199 | 205 | private NetworkStats mLastPersistNetworkSnapshot; |
200 | 206 | private NetworkStats mLastPersistUidSnapshot; |
@@ -258,6 +264,10 @@ public void systemReady() { |
258 | 264 | final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE); |
259 | 265 | mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler); |
260 | 266 |
|
| 267 | + // watch for tethering changes |
| 268 | + final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED); |
| 269 | + mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler); |
| 270 | + |
261 | 271 | // listen for periodic polling events |
262 | 272 | final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL); |
263 | 273 | mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler); |
@@ -543,6 +553,18 @@ public void onReceive(Context context, Intent intent) { |
543 | 553 | } |
544 | 554 | }; |
545 | 555 |
|
| 556 | + /** |
| 557 | + * Receiver that watches for {@link Tethering} to claim interface pairs. |
| 558 | + */ |
| 559 | + private BroadcastReceiver mTetherReceiver = new BroadcastReceiver() { |
| 560 | + @Override |
| 561 | + public void onReceive(Context context, Intent intent) { |
| 562 | + // on background handler thread, and verified CONNECTIVITY_INTERNAL |
| 563 | + // permission above. |
| 564 | + performPoll(FLAG_POLL_TETHER); |
| 565 | + } |
| 566 | + }; |
| 567 | + |
546 | 568 | private BroadcastReceiver mPollReceiver = new BroadcastReceiver() { |
547 | 569 | @Override |
548 | 570 | public void onReceive(Context context, Intent intent) { |
@@ -686,12 +708,14 @@ private void performPollLocked(int flags) { |
686 | 708 |
|
687 | 709 | boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0; |
688 | 710 | boolean pollUid = (flags & FLAG_POLL_UID) != 0; |
| 711 | + boolean pollTether = (flags & FLAG_POLL_TETHER) != 0; |
689 | 712 |
|
690 | 713 | // when complete poll requested, any partial poll enables everything |
691 | 714 | final boolean forceCompletePoll = mSettings.getForceCompletePoll(); |
692 | | - if (forceCompletePoll && (pollNetwork || pollUid)) { |
| 715 | + if (forceCompletePoll && (pollNetwork || pollUid || pollTether)) { |
693 | 716 | pollNetwork = true; |
694 | 717 | pollUid = true; |
| 718 | + pollTether = true; |
695 | 719 | } |
696 | 720 |
|
697 | 721 | final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0; |
@@ -723,6 +747,15 @@ private void performPollLocked(int flags) { |
723 | 747 | } |
724 | 748 | } |
725 | 749 |
|
| 750 | + if (pollTether) { |
| 751 | + final String[] ifacePairs = mConnManager.getTetheredIfacePairs(); |
| 752 | + final NetworkStats tetherSnapshot = mNetworkManager.getNetworkStatsTethering( |
| 753 | + ifacePairs); |
| 754 | + performTetherPollLocked(tetherSnapshot, currentTime); |
| 755 | + |
| 756 | + // persisted during normal UID cycle below |
| 757 | + } |
| 758 | + |
726 | 759 | if (pollUid) { |
727 | 760 | final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL); |
728 | 761 | performUidPollLocked(uidSnapshot, currentTime); |
@@ -848,6 +881,38 @@ private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) { |
848 | 881 | mOperations = new NetworkStats(0L, 10); |
849 | 882 | } |
850 | 883 |
|
| 884 | + /** |
| 885 | + * Update {@link #mUidStats} historical usage for |
| 886 | + * {@link TrafficStats#UID_TETHERING} based on tethering statistics. |
| 887 | + */ |
| 888 | + private void performTetherPollLocked(NetworkStats tetherSnapshot, long currentTime) { |
| 889 | + ensureUidStatsLoadedLocked(); |
| 890 | + |
| 891 | + final NetworkStats delta = computeStatsDelta( |
| 892 | + mLastPollTetherSnapshot, tetherSnapshot, false); |
| 893 | + final long timeStart = currentTime - delta.getElapsedRealtime(); |
| 894 | + |
| 895 | + NetworkStats.Entry entry = null; |
| 896 | + for (int i = 0; i < delta.size(); i++) { |
| 897 | + entry = delta.getValues(i, entry); |
| 898 | + final NetworkIdentitySet ident = mActiveIfaces.get(entry.iface); |
| 899 | + if (ident == null) { |
| 900 | + if (entry.rxBytes > 0 || entry.rxPackets > 0 || entry.txBytes > 0 |
| 901 | + || entry.txPackets > 0) { |
| 902 | + Log.w(TAG, "dropping tether delta from unknown iface: " + entry); |
| 903 | + } |
| 904 | + continue; |
| 905 | + } |
| 906 | + |
| 907 | + final NetworkStatsHistory history = findOrCreateUidStatsLocked( |
| 908 | + ident, UID_TETHERING, SET_DEFAULT, TAG_NONE); |
| 909 | + history.recordData(timeStart, currentTime, entry); |
| 910 | + } |
| 911 | + |
| 912 | + // normal UID poll will trim any history beyond max |
| 913 | + mLastPollTetherSnapshot = tetherSnapshot; |
| 914 | + } |
| 915 | + |
851 | 916 | /** |
852 | 917 | * Sample recent statistics summary into {@link EventLog}. |
853 | 918 | */ |
|
0 commit comments