Loading services/core/java/com/android/server/connectivity/tethering/OffloadController.java +47 −2 Original line number Original line Diff line number Diff line Loading @@ -20,10 +20,15 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import android.content.ContentResolver; import android.content.ContentResolver; import android.net.LinkProperties; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.os.Handler; import android.os.Handler; import android.provider.Settings; import android.provider.Settings; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; /** /** * A class to encapsulate the business logic of programming the tethering * A class to encapsulate the business logic of programming the tethering * hardware offload interface. * hardware offload interface. Loading Loading @@ -92,8 +97,12 @@ public class OffloadController { public void setUpstreamLinkProperties(LinkProperties lp) { public void setUpstreamLinkProperties(LinkProperties lp) { if (!started()) return; if (!started()) return; // TODO: setUpstreamParameters(). mUpstreamLinkProperties = (lp != null) ? new LinkProperties(lp) : null; mUpstreamLinkProperties = lp; // TODO: examine return code and decide what to do if programming // upstream parameters fails (probably just wait for a subsequent // onOffloadEvent() callback to tell us offload is available again and // then reapply all state). pushUpstreamParameters(); } } // TODO: public void addDownStream(...) // TODO: public void addDownStream(...) Loading @@ -106,4 +115,40 @@ public class OffloadController { private boolean started() { private boolean started() { return mConfigInitialized && mControlInitialized; return mConfigInitialized && mControlInitialized; } } private boolean pushUpstreamParameters() { if (mUpstreamLinkProperties == null) { return mHwInterface.setUpstreamParameters(null, null, null, null); } // A stacked interface cannot be an upstream for hardware offload. // Consequently, we examine only the primary interface name, look at // getAddresses() rather than getAllAddresses(), and check getRoutes() // rather than getAllRoutes(). final String iface = mUpstreamLinkProperties.getInterfaceName(); final ArrayList<String> v6gateways = new ArrayList<>(); String v4addr = null; String v4gateway = null; for (InetAddress ip : mUpstreamLinkProperties.getAddresses()) { if (ip instanceof Inet4Address) { v4addr = ip.getHostAddress(); break; } } // Find the gateway addresses of all default routes of either address family. for (RouteInfo ri : mUpstreamLinkProperties.getRoutes()) { if (!ri.hasGateway()) continue; final String gateway = ri.getGateway().getHostAddress(); if (ri.isIPv4Default()) { v4gateway = gateway; } else if (ri.isIPv6Default()) { v6gateways.add(gateway); } } return mHwInterface.setUpstreamParameters(iface, v4addr, v4gateway, v6gateways); } } } services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +21 −0 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.os.Handler; import android.os.RemoteException; import android.os.RemoteException; import android.net.util.SharedLog; import android.net.util.SharedLog; import java.util.ArrayList; /** /** * Capture tethering dependencies, for injection. * Capture tethering dependencies, for injection. Loading Loading @@ -103,6 +105,25 @@ public class OffloadHardwareInterface { mControlCallback = null; mControlCallback = null; } } public boolean setUpstreamParameters( String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) { final CbResults results = new CbResults(); try { mOffloadControl.setUpstreamParameters( iface, v4addr, v4gateway, v6gws, (boolean success, String errMsg) -> { results.success = success; results.errMsg = errMsg; }); } catch (RemoteException e) { mLog.e("failed to setUpstreamParameters: " + e); return false; } if (!results.success) mLog.e("setUpstreamParameters failed: " + results.errMsg); return results.success; } private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub { private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub { public final Handler handler; public final Handler handler; public final ControlCallback controlCb; public final ControlCallback controlCb; Loading tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +95 −0 Original line number Original line Diff line number Diff line Loading @@ -17,15 +17,22 @@ package com.android.server.connectivity.tethering; package com.android.server.connectivity.tethering; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import android.content.Context; import android.content.Context; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.provider.Settings; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException; Loading @@ -35,9 +42,13 @@ import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import android.test.mock.MockContentResolver; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider; import java.net.InetAddress; import java.util.ArrayList; import org.junit.Before; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.runner.RunWith; import org.junit.Test; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; Loading @@ -49,6 +60,7 @@ public class OffloadControllerTest { @Mock private OffloadHardwareInterface mHardware; @Mock private OffloadHardwareInterface mHardware; @Mock private Context mContext; @Mock private Context mContext; final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private MockContentResolver mContentResolver; private MockContentResolver mContentResolver; @Before public void setUp() throws Exception { @Before public void setUp() throws Exception { Loading Loading @@ -114,4 +126,87 @@ public class OffloadControllerTest { inOrder.verify(mHardware, never()).initOffloadControl(anyObject()); inOrder.verify(mHardware, never()).initOffloadControl(anyObject()); inOrder.verifyNoMoreInteractions(); inOrder.verifyNoMoreInteractions(); } } @Test public void testSetUpstreamLinkPropertiesWorking() throws Exception { setupFunctioningHardwareInterface(); final OffloadController offload = new OffloadController(null, mHardware, mContentResolver, new SharedLog("test")); offload.start(); final InOrder inOrder = inOrder(mHardware); inOrder.verify(mHardware, times(1)).initOffloadConfig(); inOrder.verify(mHardware, times(1)).initOffloadControl( any(OffloadHardwareInterface.ControlCallback.class)); inOrder.verifyNoMoreInteractions(); offload.setUpstreamLinkProperties(null); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(null), eq(null), eq(null), eq(null)); inOrder.verifyNoMoreInteractions(); reset(mHardware); final LinkProperties lp = new LinkProperties(); final String testIfName = "rmnet_data17"; lp.setInterfaceName(testIfName); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(null), eq(null), mStringArrayCaptor.capture()); assertTrue(mStringArrayCaptor.getValue().isEmpty()); inOrder.verifyNoMoreInteractions(); final String ipv4Addr = "192.0.2.5"; final String linkAddr = ipv4Addr + "/24"; lp.addLinkAddress(new LinkAddress(linkAddr)); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(null), mStringArrayCaptor.capture()); assertTrue(mStringArrayCaptor.getValue().isEmpty()); inOrder.verifyNoMoreInteractions(); final String ipv4Gateway = "192.0.2.1"; lp.addRoute(new RouteInfo(InetAddress.getByName(ipv4Gateway))); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); assertTrue(mStringArrayCaptor.getValue().isEmpty()); inOrder.verifyNoMoreInteractions(); final String ipv6Gw1 = "fe80::cafe"; lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw1))); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); ArrayList<String> v6gws = mStringArrayCaptor.getValue(); assertEquals(1, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); inOrder.verifyNoMoreInteractions(); final String ipv6Gw2 = "fe80::d00d"; lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw2))); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); v6gws = mStringArrayCaptor.getValue(); assertEquals(2, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); inOrder.verifyNoMoreInteractions(); final LinkProperties stacked = new LinkProperties(); stacked.setInterfaceName("stacked"); stacked.addLinkAddress(new LinkAddress("192.0.2.129/25")); stacked.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); stacked.addRoute(new RouteInfo(InetAddress.getByName("fe80::bad:f00"))); assertTrue(lp.addStackedLink(stacked)); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); v6gws = mStringArrayCaptor.getValue(); assertEquals(2, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); inOrder.verifyNoMoreInteractions(); } } } Loading
services/core/java/com/android/server/connectivity/tethering/OffloadController.java +47 −2 Original line number Original line Diff line number Diff line Loading @@ -20,10 +20,15 @@ import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import android.content.ContentResolver; import android.content.ContentResolver; import android.net.LinkProperties; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.os.Handler; import android.os.Handler; import android.provider.Settings; import android.provider.Settings; import java.net.Inet4Address; import java.net.InetAddress; import java.util.ArrayList; /** /** * A class to encapsulate the business logic of programming the tethering * A class to encapsulate the business logic of programming the tethering * hardware offload interface. * hardware offload interface. Loading Loading @@ -92,8 +97,12 @@ public class OffloadController { public void setUpstreamLinkProperties(LinkProperties lp) { public void setUpstreamLinkProperties(LinkProperties lp) { if (!started()) return; if (!started()) return; // TODO: setUpstreamParameters(). mUpstreamLinkProperties = (lp != null) ? new LinkProperties(lp) : null; mUpstreamLinkProperties = lp; // TODO: examine return code and decide what to do if programming // upstream parameters fails (probably just wait for a subsequent // onOffloadEvent() callback to tell us offload is available again and // then reapply all state). pushUpstreamParameters(); } } // TODO: public void addDownStream(...) // TODO: public void addDownStream(...) Loading @@ -106,4 +115,40 @@ public class OffloadController { private boolean started() { private boolean started() { return mConfigInitialized && mControlInitialized; return mConfigInitialized && mControlInitialized; } } private boolean pushUpstreamParameters() { if (mUpstreamLinkProperties == null) { return mHwInterface.setUpstreamParameters(null, null, null, null); } // A stacked interface cannot be an upstream for hardware offload. // Consequently, we examine only the primary interface name, look at // getAddresses() rather than getAllAddresses(), and check getRoutes() // rather than getAllRoutes(). final String iface = mUpstreamLinkProperties.getInterfaceName(); final ArrayList<String> v6gateways = new ArrayList<>(); String v4addr = null; String v4gateway = null; for (InetAddress ip : mUpstreamLinkProperties.getAddresses()) { if (ip instanceof Inet4Address) { v4addr = ip.getHostAddress(); break; } } // Find the gateway addresses of all default routes of either address family. for (RouteInfo ri : mUpstreamLinkProperties.getRoutes()) { if (!ri.hasGateway()) continue; final String gateway = ri.getGateway().getHostAddress(); if (ri.isIPv4Default()) { v4gateway = gateway; } else if (ri.isIPv6Default()) { v6gateways.add(gateway); } } return mHwInterface.setUpstreamParameters(iface, v4addr, v4gateway, v6gateways); } } }
services/core/java/com/android/server/connectivity/tethering/OffloadHardwareInterface.java +21 −0 Original line number Original line Diff line number Diff line Loading @@ -23,6 +23,8 @@ import android.os.Handler; import android.os.RemoteException; import android.os.RemoteException; import android.net.util.SharedLog; import android.net.util.SharedLog; import java.util.ArrayList; /** /** * Capture tethering dependencies, for injection. * Capture tethering dependencies, for injection. Loading Loading @@ -103,6 +105,25 @@ public class OffloadHardwareInterface { mControlCallback = null; mControlCallback = null; } } public boolean setUpstreamParameters( String iface, String v4addr, String v4gateway, ArrayList<String> v6gws) { final CbResults results = new CbResults(); try { mOffloadControl.setUpstreamParameters( iface, v4addr, v4gateway, v6gws, (boolean success, String errMsg) -> { results.success = success; results.errMsg = errMsg; }); } catch (RemoteException e) { mLog.e("failed to setUpstreamParameters: " + e); return false; } if (!results.success) mLog.e("setUpstreamParameters failed: " + results.errMsg); return results.success; } private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub { private static class TetheringOffloadCallback extends ITetheringOffloadCallback.Stub { public final Handler handler; public final Handler handler; public final ControlCallback controlCb; public final ControlCallback controlCb; Loading
tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +95 −0 Original line number Original line Diff line number Diff line Loading @@ -17,15 +17,22 @@ package com.android.server.connectivity.tethering; package com.android.server.connectivity.tethering; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static android.provider.Settings.Global.TETHER_OFFLOAD_DISABLED; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; import static org.mockito.Matchers.any; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.anyObject; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.inOrder; import static org.mockito.Mockito.never; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.times; import static org.mockito.Mockito.times; import static org.mockito.Mockito.when; import static org.mockito.Mockito.when; import android.content.Context; import android.content.Context; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.RouteInfo; import android.net.util.SharedLog; import android.net.util.SharedLog; import android.provider.Settings; import android.provider.Settings; import android.provider.Settings.SettingNotFoundException; import android.provider.Settings.SettingNotFoundException; Loading @@ -35,9 +42,13 @@ import android.support.test.runner.AndroidJUnit4; import android.test.mock.MockContentResolver; import android.test.mock.MockContentResolver; import com.android.internal.util.test.FakeSettingsProvider; import com.android.internal.util.test.FakeSettingsProvider; import java.net.InetAddress; import java.util.ArrayList; import org.junit.Before; import org.junit.Before; import org.junit.runner.RunWith; import org.junit.runner.RunWith; import org.junit.Test; import org.junit.Test; import org.mockito.ArgumentCaptor; import org.mockito.InOrder; import org.mockito.InOrder; import org.mockito.Mock; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.mockito.MockitoAnnotations; Loading @@ -49,6 +60,7 @@ public class OffloadControllerTest { @Mock private OffloadHardwareInterface mHardware; @Mock private OffloadHardwareInterface mHardware; @Mock private Context mContext; @Mock private Context mContext; final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private MockContentResolver mContentResolver; private MockContentResolver mContentResolver; @Before public void setUp() throws Exception { @Before public void setUp() throws Exception { Loading Loading @@ -114,4 +126,87 @@ public class OffloadControllerTest { inOrder.verify(mHardware, never()).initOffloadControl(anyObject()); inOrder.verify(mHardware, never()).initOffloadControl(anyObject()); inOrder.verifyNoMoreInteractions(); inOrder.verifyNoMoreInteractions(); } } @Test public void testSetUpstreamLinkPropertiesWorking() throws Exception { setupFunctioningHardwareInterface(); final OffloadController offload = new OffloadController(null, mHardware, mContentResolver, new SharedLog("test")); offload.start(); final InOrder inOrder = inOrder(mHardware); inOrder.verify(mHardware, times(1)).initOffloadConfig(); inOrder.verify(mHardware, times(1)).initOffloadControl( any(OffloadHardwareInterface.ControlCallback.class)); inOrder.verifyNoMoreInteractions(); offload.setUpstreamLinkProperties(null); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(null), eq(null), eq(null), eq(null)); inOrder.verifyNoMoreInteractions(); reset(mHardware); final LinkProperties lp = new LinkProperties(); final String testIfName = "rmnet_data17"; lp.setInterfaceName(testIfName); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(null), eq(null), mStringArrayCaptor.capture()); assertTrue(mStringArrayCaptor.getValue().isEmpty()); inOrder.verifyNoMoreInteractions(); final String ipv4Addr = "192.0.2.5"; final String linkAddr = ipv4Addr + "/24"; lp.addLinkAddress(new LinkAddress(linkAddr)); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(null), mStringArrayCaptor.capture()); assertTrue(mStringArrayCaptor.getValue().isEmpty()); inOrder.verifyNoMoreInteractions(); final String ipv4Gateway = "192.0.2.1"; lp.addRoute(new RouteInfo(InetAddress.getByName(ipv4Gateway))); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); assertTrue(mStringArrayCaptor.getValue().isEmpty()); inOrder.verifyNoMoreInteractions(); final String ipv6Gw1 = "fe80::cafe"; lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw1))); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); ArrayList<String> v6gws = mStringArrayCaptor.getValue(); assertEquals(1, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); inOrder.verifyNoMoreInteractions(); final String ipv6Gw2 = "fe80::d00d"; lp.addRoute(new RouteInfo(InetAddress.getByName(ipv6Gw2))); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); v6gws = mStringArrayCaptor.getValue(); assertEquals(2, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); inOrder.verifyNoMoreInteractions(); final LinkProperties stacked = new LinkProperties(); stacked.setInterfaceName("stacked"); stacked.addLinkAddress(new LinkAddress("192.0.2.129/25")); stacked.addRoute(new RouteInfo(InetAddress.getByName("192.0.2.254"))); stacked.addRoute(new RouteInfo(InetAddress.getByName("fe80::bad:f00"))); assertTrue(lp.addStackedLink(stacked)); offload.setUpstreamLinkProperties(lp); inOrder.verify(mHardware, times(1)).setUpstreamParameters( eq(testIfName), eq(ipv4Addr), eq(ipv4Gateway), mStringArrayCaptor.capture()); v6gws = mStringArrayCaptor.getValue(); assertEquals(2, v6gws.size()); assertTrue(v6gws.contains(ipv6Gw1)); assertTrue(v6gws.contains(ipv6Gw2)); inOrder.verifyNoMoreInteractions(); } } }