diff --git a/core/java/android/net/IConnectivityManager.aidl b/core/java/android/net/IConnectivityManager.aidl index eef658e4591a1..70460087ca912 100644 --- a/core/java/android/net/IConnectivityManager.aidl +++ b/core/java/android/net/IConnectivityManager.aidl @@ -83,6 +83,12 @@ interface IConnectivityManager String[] getTetheredIfaces(); + /** + * Return list of interface pairs that are actively tethered. Even indexes are + * remote interface, and odd indexes are corresponding local interfaces. + */ + String[] getTetheredIfacePairs(); + String[] getTetheringErroredIfaces(); String[] getTetherableUsbRegexs(); diff --git a/core/java/android/net/TrafficStats.java b/core/java/android/net/TrafficStats.java index 47cfa73de0d80..18eb9f69daf81 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/core/java/android/os/INetworkManagementService.aidl b/core/java/android/os/INetworkManagementService.aidl
index 4e5645d53beb2..66373fe242e63 100644
--- a/core/java/android/os/INetworkManagementService.aidl
+++ b/core/java/android/os/INetworkManagementService.aidl
@@ -230,6 +230,13 @@ interface INetworkManagementService
*/
NetworkStats getNetworkStatsUidDetail(int uid);
+ /**
+ * Return summary of network statistics for the requested pairs of
+ * tethering interfaces. Even indexes are remote interface, and odd
+ * indexes are corresponding local interfaces.
+ */
+ NetworkStats getNetworkStatsTethering(in String[] ifacePairs);
+
/**
* Set quota for an interface.
*/
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 2348d76bb6169..e0a2adc0fd706 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -2394,6 +2394,12 @@ public class ConnectivityService extends IConnectivityManager.Stub {
return mTethering.getTetheredIfaces();
}
+ @Override
+ public String[] getTetheredIfacePairs() {
+ enforceTetherAccessPermission();
+ return mTethering.getTetheredIfacePairs();
+ }
+
public String[] getTetheringErroredIfaces() {
enforceTetherAccessPermission();
return mTethering.getErroredIfaces();
diff --git a/services/java/com/android/server/NetworkManagementService.java b/services/java/com/android/server/NetworkManagementService.java
index c517965759fbe..0cffb15b37580 100644
--- a/services/java/com/android/server/NetworkManagementService.java
+++ b/services/java/com/android/server/NetworkManagementService.java
@@ -123,6 +123,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub
public static final int InterfaceTxCounterResult = 217;
public static final int InterfaceRxThrottleResult = 218;
public static final int InterfaceTxThrottleResult = 219;
+ public static final int QuotaCounterResult = 220;
+ public static final int TetheringStatsResult = 221;
public static final int InterfaceChange = 600;
public static final int BandwidthControl = 601;
@@ -1443,6 +1445,73 @@ public class NetworkManagementService extends INetworkManagementService.Stub
return stats;
}
+ @Override
+ public NetworkStats getNetworkStatsTethering(String[] ifacePairs) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.ACCESS_NETWORK_STATE, "NetworkManagementService");
+
+ if (ifacePairs.length % 2 != 0) {
+ throw new IllegalArgumentException(
+ "unexpected ifacePairs; length=" + ifacePairs.length);
+ }
+
+ final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
+ for (int i = 0; i < ifacePairs.length; i += 2) {
+ final String ifaceIn = ifacePairs[i];
+ final String ifaceOut = ifacePairs[i + 1];
+ if (ifaceIn != null && ifaceOut != null) {
+ stats.combineValues(getNetworkStatsTethering(ifaceIn, ifaceOut));
+ }
+ }
+ return stats;
+ }
+
+ private NetworkStats.Entry getNetworkStatsTethering(String ifaceIn, String ifaceOut) {
+ final StringBuilder command = new StringBuilder();
+ command.append("bandwidth gettetherstats ").append(ifaceIn).append(" ").append(ifaceOut);
+
+ final String rsp;
+ try {
+ rsp = mConnector.doCommand(command.toString()).get(0);
+ } catch (NativeDaemonConnectorException e) {
+ throw new IllegalStateException("Error communicating to native daemon", e);
+ }
+
+ final String[] tok = rsp.split(" ");
+ /* Expecting: "code ifaceIn ifaceOut rx_bytes rx_packets tx_bytes tx_packets" */
+ if (tok.length != 7) {
+ throw new IllegalStateException("Native daemon returned unexpected result: " + rsp);
+ }
+
+ final int code;
+ try {
+ code = Integer.parseInt(tok[0]);
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(
+ "Failed to parse native daemon return code for " + ifaceIn + " " + ifaceOut);
+ }
+ if (code != NetdResponseCode.TetheringStatsResult) {
+ throw new IllegalStateException(
+ "Unexpected return code from native daemon for " + ifaceIn + " " + ifaceOut);
+ }
+
+ try {
+ final NetworkStats.Entry entry = new NetworkStats.Entry();
+ entry.iface = ifaceIn;
+ entry.uid = UID_ALL;
+ entry.set = SET_DEFAULT;
+ entry.tag = TAG_NONE;
+ entry.rxBytes = Long.parseLong(tok[3]);
+ entry.rxPackets = Long.parseLong(tok[4]);
+ entry.txBytes = Long.parseLong(tok[5]);
+ entry.txPackets = Long.parseLong(tok[6]);
+ return entry;
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException(
+ "problem parsing tethering stats for " + ifaceIn + " " + ifaceOut + ": " + e);
+ }
+ }
+
public void setInterfaceThrottle(String iface, int rxKbps, int txKbps) {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CHANGE_NETWORK_STATE, "NetworkManagementService");
diff --git a/services/java/com/android/server/connectivity/Tethering.java b/services/java/com/android/server/connectivity/Tethering.java
index ae8b89d146967..52868242750f5 100644
--- a/services/java/com/android/server/connectivity/Tethering.java
+++ b/services/java/com/android/server/connectivity/Tethering.java
@@ -19,7 +19,6 @@ package com.android.server.connectivity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.bluetooth.BluetoothPan;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -28,15 +27,14 @@ import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.hardware.usb.UsbManager;
import android.net.ConnectivityManager;
-import android.net.InterfaceConfiguration;
import android.net.IConnectivityManager;
import android.net.INetworkManagementEventObserver;
+import android.net.InterfaceConfiguration;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.NetworkInfo;
import android.net.NetworkUtils;
import android.os.Binder;
-import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.INetworkManagementService;
@@ -51,6 +49,7 @@ import com.android.internal.telephony.Phone;
import com.android.internal.util.IState;
import com.android.internal.util.State;
import com.android.internal.util.StateMachine;
+import com.google.android.collect.Lists;
import java.io.FileDescriptor;
import java.io.PrintWriter;
@@ -59,8 +58,8 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
-import java.util.LinkedList;
import java.util.Set;
+
/**
* @hide
*
@@ -68,7 +67,6 @@ import java.util.Set;
*
* TODO - look for parent classes and code sharing
*/
-
public class Tethering extends INetworkManagementEventObserver.Stub {
private Context mContext;
@@ -629,6 +627,19 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
return retVal;
}
+ public String[] getTetheredIfacePairs() {
+ final ArrayList