diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/moduleutils/src/android/net/shared/NetdUtils.java | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/common/moduleutils/src/android/net/shared/NetdUtils.java b/common/moduleutils/src/android/net/shared/NetdUtils.java index 0137bb77..5fa29c9b 100644 --- a/common/moduleutils/src/android/net/shared/NetdUtils.java +++ b/common/moduleutils/src/android/net/shared/NetdUtils.java @@ -17,6 +17,7 @@ package android.net.shared; import static android.net.RouteInfo.RTN_UNICAST; +import static android.system.OsConstants.EBUSY; import android.net.INetd; import android.net.IpPrefix; @@ -24,6 +25,8 @@ import android.net.RouteInfo; import android.net.TetherConfigParcel; import android.os.RemoteException; import android.os.ServiceSpecificException; +import android.os.SystemClock; +import android.util.Log; import java.util.ArrayList; import java.util.List; @@ -33,6 +36,8 @@ import java.util.List; * @hide */ public class NetdUtils { + private static final String TAG = NetdUtils.class.getSimpleName(); + /** Start tethering. */ public static void tetherStart(final INetd netd, final boolean usingLegacyDnsProxy, final String[] dhcpRange) throws RemoteException, ServiceSpecificException { @@ -45,14 +50,46 @@ public class NetdUtils { /** Setup interface for tethering. */ public static void tetherInterface(final INetd netd, final String iface, final IpPrefix dest) throws RemoteException, ServiceSpecificException { - netd.tetherInterfaceAdd(iface); + tetherInterface(netd, iface, dest, 20 /* maxAttempts */, 50 /* pollingIntervalMs */); + } - netd.networkAddInterface(INetd.LOCAL_NET_ID, iface); + /** Setup interface with configurable retries for tethering. */ + public static void tetherInterface(final INetd netd, final String iface, final IpPrefix dest, + int maxAttempts, int pollingIntervalMs) + throws RemoteException, ServiceSpecificException { + netd.tetherInterfaceAdd(iface); + networkAddInterface(netd, iface, maxAttempts, pollingIntervalMs); List<RouteInfo> routes = new ArrayList<>(); routes.add(new RouteInfo(dest, null, iface, RTN_UNICAST)); RouteUtils.addRoutesToLocalNetwork(netd, iface, routes); } + /** + * Retry Netd#networkAddInterface for EBUSY error code. + * If the same interface (e.g., wlan0) is in client mode and then switches to tethered mode. + * There can be a race where puts the interface into the local network but interface is still + * in use in netd because the ConnectivityService thread hasn't processed the disconnect yet. + * See b/158269544 for detail. + */ + private static void networkAddInterface(final INetd netd, final String iface, + int maxAttempts, int pollingIntervalMs) + throws ServiceSpecificException, RemoteException { + for (int i = 1; i <= maxAttempts; i++) { + try { + netd.networkAddInterface(INetd.LOCAL_NET_ID, iface); + return; + } catch (ServiceSpecificException e) { + if (e.errorCode == EBUSY && i < maxAttempts) { + SystemClock.sleep(pollingIntervalMs); + continue; + } + + Log.e(TAG, "Retry Netd#networkAddInterface failure: " + e); + throw e; + } + } + } + /** Reset interface for tethering. */ public static void untetherInterface(final INetd netd, String iface) throws RemoteException, ServiceSpecificException { |
