Skip to content

Commit 3d1d57d

Browse files
jsharkeyAndroid (Google) Code Review
authored andcommitted
Merge "Collect and persist tethering stats." into ics-factoryrom
2 parents 79aa403 + cdd02c5 commit 3d1d57d

File tree

7 files changed

+186
-10
lines changed

7 files changed

+186
-10
lines changed

core/java/android/net/IConnectivityManager.aidl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ interface IConnectivityManager
8383

8484
String[] getTetheredIfaces();
8585

86+
/**
87+
* Return list of interface pairs that are actively tethered. Even indexes are
88+
* remote interface, and odd indexes are corresponding local interfaces.
89+
*/
90+
String[] getTetheredIfacePairs();
91+
8692
String[] getTetheringErroredIfaces();
8793

8894
String[] getTetherableUsbRegexs();

core/java/android/net/TrafficStats.java

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -52,26 +52,34 @@ public class TrafficStats {
5252
*/
5353
public static final int UID_REMOVED = -4;
5454

55+
/**
56+
* Special UID value used when collecting {@link NetworkStatsHistory} for
57+
* tethering traffic.
58+
*
59+
* @hide
60+
*/
61+
public static final int UID_TETHERING = -5;
62+
5563
/**
5664
* Default tag value for {@link DownloadManager} traffic.
5765
*
5866
* @hide
5967
*/
60-
public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFF0001;
68+
public static final int TAG_SYSTEM_DOWNLOAD = 0xFFFFFF01;
6169

6270
/**
6371
* Default tag value for {@link MediaPlayer} traffic.
6472
*
6573
* @hide
6674
*/
67-
public static final int TAG_SYSTEM_MEDIA = 0xFFFF0002;
75+
public static final int TAG_SYSTEM_MEDIA = 0xFFFFFF02;
6876

6977
/**
7078
* Default tag value for {@link BackupManager} traffic.
7179
*
7280
* @hide
7381
*/
74-
public static final int TAG_SYSTEM_BACKUP = 0xFFFF0003;
82+
public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
7583

7684
/**
7785
* Snapshot of {@link NetworkStats} when the currently active profiling
@@ -90,6 +98,10 @@ public class TrafficStats {
9098
* <p>
9199
* Changes only take effect during subsequent calls to
92100
* {@link #tagSocket(Socket)}.
101+
* <p>
102+
* Tags between {@code 0xFFFFFF00} and {@code 0xFFFFFFFF} are reserved and
103+
* used internally by system services like {@link DownloadManager} when
104+
* performing traffic on behalf of an application.
93105
*/
94106
public static void setThreadStatsTag(int tag) {
95107
NetworkManagementSocketTagger.setThreadSocketStatsTag(tag);

core/java/android/os/INetworkManagementService.aidl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,13 @@ interface INetworkManagementService
230230
*/
231231
NetworkStats getNetworkStatsUidDetail(int uid);
232232

233+
/**
234+
* Return summary of network statistics for the requested pairs of
235+
* tethering interfaces. Even indexes are remote interface, and odd
236+
* indexes are corresponding local interfaces.
237+
*/
238+
NetworkStats getNetworkStatsTethering(in String[] ifacePairs);
239+
233240
/**
234241
* Set quota for an interface.
235242
*/

services/java/com/android/server/ConnectivityService.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2394,6 +2394,12 @@ public String[] getTetheredIfaces() {
23942394
return mTethering.getTetheredIfaces();
23952395
}
23962396

2397+
@Override
2398+
public String[] getTetheredIfacePairs() {
2399+
enforceTetherAccessPermission();
2400+
return mTethering.getTetheredIfacePairs();
2401+
}
2402+
23972403
public String[] getTetheringErroredIfaces() {
23982404
enforceTetherAccessPermission();
23992405
return mTethering.getErroredIfaces();

services/java/com/android/server/NetworkManagementService.java

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class NetdResponseCode {
123123
public static final int InterfaceTxCounterResult = 217;
124124
public static final int InterfaceRxThrottleResult = 218;
125125
public static final int InterfaceTxThrottleResult = 219;
126+
public static final int QuotaCounterResult = 220;
127+
public static final int TetheringStatsResult = 221;
126128

127129
public static final int InterfaceChange = 600;
128130
public static final int BandwidthControl = 601;
@@ -1443,6 +1445,73 @@ private NetworkStats getNetworkStatsDetailUidstat(int limitUid) {
14431445
return stats;
14441446
}
14451447

1448+
@Override
1449+
public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
1450+
mContext.enforceCallingOrSelfPermission(
1451+
android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
1452+
1453+
if (ifacePairs.length % 2 != 0) {
1454+
throw new IllegalArgumentException(
1455+
"unexpected ifacePairs; length=" + ifacePairs.length);
1456+
}
1457+
1458+
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
1459+
for (int i = 0; i < ifacePairs.length; i += 2) {
1460+
final String ifaceIn = ifacePairs[i];
1461+
final String ifaceOut = ifacePairs[i + 1];
1462+
if (ifaceIn != null && ifaceOut != null) {
1463+
stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
1464+
}
1465+
}
1466+
return stats;
1467+
}
1468+
1469+
private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
1470+
final StringBuilder command = new StringBuilder();
1471+
command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut);
1472+
1473+
final String rsp;
1474+
try {
1475+
rsp = mConnector.doCommand(command.toString()).get(0);
1476+
} catch (NativeDaemonConnectorException e) {
1477+
throw new IllegalStateException("Error communicating to native daemon", e);
1478+
}
1479+
1480+
final String[] tok = rsp.split(" ");
1481+
/* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */
1482+
if (tok.length != 7) {
1483+
throw new IllegalStateException("Native daemon returned unexpected result: " + rsp);
1484+
}
1485+
1486+
final int code;
1487+
try {
1488+
code = Integer.parseInt(tok[0]);
1489+
} catch (NumberFormatException e) {
1490+
throw new IllegalStateException(
1491+
"Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut);
1492+
}
1493+
if (code != NetdResponseCode.TetheringStatsResult) {
1494+
throw new IllegalStateException(
1495+
"Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut);
1496+
}
1497+
1498+
try {
1499+
final NetworkStats.Entry entry = new NetworkStats.Entry();
1500+
entry.iface = ifaceIn;
1501+
entry.uid = UID_ALL;
1502+
entry.set = SET_DEFAULT;
1503+
entry.tag = TAG_NONE;
1504+
entry.rxBytes = Long.parseLong(tok[3]);
1505+
entry.rxPackets = Long.parseLong(tok[4]);
1506+
entry.txBytes = Long.parseLong(tok[5]);
1507+
entry.txPackets = Long.parseLong(tok[6]);
1508+
return entry;
1509+
} catch (NumberFormatException e) {
1510+
throw new IllegalStateException(
1511+
"problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
1512+
}
1513+
}
1514+
14461515
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
14471516
mContext.enforceCallingOrSelfPermission(
14481517
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");

services/java/com/android/server/connectivity/Tethering.java

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import android.app.Notification;
2020
import android.app.NotificationManager;
2121
import android.app.PendingIntent;
22-
import android.bluetooth.BluetoothPan;
2322
import android.content.BroadcastReceiver;
2423
import android.content.Context;
2524
import android.content.Intent;
@@ -28,15 +27,14 @@
2827
import android.content.res.Resources;
2928
import android.hardware.usb.UsbManager;
3029
import android.net.ConnectivityManager;
31-
import android.net.InterfaceConfiguration;
3230
import android.net.IConnectivityManager;
3331
import android.net.INetworkManagementEventObserver;
32+
import android.net.InterfaceConfiguration;
3433
import android.net.LinkAddress;
3534
import android.net.LinkProperties;
3635
import android.net.NetworkInfo;
3736
import android.net.NetworkUtils;
3837
import android.os.Binder;
39-
import android.os.Handler;
4038
import android.os.HandlerThread;
4139
import android.os.IBinder;
4240
import android.os.INetworkManagementService;
@@ -51,6 +49,7 @@
5149
import com.android.internal.util.IState;
5250
import com.android.internal.util.State;
5351
import com.android.internal.util.StateMachine;
52+
import com.google.android.collect.Lists;
5453

5554
import java.io.FileDescriptor;
5655
import java.io.PrintWriter;
@@ -59,16 +58,15 @@
5958
import java.util.Collection;
6059
import java.util.HashMap;
6160
import java.util.Iterator;
62-
import java.util.LinkedList;
6361
import java.util.Set;
62+
6463
/**
6564
* @hide
6665
*
6766
* Timeout
6867
*
6968
* TODO - look for parent classes and code sharing
7069
*/
71-
7270
public class Tethering extends INetworkManagementEventObserver.Stub {
7371

7472
private Context mContext;
@@ -629,6 +627,19 @@ public String[] getTetheredIfaces() {
629627
return retVal;
630628
}
631629

630+
public String[] getTetheredIfacePairs() {
631+
final ArrayList<String> list = Lists.newArrayList();
632+
synchronized (mIfaces) {
633+
for (TetherInterfaceSM sm : mIfaces.values()) {
634+
if (sm.isTethered()) {
635+
list.add(sm.mMyUpstreamIfaceName);
636+
list.add(sm.mIfaceName);
637+
}
638+
}
639+
}
640+
return list.toArray(new String[list.size()]);
641+
}
642+
632643
public String[] getTetherableIfaces() {
633644
ArrayList<String> list = new ArrayList<String>();
634645
synchronized (mIfaces) {

services/java/com/android/server/net/NetworkStatsService.java

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import static android.content.Intent.ACTION_UID_REMOVED;
2626
import static android.content.Intent.EXTRA_UID;
2727
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
28+
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
2829
import static android.net.NetworkStats.IFACE_ALL;
2930
import static android.net.NetworkStats.SET_ALL;
3031
import static android.net.NetworkStats.SET_DEFAULT;
@@ -34,6 +35,7 @@
3435
import static android.net.NetworkTemplate.buildTemplateMobileAll;
3536
import static android.net.NetworkTemplate.buildTemplateWifi;
3637
import static android.net.TrafficStats.UID_REMOVED;
38+
import static android.net.TrafficStats.UID_TETHERING;
3739
import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL;
3840
import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
3941
import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
@@ -68,6 +70,7 @@
6870
import android.net.NetworkStats;
6971
import android.net.NetworkStatsHistory;
7072
import android.net.NetworkTemplate;
73+
import android.net.TrafficStats;
7174
import android.os.Binder;
7275
import android.os.Environment;
7376
import android.os.Handler;
@@ -89,6 +92,7 @@
8992
import com.android.internal.os.AtomicFile;
9093
import com.android.internal.util.Objects;
9194
import com.android.server.EventLogTags;
95+
import com.android.server.connectivity.Tethering;
9296
import com.google.android.collect.Lists;
9397
import com.google.android.collect.Maps;
9498
import com.google.android.collect.Sets;
@@ -134,11 +138,12 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
134138
/** Flags to control detail level of poll event. */
135139
private static final int FLAG_POLL_NETWORK = 0x1;
136140
private static final int FLAG_POLL_UID = 0x2;
141+
private static final int FLAG_POLL_TETHER = 0x3;
137142
private static final int FLAG_PERSIST_NETWORK = 0x10;
138143
private static final int FLAG_PERSIST_UID = 0x20;
139144
private static final int FLAG_FORCE_PERSIST = 0x100;
140145

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;
142147
private static final int FLAG_PERSIST_ALL = FLAG_PERSIST_NETWORK | FLAG_PERSIST_UID;
143148

144149
private final Context mContext;
@@ -195,6 +200,7 @@ public interface NetworkStatsSettings {
195200
private NetworkStats mLastPollNetworkSnapshot;
196201
private NetworkStats mLastPollUidSnapshot;
197202
private NetworkStats mLastPollOperationsSnapshot;
203+
private NetworkStats mLastPollTetherSnapshot;
198204

199205
private NetworkStats mLastPersistNetworkSnapshot;
200206
private NetworkStats mLastPersistUidSnapshot;
@@ -258,6 +264,10 @@ public void systemReady() {
258264
final IntentFilter connFilter = new IntentFilter(CONNECTIVITY_ACTION_IMMEDIATE);
259265
mContext.registerReceiver(mConnReceiver, connFilter, CONNECTIVITY_INTERNAL, mHandler);
260266

267+
// watch for tethering changes
268+
final IntentFilter tetherFilter = new IntentFilter(ACTION_TETHER_STATE_CHANGED);
269+
mContext.registerReceiver(mTetherReceiver, tetherFilter, CONNECTIVITY_INTERNAL, mHandler);
270+
261271
// listen for periodic polling events
262272
final IntentFilter pollFilter = new IntentFilter(ACTION_NETWORK_STATS_POLL);
263273
mContext.registerReceiver(mPollReceiver, pollFilter, READ_NETWORK_USAGE_HISTORY, mHandler);
@@ -543,6 +553,18 @@ public void onReceive(Context context, Intent intent) {
543553
}
544554
};
545555

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+
546568
private BroadcastReceiver mPollReceiver = new BroadcastReceiver() {
547569
@Override
548570
public void onReceive(Context context, Intent intent) {
@@ -686,12 +708,14 @@ private void performPollLocked(int flags) {
686708

687709
boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0;
688710
boolean pollUid = (flags & FLAG_POLL_UID) != 0;
711+
boolean pollTether = (flags & FLAG_POLL_TETHER) != 0;
689712

690713
// when complete poll requested, any partial poll enables everything
691714
final boolean forceCompletePoll = mSettings.getForceCompletePoll();
692-
if (forceCompletePoll && (pollNetwork || pollUid)) {
715+
if (forceCompletePoll && (pollNetwork || pollUid || pollTether)) {
693716
pollNetwork = true;
694717
pollUid = true;
718+
pollTether = true;
695719
}
696720

697721
final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
@@ -723,6 +747,15 @@ private void performPollLocked(int flags) {
723747
}
724748
}
725749

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+
726759
if (pollUid) {
727760
final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
728761
performUidPollLocked(uidSnapshot, currentTime);
@@ -848,6 +881,38 @@ private void performUidPollLocked(NetworkStats uidSnapshot, long currentTime) {
848881
mOperations = new NetworkStats(0L, 10);
849882
}
850883

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+
851916
/**
852917
* Sample recent statistics summary into {@link EventLog}.
853918
*/

0 commit comments

Comments
 (0)