Merge "Merge "Add tether offload traffic to interface stats as well." into oc-mr1-dev am: 21bc3a39a4 am: 1af850fdfe"
This commit is contained in:
committed by
Android (Google) Code Review
commit
f751caf642
@@ -30,7 +30,10 @@ import android.net.NetworkStats;
|
||||
*/
|
||||
interface ITetheringStatsProvider {
|
||||
// Returns cumulative statistics for all tethering sessions since boot, on all upstreams.
|
||||
NetworkStats getTetherStats();
|
||||
// @code {how} is one of the NetworkStats.STATS_PER_* constants. If {@code how} is
|
||||
// {@code STATS_PER_IFACE}, the provider should not include any traffic that is already
|
||||
// counted by kernel interface counters.
|
||||
NetworkStats getTetherStats(int how);
|
||||
|
||||
// Sets the interface quota for the specified upstream interface. This is defined as the number
|
||||
// of bytes, starting from zero and counting from now, after which data should stop being
|
||||
|
||||
@@ -82,6 +82,11 @@ public class NetworkStats implements Parcelable {
|
||||
/** {@link #roaming} value where roaming data is accounted. */
|
||||
public static final int ROAMING_YES = 1;
|
||||
|
||||
/** Denotes a request for stats at the interface level. */
|
||||
public static final int STATS_PER_IFACE = 0;
|
||||
/** Denotes a request for stats at the interface and UID level. */
|
||||
public static final int STATS_PER_UID = 1;
|
||||
|
||||
// TODO: move fields to "mVariable" notation
|
||||
|
||||
/**
|
||||
|
||||
@@ -281,7 +281,7 @@ interface INetworkManagementService
|
||||
/**
|
||||
* Return summary of network statistics all tethering interfaces.
|
||||
*/
|
||||
NetworkStats getNetworkStatsTethering();
|
||||
NetworkStats getNetworkStatsTethering(int how);
|
||||
|
||||
/**
|
||||
* Set quota for an interface.
|
||||
|
||||
@@ -34,6 +34,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DENY;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_TYPE_BLACKLIST;
|
||||
import static android.net.NetworkPolicyManager.FIREWALL_TYPE_WHITELIST;
|
||||
import static android.net.NetworkStats.SET_DEFAULT;
|
||||
import static android.net.NetworkStats.STATS_PER_UID;
|
||||
import static android.net.NetworkStats.TAG_ALL;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
@@ -1863,7 +1864,13 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
|
||||
private class NetdTetheringStatsProvider extends ITetheringStatsProvider.Stub {
|
||||
@Override
|
||||
public NetworkStats getTetherStats() {
|
||||
public NetworkStats getTetherStats(int how) {
|
||||
// We only need to return per-UID stats. Per-device stats are already counted by
|
||||
// interface counters.
|
||||
if (how != STATS_PER_UID) {
|
||||
return new NetworkStats(SystemClock.elapsedRealtime(), 0);
|
||||
}
|
||||
|
||||
final NativeDaemonEvent[] events;
|
||||
try {
|
||||
events = mConnector.executeForList("bandwidth", "gettetherstats");
|
||||
@@ -1906,14 +1913,14 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
|
||||
@Override
|
||||
public NetworkStats getNetworkStatsTethering() {
|
||||
public NetworkStats getNetworkStatsTethering(int how) {
|
||||
mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
|
||||
|
||||
final NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 1);
|
||||
synchronized (mTetheringStatsProviders) {
|
||||
for (ITetheringStatsProvider provider: mTetheringStatsProviders.keySet()) {
|
||||
try {
|
||||
stats.combineAllValues(provider.getTetherStats());
|
||||
stats.combineAllValues(provider.getTetherStats(how));
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Problem reading tethering stats from " +
|
||||
mTetheringStatsProviders.get(provider) + ": " + e);
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import static android.net.NetworkStats.SET_DEFAULT;
|
||||
import static android.net.NetworkStats.STATS_PER_UID;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.TrafficStats.UID_TETHERING;
|
||||
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
|
||||
|
||||
@@ -202,16 +204,18 @@ public class OffloadController {
|
||||
|
||||
private class OffloadTetheringStatsProvider extends ITetheringStatsProvider.Stub {
|
||||
@Override
|
||||
public NetworkStats getTetherStats() {
|
||||
public NetworkStats getTetherStats(int how) {
|
||||
NetworkStats stats = new NetworkStats(SystemClock.elapsedRealtime(), 0);
|
||||
|
||||
// We can't just post to mHandler because we are mostly (but not always) called by
|
||||
// NetworkStatsService#performPollLocked, which is (currently) on the same thread as us.
|
||||
mHandler.runWithScissors(() -> {
|
||||
// We have to report both per-interface and per-UID stats, because offloaded traffic
|
||||
// is not seen by kernel interface counters.
|
||||
NetworkStats.Entry entry = new NetworkStats.Entry();
|
||||
entry.set = SET_DEFAULT;
|
||||
entry.tag = TAG_NONE;
|
||||
entry.uid = UID_TETHERING;
|
||||
entry.uid = (how == STATS_PER_UID) ? UID_TETHERING : UID_ALL;
|
||||
|
||||
updateStatsForCurrentUpstream();
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ import static android.net.NetworkStats.IFACE_ALL;
|
||||
import static android.net.NetworkStats.SET_ALL;
|
||||
import static android.net.NetworkStats.SET_DEFAULT;
|
||||
import static android.net.NetworkStats.SET_FOREGROUND;
|
||||
import static android.net.NetworkStats.STATS_PER_IFACE;
|
||||
import static android.net.NetworkStats.STATS_PER_UID;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.NetworkTemplate.buildTemplateMobileWildcard;
|
||||
@@ -1041,6 +1043,11 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
final NetworkStats xtSnapshot = getNetworkStatsXt();
|
||||
final NetworkStats devSnapshot = mNetworkManager.getNetworkStatsSummaryDev();
|
||||
|
||||
// Tethering snapshot for dev and xt stats. Counts per-interface data from tethering stats
|
||||
// providers that isn't already counted by dev and XT stats.
|
||||
final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_IFACE);
|
||||
xtSnapshot.combineAllValues(tetherSnapshot);
|
||||
devSnapshot.combineAllValues(tetherSnapshot);
|
||||
|
||||
// For xt/dev, we pass a null VPN array because usage is aggregated by UID, so VPN traffic
|
||||
// can't be reattributed to responsible apps.
|
||||
@@ -1371,14 +1378,14 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
final NetworkStats uidSnapshot = mNetworkManager.getNetworkStatsUidDetail(UID_ALL);
|
||||
|
||||
// fold tethering stats and operations into uid snapshot
|
||||
final NetworkStats tetherSnapshot = getNetworkStatsTethering();
|
||||
final NetworkStats tetherSnapshot = getNetworkStatsTethering(STATS_PER_UID);
|
||||
uidSnapshot.combineAllValues(tetherSnapshot);
|
||||
|
||||
final TelephonyManager telephonyManager = (TelephonyManager) mContext.getSystemService(
|
||||
Context.TELEPHONY_SERVICE);
|
||||
|
||||
// fold video calling data usage stats into uid snapshot
|
||||
final NetworkStats vtStats = telephonyManager.getVtDataUsage(true);
|
||||
final NetworkStats vtStats = telephonyManager.getVtDataUsage(STATS_PER_UID);
|
||||
if (vtStats != null) {
|
||||
uidSnapshot.combineAllValues(vtStats);
|
||||
}
|
||||
@@ -1397,7 +1404,7 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
Context.TELEPHONY_SERVICE);
|
||||
|
||||
// Merge video calling data usage into XT
|
||||
final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(false);
|
||||
final NetworkStats vtSnapshot = telephonyManager.getVtDataUsage(STATS_PER_IFACE);
|
||||
if (vtSnapshot != null) {
|
||||
xtSnapshot.combineAllValues(vtSnapshot);
|
||||
}
|
||||
@@ -1409,9 +1416,9 @@ public class NetworkStatsService extends INetworkStatsService.Stub {
|
||||
* Return snapshot of current tethering statistics. Will return empty
|
||||
* {@link NetworkStats} if any problems are encountered.
|
||||
*/
|
||||
private NetworkStats getNetworkStatsTethering() throws RemoteException {
|
||||
private NetworkStats getNetworkStatsTethering(int how) throws RemoteException {
|
||||
try {
|
||||
return mNetworkManager.getNetworkStatsTethering();
|
||||
return mNetworkManager.getNetworkStatsTethering(how);
|
||||
} catch (IllegalStateException e) {
|
||||
Log.wtf(TAG, "problem reading network stats", e);
|
||||
return new NetworkStats(0L, 10);
|
||||
|
||||
@@ -6741,11 +6741,13 @@ public class TelephonyManager {
|
||||
* Get aggregated video call data usage since boot.
|
||||
* Permissions android.Manifest.permission.READ_NETWORK_USAGE_HISTORY is required.
|
||||
*
|
||||
* @param perUidStats True if requesting data usage per uid, otherwise overall usage.
|
||||
* @param how one of the NetworkStats.STATS_PER_* constants depending on whether the request is
|
||||
* for data usage per uid or overall usage.
|
||||
* @return Snapshot of video call data usage
|
||||
* @hide
|
||||
*/
|
||||
public NetworkStats getVtDataUsage(boolean perUidStats) {
|
||||
public NetworkStats getVtDataUsage(int how) {
|
||||
boolean perUidStats = (how == NetworkStats.STATS_PER_UID);
|
||||
try {
|
||||
ITelephony service = getITelephony();
|
||||
if (service != null) {
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
package com.android.server.connectivity.tethering;
|
||||
|
||||
import static android.net.NetworkStats.SET_DEFAULT;
|
||||
import static android.net.NetworkStats.STATS_PER_IFACE;
|
||||
import static android.net.NetworkStats.STATS_PER_UID;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.TrafficStats.UID_TETHERING;
|
||||
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
|
||||
import static com.android.server.connectivity.tethering.OffloadHardwareInterface.ForwardedStats;
|
||||
@@ -373,7 +376,6 @@ public class OffloadControllerTest {
|
||||
assertEquals(stats.txBytes, entry.txBytes);
|
||||
assertEquals(SET_DEFAULT, entry.set);
|
||||
assertEquals(TAG_NONE, entry.tag);
|
||||
assertEquals(UID_TETHERING, entry.uid);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -412,20 +414,33 @@ public class OffloadControllerTest {
|
||||
ethernetStats.txBytes = 100000;
|
||||
offload.setUpstreamLinkProperties(null);
|
||||
|
||||
NetworkStats stats = mTetherStatsProviderCaptor.getValue().getTetherStats();
|
||||
ITetheringStatsProvider provider = mTetherStatsProviderCaptor.getValue();
|
||||
NetworkStats stats = provider.getTetherStats(STATS_PER_IFACE);
|
||||
NetworkStats perUidStats = provider.getTetherStats(STATS_PER_UID);
|
||||
|
||||
assertEquals(2, stats.size());
|
||||
assertEquals(2, perUidStats.size());
|
||||
|
||||
NetworkStats.Entry entry = null;
|
||||
for (int i = 0; i < stats.size(); i++) {
|
||||
assertEquals(UID_ALL, stats.getValues(i, entry).uid);
|
||||
assertEquals(UID_TETHERING, perUidStats.getValues(i, entry).uid);
|
||||
}
|
||||
|
||||
int ethernetPosition = ethernetIface.equals(stats.getValues(0, entry).iface) ? 0 : 1;
|
||||
int mobilePosition = 1 - ethernetPosition;
|
||||
|
||||
entry = stats.getValues(mobilePosition, entry);
|
||||
assertNetworkStats(mobileIface, mobileStats, entry);
|
||||
entry = perUidStats.getValues(mobilePosition, entry);
|
||||
assertNetworkStats(mobileIface, mobileStats, entry);
|
||||
|
||||
ethernetStats.rxBytes = 12345 + 100000;
|
||||
ethernetStats.txBytes = 54321 + 100000;
|
||||
entry = stats.getValues(ethernetPosition, entry);
|
||||
assertNetworkStats(ethernetIface, ethernetStats, entry);
|
||||
entry = perUidStats.getValues(ethernetPosition, entry);
|
||||
assertNetworkStats(ethernetIface, ethernetStats, entry);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -31,6 +31,8 @@ import static android.net.NetworkStats.ROAMING_YES;
|
||||
import static android.net.NetworkStats.SET_ALL;
|
||||
import static android.net.NetworkStats.SET_DEFAULT;
|
||||
import static android.net.NetworkStats.SET_FOREGROUND;
|
||||
import static android.net.NetworkStats.STATS_PER_IFACE;
|
||||
import static android.net.NetworkStats.STATS_PER_UID;
|
||||
import static android.net.NetworkStats.TAG_NONE;
|
||||
import static android.net.NetworkStats.UID_ALL;
|
||||
import static android.net.NetworkStatsHistory.FIELD_ALL;
|
||||
@@ -823,17 +825,24 @@ public class NetworkStatsServiceTest {
|
||||
incrementCurrentTime(HOUR_IN_MILLIS);
|
||||
expectCurrentTime();
|
||||
expectDefaultSettings();
|
||||
expectNetworkStatsSummary(new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addIfaceValues(TEST_IFACE, 2048L, 16L, 512L, 4L));
|
||||
|
||||
// Traffic seen by kernel counters (includes software tethering).
|
||||
final NetworkStats ifaceStats = new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addIfaceValues(TEST_IFACE, 1536L, 12L, 384L, 3L);
|
||||
// Hardware tethering traffic, not seen by kernel counters.
|
||||
final NetworkStats tetherStatsHardware = new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addIfaceValues(TEST_IFACE, 512L, 4L, 128L, 1L);
|
||||
|
||||
// Traffic for UID_RED.
|
||||
final NetworkStats uidStats = new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addValues(TEST_IFACE, UID_RED, SET_DEFAULT, TAG_NONE, 128L, 2L, 128L, 2L, 0L);
|
||||
final String[] tetherIfacePairs = new String[] { TEST_IFACE, "wlan0" };
|
||||
// All tethering traffic, both hardware and software.
|
||||
final NetworkStats tetherStats = new NetworkStats(getElapsedRealtime(), 1)
|
||||
.addValues(TEST_IFACE, UID_TETHERING, SET_DEFAULT, TAG_NONE, 1920L, 14L, 384L, 2L,
|
||||
0L);
|
||||
|
||||
expectNetworkStatsUidDetail(uidStats, tetherIfacePairs, tetherStats);
|
||||
expectNetworkStatsSummary(ifaceStats, tetherStatsHardware);
|
||||
expectNetworkStatsUidDetail(uidStats, tetherStats);
|
||||
forcePollAndWaitForIdle();
|
||||
|
||||
// verify service recorded history
|
||||
@@ -1013,10 +1022,16 @@ public class NetworkStatsServiceTest {
|
||||
}
|
||||
|
||||
private void expectNetworkStatsSummary(NetworkStats summary) throws Exception {
|
||||
expectNetworkStatsSummary(summary, new NetworkStats(0L, 0));
|
||||
}
|
||||
|
||||
private void expectNetworkStatsSummary(NetworkStats summary, NetworkStats tetherStats)
|
||||
throws Exception {
|
||||
when(mConnManager.getAllVpnInfo()).thenReturn(new VpnInfo[0]);
|
||||
|
||||
expectNetworkStatsSummaryDev(summary);
|
||||
expectNetworkStatsSummaryXt(summary);
|
||||
expectNetworkStatsTethering(STATS_PER_IFACE, tetherStats);
|
||||
expectNetworkStatsSummaryDev(summary.clone());
|
||||
expectNetworkStatsSummaryXt(summary.clone());
|
||||
}
|
||||
|
||||
private void expectNetworkStatsSummaryDev(NetworkStats summary) throws Exception {
|
||||
@@ -1027,17 +1042,21 @@ public class NetworkStatsServiceTest {
|
||||
when(mNetManager.getNetworkStatsSummaryXt()).thenReturn(summary);
|
||||
}
|
||||
|
||||
private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception {
|
||||
expectNetworkStatsUidDetail(detail, new String[0], new NetworkStats(0L, 0));
|
||||
private void expectNetworkStatsTethering(int how, NetworkStats stats)
|
||||
throws Exception {
|
||||
when(mNetManager.getNetworkStatsTethering(how)).thenReturn(stats);
|
||||
}
|
||||
|
||||
private void expectNetworkStatsUidDetail(
|
||||
NetworkStats detail, String[] tetherIfacePairs, NetworkStats tetherStats)
|
||||
private void expectNetworkStatsUidDetail(NetworkStats detail) throws Exception {
|
||||
expectNetworkStatsUidDetail(detail, new NetworkStats(0L, 0));
|
||||
}
|
||||
|
||||
private void expectNetworkStatsUidDetail(NetworkStats detail, NetworkStats tetherStats)
|
||||
throws Exception {
|
||||
when(mNetManager.getNetworkStatsUidDetail(UID_ALL)).thenReturn(detail);
|
||||
|
||||
// also include tethering details, since they are folded into UID
|
||||
when(mNetManager.getNetworkStatsTethering()).thenReturn(tetherStats);
|
||||
when(mNetManager.getNetworkStatsTethering(STATS_PER_UID)).thenReturn(tetherStats);
|
||||
}
|
||||
|
||||
private void expectDefaultSettings() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user