• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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