Loading services/core/java/com/android/server/connectivity/Tethering.java +5 −3 Original line number Diff line number Diff line Loading @@ -1268,10 +1268,10 @@ public class Tethering extends BaseNetworkObserver { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); } } setUpstreamByType(ns); setUpstreamNetwork(ns); } protected void setUpstreamByType(NetworkState ns) { protected void setUpstreamNetwork(NetworkState ns) { String iface = null; if (ns != null && ns.linkProperties != null) { // Find the interface with the default IPv4 route. It may be the Loading Loading @@ -1790,7 +1790,9 @@ public class Tethering extends BaseNetworkObserver { } } mLog.log(String.format("OBSERVED LinkProperties update iface=%s state=%s", iface, state)); mLog.log(String.format( "OBSERVED LinkProperties update iface=%s state=%s lp=%s", iface, IControlsTethering.getStateString(state), newLp)); final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES; mTetherMasterSM.sendMessage(which, state, 0, newLp); } Loading services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java +10 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,16 @@ public class IControlsTethering { public static final int STATE_TETHERED = 2; public static final int STATE_LOCAL_ONLY = 3; public static String getStateString(int state) { switch (state) { case STATE_UNAVAILABLE: return "UNAVAILABLE"; case STATE_AVAILABLE: return "AVAILABLE"; case STATE_TETHERED: return "TETHERED"; case STATE_LOCAL_ONLY: return "LOCAL_ONLY"; } return "UNKNOWN: " + state; } /** * Notify that |who| has changed its tethering state. * Loading services/core/java/com/android/server/connectivity/tethering/OffloadController.java +3 −0 Original line number Diff line number Diff line Loading @@ -85,13 +85,16 @@ public class OffloadController { mLog.i("tethering offload control not supported"); stop(); } mLog.log("tethering offload started"); } public void stop() { final boolean wasStarted = started(); mUpstreamLinkProperties = null; mHwInterface.stopOffloadControl(); mControlInitialized = false; mConfigInitialized = false; if (wasStarted) mLog.log("tethering offload stopped"); } public void setUpstreamLinkProperties(LinkProperties lp) { Loading services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +76 −35 Original line number Diff line number Diff line Loading @@ -56,9 +56,10 @@ import java.util.Objects; import java.util.Random; /** * @hide * Provides the interface to IP-layer serving functionality for a given network * interface, e.g. for tethering or "local-only hotspot" mode. * * Tracks the eligibility of a given network interface for tethering. * @hide */ public class TetherInterfaceStateMachine extends StateMachine { private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64"); Loading Loading @@ -117,6 +118,12 @@ public class TetherInterfaceStateMachine extends StateMachine { private String mMyUpstreamIfaceName; // may change over time private NetworkInterface mNetworkInterface; private byte[] mHwAddr; // TODO: De-duplicate this with mLinkProperties above. Currently, these link // properties are those selected by the IPv6TetheringCoordinator and relayed // to us. By comparison, mLinkProperties contains the addresses and directly // connected routes that have been formed from these properties iff. we have // succeeded in configuring them and are able to announce them within Router // Advertisements (otherwise, we do not add them to mLinkProperties at all). private LinkProperties mLastIPv6LinkProperties; private RouterAdvertisementDaemon mRaDaemon; private RaParams mLastRaParams; Loading @@ -133,7 +140,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mIfaceName = ifaceName; mInterfaceType = interfaceType; mLinkProperties = new LinkProperties(); mLinkProperties.setInterfaceName(mIfaceName); resetLinkProperties(); mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; mInitialState = new InitialState(); Loading Loading @@ -162,10 +169,15 @@ public class TetherInterfaceStateMachine extends StateMachine { * Internals. */ // configured when we start tethering and unconfig'd on error or conclusion private boolean configureIfaceIp(boolean enabled) { if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")"); private boolean startIPv4() { return configureIPv4(true); } private void stopIPv4() { configureIPv4(false); } private boolean configureIPv4(boolean enabled) { if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); // TODO: Replace this hard-coded information with dynamically selected // config passed down to us by a higher layer IP-coordinating element. String ipAsString = null; int prefixLen = 0; if (mInterfaceType == ConnectivityManager.TETHERING_USB) { Loading @@ -179,15 +191,20 @@ public class TetherInterfaceStateMachine extends StateMachine { return true; } InterfaceConfiguration ifcg = null; final LinkAddress linkAddr; try { ifcg = mNMService.getInterfaceConfig(mIfaceName); if (ifcg != null) { final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName); if (ifcg == null) { mLog.e("Received null interface config"); return false; } InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString); ifcg.setLinkAddress(new LinkAddress(addr, prefixLen)); linkAddr = new LinkAddress(addr, prefixLen); ifcg.setLinkAddress(linkAddr); if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { // The WiFi stack has ownership of the interface up/down state. // It is unclear whether the bluetooth or USB stacks will manage their own // It is unclear whether the Bluetooth or USB stacks will manage their own // state. ifcg.ignoreInterfaceUpDownStatus(); } else { Loading @@ -199,12 +216,20 @@ public class TetherInterfaceStateMachine extends StateMachine { } ifcg.clearFlag("running"); mNMService.setInterfaceConfig(mIfaceName, ifcg); } } catch (Exception e) { mLog.e("Error configuring interface " + e); return false; } // Directly-connected route. final RouteInfo route = new RouteInfo(linkAddr); if (enabled) { mLinkProperties.addLinkAddress(linkAddr); mLinkProperties.addRoute(route); } else { mLinkProperties.removeLinkAddress(linkAddr); mLinkProperties.removeRoute(route); } return true; } Loading Loading @@ -294,7 +319,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mLastIPv6LinkProperties = v6only; } private void configureLocalRoutes( private void configureLocalIPv6Routes( HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) { // [1] Remove the routes that are deprecated. if (!deprecatedPrefixes.isEmpty()) { Loading @@ -309,6 +334,8 @@ public class TetherInterfaceStateMachine extends StateMachine { } catch (RemoteException e) { mLog.e("Failed to remove IPv6 routes from local table: " + e); } for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); } // [2] Add only the routes that have not previously been added. Loading Loading @@ -340,11 +367,13 @@ public class TetherInterfaceStateMachine extends StateMachine { } catch (RemoteException e) { mLog.e("Failed to add IPv6 routes to local table: " + e); } for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); } } } private void configureLocalDns( private void configureLocalIPv6Dns( HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) { final INetd netd = NetdService.getInstance(); if (netd == null) { Loading @@ -362,6 +391,8 @@ public class TetherInterfaceStateMachine extends StateMachine { } catch (ServiceSpecificException | RemoteException e) { mLog.e("Failed to remove local dns IP " + dnsString + ": " + e); } mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); } } Loading @@ -380,6 +411,8 @@ public class TetherInterfaceStateMachine extends StateMachine { mLog.e("Failed to add local dns IP " + dnsString + ": " + e); newDnses.remove(dns); } mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); } } Loading @@ -396,10 +429,10 @@ public class TetherInterfaceStateMachine extends StateMachine { final RaParams deprecatedParams = RaParams.getDeprecatedRaParams(mLastRaParams, newParams); configureLocalRoutes(deprecatedParams.prefixes, configureLocalIPv6Routes(deprecatedParams.prefixes, (newParams != null) ? newParams.prefixes : null); configureLocalDns(deprecatedParams.dnses, configureLocalIPv6Dns(deprecatedParams.dnses, (newParams != null) ? newParams.dnses : null); mRaDaemon.buildNewRa(deprecatedParams, newParams); Loading @@ -419,12 +452,19 @@ public class TetherInterfaceStateMachine extends StateMachine { private void sendInterfaceState(int newInterfaceState) { mTetherController.updateInterfaceState( TetherInterfaceStateMachine.this, newInterfaceState, mLastError); // TODO: Populate mLinkProperties correctly, and send more sensible // updates more frequently (not just here). sendLinkProperties(); } private void sendLinkProperties() { mTetherController.updateLinkProperties( TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties)); } private void resetLinkProperties() { mLinkProperties.clear(); mLinkProperties.setInterfaceName(mIfaceName); } class InitialState extends State { @Override public void enter() { Loading Loading @@ -464,7 +504,7 @@ public class TetherInterfaceStateMachine extends StateMachine { class BaseServingState extends State { @Override public void enter() { if (!configureIfaceIp(true)) { if (!startIPv4()) { mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR; return; } Loading Loading @@ -498,7 +538,9 @@ public class TetherInterfaceStateMachine extends StateMachine { mLog.e("Failed to untether interface: " + e); } configureIfaceIp(false); stopIPv4(); resetLinkProperties(); } @Override Loading @@ -515,6 +557,7 @@ public class TetherInterfaceStateMachine extends StateMachine { break; case CMD_IPV6_TETHER_UPDATE: updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); sendLinkProperties(); break; case CMD_IP_FORWARDING_ENABLE_ERROR: case CMD_IP_FORWARDING_DISABLE_ERROR: Loading Loading @@ -625,7 +668,6 @@ public class TetherInterfaceStateMachine extends StateMachine { if (super.processMessage(message)) return true; maybeLogMessage(this, message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_REQUESTED: mLog.e("CMD_TETHER_REQUESTED while already tethering."); Loading Loading @@ -655,10 +697,9 @@ public class TetherInterfaceStateMachine extends StateMachine { mMyUpstreamIfaceName = newUpstreamIfaceName; break; default: retValue = false; break; return false; } return retValue; return true; } } Loading tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ public class OffloadControllerTest { @Mock private OffloadHardwareInterface mHardware; @Mock private ApplicationInfo mApplicationInfo; @Mock private Context mContext; final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private MockContentResolver mContentResolver; @Before public void setUp() throws Exception { Loading Loading
services/core/java/com/android/server/connectivity/Tethering.java +5 −3 Original line number Diff line number Diff line Loading @@ -1268,10 +1268,10 @@ public class Tethering extends BaseNetworkObserver { sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS); } } setUpstreamByType(ns); setUpstreamNetwork(ns); } protected void setUpstreamByType(NetworkState ns) { protected void setUpstreamNetwork(NetworkState ns) { String iface = null; if (ns != null && ns.linkProperties != null) { // Find the interface with the default IPv4 route. It may be the Loading Loading @@ -1790,7 +1790,9 @@ public class Tethering extends BaseNetworkObserver { } } mLog.log(String.format("OBSERVED LinkProperties update iface=%s state=%s", iface, state)); mLog.log(String.format( "OBSERVED LinkProperties update iface=%s state=%s lp=%s", iface, IControlsTethering.getStateString(state), newLp)); final int which = TetherMasterSM.EVENT_IFACE_UPDATE_LINKPROPERTIES; mTetherMasterSM.sendMessage(which, state, 0, newLp); } Loading
services/core/java/com/android/server/connectivity/tethering/IControlsTethering.java +10 −0 Original line number Diff line number Diff line Loading @@ -33,6 +33,16 @@ public class IControlsTethering { public static final int STATE_TETHERED = 2; public static final int STATE_LOCAL_ONLY = 3; public static String getStateString(int state) { switch (state) { case STATE_UNAVAILABLE: return "UNAVAILABLE"; case STATE_AVAILABLE: return "AVAILABLE"; case STATE_TETHERED: return "TETHERED"; case STATE_LOCAL_ONLY: return "LOCAL_ONLY"; } return "UNKNOWN: " + state; } /** * Notify that |who| has changed its tethering state. * Loading
services/core/java/com/android/server/connectivity/tethering/OffloadController.java +3 −0 Original line number Diff line number Diff line Loading @@ -85,13 +85,16 @@ public class OffloadController { mLog.i("tethering offload control not supported"); stop(); } mLog.log("tethering offload started"); } public void stop() { final boolean wasStarted = started(); mUpstreamLinkProperties = null; mHwInterface.stopOffloadControl(); mControlInitialized = false; mConfigInitialized = false; if (wasStarted) mLog.log("tethering offload stopped"); } public void setUpstreamLinkProperties(LinkProperties lp) { Loading
services/core/java/com/android/server/connectivity/tethering/TetherInterfaceStateMachine.java +76 −35 Original line number Diff line number Diff line Loading @@ -56,9 +56,10 @@ import java.util.Objects; import java.util.Random; /** * @hide * Provides the interface to IP-layer serving functionality for a given network * interface, e.g. for tethering or "local-only hotspot" mode. * * Tracks the eligibility of a given network interface for tethering. * @hide */ public class TetherInterfaceStateMachine extends StateMachine { private static final IpPrefix LINK_LOCAL_PREFIX = new IpPrefix("fe80::/64"); Loading Loading @@ -117,6 +118,12 @@ public class TetherInterfaceStateMachine extends StateMachine { private String mMyUpstreamIfaceName; // may change over time private NetworkInterface mNetworkInterface; private byte[] mHwAddr; // TODO: De-duplicate this with mLinkProperties above. Currently, these link // properties are those selected by the IPv6TetheringCoordinator and relayed // to us. By comparison, mLinkProperties contains the addresses and directly // connected routes that have been formed from these properties iff. we have // succeeded in configuring them and are able to announce them within Router // Advertisements (otherwise, we do not add them to mLinkProperties at all). private LinkProperties mLastIPv6LinkProperties; private RouterAdvertisementDaemon mRaDaemon; private RaParams mLastRaParams; Loading @@ -133,7 +140,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mIfaceName = ifaceName; mInterfaceType = interfaceType; mLinkProperties = new LinkProperties(); mLinkProperties.setInterfaceName(mIfaceName); resetLinkProperties(); mLastError = ConnectivityManager.TETHER_ERROR_NO_ERROR; mInitialState = new InitialState(); Loading Loading @@ -162,10 +169,15 @@ public class TetherInterfaceStateMachine extends StateMachine { * Internals. */ // configured when we start tethering and unconfig'd on error or conclusion private boolean configureIfaceIp(boolean enabled) { if (VDBG) Log.d(TAG, "configureIfaceIp(" + enabled + ")"); private boolean startIPv4() { return configureIPv4(true); } private void stopIPv4() { configureIPv4(false); } private boolean configureIPv4(boolean enabled) { if (VDBG) Log.d(TAG, "configureIPv4(" + enabled + ")"); // TODO: Replace this hard-coded information with dynamically selected // config passed down to us by a higher layer IP-coordinating element. String ipAsString = null; int prefixLen = 0; if (mInterfaceType == ConnectivityManager.TETHERING_USB) { Loading @@ -179,15 +191,20 @@ public class TetherInterfaceStateMachine extends StateMachine { return true; } InterfaceConfiguration ifcg = null; final LinkAddress linkAddr; try { ifcg = mNMService.getInterfaceConfig(mIfaceName); if (ifcg != null) { final InterfaceConfiguration ifcg = mNMService.getInterfaceConfig(mIfaceName); if (ifcg == null) { mLog.e("Received null interface config"); return false; } InetAddress addr = NetworkUtils.numericToInetAddress(ipAsString); ifcg.setLinkAddress(new LinkAddress(addr, prefixLen)); linkAddr = new LinkAddress(addr, prefixLen); ifcg.setLinkAddress(linkAddr); if (mInterfaceType == ConnectivityManager.TETHERING_WIFI) { // The WiFi stack has ownership of the interface up/down state. // It is unclear whether the bluetooth or USB stacks will manage their own // It is unclear whether the Bluetooth or USB stacks will manage their own // state. ifcg.ignoreInterfaceUpDownStatus(); } else { Loading @@ -199,12 +216,20 @@ public class TetherInterfaceStateMachine extends StateMachine { } ifcg.clearFlag("running"); mNMService.setInterfaceConfig(mIfaceName, ifcg); } } catch (Exception e) { mLog.e("Error configuring interface " + e); return false; } // Directly-connected route. final RouteInfo route = new RouteInfo(linkAddr); if (enabled) { mLinkProperties.addLinkAddress(linkAddr); mLinkProperties.addRoute(route); } else { mLinkProperties.removeLinkAddress(linkAddr); mLinkProperties.removeRoute(route); } return true; } Loading Loading @@ -294,7 +319,7 @@ public class TetherInterfaceStateMachine extends StateMachine { mLastIPv6LinkProperties = v6only; } private void configureLocalRoutes( private void configureLocalIPv6Routes( HashSet<IpPrefix> deprecatedPrefixes, HashSet<IpPrefix> newPrefixes) { // [1] Remove the routes that are deprecated. if (!deprecatedPrefixes.isEmpty()) { Loading @@ -309,6 +334,8 @@ public class TetherInterfaceStateMachine extends StateMachine { } catch (RemoteException e) { mLog.e("Failed to remove IPv6 routes from local table: " + e); } for (RouteInfo route : toBeRemoved) mLinkProperties.removeRoute(route); } // [2] Add only the routes that have not previously been added. Loading Loading @@ -340,11 +367,13 @@ public class TetherInterfaceStateMachine extends StateMachine { } catch (RemoteException e) { mLog.e("Failed to add IPv6 routes to local table: " + e); } for (RouteInfo route : toBeAdded) mLinkProperties.addRoute(route); } } } private void configureLocalDns( private void configureLocalIPv6Dns( HashSet<Inet6Address> deprecatedDnses, HashSet<Inet6Address> newDnses) { final INetd netd = NetdService.getInstance(); if (netd == null) { Loading @@ -362,6 +391,8 @@ public class TetherInterfaceStateMachine extends StateMachine { } catch (ServiceSpecificException | RemoteException e) { mLog.e("Failed to remove local dns IP " + dnsString + ": " + e); } mLinkProperties.removeLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); } } Loading @@ -380,6 +411,8 @@ public class TetherInterfaceStateMachine extends StateMachine { mLog.e("Failed to add local dns IP " + dnsString + ": " + e); newDnses.remove(dns); } mLinkProperties.addLinkAddress(new LinkAddress(dns, RFC7421_PREFIX_LENGTH)); } } Loading @@ -396,10 +429,10 @@ public class TetherInterfaceStateMachine extends StateMachine { final RaParams deprecatedParams = RaParams.getDeprecatedRaParams(mLastRaParams, newParams); configureLocalRoutes(deprecatedParams.prefixes, configureLocalIPv6Routes(deprecatedParams.prefixes, (newParams != null) ? newParams.prefixes : null); configureLocalDns(deprecatedParams.dnses, configureLocalIPv6Dns(deprecatedParams.dnses, (newParams != null) ? newParams.dnses : null); mRaDaemon.buildNewRa(deprecatedParams, newParams); Loading @@ -419,12 +452,19 @@ public class TetherInterfaceStateMachine extends StateMachine { private void sendInterfaceState(int newInterfaceState) { mTetherController.updateInterfaceState( TetherInterfaceStateMachine.this, newInterfaceState, mLastError); // TODO: Populate mLinkProperties correctly, and send more sensible // updates more frequently (not just here). sendLinkProperties(); } private void sendLinkProperties() { mTetherController.updateLinkProperties( TetherInterfaceStateMachine.this, new LinkProperties(mLinkProperties)); } private void resetLinkProperties() { mLinkProperties.clear(); mLinkProperties.setInterfaceName(mIfaceName); } class InitialState extends State { @Override public void enter() { Loading Loading @@ -464,7 +504,7 @@ public class TetherInterfaceStateMachine extends StateMachine { class BaseServingState extends State { @Override public void enter() { if (!configureIfaceIp(true)) { if (!startIPv4()) { mLastError = ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR; return; } Loading Loading @@ -498,7 +538,9 @@ public class TetherInterfaceStateMachine extends StateMachine { mLog.e("Failed to untether interface: " + e); } configureIfaceIp(false); stopIPv4(); resetLinkProperties(); } @Override Loading @@ -515,6 +557,7 @@ public class TetherInterfaceStateMachine extends StateMachine { break; case CMD_IPV6_TETHER_UPDATE: updateUpstreamIPv6LinkProperties((LinkProperties) message.obj); sendLinkProperties(); break; case CMD_IP_FORWARDING_ENABLE_ERROR: case CMD_IP_FORWARDING_DISABLE_ERROR: Loading Loading @@ -625,7 +668,6 @@ public class TetherInterfaceStateMachine extends StateMachine { if (super.processMessage(message)) return true; maybeLogMessage(this, message.what); boolean retValue = true; switch (message.what) { case CMD_TETHER_REQUESTED: mLog.e("CMD_TETHER_REQUESTED while already tethering."); Loading Loading @@ -655,10 +697,9 @@ public class TetherInterfaceStateMachine extends StateMachine { mMyUpstreamIfaceName = newUpstreamIfaceName; break; default: retValue = false; break; return false; } return retValue; return true; } } Loading
tests/net/java/com/android/server/connectivity/tethering/OffloadControllerTest.java +2 −1 Original line number Diff line number Diff line Loading @@ -62,7 +62,8 @@ public class OffloadControllerTest { @Mock private OffloadHardwareInterface mHardware; @Mock private ApplicationInfo mApplicationInfo; @Mock private Context mContext; final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private final ArgumentCaptor<ArrayList> mStringArrayCaptor = ArgumentCaptor.forClass(ArrayList.class); private MockContentResolver mContentResolver; @Before public void setUp() throws Exception { Loading