Merge changes I325b13d5,I89719fe7
am: 23868e9c09
Change-Id: Iaced543ab17ea87c8f701975764d957bc1b17fc7
This commit is contained in:
@@ -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
|
||||
|
||||
/**
|
||||
|
||||
@@ -219,6 +219,21 @@ interface INetworkManagementService
|
||||
*/
|
||||
void unregisterTetheringStatsProvider(ITetheringStatsProvider provider);
|
||||
|
||||
/**
|
||||
* Reports that a tethering provider has reached a data limit.
|
||||
*
|
||||
* Currently triggers a global alert, which causes NetworkStatsService to poll counters and
|
||||
* re-evaluate data usage.
|
||||
*
|
||||
* This does not take an interface name because:
|
||||
* 1. The tethering offload stats provider cannot reliably determine the interface on which the
|
||||
* limit was reached, because the HAL does not provide it.
|
||||
* 2. Firing an interface-specific alert instead of a global alert isn't really useful since in
|
||||
* all cases of interest, the system responds to both in the same way - it polls stats, and
|
||||
* then notifies NetworkPolicyManagerService of the fact.
|
||||
*/
|
||||
void tetherLimitReached(ITetheringStatsProvider provider);
|
||||
|
||||
/**
|
||||
** PPPD
|
||||
**/
|
||||
@@ -266,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;
|
||||
@@ -550,6 +551,18 @@ public class NetworkManagementService extends INetworkManagementService.Stub
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tetherLimitReached(ITetheringStatsProvider provider) {
|
||||
mContext.enforceCallingOrSelfPermission(NETWORK_STACK, TAG);
|
||||
synchronized(mTetheringStatsProviders) {
|
||||
if (!mTetheringStatsProviders.containsKey(provider)) {
|
||||
return;
|
||||
}
|
||||
// No current code examines the interface parameter in a global alert. Just pass null.
|
||||
notifyLimitReached(LIMIT_GLOBAL_ALERT, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Sync the state of the given chain with the native daemon.
|
||||
private void syncFirewallChainLocked(int chain, String name) {
|
||||
SparseIntArray rules;
|
||||
@@ -1851,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");
|
||||
@@ -1894,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;
|
||||
|
||||
@@ -60,6 +62,8 @@ public class OffloadController {
|
||||
private final Handler mHandler;
|
||||
private final OffloadHardwareInterface mHwInterface;
|
||||
private final ContentResolver mContentResolver;
|
||||
private final INetworkManagementService mNms;
|
||||
private final ITetheringStatsProvider mStatsProvider;
|
||||
private final SharedLog mLog;
|
||||
private boolean mConfigInitialized;
|
||||
private boolean mControlInitialized;
|
||||
@@ -89,13 +93,14 @@ public class OffloadController {
|
||||
mHandler = h;
|
||||
mHwInterface = hwi;
|
||||
mContentResolver = contentResolver;
|
||||
mNms = nms;
|
||||
mStatsProvider = new OffloadTetheringStatsProvider();
|
||||
mLog = log.forSubComponent(TAG);
|
||||
mExemptPrefixes = new HashSet<>();
|
||||
mLastLocalPrefixStrs = new HashSet<>();
|
||||
|
||||
try {
|
||||
nms.registerTetheringStatsProvider(
|
||||
new OffloadTetheringStatsProvider(), getClass().getSimpleName());
|
||||
mNms.registerTetheringStatsProvider(mStatsProvider, getClass().getSimpleName());
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Cannot register offload stats provider: " + e);
|
||||
}
|
||||
@@ -150,7 +155,26 @@ public class OffloadController {
|
||||
@Override
|
||||
public void onStoppedLimitReached() {
|
||||
mLog.log("onStoppedLimitReached");
|
||||
// Poll for statistics and notify NetworkStats
|
||||
|
||||
// We cannot reliably determine on which interface the limit was reached,
|
||||
// because the HAL interface does not specify it. We cannot just use the
|
||||
// current upstream, because that might have changed since the time that
|
||||
// the HAL queued the callback.
|
||||
// TODO: rev the HAL so that it provides an interface name.
|
||||
|
||||
// Fetch current stats, so that when our notification reaches
|
||||
// NetworkStatsService and triggers a poll, we will respond with
|
||||
// current data (which will be above the limit that was reached).
|
||||
// Note that if we just changed upstream, this is unnecessary but harmless.
|
||||
// The stats for the previous upstream were already updated on this thread
|
||||
// just after the upstream was changed, so they are also up-to-date.
|
||||
updateStatsForCurrentUpstream();
|
||||
|
||||
try {
|
||||
mNms.tetherLimitReached(mStatsProvider);
|
||||
} catch (RemoteException e) {
|
||||
mLog.e("Cannot report data limit reached: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -180,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();
|
||||
|
||||
|
||||
@@ -31,6 +31,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;
|
||||
@@ -1042,6 +1044,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.
|
||||
@@ -1372,14 +1379,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);
|
||||
}
|
||||
@@ -1398,7 +1405,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);
|
||||
}
|
||||
@@ -1410,9 +1417,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);
|
||||
|
||||
@@ -6649,11 +6649,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;
|
||||
@@ -85,6 +88,8 @@ public class OffloadControllerTest {
|
||||
ArgumentCaptor.forClass(ArrayList.class);
|
||||
private final ArgumentCaptor<ITetheringStatsProvider.Stub> mTetherStatsProviderCaptor =
|
||||
ArgumentCaptor.forClass(ITetheringStatsProvider.Stub.class);
|
||||
private final ArgumentCaptor<OffloadHardwareInterface.ControlCallback> mControlCallbackCaptor =
|
||||
ArgumentCaptor.forClass(OffloadHardwareInterface.ControlCallback.class);
|
||||
private MockContentResolver mContentResolver;
|
||||
|
||||
@Before public void setUp() {
|
||||
@@ -105,7 +110,7 @@ public class OffloadControllerTest {
|
||||
|
||||
private void setupFunctioningHardwareInterface() {
|
||||
when(mHardware.initOffloadConfig()).thenReturn(true);
|
||||
when(mHardware.initOffloadControl(any(OffloadHardwareInterface.ControlCallback.class)))
|
||||
when(mHardware.initOffloadControl(mControlCallbackCaptor.capture()))
|
||||
.thenReturn(true);
|
||||
when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats());
|
||||
}
|
||||
@@ -375,7 +380,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
|
||||
@@ -414,20 +418,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
|
||||
@@ -493,4 +510,17 @@ public class OffloadControllerTest {
|
||||
waitForIdle();
|
||||
inOrder.verify(mHardware).stopOffloadControl();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDataLimitCallback() throws Exception {
|
||||
setupFunctioningHardwareInterface();
|
||||
enableOffload();
|
||||
|
||||
final OffloadController offload = makeOffloadController();
|
||||
offload.start();
|
||||
|
||||
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
|
||||
callback.onStoppedLimitReached();
|
||||
verify(mNMService, times(1)).tetherLimitReached(mTetherStatsProviderCaptor.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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