1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package android.net.shared; 18 19 import static android.system.OsConstants.EBUSY; 20 21 import android.net.INetd; 22 import android.net.TetherConfigParcel; 23 import android.os.RemoteException; 24 import android.os.ServiceSpecificException; 25 import android.os.SystemClock; 26 import android.util.Log; 27 28 /** 29 * Implements common operations on INetd 30 * @hide 31 */ 32 public class NetdUtils { 33 private static final String TAG = NetdUtils.class.getSimpleName(); 34 35 /** Start tethering. */ tetherStart(final INetd netd, final boolean usingLegacyDnsProxy, final String[] dhcpRange)36 public static void tetherStart(final INetd netd, final boolean usingLegacyDnsProxy, 37 final String[] dhcpRange) throws RemoteException, ServiceSpecificException { 38 final TetherConfigParcel config = new TetherConfigParcel(); 39 config.usingLegacyDnsProxy = usingLegacyDnsProxy; 40 config.dhcpRanges = dhcpRange; 41 netd.tetherStartWithConfiguration(config); 42 } 43 44 /** 45 * Retry Netd#networkAddInterface for EBUSY error code. 46 * If the same interface (e.g., wlan0) is in client mode and then switches to tethered mode. 47 * There can be a race where puts the interface into the local network but interface is still 48 * in use in netd because the ConnectivityService thread hasn't processed the disconnect yet. 49 * See b/158269544 for detail. 50 */ networkAddInterface(final INetd netd, final String iface, int maxAttempts, int pollingIntervalMs)51 private static void networkAddInterface(final INetd netd, final String iface, 52 int maxAttempts, int pollingIntervalMs) 53 throws ServiceSpecificException, RemoteException { 54 for (int i = 1; i <= maxAttempts; i++) { 55 try { 56 netd.networkAddInterface(INetd.LOCAL_NET_ID, iface); 57 return; 58 } catch (ServiceSpecificException e) { 59 if (e.errorCode == EBUSY && i < maxAttempts) { 60 SystemClock.sleep(pollingIntervalMs); 61 continue; 62 } 63 64 Log.e(TAG, "Retry Netd#networkAddInterface failure: " + e); 65 throw e; 66 } 67 } 68 } 69 70 /** Reset interface for tethering. */ untetherInterface(final INetd netd, String iface)71 public static void untetherInterface(final INetd netd, String iface) 72 throws RemoteException, ServiceSpecificException { 73 try { 74 netd.tetherInterfaceRemove(iface); 75 } finally { 76 netd.networkRemoveInterface(INetd.LOCAL_NET_ID, iface); 77 } 78 } 79 } 80