Merge "Move TrafficStats iface counters to xt_qtaguid."
This commit is contained in:
@@ -32,6 +32,9 @@ interface INetworkStatsService {
|
|||||||
|
|
||||||
/** Return data layer snapshot of UID network usage. */
|
/** Return data layer snapshot of UID network usage. */
|
||||||
NetworkStats getDataLayerSnapshotForUid(int uid);
|
NetworkStats getDataLayerSnapshotForUid(int uid);
|
||||||
|
/** Return set of any ifaces associated with mobile networks since boot. */
|
||||||
|
String[] getMobileIfaces();
|
||||||
|
|
||||||
/** Increment data layer count of operations performed for UID and tag. */
|
/** Increment data layer count of operations performed for UID and tag. */
|
||||||
void incrementOperationCount(int uid, int tag, int operationCount);
|
void incrementOperationCount(int uid, int tag, int operationCount);
|
||||||
|
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
public static final int MATCH_MOBILE_4G = 3;
|
public static final int MATCH_MOBILE_4G = 3;
|
||||||
public static final int MATCH_WIFI = 4;
|
public static final int MATCH_WIFI = 4;
|
||||||
public static final int MATCH_ETHERNET = 5;
|
public static final int MATCH_ETHERNET = 5;
|
||||||
|
public static final int MATCH_MOBILE_WILDCARD = 6;
|
||||||
|
public static final int MATCH_WIFI_WILDCARD = 7;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set of {@link NetworkInfo#getType()} that reflect data usage.
|
* Set of {@link NetworkInfo#getType()} that reflect data usage.
|
||||||
@@ -85,12 +87,20 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
|
return new NetworkTemplate(MATCH_MOBILE_4G, subscriberId, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Template to match {@link ConnectivityManager#TYPE_MOBILE} networks,
|
||||||
|
* regardless of IMSI.
|
||||||
|
*/
|
||||||
|
public static NetworkTemplate buildTemplateMobileWildcard() {
|
||||||
|
return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
|
* Template to match all {@link ConnectivityManager#TYPE_WIFI} networks,
|
||||||
* regardless of SSID.
|
* regardless of SSID.
|
||||||
*/
|
*/
|
||||||
public static NetworkTemplate buildTemplateWifiWildcard() {
|
public static NetworkTemplate buildTemplateWifiWildcard() {
|
||||||
return new NetworkTemplate(MATCH_WIFI, null, null);
|
return new NetworkTemplate(MATCH_WIFI_WILDCARD, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@@ -198,6 +208,10 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
return matchesWifi(ident);
|
return matchesWifi(ident);
|
||||||
case MATCH_ETHERNET:
|
case MATCH_ETHERNET:
|
||||||
return matchesEthernet(ident);
|
return matchesEthernet(ident);
|
||||||
|
case MATCH_MOBILE_WILDCARD:
|
||||||
|
return matchesMobileWildcard(ident);
|
||||||
|
case MATCH_WIFI_WILDCARD:
|
||||||
|
return matchesWifiWildcard(ident);
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("unknown network template");
|
throw new IllegalArgumentException("unknown network template");
|
||||||
}
|
}
|
||||||
@@ -257,13 +271,7 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
private boolean matchesWifi(NetworkIdentity ident) {
|
private boolean matchesWifi(NetworkIdentity ident) {
|
||||||
switch (ident.mType) {
|
switch (ident.mType) {
|
||||||
case TYPE_WIFI:
|
case TYPE_WIFI:
|
||||||
if (mNetworkId == null) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return Objects.equal(mNetworkId, ident.mNetworkId);
|
return Objects.equal(mNetworkId, ident.mNetworkId);
|
||||||
}
|
|
||||||
case TYPE_WIFI_P2P:
|
|
||||||
return mNetworkId == null;
|
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -279,6 +287,24 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean matchesMobileWildcard(NetworkIdentity ident) {
|
||||||
|
if (ident.mType == TYPE_WIMAX) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return contains(DATA_USAGE_NETWORK_TYPES, ident.mType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean matchesWifiWildcard(NetworkIdentity ident) {
|
||||||
|
switch (ident.mType) {
|
||||||
|
case TYPE_WIFI:
|
||||||
|
case TYPE_WIFI_P2P:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static String getMatchRuleName(int matchRule) {
|
private static String getMatchRuleName(int matchRule) {
|
||||||
switch (matchRule) {
|
switch (matchRule) {
|
||||||
case MATCH_MOBILE_3G_LOWER:
|
case MATCH_MOBILE_3G_LOWER:
|
||||||
@@ -291,6 +317,10 @@ public class NetworkTemplate implements Parcelable {
|
|||||||
return "WIFI";
|
return "WIFI";
|
||||||
case MATCH_ETHERNET:
|
case MATCH_ETHERNET:
|
||||||
return "ETHERNET";
|
return "ETHERNET";
|
||||||
|
case MATCH_MOBILE_WILDCARD:
|
||||||
|
return "MOBILE_WILDCARD";
|
||||||
|
case MATCH_WIFI_WILDCARD:
|
||||||
|
return "WIFI_WILDCARD";
|
||||||
default:
|
default:
|
||||||
return "UNKNOWN";
|
return "UNKNOWN";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -88,6 +88,16 @@ public class TrafficStats {
|
|||||||
*/
|
*/
|
||||||
public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
|
public static final int TAG_SYSTEM_BACKUP = 0xFFFFFF03;
|
||||||
|
|
||||||
|
private static INetworkStatsService sStatsService;
|
||||||
|
|
||||||
|
private synchronized static INetworkStatsService getStatsService() {
|
||||||
|
if (sStatsService == null) {
|
||||||
|
sStatsService = INetworkStatsService.Stub.asInterface(
|
||||||
|
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
||||||
|
}
|
||||||
|
return sStatsService;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Snapshot of {@link NetworkStats} when the currently active profiling
|
* Snapshot of {@link NetworkStats} when the currently active profiling
|
||||||
* session started, or {@code null} if no session active.
|
* session started, or {@code null} if no session active.
|
||||||
@@ -228,11 +238,9 @@ public class TrafficStats {
|
|||||||
* @param operationCount Number of operations to increment count by.
|
* @param operationCount Number of operations to increment count by.
|
||||||
*/
|
*/
|
||||||
public static void incrementOperationCount(int tag, int operationCount) {
|
public static void incrementOperationCount(int tag, int operationCount) {
|
||||||
final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
|
|
||||||
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
|
||||||
final int uid = android.os.Process.myUid();
|
final int uid = android.os.Process.myUid();
|
||||||
try {
|
try {
|
||||||
statsService.incrementOperationCount(uid, tag, operationCount);
|
getStatsService().incrementOperationCount(uid, tag, operationCount);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
@@ -257,7 +265,13 @@ public class TrafficStats {
|
|||||||
* @return number of packets. If the statistics are not supported by this device,
|
* @return number of packets. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getMobileTxPackets();
|
public static long getMobileTxPackets() {
|
||||||
|
long total = 0;
|
||||||
|
for (String iface : getMobileIfaces()) {
|
||||||
|
total += getTxPackets(iface);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of packets received through the mobile interface.
|
* Get the total number of packets received through the mobile interface.
|
||||||
@@ -265,7 +279,13 @@ public class TrafficStats {
|
|||||||
* @return number of packets. If the statistics are not supported by this device,
|
* @return number of packets. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getMobileRxPackets();
|
public static long getMobileRxPackets() {
|
||||||
|
long total = 0;
|
||||||
|
for (String iface : getMobileIfaces()) {
|
||||||
|
total += getRxPackets(iface);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of bytes transmitted through the mobile interface.
|
* Get the total number of bytes transmitted through the mobile interface.
|
||||||
@@ -273,7 +293,13 @@ public class TrafficStats {
|
|||||||
* @return number of bytes. If the statistics are not supported by this device,
|
* @return number of bytes. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getMobileTxBytes();
|
public static long getMobileTxBytes() {
|
||||||
|
long total = 0;
|
||||||
|
for (String iface : getMobileIfaces()) {
|
||||||
|
total += getTxBytes(iface);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of bytes received through the mobile interface.
|
* Get the total number of bytes received through the mobile interface.
|
||||||
@@ -281,7 +307,13 @@ public class TrafficStats {
|
|||||||
* @return number of bytes. If the statistics are not supported by this device,
|
* @return number of bytes. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getMobileRxBytes();
|
public static long getMobileRxBytes() {
|
||||||
|
long total = 0;
|
||||||
|
for (String iface : getMobileIfaces()) {
|
||||||
|
total += getRxBytes(iface);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of packets transmitted through the specified interface.
|
* Get the total number of packets transmitted through the specified interface.
|
||||||
@@ -290,7 +322,9 @@ public class TrafficStats {
|
|||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static native long getTxPackets(String iface);
|
public static long getTxPackets(String iface) {
|
||||||
|
return nativeGetIfaceStat(iface, TYPE_TX_PACKETS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of packets received through the specified interface.
|
* Get the total number of packets received through the specified interface.
|
||||||
@@ -299,7 +333,9 @@ public class TrafficStats {
|
|||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static native long getRxPackets(String iface);
|
public static long getRxPackets(String iface) {
|
||||||
|
return nativeGetIfaceStat(iface, TYPE_RX_PACKETS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of bytes transmitted through the specified interface.
|
* Get the total number of bytes transmitted through the specified interface.
|
||||||
@@ -308,7 +344,9 @@ public class TrafficStats {
|
|||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static native long getTxBytes(String iface);
|
public static long getTxBytes(String iface) {
|
||||||
|
return nativeGetIfaceStat(iface, TYPE_TX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of bytes received through the specified interface.
|
* Get the total number of bytes received through the specified interface.
|
||||||
@@ -317,8 +355,9 @@ public class TrafficStats {
|
|||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
* @hide
|
* @hide
|
||||||
*/
|
*/
|
||||||
public static native long getRxBytes(String iface);
|
public static long getRxBytes(String iface) {
|
||||||
|
return nativeGetIfaceStat(iface, TYPE_RX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of packets sent through all network interfaces.
|
* Get the total number of packets sent through all network interfaces.
|
||||||
@@ -326,7 +365,9 @@ public class TrafficStats {
|
|||||||
* @return the number of packets. If the statistics are not supported by this device,
|
* @return the number of packets. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getTotalTxPackets();
|
public static long getTotalTxPackets() {
|
||||||
|
return nativeGetTotalStat(TYPE_TX_PACKETS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of packets received through all network interfaces.
|
* Get the total number of packets received through all network interfaces.
|
||||||
@@ -334,7 +375,9 @@ public class TrafficStats {
|
|||||||
* @return number of packets. If the statistics are not supported by this device,
|
* @return number of packets. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getTotalRxPackets();
|
public static long getTotalRxPackets() {
|
||||||
|
return nativeGetTotalStat(TYPE_RX_PACKETS);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of bytes sent through all network interfaces.
|
* Get the total number of bytes sent through all network interfaces.
|
||||||
@@ -342,7 +385,9 @@ public class TrafficStats {
|
|||||||
* @return number of bytes. If the statistics are not supported by this device,
|
* @return number of bytes. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getTotalTxBytes();
|
public static long getTotalTxBytes() {
|
||||||
|
return nativeGetTotalStat(TYPE_TX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the total number of bytes received through all network interfaces.
|
* Get the total number of bytes received through all network interfaces.
|
||||||
@@ -350,7 +395,9 @@ public class TrafficStats {
|
|||||||
* @return number of bytes. If the statistics are not supported by this device,
|
* @return number of bytes. If the statistics are not supported by this device,
|
||||||
* {@link #UNSUPPORTED} will be returned.
|
* {@link #UNSUPPORTED} will be returned.
|
||||||
*/
|
*/
|
||||||
public static native long getTotalRxBytes();
|
public static long getTotalRxBytes() {
|
||||||
|
return nativeGetTotalStat(TYPE_RX_BYTES);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of bytes sent through the network for this UID.
|
* Get the number of bytes sent through the network for this UID.
|
||||||
@@ -483,7 +530,6 @@ public class TrafficStats {
|
|||||||
*/
|
*/
|
||||||
public static native long getUidTcpRxSegments(int uid);
|
public static native long getUidTcpRxSegments(int uid);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of UDP packets sent for this UID.
|
* Get the number of UDP packets sent for this UID.
|
||||||
* Includes DNS requests.
|
* Includes DNS requests.
|
||||||
@@ -515,13 +561,33 @@ public class TrafficStats {
|
|||||||
* special permission.
|
* special permission.
|
||||||
*/
|
*/
|
||||||
private static NetworkStats getDataLayerSnapshotForUid(Context context) {
|
private static NetworkStats getDataLayerSnapshotForUid(Context context) {
|
||||||
final INetworkStatsService statsService = INetworkStatsService.Stub.asInterface(
|
|
||||||
ServiceManager.getService(Context.NETWORK_STATS_SERVICE));
|
|
||||||
final int uid = android.os.Process.myUid();
|
final int uid = android.os.Process.myUid();
|
||||||
try {
|
try {
|
||||||
return statsService.getDataLayerSnapshotForUid(uid);
|
return getStatsService().getDataLayerSnapshotForUid(uid);
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return set of any ifaces associated with mobile networks since boot.
|
||||||
|
* Interfaces are never removed from this list, so counters should always be
|
||||||
|
* monotonic.
|
||||||
|
*/
|
||||||
|
private static String[] getMobileIfaces() {
|
||||||
|
try {
|
||||||
|
return getStatsService().getMobileIfaces();
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: keep these in sync with android_net_TrafficStats.cpp
|
||||||
|
private static final int TYPE_RX_BYTES = 0;
|
||||||
|
private static final int TYPE_RX_PACKETS = 1;
|
||||||
|
private static final int TYPE_TX_BYTES = 2;
|
||||||
|
private static final int TYPE_TX_PACKETS = 3;
|
||||||
|
|
||||||
|
private static native long nativeGetTotalStat(int type);
|
||||||
|
private static native long nativeGetIfaceStat(String iface, int type);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,9 @@
|
|||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
|
static const uint64_t VALUE_UNKNOWN = -1;
|
||||||
|
static const char* IFACE_STAT_ALL = "/proc/net/xt_qtaguid/iface_stat_all";
|
||||||
|
|
||||||
enum Tx_Rx {
|
enum Tx_Rx {
|
||||||
TX,
|
TX,
|
||||||
RX
|
RX
|
||||||
@@ -42,6 +45,21 @@ enum Tcp_Udp {
|
|||||||
TCP_AND_UDP
|
TCP_AND_UDP
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// NOTE: keep these in sync with TrafficStats.java
|
||||||
|
enum IfaceStatType {
|
||||||
|
RX_BYTES = 0,
|
||||||
|
RX_PACKETS = 1,
|
||||||
|
TX_BYTES = 2,
|
||||||
|
TX_PACKETS = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IfaceStat {
|
||||||
|
uint64_t rxBytes;
|
||||||
|
uint64_t rxPackets;
|
||||||
|
uint64_t txBytes;
|
||||||
|
uint64_t txPackets;
|
||||||
|
};
|
||||||
|
|
||||||
// Returns an ASCII decimal number read from the specified file, -1 on error.
|
// Returns an ASCII decimal number read from the specified file, -1 on error.
|
||||||
static jlong readNumber(char const* filename) {
|
static jlong readNumber(char const* filename) {
|
||||||
char buf[80];
|
char buf[80];
|
||||||
@@ -63,130 +81,82 @@ static jlong readNumber(char const* filename) {
|
|||||||
return atoll(buf);
|
return atoll(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* mobile_iface_list[] = {
|
static int parseIfaceStat(const char* iface, struct IfaceStat* stat) {
|
||||||
"rmnet0",
|
FILE *fp = fopen(IFACE_STAT_ALL, "r");
|
||||||
"rmnet1",
|
if (!fp) {
|
||||||
"rmnet2",
|
return errno;
|
||||||
"rmnet3",
|
|
||||||
"cdma_rmnet4",
|
|
||||||
"ppp0",
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
static jlong getAll(const char** iface_list, const char* what) {
|
|
||||||
|
|
||||||
char filename[80];
|
|
||||||
int idx = 0;
|
|
||||||
bool supported = false;
|
|
||||||
jlong total = 0;
|
|
||||||
while (iface_list[idx] != 0) {
|
|
||||||
|
|
||||||
snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s",
|
|
||||||
iface_list[idx], what);
|
|
||||||
jlong number = readNumber(filename);
|
|
||||||
if (number >= 0) {
|
|
||||||
supported = true;
|
|
||||||
total += number;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
if (supported) return total;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the sum of numbers from the specified path under /sys/class/net/*,
|
|
||||||
// -1 if no such file exists.
|
|
||||||
static jlong readTotal(char const* suffix) {
|
|
||||||
char filename[PATH_MAX] = "/sys/class/net/";
|
|
||||||
DIR *dir = opendir(filename);
|
|
||||||
if (dir == NULL) {
|
|
||||||
ALOGE("Can't list %s: %s", filename, strerror(errno));
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = strlen(filename);
|
char buffer[256];
|
||||||
jlong total = -1;
|
char cur_iface[32];
|
||||||
while (struct dirent *entry = readdir(dir)) {
|
int active;
|
||||||
// Skip ., .., and localhost interfaces.
|
uint64_t rxBytes, rxPackets, txBytes, txPackets, devRxBytes, devRxPackets, devTxBytes,
|
||||||
if (entry->d_name[0] != '.' && strncmp(entry->d_name, "lo", 2) != 0) {
|
devTxPackets;
|
||||||
strlcpy(filename + len, entry->d_name, sizeof(filename) - len);
|
|
||||||
strlcat(filename, suffix, sizeof(filename));
|
while (fgets(buffer, 256, fp) != NULL) {
|
||||||
jlong num = readNumber(filename);
|
if (sscanf(buffer, "%31s %d %llu %llu %llu %llu %llu %llu %llu %llu", cur_iface, &active,
|
||||||
if (num >= 0) total = total < 0 ? num : total + num;
|
&rxBytes, &rxPackets, &txBytes, &txPackets, &devRxBytes, &devRxPackets,
|
||||||
|
&devTxBytes, &devTxPackets) != 10) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iface || !strcmp(iface, cur_iface)) {
|
||||||
|
stat->rxBytes += rxBytes;
|
||||||
|
stat->rxPackets += rxPackets;
|
||||||
|
stat->txBytes += txBytes;
|
||||||
|
stat->txPackets += txPackets;
|
||||||
|
|
||||||
|
if (active) {
|
||||||
|
stat->rxBytes += devRxBytes;
|
||||||
|
stat->rxPackets += devRxPackets;
|
||||||
|
stat->txBytes += devTxBytes;
|
||||||
|
stat->txPackets += devTxPackets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
closedir(dir);
|
fclose(fp);
|
||||||
return total;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mobile stats get accessed a lot more often than total stats.
|
static uint64_t getIfaceStatType(const char* iface, IfaceStatType type) {
|
||||||
// Note the individual files can come and go at runtime, so we check
|
struct IfaceStat stat;
|
||||||
// each file every time (rather than caching which ones exist).
|
memset(&stat, 0, sizeof(IfaceStat));
|
||||||
|
|
||||||
static jlong getMobileTxPackets(JNIEnv* env, jobject clazz) {
|
if (parseIfaceStat(iface, &stat)) {
|
||||||
return getAll(mobile_iface_list, "tx_packets");
|
return VALUE_UNKNOWN;
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getMobileRxPackets(JNIEnv* env, jobject clazz) {
|
|
||||||
return getAll(mobile_iface_list, "rx_packets");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getMobileTxBytes(JNIEnv* env, jobject clazz) {
|
|
||||||
return getAll(mobile_iface_list, "tx_bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getMobileRxBytes(JNIEnv* env, jobject clazz) {
|
|
||||||
return getAll(mobile_iface_list, "rx_bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getData(JNIEnv* env, const char* what, jstring javaInterface) {
|
|
||||||
ScopedUtfChars interface(env, javaInterface);
|
|
||||||
if (interface.c_str() == NULL) {
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
char filename[80];
|
switch (type) {
|
||||||
snprintf(filename, sizeof(filename), "/sys/class/net/%s/statistics/%s", interface.c_str(), what);
|
case RX_BYTES:
|
||||||
return readNumber(filename);
|
return stat.rxBytes;
|
||||||
|
case RX_PACKETS:
|
||||||
|
return stat.rxPackets;
|
||||||
|
case TX_BYTES:
|
||||||
|
return stat.txBytes;
|
||||||
|
case TX_PACKETS:
|
||||||
|
return stat.txPackets;
|
||||||
|
default:
|
||||||
|
return VALUE_UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong getTxPackets(JNIEnv* env, jobject clazz, jstring interface) {
|
static jlong getTotalStat(JNIEnv* env, jclass clazz, jint type) {
|
||||||
return getData(env, "tx_packets", interface);
|
return getIfaceStatType(NULL, (IfaceStatType) type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong getRxPackets(JNIEnv* env, jobject clazz, jstring interface) {
|
static jlong getIfaceStat(JNIEnv* env, jclass clazz, jstring iface, jint type) {
|
||||||
return getData(env, "rx_packets", interface);
|
struct IfaceStat stat;
|
||||||
|
const char* ifaceChars = env->GetStringUTFChars(iface, NULL);
|
||||||
|
if (ifaceChars) {
|
||||||
|
uint64_t stat = getIfaceStatType(ifaceChars, (IfaceStatType) type);
|
||||||
|
env->ReleaseStringUTFChars(iface, ifaceChars);
|
||||||
|
return stat;
|
||||||
|
} else {
|
||||||
|
return VALUE_UNKNOWN;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static jlong getTxBytes(JNIEnv* env, jobject clazz, jstring interface) {
|
|
||||||
return getData(env, "tx_bytes", interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getRxBytes(JNIEnv* env, jobject clazz, jstring interface) {
|
|
||||||
return getData(env, "rx_bytes", interface);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Total stats are read less often, so we're willing to put up
|
|
||||||
// with listing the directory and concatenating filenames.
|
|
||||||
|
|
||||||
static jlong getTotalTxPackets(JNIEnv* env, jobject clazz) {
|
|
||||||
return readTotal("/statistics/tx_packets");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getTotalRxPackets(JNIEnv* env, jobject clazz) {
|
|
||||||
return readTotal("/statistics/rx_packets");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getTotalTxBytes(JNIEnv* env, jobject clazz) {
|
|
||||||
return readTotal("/statistics/tx_bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
static jlong getTotalRxBytes(JNIEnv* env, jobject clazz) {
|
|
||||||
return readTotal("/statistics/rx_bytes");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per-UID stats require reading from a constructed filename.
|
// Per-UID stats require reading from a constructed filename.
|
||||||
|
|
||||||
@@ -323,18 +293,8 @@ static jlong getUidUdpRxPackets(JNIEnv* env, jobject clazz, jint uid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static JNINativeMethod gMethods[] = {
|
static JNINativeMethod gMethods[] = {
|
||||||
{"getMobileTxPackets", "()J", (void*) getMobileTxPackets},
|
{"nativeGetTotalStat", "(I)J", (void*) getTotalStat},
|
||||||
{"getMobileRxPackets", "()J", (void*) getMobileRxPackets},
|
{"nativeGetIfaceStat", "(Ljava/lang/String;I)J", (void*) getIfaceStat},
|
||||||
{"getMobileTxBytes", "()J", (void*) getMobileTxBytes},
|
|
||||||
{"getMobileRxBytes", "()J", (void*) getMobileRxBytes},
|
|
||||||
{"getTxPackets", "(Ljava/lang/String;)J", (void*) getTxPackets},
|
|
||||||
{"getRxPackets", "(Ljava/lang/String;)J", (void*) getRxPackets},
|
|
||||||
{"getTxBytes", "(Ljava/lang/String;)J", (void*) getTxBytes},
|
|
||||||
{"getRxBytes", "(Ljava/lang/String;)J", (void*) getRxBytes},
|
|
||||||
{"getTotalTxPackets", "()J", (void*) getTotalTxPackets},
|
|
||||||
{"getTotalRxPackets", "()J", (void*) getTotalRxPackets},
|
|
||||||
{"getTotalTxBytes", "()J", (void*) getTotalTxBytes},
|
|
||||||
{"getTotalRxBytes", "()J", (void*) getTotalRxBytes},
|
|
||||||
|
|
||||||
/* Per-UID Stats */
|
/* Per-UID Stats */
|
||||||
{"getUidTxBytes", "(I)J", (void*) getUidTxBytes},
|
{"getUidTxBytes", "(I)J", (void*) getUidTxBytes},
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import static android.content.Intent.ACTION_UID_REMOVED;
|
|||||||
import static android.content.Intent.EXTRA_UID;
|
import static android.content.Intent.EXTRA_UID;
|
||||||
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
|
import static android.net.ConnectivityManager.ACTION_TETHER_STATE_CHANGED;
|
||||||
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
|
import static android.net.ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE;
|
||||||
|
import static android.net.ConnectivityManager.isNetworkTypeMobile;
|
||||||
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
|
import static android.net.NetworkIdentity.COMBINE_SUBTYPE_ENABLED;
|
||||||
import static android.net.NetworkStats.IFACE_ALL;
|
import static android.net.NetworkStats.IFACE_ALL;
|
||||||
import static android.net.NetworkStats.SET_ALL;
|
import static android.net.NetworkStats.SET_ALL;
|
||||||
@@ -33,7 +34,7 @@ import static android.net.NetworkStats.SET_DEFAULT;
|
|||||||
import static android.net.NetworkStats.SET_FOREGROUND;
|
import static android.net.NetworkStats.SET_FOREGROUND;
|
||||||
import static android.net.NetworkStats.TAG_NONE;
|
import static android.net.NetworkStats.TAG_NONE;
|
||||||
import static android.net.NetworkStats.UID_ALL;
|
import static android.net.NetworkStats.UID_ALL;
|
||||||
import static android.net.NetworkTemplate.buildTemplateMobileAll;
|
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
|
||||||
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
|
import static android.net.NetworkTemplate.buildTemplateWifiWildcard;
|
||||||
import static android.net.TrafficStats.MB_IN_BYTES;
|
import static android.net.TrafficStats.MB_IN_BYTES;
|
||||||
import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
|
import static android.provider.Settings.Secure.NETSTATS_DEV_BUCKET_DURATION;
|
||||||
@@ -54,6 +55,8 @@ import static android.text.format.DateUtils.DAY_IN_MILLIS;
|
|||||||
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
import static android.text.format.DateUtils.HOUR_IN_MILLIS;
|
||||||
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
|
||||||
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
|
import static android.text.format.DateUtils.SECOND_IN_MILLIS;
|
||||||
|
import static com.android.internal.util.ArrayUtils.appendElement;
|
||||||
|
import static com.android.internal.util.ArrayUtils.contains;
|
||||||
import static com.android.internal.util.Preconditions.checkNotNull;
|
import static com.android.internal.util.Preconditions.checkNotNull;
|
||||||
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
|
import static com.android.server.NetworkManagementService.LIMIT_GLOBAL_ALERT;
|
||||||
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
|
import static com.android.server.NetworkManagementSocketTagger.resetKernelUidStats;
|
||||||
@@ -194,6 +197,8 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
|
private HashMap<String, NetworkIdentitySet> mActiveIfaces = Maps.newHashMap();
|
||||||
/** Current default active iface. */
|
/** Current default active iface. */
|
||||||
private String mActiveIface;
|
private String mActiveIface;
|
||||||
|
/** Set of any ifaces associated with mobile networks since boot. */
|
||||||
|
private String[] mMobileIfaces = new String[0];
|
||||||
|
|
||||||
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
|
private final DropBoxNonMonotonicObserver mNonMonotonicObserver =
|
||||||
new DropBoxNonMonotonicObserver();
|
new DropBoxNonMonotonicObserver();
|
||||||
@@ -516,6 +521,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
return dataLayer;
|
return dataLayer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getMobileIfaces() {
|
||||||
|
return mMobileIfaces;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void incrementOperationCount(int uid, int tag, int operationCount) {
|
public void incrementOperationCount(int uid, int tag, int operationCount) {
|
||||||
if (Binder.getCallingUid() != uid) {
|
if (Binder.getCallingUid() != uid) {
|
||||||
@@ -735,6 +745,13 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
|
ident.add(NetworkIdentity.buildNetworkIdentity(mContext, state));
|
||||||
|
|
||||||
|
// remember any ifaces associated with mobile networks
|
||||||
|
if (isNetworkTypeMobile(state.networkInfo.getType())) {
|
||||||
|
if (!contains(mMobileIfaces, iface)) {
|
||||||
|
mMobileIfaces = appendElement(String.class, mMobileIfaces, iface);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -861,7 +878,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
NetworkStats.Entry uidTotal;
|
NetworkStats.Entry uidTotal;
|
||||||
|
|
||||||
// collect mobile sample
|
// collect mobile sample
|
||||||
template = buildTemplateMobileAll(getActiveSubscriberId(mContext));
|
template = buildTemplateMobileWildcard();
|
||||||
devTotal = mDevRecorder.getTotalSinceBootLocked(template);
|
devTotal = mDevRecorder.getTotalSinceBootLocked(template);
|
||||||
xtTotal = new NetworkStats.Entry();
|
xtTotal = new NetworkStats.Entry();
|
||||||
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
|
uidTotal = mUidRecorder.getTotalSinceBootLocked(template);
|
||||||
@@ -1022,12 +1039,6 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private static String getActiveSubscriberId(Context context) {
|
|
||||||
final TelephonyManager telephony = (TelephonyManager) context.getSystemService(
|
|
||||||
Context.TELEPHONY_SERVICE);
|
|
||||||
return telephony.getSubscriberId();
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean isBandwidthControlEnabled() {
|
private boolean isBandwidthControlEnabled() {
|
||||||
try {
|
try {
|
||||||
return mNetworkManager.isBandwidthControlEnabled();
|
return mNetworkManager.isBandwidthControlEnabled();
|
||||||
|
|||||||
Reference in New Issue
Block a user