Merge "have OffloaderController store and re-push more state"
am: 69efc596af
Change-Id: I468b9d774bb273c765ee6ff597ff207d047e1cc6
This commit is contained in:
@@ -52,6 +52,7 @@ import java.net.Inet4Address;
|
|||||||
import java.net.Inet6Address;
|
import java.net.Inet6Address;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -73,6 +74,8 @@ public class OffloadController {
|
|||||||
private static final String ANYIP = "0.0.0.0";
|
private static final String ANYIP = "0.0.0.0";
|
||||||
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
|
private static final ForwardedStats EMPTY_STATS = new ForwardedStats();
|
||||||
|
|
||||||
|
private static enum UpdateType { IF_NEEDED, FORCE };
|
||||||
|
|
||||||
private final Handler mHandler;
|
private final Handler mHandler;
|
||||||
private final OffloadHardwareInterface mHwInterface;
|
private final OffloadHardwareInterface mHwInterface;
|
||||||
private final ContentResolver mContentResolver;
|
private final ContentResolver mContentResolver;
|
||||||
@@ -185,8 +188,8 @@ public class OffloadController {
|
|||||||
updateStatsForAllUpstreams();
|
updateStatsForAllUpstreams();
|
||||||
forceTetherStatsPoll();
|
forceTetherStatsPoll();
|
||||||
// [2] (Re)Push all state.
|
// [2] (Re)Push all state.
|
||||||
// TODO: computeAndPushLocalPrefixes()
|
computeAndPushLocalPrefixes(UpdateType.FORCE);
|
||||||
// TODO: push all downstream state.
|
pushAllDownstreamState();
|
||||||
pushUpstreamParameters(null);
|
pushUpstreamParameters(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -319,7 +322,7 @@ public class OffloadController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean maybeUpdateDataLimit(String iface) {
|
private boolean maybeUpdateDataLimit(String iface) {
|
||||||
// setDataLimit may only be called while offload is occuring on this upstream.
|
// setDataLimit 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;
|
||||||
}
|
}
|
||||||
@@ -368,15 +371,15 @@ public class OffloadController {
|
|||||||
// upstream parameters fails (probably just wait for a subsequent
|
// upstream parameters fails (probably just wait for a subsequent
|
||||||
// onOffloadEvent() callback to tell us offload is available again and
|
// onOffloadEvent() callback to tell us offload is available again and
|
||||||
// then reapply all state).
|
// then reapply all state).
|
||||||
computeAndPushLocalPrefixes();
|
computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
|
||||||
pushUpstreamParameters(prevUpstream);
|
pushUpstreamParameters(prevUpstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
|
public void setLocalPrefixes(Set<IpPrefix> localPrefixes) {
|
||||||
if (!started()) return;
|
|
||||||
|
|
||||||
mExemptPrefixes = localPrefixes;
|
mExemptPrefixes = localPrefixes;
|
||||||
computeAndPushLocalPrefixes();
|
|
||||||
|
if (!started()) return;
|
||||||
|
computeAndPushLocalPrefixes(UpdateType.IF_NEEDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void notifyDownstreamLinkProperties(LinkProperties lp) {
|
public void notifyDownstreamLinkProperties(LinkProperties lp) {
|
||||||
@@ -385,27 +388,38 @@ public class OffloadController {
|
|||||||
if (Objects.equals(oldLp, lp)) return;
|
if (Objects.equals(oldLp, lp)) return;
|
||||||
|
|
||||||
if (!started()) return;
|
if (!started()) return;
|
||||||
|
pushDownstreamState(oldLp, lp);
|
||||||
|
}
|
||||||
|
|
||||||
final List<RouteInfo> oldRoutes = (oldLp != null) ? oldLp.getRoutes() : new ArrayList<>();
|
private void pushDownstreamState(LinkProperties oldLp, LinkProperties newLp) {
|
||||||
final List<RouteInfo> newRoutes = lp.getRoutes();
|
final String ifname = newLp.getInterfaceName();
|
||||||
|
final List<RouteInfo> oldRoutes =
|
||||||
|
(oldLp != null) ? oldLp.getRoutes() : Collections.EMPTY_LIST;
|
||||||
|
final List<RouteInfo> newRoutes = newLp.getRoutes();
|
||||||
|
|
||||||
// For each old route, if not in new routes: remove.
|
// For each old route, if not in new routes: remove.
|
||||||
for (RouteInfo oldRoute : oldRoutes) {
|
for (RouteInfo ri : oldRoutes) {
|
||||||
if (shouldIgnoreDownstreamRoute(oldRoute)) continue;
|
if (shouldIgnoreDownstreamRoute(ri)) continue;
|
||||||
if (!newRoutes.contains(oldRoute)) {
|
if (!newRoutes.contains(ri)) {
|
||||||
mHwInterface.removeDownstreamPrefix(ifname, oldRoute.getDestination().toString());
|
mHwInterface.removeDownstreamPrefix(ifname, ri.getDestination().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each new route, if not in old routes: add.
|
// For each new route, if not in old routes: add.
|
||||||
for (RouteInfo newRoute : newRoutes) {
|
for (RouteInfo ri : newRoutes) {
|
||||||
if (shouldIgnoreDownstreamRoute(newRoute)) continue;
|
if (shouldIgnoreDownstreamRoute(ri)) continue;
|
||||||
if (!oldRoutes.contains(newRoute)) {
|
if (!oldRoutes.contains(ri)) {
|
||||||
mHwInterface.addDownstreamPrefix(ifname, newRoute.getDestination().toString());
|
mHwInterface.addDownstreamPrefix(ifname, ri.getDestination().toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void pushAllDownstreamState() {
|
||||||
|
for (LinkProperties lp : mDownstreams.values()) {
|
||||||
|
pushDownstreamState(null, lp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void removeDownstreamInterface(String ifname) {
|
public void removeDownstreamInterface(String ifname) {
|
||||||
final LinkProperties lp = mDownstreams.remove(ifname);
|
final LinkProperties lp = mDownstreams.remove(ifname);
|
||||||
if (lp == null) return;
|
if (lp == null) return;
|
||||||
@@ -484,10 +498,11 @@ public class OffloadController {
|
|||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean computeAndPushLocalPrefixes() {
|
private boolean computeAndPushLocalPrefixes(UpdateType how) {
|
||||||
|
final boolean force = (how == UpdateType.FORCE);
|
||||||
final Set<String> localPrefixStrs = computeLocalPrefixStrings(
|
final Set<String> localPrefixStrs = computeLocalPrefixStrings(
|
||||||
mExemptPrefixes, mUpstreamLinkProperties);
|
mExemptPrefixes, mUpstreamLinkProperties);
|
||||||
if (mLastLocalPrefixStrs.equals(localPrefixStrs)) return true;
|
if (!force && mLastLocalPrefixStrs.equals(localPrefixStrs)) return true;
|
||||||
|
|
||||||
mLastLocalPrefixStrs = localPrefixStrs;
|
mLastLocalPrefixStrs = localPrefixStrs;
|
||||||
return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs));
|
return mHwInterface.setLocalPrefixes(new ArrayList<>(localPrefixStrs));
|
||||||
|
|||||||
@@ -671,6 +671,35 @@ public class OffloadControllerTest {
|
|||||||
offload.setUpstreamLinkProperties(upstreamLp);
|
offload.setUpstreamLinkProperties(upstreamLp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Pretend that some local prefixes and downstreams have been added
|
||||||
|
// (and removed, for good measure).
|
||||||
|
final Set<IpPrefix> minimumLocalPrefixes = new HashSet<>();
|
||||||
|
for (String s : new String[]{
|
||||||
|
"127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64"}) {
|
||||||
|
minimumLocalPrefixes.add(new IpPrefix(s));
|
||||||
|
}
|
||||||
|
offload.setLocalPrefixes(minimumLocalPrefixes);
|
||||||
|
|
||||||
|
final LinkProperties usbLinkProperties = new LinkProperties();
|
||||||
|
usbLinkProperties.setInterfaceName(RNDIS0);
|
||||||
|
usbLinkProperties.addLinkAddress(new LinkAddress("192.168.42.1/24"));
|
||||||
|
usbLinkProperties.addRoute(new RouteInfo(new IpPrefix(USB_PREFIX)));
|
||||||
|
offload.notifyDownstreamLinkProperties(usbLinkProperties);
|
||||||
|
|
||||||
|
final LinkProperties wifiLinkProperties = new LinkProperties();
|
||||||
|
wifiLinkProperties.setInterfaceName(WLAN0);
|
||||||
|
wifiLinkProperties.addLinkAddress(new LinkAddress("192.168.43.1/24"));
|
||||||
|
wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(WIFI_PREFIX)));
|
||||||
|
wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix(IPV6_LINKLOCAL)));
|
||||||
|
// Use a benchmark prefix (RFC 5180 + erratum), since the documentation
|
||||||
|
// prefix is included in the excluded prefix list.
|
||||||
|
wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::1/64"));
|
||||||
|
wifiLinkProperties.addLinkAddress(new LinkAddress("2001:2::2/64"));
|
||||||
|
wifiLinkProperties.addRoute(new RouteInfo(new IpPrefix("2001:2::/64")));
|
||||||
|
offload.notifyDownstreamLinkProperties(wifiLinkProperties);
|
||||||
|
|
||||||
|
offload.removeDownstreamInterface(RNDIS0);
|
||||||
|
|
||||||
// Clear invocation history, especially the getForwardedStats() calls
|
// Clear invocation history, especially the getForwardedStats() calls
|
||||||
// that happen with setUpstreamParameters().
|
// that happen with setUpstreamParameters().
|
||||||
clearInvocations(mHardware);
|
clearInvocations(mHardware);
|
||||||
@@ -685,6 +714,17 @@ public class OffloadControllerTest {
|
|||||||
verifyNoMoreInteractions(mNMService);
|
verifyNoMoreInteractions(mNMService);
|
||||||
|
|
||||||
// TODO: verify local prefixes and downstreams are also pushed to the HAL.
|
// TODO: verify local prefixes and downstreams are also pushed to the HAL.
|
||||||
|
verify(mHardware, times(1)).setLocalPrefixes(mStringArrayCaptor.capture());
|
||||||
|
ArrayList<String> localPrefixes = mStringArrayCaptor.getValue();
|
||||||
|
assertEquals(4, localPrefixes.size());
|
||||||
|
assertArrayListContains(localPrefixes,
|
||||||
|
// TODO: The logic to find and exclude downstream IP prefixes
|
||||||
|
// is currently in Tethering's OffloadWrapper but must be moved
|
||||||
|
// into OffloadController proper. After this, also check for:
|
||||||
|
// "192.168.43.1/32", "2001:2::1/128", "2001:2::2/128"
|
||||||
|
"127.0.0.0/8", "192.0.2.0/24", "fe80::/64", "2001:db8::/64");
|
||||||
|
verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "192.168.43.0/24");
|
||||||
|
verify(mHardware, times(1)).addDownstreamPrefix(WLAN0, "2001:2::/64");
|
||||||
verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
|
verify(mHardware, times(1)).setUpstreamParameters(eq(RMNET0), any(), any(), any());
|
||||||
verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
|
verify(mHardware, times(1)).setDataLimit(eq(RMNET0), anyLong());
|
||||||
verifyNoMoreInteractions(mHardware);
|
verifyNoMoreInteractions(mHardware);
|
||||||
@@ -692,7 +732,7 @@ public class OffloadControllerTest {
|
|||||||
|
|
||||||
private static void assertArrayListContains(ArrayList<String> list, String... elems) {
|
private static void assertArrayListContains(ArrayList<String> list, String... elems) {
|
||||||
for (String element : elems) {
|
for (String element : elems) {
|
||||||
assertTrue(list.contains(element));
|
assertTrue(element + " not in list", list.contains(element));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user