[SP34] Adapt onSetWarningAndLimit

This is a no-op change that just adapt new API from
NetworkStatsProvider to get warning and limit bytes at the same
time. This change also stores them locally for subsequent
patches to set warning bytes to hardware.

Test: Will be included in the subsequent patch.
Bug: 149467454
Ignore-AOSP-First: avoid long automerger delay
Change-Id: Iec01cb01fd1ce481ce0bd736762baddde1e38084
This commit is contained in:
junyulai
2021-03-10 19:36:43 +08:00
parent 5454e8978e
commit 6d8da9f72d
2 changed files with 63 additions and 20 deletions

View File

@@ -114,11 +114,42 @@ public class OffloadController {
private ConcurrentHashMap<String, ForwardedStats> mForwardedStats = private ConcurrentHashMap<String, ForwardedStats> mForwardedStats =
new ConcurrentHashMap<>(16, 0.75F, 1); new ConcurrentHashMap<>(16, 0.75F, 1);
private static class InterfaceQuota {
public final long warningBytes;
public final long limitBytes;
public static InterfaceQuota MAX_VALUE = new InterfaceQuota(Long.MAX_VALUE, Long.MAX_VALUE);
InterfaceQuota(long warningBytes, long limitBytes) {
this.warningBytes = warningBytes;
this.limitBytes = limitBytes;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof InterfaceQuota)) return false;
InterfaceQuota that = (InterfaceQuota) o;
return warningBytes == that.warningBytes
&& limitBytes == that.limitBytes;
}
@Override
public int hashCode() {
return (int) (warningBytes * 3 + limitBytes * 5);
}
@Override
public String toString() {
return "InterfaceQuota{" + "warning=" + warningBytes + ", limit=" + limitBytes + '}';
}
}
// Maps upstream interface names to interface quotas. // Maps upstream interface names to interface quotas.
// Always contains the latest value received from the framework for each interface, regardless // Always contains the latest value received from the framework for each interface, regardless
// of whether offload is currently running (or is even supported) on that interface. Only // of whether offload is currently running (or is even supported) on that interface. Only
// includes upstream interfaces that have a quota set. // includes upstream interfaces that have a quota set.
private HashMap<String, Long> mInterfaceQuotas = new HashMap<>(); private HashMap<String, InterfaceQuota> mInterfaceQuotas = new HashMap<>();
// Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert // Tracking remaining alert quota. Unlike limit quota is subject to interface, the alert
// quota is interface independent and global for tether offload. Note that this is only // quota is interface independent and global for tether offload. Note that this is only
@@ -263,7 +294,8 @@ public class OffloadController {
mLog.i("tethering offload control not supported"); mLog.i("tethering offload control not supported");
stop(); stop();
} else { } else {
mLog.log("tethering offload started"); mLog.log("tethering offload started, version: "
+ OffloadHardwareInterface.halVerToString(mControlHalVersion));
mNatUpdateCallbacksReceived = 0; mNatUpdateCallbacksReceived = 0;
mNatUpdateNetlinkErrors = 0; mNatUpdateNetlinkErrors = 0;
maybeSchedulePollingStats(); maybeSchedulePollingStats();
@@ -322,24 +354,35 @@ public class OffloadController {
@Override @Override
public void onSetLimit(String iface, long quotaBytes) { public void onSetLimit(String iface, long quotaBytes) {
onSetWarningAndLimit(iface, QUOTA_UNLIMITED, quotaBytes);
}
@Override
public void onSetWarningAndLimit(@NonNull String iface,
long warningBytes, long limitBytes) {
// Listen for all iface is necessary since upstream might be changed after limit // Listen for all iface is necessary since upstream might be changed after limit
// is set. // is set.
mHandler.post(() -> { mHandler.post(() -> {
final Long curIfaceQuota = mInterfaceQuotas.get(iface); final InterfaceQuota curIfaceQuota = mInterfaceQuotas.get(iface);
final InterfaceQuota newIfaceQuota = new InterfaceQuota(
warningBytes == QUOTA_UNLIMITED ? Long.MAX_VALUE : warningBytes,
limitBytes == QUOTA_UNLIMITED ? Long.MAX_VALUE : limitBytes);
// If the quota is set to unlimited, the value set to HAL is Long.MAX_VALUE, // If the quota is set to unlimited, the value set to HAL is Long.MAX_VALUE,
// which is ~8.4 x 10^6 TiB, no one can actually reach it. Thus, it is not // which is ~8.4 x 10^6 TiB, no one can actually reach it. Thus, it is not
// useful to set it multiple times. // useful to set it multiple times.
// Otherwise, the quota needs to be updated to tell HAL to re-count from now even // Otherwise, the quota needs to be updated to tell HAL to re-count from now even
// if the quota is the same as the existing one. // if the quota is the same as the existing one.
if (null == curIfaceQuota && QUOTA_UNLIMITED == quotaBytes) return; if (null == curIfaceQuota && InterfaceQuota.MAX_VALUE.equals(newIfaceQuota)) {
return;
}
if (quotaBytes == QUOTA_UNLIMITED) { if (InterfaceQuota.MAX_VALUE.equals(newIfaceQuota)) {
mInterfaceQuotas.remove(iface); mInterfaceQuotas.remove(iface);
} else { } else {
mInterfaceQuotas.put(iface, quotaBytes); mInterfaceQuotas.put(iface, newIfaceQuota);
} }
maybeUpdateDataLimit(iface); maybeUpdateDataWarningAndLimit(iface);
}); });
} }
@@ -465,18 +508,15 @@ public class OffloadController {
>= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS; >= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
} }
private boolean maybeUpdateDataLimit(String iface) { private boolean maybeUpdateDataWarningAndLimit(String iface) {
// setDataLimit may only be called while offload is occurring on this upstream. // setDataLimit or setDataWarningAndLimit may only be called while offload is occurring
// on this upstream.
if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) { if (!started() || !TextUtils.equals(iface, currentUpstreamInterface())) {
return true; return true;
} }
Long limit = mInterfaceQuotas.get(iface); final InterfaceQuota quota = mInterfaceQuotas.getOrDefault(iface, InterfaceQuota.MAX_VALUE);
if (limit == null) { return mHwInterface.setDataLimit(iface, quota.limitBytes);
limit = Long.MAX_VALUE;
}
return mHwInterface.setDataLimit(iface, limit);
} }
private void updateStatsForCurrentUpstream() { private void updateStatsForCurrentUpstream() {
@@ -630,7 +670,7 @@ public class OffloadController {
maybeUpdateStats(prevUpstream); maybeUpdateStats(prevUpstream);
// Data limits can only be set once offload is running on the upstream. // Data limits can only be set once offload is running on the upstream.
success = maybeUpdateDataLimit(iface); success = maybeUpdateDataWarningAndLimit(iface);
if (!success) { if (!success) {
// If we failed to set a data limit, don't use this upstream, because we don't want to // If we failed to set a data limit, don't use this upstream, because we don't want to
// blow through the data limit that we were told to apply. // blow through the data limit that we were told to apply.

View File

@@ -58,7 +58,6 @@ import android.annotation.NonNull;
import android.app.usage.NetworkStatsManager; import android.app.usage.NetworkStatsManager;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.net.ITetheringStatsProvider;
import android.net.IpPrefix; import android.net.IpPrefix;
import android.net.LinkAddress; import android.net.LinkAddress;
import android.net.LinkProperties; import android.net.LinkProperties;
@@ -503,8 +502,12 @@ public class OffloadControllerTest {
expectedUidStatsDiff); expectedUidStatsDiff);
} }
/**
* Test OffloadController that uses V1.0 HAL setDataLimit with NetworkStatsProvider#onSetLimit
* which is called by R framework.
*/
@Test @Test
public void testSetInterfaceQuota() throws Exception { public void testSetDataLimit() throws Exception {
enableOffload(); enableOffload();
final OffloadController offload = final OffloadController offload =
startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/); startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
@@ -540,9 +543,9 @@ public class OffloadControllerTest {
waitForIdle(); waitForIdle();
inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit); inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit);
// Setting a limit of ITetheringStatsProvider.QUOTA_UNLIMITED causes the limit to be set // Setting a limit of NetworkStatsProvider.QUOTA_UNLIMITED causes the limit to be set
// to Long.MAX_VALUE. // to Long.MAX_VALUE.
mTetherStatsProvider.onSetLimit(mobileIface, ITetheringStatsProvider.QUOTA_UNLIMITED); mTetherStatsProvider.onSetLimit(mobileIface, NetworkStatsProvider.QUOTA_UNLIMITED);
waitForIdle(); waitForIdle();
inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE); inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);