Merge changes from topic "sp31" am: a6cb322d00
Original change: https://android-review.googlesource.com/c/platform/packages/modules/Connectivity/+/1626082 Change-Id: I906d49ba06054f124e60f39ed40c40472e28546d
This commit is contained in:
@@ -26,6 +26,8 @@ import static android.net.NetworkStats.UID_TETHERING;
|
|||||||
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
|
import static android.net.netstats.provider.NetworkStatsProvider.QUOTA_UNLIMITED;
|
||||||
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
|
import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED;
|
||||||
|
|
||||||
|
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_0;
|
||||||
|
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_1_1;
|
||||||
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
|
import static com.android.networkstack.tethering.OffloadHardwareInterface.OFFLOAD_HAL_VERSION_NONE;
|
||||||
import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
|
import static com.android.networkstack.tethering.TetheringConfiguration.DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
|
||||||
|
|
||||||
@@ -280,6 +282,18 @@ public class OffloadController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onWarningReached() {
|
||||||
|
if (!started()) return;
|
||||||
|
mLog.log("onWarningReached");
|
||||||
|
|
||||||
|
updateStatsForCurrentUpstream();
|
||||||
|
if (mStatsProvider != null) {
|
||||||
|
mStatsProvider.pushTetherStats();
|
||||||
|
mStatsProvider.notifyWarningReached();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onNatTimeoutUpdate(int proto,
|
public void onNatTimeoutUpdate(int proto,
|
||||||
String srcAddr, int srcPort,
|
String srcAddr, int srcPort,
|
||||||
@@ -417,7 +431,11 @@ public class OffloadController {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onSetAlert(long quotaBytes) {
|
public void onSetAlert(long quotaBytes) {
|
||||||
// TODO: Ask offload HAL to notify alert without stopping traffic.
|
// Ignore set alert calls from HAL V1.1 since the hardware supports set warning now.
|
||||||
|
// Thus, the software polling mechanism is not needed.
|
||||||
|
if (!useStatsPolling()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// Post it to handler thread since it access remaining quota bytes.
|
// Post it to handler thread since it access remaining quota bytes.
|
||||||
mHandler.post(() -> {
|
mHandler.post(() -> {
|
||||||
updateAlertQuota(quotaBytes);
|
updateAlertQuota(quotaBytes);
|
||||||
@@ -502,12 +520,17 @@ public class OffloadController {
|
|||||||
|
|
||||||
private boolean isPollingStatsNeeded() {
|
private boolean isPollingStatsNeeded() {
|
||||||
return started() && mRemainingAlertQuota > 0
|
return started() && mRemainingAlertQuota > 0
|
||||||
|
&& useStatsPolling()
|
||||||
&& !TextUtils.isEmpty(currentUpstreamInterface())
|
&& !TextUtils.isEmpty(currentUpstreamInterface())
|
||||||
&& mDeps.getTetherConfig() != null
|
&& mDeps.getTetherConfig() != null
|
||||||
&& mDeps.getTetherConfig().getOffloadPollInterval()
|
&& mDeps.getTetherConfig().getOffloadPollInterval()
|
||||||
>= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
|
>= DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean useStatsPolling() {
|
||||||
|
return mControlHalVersion == OFFLOAD_HAL_VERSION_1_0;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean maybeUpdateDataWarningAndLimit(String iface) {
|
private boolean maybeUpdateDataWarningAndLimit(String iface) {
|
||||||
// setDataLimit or setDataWarningAndLimit may only be called while offload is occurring
|
// setDataLimit or setDataWarningAndLimit may only be called while offload is occurring
|
||||||
// on this upstream.
|
// on this upstream.
|
||||||
@@ -516,7 +539,13 @@ public class OffloadController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final InterfaceQuota quota = mInterfaceQuotas.getOrDefault(iface, InterfaceQuota.MAX_VALUE);
|
final InterfaceQuota quota = mInterfaceQuotas.getOrDefault(iface, InterfaceQuota.MAX_VALUE);
|
||||||
return mHwInterface.setDataLimit(iface, quota.limitBytes);
|
final boolean ret;
|
||||||
|
if (mControlHalVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
ret = mHwInterface.setDataWarningAndLimit(iface, quota.warningBytes, quota.limitBytes);
|
||||||
|
} else {
|
||||||
|
ret = mHwInterface.setDataLimit(iface, quota.limitBytes);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateStatsForCurrentUpstream() {
|
private void updateStatsForCurrentUpstream() {
|
||||||
|
|||||||
@@ -149,6 +149,7 @@ public class OffloadControllerTest {
|
|||||||
when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true);
|
when(mHardware.setUpstreamParameters(anyString(), any(), any(), any())).thenReturn(true);
|
||||||
when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats());
|
when(mHardware.getForwardedStats(any())).thenReturn(new ForwardedStats());
|
||||||
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
|
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
|
||||||
|
when(mHardware.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void enableOffload() {
|
private void enableOffload() {
|
||||||
@@ -503,80 +504,166 @@ public class OffloadControllerTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test OffloadController that uses V1.0 HAL setDataLimit with NetworkStatsProvider#onSetLimit
|
* Test OffloadController with different combinations of HAL and framework versions can set
|
||||||
* which is called by R framework.
|
* data warning and/or limit correctly.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testSetDataLimit() throws Exception {
|
public void testSetDataWarningAndLimit() throws Exception {
|
||||||
|
// Verify the OffloadController is called by R framework, where the framework doesn't send
|
||||||
|
// warning.
|
||||||
|
checkSetDataWarningAndLimit(false, OFFLOAD_HAL_VERSION_1_0);
|
||||||
|
checkSetDataWarningAndLimit(false, OFFLOAD_HAL_VERSION_1_1);
|
||||||
|
// Verify the OffloadController is called by S+ framework, where the framework sends
|
||||||
|
// warning along with limit.
|
||||||
|
checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_1_0);
|
||||||
|
checkSetDataWarningAndLimit(true, OFFLOAD_HAL_VERSION_1_1);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSetDataWarningAndLimit(boolean isProviderSetWarning, int controlVersion)
|
||||||
|
throws Exception {
|
||||||
enableOffload();
|
enableOffload();
|
||||||
final OffloadController offload =
|
final OffloadController offload =
|
||||||
startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
|
startOffloadController(controlVersion, true /*expectStart*/);
|
||||||
|
|
||||||
final String ethernetIface = "eth1";
|
final String ethernetIface = "eth1";
|
||||||
final String mobileIface = "rmnet_data0";
|
final String mobileIface = "rmnet_data0";
|
||||||
final long ethernetLimit = 12345;
|
final long ethernetLimit = 12345;
|
||||||
|
final long mobileWarning = 123456;
|
||||||
final long mobileLimit = 12345678;
|
final long mobileLimit = 12345678;
|
||||||
|
|
||||||
final LinkProperties lp = new LinkProperties();
|
final LinkProperties lp = new LinkProperties();
|
||||||
lp.setInterfaceName(ethernetIface);
|
lp.setInterfaceName(ethernetIface);
|
||||||
offload.setUpstreamLinkProperties(lp);
|
|
||||||
|
|
||||||
final InOrder inOrder = inOrder(mHardware);
|
final InOrder inOrder = inOrder(mHardware);
|
||||||
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
|
when(mHardware.setUpstreamParameters(
|
||||||
|
any(), any(), any(), any())).thenReturn(true);
|
||||||
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
|
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(true);
|
||||||
|
when(mHardware.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(true);
|
||||||
|
offload.setUpstreamLinkProperties(lp);
|
||||||
|
// Applying an interface sends the initial quota to the hardware.
|
||||||
|
if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
inOrder.verify(mHardware).setDataWarningAndLimit(ethernetIface, Long.MAX_VALUE,
|
||||||
|
Long.MAX_VALUE);
|
||||||
|
} else {
|
||||||
|
inOrder.verify(mHardware).setDataLimit(ethernetIface, Long.MAX_VALUE);
|
||||||
|
}
|
||||||
|
inOrder.verifyNoMoreInteractions();
|
||||||
|
|
||||||
|
// Verify that set to unlimited again won't cause duplicated calls to the hardware.
|
||||||
|
if (isProviderSetWarning) {
|
||||||
|
mTetherStatsProvider.onSetWarningAndLimit(ethernetIface,
|
||||||
|
NetworkStatsProvider.QUOTA_UNLIMITED, NetworkStatsProvider.QUOTA_UNLIMITED);
|
||||||
|
} else {
|
||||||
|
mTetherStatsProvider.onSetLimit(ethernetIface, NetworkStatsProvider.QUOTA_UNLIMITED);
|
||||||
|
}
|
||||||
|
waitForIdle();
|
||||||
|
inOrder.verifyNoMoreInteractions();
|
||||||
|
|
||||||
// Applying an interface quota to the current upstream immediately sends it to the hardware.
|
// Applying an interface quota to the current upstream immediately sends it to the hardware.
|
||||||
mTetherStatsProvider.onSetLimit(ethernetIface, ethernetLimit);
|
if (isProviderSetWarning) {
|
||||||
|
mTetherStatsProvider.onSetWarningAndLimit(ethernetIface,
|
||||||
|
NetworkStatsProvider.QUOTA_UNLIMITED, ethernetLimit);
|
||||||
|
} else {
|
||||||
|
mTetherStatsProvider.onSetLimit(ethernetIface, ethernetLimit);
|
||||||
|
}
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit);
|
if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
inOrder.verify(mHardware).setDataWarningAndLimit(ethernetIface, Long.MAX_VALUE,
|
||||||
|
ethernetLimit);
|
||||||
|
} else {
|
||||||
|
inOrder.verify(mHardware).setDataLimit(ethernetIface, ethernetLimit);
|
||||||
|
}
|
||||||
inOrder.verifyNoMoreInteractions();
|
inOrder.verifyNoMoreInteractions();
|
||||||
|
|
||||||
// Applying an interface quota to another upstream does not take any immediate action.
|
// Applying an interface quota to another upstream does not take any immediate action.
|
||||||
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
|
if (isProviderSetWarning) {
|
||||||
|
mTetherStatsProvider.onSetWarningAndLimit(mobileIface, mobileWarning, mobileLimit);
|
||||||
|
} else {
|
||||||
|
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
|
||||||
|
}
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
|
if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
inOrder.verify(mHardware, never()).setDataWarningAndLimit(anyString(), anyLong(),
|
||||||
|
anyLong());
|
||||||
|
} else {
|
||||||
|
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
|
||||||
|
}
|
||||||
|
|
||||||
// Switching to that upstream causes the quota to be applied if the parameters were applied
|
// Switching to that upstream causes the quota to be applied if the parameters were applied
|
||||||
// correctly.
|
// correctly.
|
||||||
lp.setInterfaceName(mobileIface);
|
lp.setInterfaceName(mobileIface);
|
||||||
offload.setUpstreamLinkProperties(lp);
|
offload.setUpstreamLinkProperties(lp);
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit);
|
if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
inOrder.verify(mHardware).setDataWarningAndLimit(mobileIface,
|
||||||
|
isProviderSetWarning ? mobileWarning : Long.MAX_VALUE,
|
||||||
|
mobileLimit);
|
||||||
|
} else {
|
||||||
|
inOrder.verify(mHardware).setDataLimit(mobileIface, mobileLimit);
|
||||||
|
}
|
||||||
|
|
||||||
// Setting a limit of NetworkStatsProvider.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, NetworkStatsProvider.QUOTA_UNLIMITED);
|
if (isProviderSetWarning) {
|
||||||
|
mTetherStatsProvider.onSetWarningAndLimit(mobileIface,
|
||||||
|
NetworkStatsProvider.QUOTA_UNLIMITED, NetworkStatsProvider.QUOTA_UNLIMITED);
|
||||||
|
} else {
|
||||||
|
mTetherStatsProvider.onSetLimit(mobileIface, NetworkStatsProvider.QUOTA_UNLIMITED);
|
||||||
|
}
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);
|
if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
inOrder.verify(mHardware).setDataWarningAndLimit(mobileIface, Long.MAX_VALUE,
|
||||||
|
Long.MAX_VALUE);
|
||||||
|
} else {
|
||||||
|
inOrder.verify(mHardware).setDataLimit(mobileIface, Long.MAX_VALUE);
|
||||||
|
}
|
||||||
|
|
||||||
// If setting upstream parameters fails, then the data limit is not set.
|
// If setting upstream parameters fails, then the data warning and limit is not set.
|
||||||
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false);
|
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(false);
|
||||||
lp.setInterfaceName(ethernetIface);
|
lp.setInterfaceName(ethernetIface);
|
||||||
offload.setUpstreamLinkProperties(lp);
|
offload.setUpstreamLinkProperties(lp);
|
||||||
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
|
if (isProviderSetWarning) {
|
||||||
|
mTetherStatsProvider.onSetWarningAndLimit(mobileIface, mobileWarning, mobileLimit);
|
||||||
|
} else {
|
||||||
|
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
|
||||||
|
}
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
|
inOrder.verify(mHardware, never()).setDataLimit(anyString(), anyLong());
|
||||||
|
inOrder.verify(mHardware, never()).setDataWarningAndLimit(anyString(), anyLong(),
|
||||||
|
anyLong());
|
||||||
|
|
||||||
// If setting the data limit fails while changing upstreams, offload is stopped.
|
// If setting the data warning and/or limit fails while changing upstreams, offload is
|
||||||
|
// stopped.
|
||||||
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
|
when(mHardware.setUpstreamParameters(any(), any(), any(), any())).thenReturn(true);
|
||||||
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false);
|
when(mHardware.setDataLimit(anyString(), anyLong())).thenReturn(false);
|
||||||
|
when(mHardware.setDataWarningAndLimit(anyString(), anyLong(), anyLong())).thenReturn(false);
|
||||||
lp.setInterfaceName(mobileIface);
|
lp.setInterfaceName(mobileIface);
|
||||||
offload.setUpstreamLinkProperties(lp);
|
offload.setUpstreamLinkProperties(lp);
|
||||||
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
|
if (isProviderSetWarning) {
|
||||||
|
mTetherStatsProvider.onSetWarningAndLimit(mobileIface, mobileWarning, mobileLimit);
|
||||||
|
} else {
|
||||||
|
mTetherStatsProvider.onSetLimit(mobileIface, mobileLimit);
|
||||||
|
}
|
||||||
waitForIdle();
|
waitForIdle();
|
||||||
inOrder.verify(mHardware).getForwardedStats(ethernetIface);
|
inOrder.verify(mHardware).getForwardedStats(ethernetIface);
|
||||||
inOrder.verify(mHardware).stopOffloadControl();
|
inOrder.verify(mHardware).stopOffloadControl();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testDataLimitCallback() throws Exception {
|
public void testDataWarningAndLimitCallback() throws Exception {
|
||||||
enableOffload();
|
enableOffload();
|
||||||
final OffloadController offload =
|
startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
|
||||||
startOffloadController(OFFLOAD_HAL_VERSION_1_0, true /*expectStart*/);
|
|
||||||
|
|
||||||
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
|
OffloadHardwareInterface.ControlCallback callback = mControlCallbackCaptor.getValue();
|
||||||
callback.onStoppedLimitReached();
|
callback.onStoppedLimitReached();
|
||||||
mTetherStatsProviderCb.expectNotifyStatsUpdated();
|
mTetherStatsProviderCb.expectNotifyStatsUpdated();
|
||||||
|
mTetherStatsProviderCb.expectNotifyWarningOrLimitReached();
|
||||||
|
|
||||||
|
startOffloadController(OFFLOAD_HAL_VERSION_1_1, true /*expectStart*/);
|
||||||
|
callback = mControlCallbackCaptor.getValue();
|
||||||
|
callback.onWarningReached();
|
||||||
|
mTetherStatsProviderCb.expectNotifyStatsUpdated();
|
||||||
|
mTetherStatsProviderCb.expectNotifyWarningOrLimitReached();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -764,9 +851,7 @@ public class OffloadControllerTest {
|
|||||||
// Initialize with fake eth upstream.
|
// Initialize with fake eth upstream.
|
||||||
final String ethernetIface = "eth1";
|
final String ethernetIface = "eth1";
|
||||||
InOrder inOrder = inOrder(mHardware);
|
InOrder inOrder = inOrder(mHardware);
|
||||||
final LinkProperties lp = new LinkProperties();
|
offload.setUpstreamLinkProperties(makeEthernetLinkProperties());
|
||||||
lp.setInterfaceName(ethernetIface);
|
|
||||||
offload.setUpstreamLinkProperties(lp);
|
|
||||||
// Previous upstream was null, so no stats are fetched.
|
// Previous upstream was null, so no stats are fetched.
|
||||||
inOrder.verify(mHardware, never()).getForwardedStats(any());
|
inOrder.verify(mHardware, never()).getForwardedStats(any());
|
||||||
|
|
||||||
@@ -799,4 +884,33 @@ public class OffloadControllerTest {
|
|||||||
mTetherStatsProviderCb.assertNoCallback();
|
mTetherStatsProviderCb.assertNoCallback();
|
||||||
verify(mHardware, never()).getForwardedStats(any());
|
verify(mHardware, never()).getForwardedStats(any());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static LinkProperties makeEthernetLinkProperties() {
|
||||||
|
final String ethernetIface = "eth1";
|
||||||
|
final LinkProperties lp = new LinkProperties();
|
||||||
|
lp.setInterfaceName(ethernetIface);
|
||||||
|
return lp;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkSoftwarePollingUsed(int controlVersion) throws Exception {
|
||||||
|
enableOffload();
|
||||||
|
setOffloadPollInterval(DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS);
|
||||||
|
OffloadController offload =
|
||||||
|
startOffloadController(controlVersion, true /*expectStart*/);
|
||||||
|
offload.setUpstreamLinkProperties(makeEthernetLinkProperties());
|
||||||
|
mTetherStatsProvider.onSetAlert(0);
|
||||||
|
waitForIdle();
|
||||||
|
if (controlVersion >= OFFLOAD_HAL_VERSION_1_1) {
|
||||||
|
mTetherStatsProviderCb.assertNoCallback();
|
||||||
|
} else {
|
||||||
|
mTetherStatsProviderCb.expectNotifyAlertReached();
|
||||||
|
}
|
||||||
|
verify(mHardware, never()).getForwardedStats(any());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSoftwarePollingUsed() throws Exception {
|
||||||
|
checkSoftwarePollingUsed(OFFLOAD_HAL_VERSION_1_0);
|
||||||
|
checkSoftwarePollingUsed(OFFLOAD_HAL_VERSION_1_1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user