1 /*
2  * Copyright (C) 2010 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 com.android.server.connectivity;
18 
19 import android.app.Notification;
20 import android.app.NotificationManager;
21 import android.app.PendingIntent;
22 import android.content.BroadcastReceiver;
23 import android.content.ComponentName;
24 import android.content.Context;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.content.pm.PackageManager;
28 import android.content.res.Resources;
29 import android.hardware.usb.UsbManager;
30 import android.net.ConnectivityManager;
31 import android.net.INetworkStatsService;
32 import android.net.InterfaceConfiguration;
33 import android.net.LinkAddress;
34 import android.net.LinkProperties;
35 import android.net.Network;
36 import android.net.NetworkInfo;
37 import android.net.NetworkUtils;
38 import android.net.RouteInfo;
39 import android.os.Binder;
40 import android.os.INetworkManagementService;
41 import android.os.Looper;
42 import android.os.Message;
43 import android.os.UserHandle;
44 import android.telephony.TelephonyManager;
45 import android.util.Log;
46 
47 import com.android.internal.telephony.IccCardConstants;
48 import com.android.internal.telephony.Phone;
49 import com.android.internal.telephony.PhoneConstants;
50 import com.android.internal.telephony.TelephonyIntents;
51 import com.android.internal.util.IndentingPrintWriter;
52 import com.android.internal.util.IState;
53 import com.android.internal.util.State;
54 import com.android.internal.util.StateMachine;
55 import com.android.server.IoThread;
56 import com.android.server.net.BaseNetworkObserver;
57 
58 import java.io.FileDescriptor;
59 import java.io.PrintWriter;
60 import java.net.InetAddress;
61 import java.net.Inet4Address;
62 import java.util.ArrayList;
63 import java.util.Arrays;
64 import java.util.Collection;
65 import java.util.HashMap;
66 import java.util.Iterator;
67 import java.util.Set;
68 import java.util.concurrent.atomic.AtomicInteger;
69 
70 
71 /**
72  * @hide
73  *
74  * Timeout
75  *
76  * TODO - look for parent classes and code sharing
77  */
78 public class Tethering extends BaseNetworkObserver {
79 
80     private Context mContext;
81     private final static String TAG = "Tethering";
82     private final static boolean DBG = true;
83     private final static boolean VDBG = false;
84 
85     // TODO - remove both of these - should be part of interface inspection/selection stuff
86     private String[] mTetherableUsbRegexs;
87     private String[] mTetherableWifiRegexs;
88     private String[] mTetherableBluetoothRegexs;
89     private Collection<Integer> mUpstreamIfaceTypes;
90 
91     // used to synchronize public access to members
92     private Object mPublicSync;
93 
94     private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
95     private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
96     private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
97 
98     // if we have to connect to mobile, what APN type should we use?  Calculated by examining the
99     // upstream type list and the DUN_REQUIRED secure-setting
100     private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
101 
102     private final INetworkManagementService mNMService;
103     private final INetworkStatsService mStatsService;
104     private Looper mLooper;
105 
106     private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
107 
108     private BroadcastReceiver mStateReceiver;
109 
110     private static final String USB_NEAR_IFACE_ADDR      = "192.168.42.129";
111     private static final int USB_PREFIX_LENGTH        = 24;
112 
113     // USB is  192.168.42.1 and 255.255.255.0
114     // Wifi is 192.168.43.1 and 255.255.255.0
115     // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
116     // with 255.255.255.0
117     // P2P is 192.168.49.1 and 255.255.255.0
118 
119     private String[] mDhcpRange;
120     private static final String[] DHCP_DEFAULT_RANGE = {
121         "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
122         "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
123         "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
124         "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
125     };
126 
127     private String[] mDefaultDnsServers;
128     private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
129     private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
130 
131     private StateMachine mTetherMasterSM;
132 
133     private Notification.Builder mTetheredNotificationBuilder;
134     private int mLastNotificationId;
135 
136     private boolean mRndisEnabled;       // track the RNDIS function enabled state
137     private boolean mUsbTetherRequested; // true if USB tethering should be started
138                                          // when RNDIS is enabled
139 
Tethering(Context context, INetworkManagementService nmService, INetworkStatsService statsService, Looper looper)140     public Tethering(Context context, INetworkManagementService nmService,
141             INetworkStatsService statsService, Looper looper) {
142         mContext = context;
143         mNMService = nmService;
144         mStatsService = statsService;
145         mLooper = looper;
146 
147         mPublicSync = new Object();
148 
149         mIfaces = new HashMap<String, TetherInterfaceSM>();
150 
151         // make our own thread so we don't anr the system
152         mLooper = IoThread.get().getLooper();
153         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
154         mTetherMasterSM.start();
155 
156         mStateReceiver = new StateReceiver();
157         IntentFilter filter = new IntentFilter();
158         filter.addAction(UsbManager.ACTION_USB_STATE);
159         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
160         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
161         mContext.registerReceiver(mStateReceiver, filter);
162 
163         filter = new IntentFilter();
164         filter.addAction(Intent.ACTION_MEDIA_SHARED);
165         filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
166         filter.addDataScheme("file");
167         mContext.registerReceiver(mStateReceiver, filter);
168 
169         mDhcpRange = context.getResources().getStringArray(
170                 com.android.internal.R.array.config_tether_dhcp_range);
171         if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
172             mDhcpRange = DHCP_DEFAULT_RANGE;
173         }
174 
175         // load device config info
176         updateConfiguration();
177 
178         // TODO - remove and rely on real notifications of the current iface
179         mDefaultDnsServers = new String[2];
180         mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
181         mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
182     }
183 
184     // We can't do this once in the Tethering() constructor and cache the value, because the
185     // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed.
getConnectivityManager()186     private ConnectivityManager getConnectivityManager() {
187         return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
188     }
189 
updateConfiguration()190     void updateConfiguration() {
191         String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
192                 com.android.internal.R.array.config_tether_usb_regexs);
193         String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
194                 com.android.internal.R.array.config_tether_wifi_regexs);
195         String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
196                 com.android.internal.R.array.config_tether_bluetooth_regexs);
197 
198         int ifaceTypes[] = mContext.getResources().getIntArray(
199                 com.android.internal.R.array.config_tether_upstream_types);
200         Collection<Integer> upstreamIfaceTypes = new ArrayList();
201         for (int i : ifaceTypes) {
202             upstreamIfaceTypes.add(new Integer(i));
203         }
204 
205         synchronized (mPublicSync) {
206             mTetherableUsbRegexs = tetherableUsbRegexs;
207             mTetherableWifiRegexs = tetherableWifiRegexs;
208             mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
209             mUpstreamIfaceTypes = upstreamIfaceTypes;
210         }
211 
212         // check if the upstream type list needs to be modified due to secure-settings
213         checkDunRequired();
214     }
215 
interfaceStatusChanged(String iface, boolean up)216     public void interfaceStatusChanged(String iface, boolean up) {
217         if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
218         boolean found = false;
219         boolean usb = false;
220         synchronized (mPublicSync) {
221             if (isWifi(iface)) {
222                 found = true;
223             } else if (isUsb(iface)) {
224                 found = true;
225                 usb = true;
226             } else if (isBluetooth(iface)) {
227                 found = true;
228             }
229             if (found == false) return;
230 
231             TetherInterfaceSM sm = mIfaces.get(iface);
232             if (up) {
233                 if (sm == null) {
234                     sm = new TetherInterfaceSM(iface, mLooper, usb);
235                     mIfaces.put(iface, sm);
236                     sm.start();
237                 }
238             } else {
239                 if (isUsb(iface)) {
240                     // ignore usb0 down after enabling RNDIS
241                     // we will handle disconnect in interfaceRemoved instead
242                     if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
243                 } else if (sm != null) {
244                     sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
245                     mIfaces.remove(iface);
246                 }
247             }
248         }
249     }
250 
interfaceLinkStateChanged(String iface, boolean up)251     public void interfaceLinkStateChanged(String iface, boolean up) {
252         if (VDBG) Log.d(TAG, "interfaceLinkStateChanged " + iface + ", " + up);
253         interfaceStatusChanged(iface, up);
254     }
255 
isUsb(String iface)256     private boolean isUsb(String iface) {
257         synchronized (mPublicSync) {
258             for (String regex : mTetherableUsbRegexs) {
259                 if (iface.matches(regex)) return true;
260             }
261             return false;
262         }
263     }
264 
isWifi(String iface)265     public boolean isWifi(String iface) {
266         synchronized (mPublicSync) {
267             for (String regex : mTetherableWifiRegexs) {
268                 if (iface.matches(regex)) return true;
269             }
270             return false;
271         }
272     }
273 
isBluetooth(String iface)274     public boolean isBluetooth(String iface) {
275         synchronized (mPublicSync) {
276             for (String regex : mTetherableBluetoothRegexs) {
277                 if (iface.matches(regex)) return true;
278             }
279             return false;
280         }
281     }
282 
interfaceAdded(String iface)283     public void interfaceAdded(String iface) {
284         if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
285         boolean found = false;
286         boolean usb = false;
287         synchronized (mPublicSync) {
288             if (isWifi(iface)) {
289                 found = true;
290             }
291             if (isUsb(iface)) {
292                 found = true;
293                 usb = true;
294             }
295             if (isBluetooth(iface)) {
296                 found = true;
297             }
298             if (found == false) {
299                 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
300                 return;
301             }
302 
303             TetherInterfaceSM sm = mIfaces.get(iface);
304             if (sm != null) {
305                 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
306                 return;
307             }
308             sm = new TetherInterfaceSM(iface, mLooper, usb);
309             mIfaces.put(iface, sm);
310             sm.start();
311         }
312     }
313 
interfaceRemoved(String iface)314     public void interfaceRemoved(String iface) {
315         if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
316         synchronized (mPublicSync) {
317             TetherInterfaceSM sm = mIfaces.get(iface);
318             if (sm == null) {
319                 if (VDBG) {
320                     Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
321                 }
322                 return;
323             }
324             sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
325             mIfaces.remove(iface);
326         }
327     }
328 
tether(String iface)329     public int tether(String iface) {
330         if (DBG) Log.d(TAG, "Tethering " + iface);
331         TetherInterfaceSM sm = null;
332         synchronized (mPublicSync) {
333             sm = mIfaces.get(iface);
334         }
335         if (sm == null) {
336             Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
337             return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
338         }
339         if (!sm.isAvailable() && !sm.isErrored()) {
340             Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
341             return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
342         }
343         sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
344         return ConnectivityManager.TETHER_ERROR_NO_ERROR;
345     }
346 
untether(String iface)347     public int untether(String iface) {
348         if (DBG) Log.d(TAG, "Untethering " + iface);
349         TetherInterfaceSM sm = null;
350         synchronized (mPublicSync) {
351             sm = mIfaces.get(iface);
352         }
353         if (sm == null) {
354             Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
355             return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
356         }
357         if (sm.isErrored()) {
358             Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
359             return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
360         }
361         sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
362         return ConnectivityManager.TETHER_ERROR_NO_ERROR;
363     }
364 
getLastTetherError(String iface)365     public int getLastTetherError(String iface) {
366         TetherInterfaceSM sm = null;
367         synchronized (mPublicSync) {
368             sm = mIfaces.get(iface);
369             if (sm == null) {
370                 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
371                         ", ignoring");
372                 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
373             }
374             return sm.getLastError();
375         }
376     }
377 
378     // TODO - move all private methods used only by the state machine into the state machine
379     // to clarify what needs synchronized protection.
sendTetherStateChangedBroadcast()380     private void sendTetherStateChangedBroadcast() {
381         if (!getConnectivityManager().isTetheringSupported()) return;
382 
383         ArrayList<String> availableList = new ArrayList<String>();
384         ArrayList<String> activeList = new ArrayList<String>();
385         ArrayList<String> erroredList = new ArrayList<String>();
386 
387         boolean wifiTethered = false;
388         boolean usbTethered = false;
389         boolean bluetoothTethered = false;
390 
391         synchronized (mPublicSync) {
392             Set ifaces = mIfaces.keySet();
393             for (Object iface : ifaces) {
394                 TetherInterfaceSM sm = mIfaces.get(iface);
395                 if (sm != null) {
396                     if (sm.isErrored()) {
397                         erroredList.add((String)iface);
398                     } else if (sm.isAvailable()) {
399                         availableList.add((String)iface);
400                     } else if (sm.isTethered()) {
401                         if (isUsb((String)iface)) {
402                             usbTethered = true;
403                         } else if (isWifi((String)iface)) {
404                             wifiTethered = true;
405                       } else if (isBluetooth((String)iface)) {
406                             bluetoothTethered = true;
407                         }
408                         activeList.add((String)iface);
409                     }
410                 }
411             }
412         }
413         Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
414         broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
415                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
416         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
417                 availableList);
418         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
419         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
420                 erroredList);
421         mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
422         if (DBG) {
423             Log.d(TAG, "sendTetherStateChangedBroadcast " + availableList.size() + ", " +
424                     activeList.size() + ", " + erroredList.size());
425         }
426 
427         if (usbTethered) {
428             if (wifiTethered || bluetoothTethered) {
429                 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
430             } else {
431                 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
432             }
433         } else if (wifiTethered) {
434             if (bluetoothTethered) {
435                 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
436             } else {
437                 /* We now have a status bar icon for WifiTethering, so drop the notification */
438                 clearTetheredNotification();
439             }
440         } else if (bluetoothTethered) {
441             showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
442         } else {
443             clearTetheredNotification();
444         }
445     }
446 
showTetheredNotification(int icon)447     private void showTetheredNotification(int icon) {
448         NotificationManager notificationManager =
449                 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
450         if (notificationManager == null) {
451             return;
452         }
453 
454         if (mLastNotificationId != 0) {
455             if (mLastNotificationId == icon) {
456                 return;
457             }
458             notificationManager.cancelAsUser(null, mLastNotificationId,
459                     UserHandle.ALL);
460             mLastNotificationId = 0;
461         }
462 
463         Intent intent = new Intent();
464         intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
465         intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
466 
467         PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
468                 null, UserHandle.CURRENT);
469 
470         Resources r = Resources.getSystem();
471         CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
472         CharSequence message = r.getText(com.android.internal.R.string.
473                 tethered_notification_message);
474 
475         if (mTetheredNotificationBuilder == null) {
476             mTetheredNotificationBuilder = new Notification.Builder(mContext);
477             mTetheredNotificationBuilder.setWhen(0)
478                     .setOngoing(true)
479                     .setColor(mContext.getColor(
480                             com.android.internal.R.color.system_notification_accent_color))
481                     .setVisibility(Notification.VISIBILITY_PUBLIC)
482                     .setCategory(Notification.CATEGORY_STATUS);
483         }
484         mTetheredNotificationBuilder.setSmallIcon(icon)
485                 .setContentTitle(title)
486                 .setContentText(message)
487                 .setContentIntent(pi);
488         mLastNotificationId = icon;
489 
490         notificationManager.notifyAsUser(null, mLastNotificationId,
491                 mTetheredNotificationBuilder.build(), UserHandle.ALL);
492     }
493 
clearTetheredNotification()494     private void clearTetheredNotification() {
495         NotificationManager notificationManager =
496             (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
497         if (notificationManager != null && mLastNotificationId != 0) {
498             notificationManager.cancelAsUser(null, mLastNotificationId,
499                     UserHandle.ALL);
500             mLastNotificationId = 0;
501         }
502     }
503 
504     private class StateReceiver extends BroadcastReceiver {
505         @Override
onReceive(Context content, Intent intent)506         public void onReceive(Context content, Intent intent) {
507             String action = intent.getAction();
508             if (action == null) { return; }
509             if (action.equals(UsbManager.ACTION_USB_STATE)) {
510                 synchronized (Tethering.this.mPublicSync) {
511                     boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
512                     mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
513                     // start tethering if we have a request pending
514                     if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
515                         tetherUsb(true);
516                     }
517                     mUsbTetherRequested = false;
518                 }
519             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
520                 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
521                         ConnectivityManager.EXTRA_NETWORK_INFO);
522                 if (networkInfo != null &&
523                         networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
524                     if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
525                     mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
526                 }
527             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
528                 updateConfiguration();
529             }
530         }
531     }
532 
tetherUsb(boolean enable)533     private void tetherUsb(boolean enable) {
534         if (VDBG) Log.d(TAG, "tetherUsb " + enable);
535 
536         String[] ifaces = new String[0];
537         try {
538             ifaces = mNMService.listInterfaces();
539         } catch (Exception e) {
540             Log.e(TAG, "Error listing Interfaces", e);
541             return;
542         }
543         for (String iface : ifaces) {
544             if (isUsb(iface)) {
545                 int result = (enable ? tether(iface) : untether(iface));
546                 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
547                     return;
548                 }
549             }
550         }
551         Log.e(TAG, "unable start or stop USB tethering");
552     }
553 
554     // configured when we start tethering and unconfig'd on error or conclusion
configureUsbIface(boolean enabled)555     private boolean configureUsbIface(boolean enabled) {
556         if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
557 
558         // toggle the USB interfaces
559         String[] ifaces = new String[0];
560         try {
561             ifaces = mNMService.listInterfaces();
562         } catch (Exception e) {
563             Log.e(TAG, "Error listing Interfaces", e);
564             return false;
565         }
566         for (String iface : ifaces) {
567             if (isUsb(iface)) {
568                 InterfaceConfiguration ifcg = null;
569                 try {
570                     ifcg = mNMService.getInterfaceConfig(iface);
571                     if (ifcg != null) {
572                         InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
573                         ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
574                         if (enabled) {
575                             ifcg.setInterfaceUp();
576                         } else {
577                             ifcg.setInterfaceDown();
578                         }
579                         ifcg.clearFlag("running");
580                         mNMService.setInterfaceConfig(iface, ifcg);
581                     }
582                 } catch (Exception e) {
583                     Log.e(TAG, "Error configuring interface " + iface, e);
584                     return false;
585                 }
586             }
587          }
588 
589         return true;
590     }
591 
592     // TODO - return copies so people can't tamper
getTetherableUsbRegexs()593     public String[] getTetherableUsbRegexs() {
594         return mTetherableUsbRegexs;
595     }
596 
getTetherableWifiRegexs()597     public String[] getTetherableWifiRegexs() {
598         return mTetherableWifiRegexs;
599     }
600 
getTetherableBluetoothRegexs()601     public String[] getTetherableBluetoothRegexs() {
602         return mTetherableBluetoothRegexs;
603     }
604 
setUsbTethering(boolean enable)605     public int setUsbTethering(boolean enable) {
606         if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
607         UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
608 
609         synchronized (mPublicSync) {
610             if (enable) {
611                 if (mRndisEnabled) {
612                     tetherUsb(true);
613                 } else {
614                     mUsbTetherRequested = true;
615                     usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS);
616                 }
617             } else {
618                 tetherUsb(false);
619                 if (mRndisEnabled) {
620                     usbManager.setCurrentFunction(null);
621                 }
622                 mUsbTetherRequested = false;
623             }
624         }
625         return ConnectivityManager.TETHER_ERROR_NO_ERROR;
626     }
627 
getUpstreamIfaceTypes()628     public int[] getUpstreamIfaceTypes() {
629         int values[];
630         synchronized (mPublicSync) {
631             updateConfiguration();  // TODO - remove?
632             values = new int[mUpstreamIfaceTypes.size()];
633             Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
634             for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
635                 values[i] = iterator.next();
636             }
637         }
638         return values;
639     }
640 
checkDunRequired()641     public void checkDunRequired() {
642         int secureSetting = 2;
643         TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
644         if (tm != null) {
645             secureSetting = tm.getTetherApnRequired();
646         }
647         synchronized (mPublicSync) {
648             // 2 = not set, 0 = DUN not required, 1 = DUN required
649             if (secureSetting != 2) {
650                 int requiredApn = (secureSetting == 1 ?
651                         ConnectivityManager.TYPE_MOBILE_DUN :
652                         ConnectivityManager.TYPE_MOBILE_HIPRI);
653                 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
654                     while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
655                         mUpstreamIfaceTypes.remove(MOBILE_TYPE);
656                     }
657                     while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
658                         mUpstreamIfaceTypes.remove(HIPRI_TYPE);
659                     }
660                     if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
661                         mUpstreamIfaceTypes.add(DUN_TYPE);
662                     }
663                 } else {
664                     while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
665                         mUpstreamIfaceTypes.remove(DUN_TYPE);
666                     }
667                     if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
668                         mUpstreamIfaceTypes.add(MOBILE_TYPE);
669                     }
670                     if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
671                         mUpstreamIfaceTypes.add(HIPRI_TYPE);
672                     }
673                 }
674             }
675             if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
676                 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
677             } else {
678                 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
679             }
680         }
681     }
682 
683     // TODO review API - maybe return ArrayList<String> here and below?
getTetheredIfaces()684     public String[] getTetheredIfaces() {
685         ArrayList<String> list = new ArrayList<String>();
686         synchronized (mPublicSync) {
687             Set keys = mIfaces.keySet();
688             for (Object key : keys) {
689                 TetherInterfaceSM sm = mIfaces.get(key);
690                 if (sm.isTethered()) {
691                     list.add((String)key);
692                 }
693             }
694         }
695         String[] retVal = new String[list.size()];
696         for (int i=0; i < list.size(); i++) {
697             retVal[i] = list.get(i);
698         }
699         return retVal;
700     }
701 
getTetherableIfaces()702     public String[] getTetherableIfaces() {
703         ArrayList<String> list = new ArrayList<String>();
704         synchronized (mPublicSync) {
705             Set keys = mIfaces.keySet();
706             for (Object key : keys) {
707                 TetherInterfaceSM sm = mIfaces.get(key);
708                 if (sm.isAvailable()) {
709                     list.add((String)key);
710                 }
711             }
712         }
713         String[] retVal = new String[list.size()];
714         for (int i=0; i < list.size(); i++) {
715             retVal[i] = list.get(i);
716         }
717         return retVal;
718     }
719 
getTetheredDhcpRanges()720     public String[] getTetheredDhcpRanges() {
721         return mDhcpRange;
722     }
723 
getErroredIfaces()724     public String[] getErroredIfaces() {
725         ArrayList<String> list = new ArrayList<String>();
726         synchronized (mPublicSync) {
727             Set keys = mIfaces.keySet();
728             for (Object key : keys) {
729                 TetherInterfaceSM sm = mIfaces.get(key);
730                 if (sm.isErrored()) {
731                     list.add((String)key);
732                 }
733             }
734         }
735         String[] retVal = new String[list.size()];
736         for (int i= 0; i< list.size(); i++) {
737             retVal[i] = list.get(i);
738         }
739         return retVal;
740     }
741 
742     class TetherInterfaceSM extends StateMachine {
743         // notification from the master SM that it's not in tether mode
744         static final int CMD_TETHER_MODE_DEAD            =  1;
745         // request from the user that it wants to tether
746         static final int CMD_TETHER_REQUESTED            =  2;
747         // request from the user that it wants to untether
748         static final int CMD_TETHER_UNREQUESTED          =  3;
749         // notification that this interface is down
750         static final int CMD_INTERFACE_DOWN              =  4;
751         // notification that this interface is up
752         static final int CMD_INTERFACE_UP                =  5;
753         // notification from the master SM that it had an error turning on cellular dun
754         static final int CMD_CELL_DUN_ERROR              =  6;
755         // notification from the master SM that it had trouble enabling IP Forwarding
756         static final int CMD_IP_FORWARDING_ENABLE_ERROR  =  7;
757         // notification from the master SM that it had trouble disabling IP Forwarding
758         static final int CMD_IP_FORWARDING_DISABLE_ERROR =  8;
759         // notification from the master SM that it had trouble starting tethering
760         static final int CMD_START_TETHERING_ERROR       =  9;
761         // notification from the master SM that it had trouble stopping tethering
762         static final int CMD_STOP_TETHERING_ERROR        = 10;
763         // notification from the master SM that it had trouble setting the DNS forwarders
764         static final int CMD_SET_DNS_FORWARDERS_ERROR    = 11;
765         // the upstream connection has changed
766         static final int CMD_TETHER_CONNECTION_CHANGED   = 12;
767 
768         private State mDefaultState;
769 
770         private State mInitialState;
771         private State mStartingState;
772         private State mTetheredState;
773 
774         private State mUnavailableState;
775 
776         private boolean mAvailable;
777         private boolean mTethered;
778         int mLastError;
779 
780         String mIfaceName;
781         String mMyUpstreamIfaceName;  // may change over time
782 
783         boolean mUsb;
784 
TetherInterfaceSM(String name, Looper looper, boolean usb)785         TetherInterfaceSM(String name, Looper looper, boolean usb) {
786             super(name, looper);
787             mIfaceName = name;
788             mUsb = usb;
789             setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
790 
791             mInitialState = new InitialState();
792             addState(mInitialState);
793             mStartingState = new StartingState();
794             addState(mStartingState);
795             mTetheredState = new TetheredState();
796             addState(mTetheredState);
797             mUnavailableState = new UnavailableState();
798             addState(mUnavailableState);
799 
800             setInitialState(mInitialState);
801         }
802 
toString()803         public String toString() {
804             String res = new String();
805             res += mIfaceName + " - ";
806             IState current = getCurrentState();
807             if (current == mInitialState) res += "InitialState";
808             if (current == mStartingState) res += "StartingState";
809             if (current == mTetheredState) res += "TetheredState";
810             if (current == mUnavailableState) res += "UnavailableState";
811             if (mAvailable) res += " - Available";
812             if (mTethered) res += " - Tethered";
813             res += " - lastError =" + mLastError;
814             return res;
815         }
816 
getLastError()817         public int getLastError() {
818             synchronized (Tethering.this.mPublicSync) {
819                 return mLastError;
820             }
821         }
822 
setLastError(int error)823         private void setLastError(int error) {
824             synchronized (Tethering.this.mPublicSync) {
825                 mLastError = error;
826 
827                 if (isErrored()) {
828                     if (mUsb) {
829                         // note everything's been unwound by this point so nothing to do on
830                         // further error..
831                         Tethering.this.configureUsbIface(false);
832                     }
833                 }
834             }
835         }
836 
isAvailable()837         public boolean isAvailable() {
838             synchronized (Tethering.this.mPublicSync) {
839                 return mAvailable;
840             }
841         }
842 
setAvailable(boolean available)843         private void setAvailable(boolean available) {
844             synchronized (Tethering.this.mPublicSync) {
845                 mAvailable = available;
846             }
847         }
848 
isTethered()849         public boolean isTethered() {
850             synchronized (Tethering.this.mPublicSync) {
851                 return mTethered;
852             }
853         }
854 
setTethered(boolean tethered)855         private void setTethered(boolean tethered) {
856             synchronized (Tethering.this.mPublicSync) {
857                 mTethered = tethered;
858             }
859         }
860 
isErrored()861         public boolean isErrored() {
862             synchronized (Tethering.this.mPublicSync) {
863                 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
864             }
865         }
866 
867         class InitialState extends State {
868             @Override
enter()869             public void enter() {
870                 setAvailable(true);
871                 setTethered(false);
872                 sendTetherStateChangedBroadcast();
873             }
874 
875             @Override
processMessage(Message message)876             public boolean processMessage(Message message) {
877                 if (DBG) Log.d(TAG, "InitialState.processMessage what=" + message.what);
878                 boolean retValue = true;
879                 switch (message.what) {
880                     case CMD_TETHER_REQUESTED:
881                         setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
882                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
883                                 TetherInterfaceSM.this);
884                         transitionTo(mStartingState);
885                         break;
886                     case CMD_INTERFACE_DOWN:
887                         transitionTo(mUnavailableState);
888                         break;
889                     default:
890                         retValue = false;
891                         break;
892                 }
893                 return retValue;
894             }
895         }
896 
897         class StartingState extends State {
898             @Override
enter()899             public void enter() {
900                 setAvailable(false);
901                 if (mUsb) {
902                     if (!Tethering.this.configureUsbIface(true)) {
903                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
904                                 TetherInterfaceSM.this);
905                         setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
906 
907                         transitionTo(mInitialState);
908                         return;
909                     }
910                 }
911                 sendTetherStateChangedBroadcast();
912 
913                 // Skipping StartingState
914                 transitionTo(mTetheredState);
915             }
916             @Override
processMessage(Message message)917             public boolean processMessage(Message message) {
918                 if (DBG) Log.d(TAG, "StartingState.processMessage what=" + message.what);
919                 boolean retValue = true;
920                 switch (message.what) {
921                     // maybe a parent class?
922                     case CMD_TETHER_UNREQUESTED:
923                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
924                                 TetherInterfaceSM.this);
925                         if (mUsb) {
926                             if (!Tethering.this.configureUsbIface(false)) {
927                                 setLastErrorAndTransitionToInitialState(
928                                     ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
929                                 break;
930                             }
931                         }
932                         transitionTo(mInitialState);
933                         break;
934                     case CMD_CELL_DUN_ERROR:
935                     case CMD_IP_FORWARDING_ENABLE_ERROR:
936                     case CMD_IP_FORWARDING_DISABLE_ERROR:
937                     case CMD_START_TETHERING_ERROR:
938                     case CMD_STOP_TETHERING_ERROR:
939                     case CMD_SET_DNS_FORWARDERS_ERROR:
940                         setLastErrorAndTransitionToInitialState(
941                                 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
942                         break;
943                     case CMD_INTERFACE_DOWN:
944                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
945                                 TetherInterfaceSM.this);
946                         transitionTo(mUnavailableState);
947                         break;
948                     default:
949                         retValue = false;
950                 }
951                 return retValue;
952             }
953         }
954 
955         class TetheredState extends State {
956             @Override
enter()957             public void enter() {
958                 try {
959                     mNMService.tetherInterface(mIfaceName);
960                 } catch (Exception e) {
961                     Log.e(TAG, "Error Tethering: " + e.toString());
962                     setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
963 
964                     transitionTo(mInitialState);
965                     return;
966                 }
967                 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
968                 setAvailable(false);
969                 setTethered(true);
970                 sendTetherStateChangedBroadcast();
971             }
972 
cleanupUpstream()973             private void cleanupUpstream() {
974                 if (mMyUpstreamIfaceName != null) {
975                     // note that we don't care about errors here.
976                     // sometimes interfaces are gone before we get
977                     // to remove their rules, which generates errors.
978                     // just do the best we can.
979                     try {
980                         // about to tear down NAT; gather remaining statistics
981                         mStatsService.forceUpdate();
982                     } catch (Exception e) {
983                         if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
984                     }
985                     try {
986                         mNMService.stopInterfaceForwarding(mIfaceName, mMyUpstreamIfaceName);
987                     } catch (Exception e) {
988                         if (VDBG) Log.e(
989                                 TAG, "Exception in removeInterfaceForward: " + e.toString());
990                     }
991                     try {
992                         mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
993                     } catch (Exception e) {
994                         if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
995                     }
996                     mMyUpstreamIfaceName = null;
997                 }
998                 return;
999             }
1000 
1001             @Override
processMessage(Message message)1002             public boolean processMessage(Message message) {
1003                 if (DBG) Log.d(TAG, "TetheredState.processMessage what=" + message.what);
1004                 boolean retValue = true;
1005                 boolean error = false;
1006                 switch (message.what) {
1007                     case CMD_TETHER_UNREQUESTED:
1008                     case CMD_INTERFACE_DOWN:
1009                         cleanupUpstream();
1010                         try {
1011                             mNMService.untetherInterface(mIfaceName);
1012                         } catch (Exception e) {
1013                             setLastErrorAndTransitionToInitialState(
1014                                     ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
1015                             break;
1016                         }
1017                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1018                                 TetherInterfaceSM.this);
1019                         if (message.what == CMD_TETHER_UNREQUESTED) {
1020                             if (mUsb) {
1021                                 if (!Tethering.this.configureUsbIface(false)) {
1022                                     setLastError(
1023                                             ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
1024                                 }
1025                             }
1026                             transitionTo(mInitialState);
1027                         } else if (message.what == CMD_INTERFACE_DOWN) {
1028                             transitionTo(mUnavailableState);
1029                         }
1030                         if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
1031                         break;
1032                     case CMD_TETHER_CONNECTION_CHANGED:
1033                         String newUpstreamIfaceName = (String)(message.obj);
1034                         if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1035                                 (mMyUpstreamIfaceName != null &&
1036                                 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
1037                             if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
1038                             break;
1039                         }
1040                         cleanupUpstream();
1041                         if (newUpstreamIfaceName != null) {
1042                             try {
1043                                 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
1044                                 mNMService.startInterfaceForwarding(mIfaceName,
1045                                         newUpstreamIfaceName);
1046                             } catch (Exception e) {
1047                                 Log.e(TAG, "Exception enabling Nat: " + e.toString());
1048                                 try {
1049                                     mNMService.disableNat(mIfaceName, newUpstreamIfaceName);
1050                                 } catch (Exception ee) {}
1051                                 try {
1052                                     mNMService.untetherInterface(mIfaceName);
1053                                 } catch (Exception ee) {}
1054 
1055                                 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1056                                 transitionTo(mInitialState);
1057                                 return true;
1058                             }
1059                         }
1060                         mMyUpstreamIfaceName = newUpstreamIfaceName;
1061                         break;
1062                     case CMD_CELL_DUN_ERROR:
1063                     case CMD_IP_FORWARDING_ENABLE_ERROR:
1064                     case CMD_IP_FORWARDING_DISABLE_ERROR:
1065                     case CMD_START_TETHERING_ERROR:
1066                     case CMD_STOP_TETHERING_ERROR:
1067                     case CMD_SET_DNS_FORWARDERS_ERROR:
1068                         error = true;
1069                         // fall through
1070                     case CMD_TETHER_MODE_DEAD:
1071                         cleanupUpstream();
1072                         try {
1073                             mNMService.untetherInterface(mIfaceName);
1074                         } catch (Exception e) {
1075                             setLastErrorAndTransitionToInitialState(
1076                                     ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
1077                             break;
1078                         }
1079                         if (error) {
1080                             setLastErrorAndTransitionToInitialState(
1081                                     ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
1082                             break;
1083                         }
1084                         if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
1085                         sendTetherStateChangedBroadcast();
1086                         if (mUsb) {
1087                             if (!Tethering.this.configureUsbIface(false)) {
1088                                 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
1089                             }
1090                         }
1091                         transitionTo(mInitialState);
1092                         break;
1093                     default:
1094                         retValue = false;
1095                         break;
1096                 }
1097                 return retValue;
1098             }
1099         }
1100 
1101         class UnavailableState extends State {
1102             @Override
enter()1103             public void enter() {
1104                 setAvailable(false);
1105                 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
1106                 setTethered(false);
1107                 sendTetherStateChangedBroadcast();
1108             }
1109             @Override
processMessage(Message message)1110             public boolean processMessage(Message message) {
1111                 boolean retValue = true;
1112                 switch (message.what) {
1113                     case CMD_INTERFACE_UP:
1114                         transitionTo(mInitialState);
1115                         break;
1116                     default:
1117                         retValue = false;
1118                         break;
1119                 }
1120                 return retValue;
1121             }
1122         }
1123 
setLastErrorAndTransitionToInitialState(int error)1124         void setLastErrorAndTransitionToInitialState(int error) {
1125             setLastError(error);
1126             transitionTo(mInitialState);
1127         }
1128 
1129     }
1130 
1131     class TetherMasterSM extends StateMachine {
1132         // an interface SM has requested Tethering
1133         static final int CMD_TETHER_MODE_REQUESTED   = 1;
1134         // an interface SM has unrequested Tethering
1135         static final int CMD_TETHER_MODE_UNREQUESTED = 2;
1136         // upstream connection change - do the right thing
1137         static final int CMD_UPSTREAM_CHANGED        = 3;
1138         // we received notice that the cellular DUN connection is up
1139         static final int CMD_CELL_CONNECTION_RENEW   = 4;
1140         // we don't have a valid upstream conn, check again after a delay
1141         static final int CMD_RETRY_UPSTREAM          = 5;
1142 
1143         // This indicates what a timeout event relates to.  A state that
1144         // sends itself a delayed timeout event and handles incoming timeout events
1145         // should inc this when it is entered and whenever it sends a new timeout event.
1146         // We do not flush the old ones.
1147         private int mSequenceNumber;
1148 
1149         private State mInitialState;
1150         private State mTetherModeAliveState;
1151 
1152         private State mSetIpForwardingEnabledErrorState;
1153         private State mSetIpForwardingDisabledErrorState;
1154         private State mStartTetheringErrorState;
1155         private State mStopTetheringErrorState;
1156         private State mSetDnsForwardersErrorState;
1157 
1158         private ArrayList<TetherInterfaceSM> mNotifyList;
1159 
1160         private int mCurrentConnectionSequence;
1161         private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
1162 
1163         private String mUpstreamIfaceName = null;
1164 
1165         private static final int UPSTREAM_SETTLE_TIME_MS     = 10000;
1166         private static final int CELL_CONNECTION_RENEW_MS    = 40000;
1167 
TetherMasterSM(String name, Looper looper)1168         TetherMasterSM(String name, Looper looper) {
1169             super(name, looper);
1170 
1171             //Add states
1172             mInitialState = new InitialState();
1173             addState(mInitialState);
1174             mTetherModeAliveState = new TetherModeAliveState();
1175             addState(mTetherModeAliveState);
1176 
1177             mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1178             addState(mSetIpForwardingEnabledErrorState);
1179             mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1180             addState(mSetIpForwardingDisabledErrorState);
1181             mStartTetheringErrorState = new StartTetheringErrorState();
1182             addState(mStartTetheringErrorState);
1183             mStopTetheringErrorState = new StopTetheringErrorState();
1184             addState(mStopTetheringErrorState);
1185             mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1186             addState(mSetDnsForwardersErrorState);
1187 
1188             mNotifyList = new ArrayList<TetherInterfaceSM>();
1189             setInitialState(mInitialState);
1190         }
1191 
1192         class TetherMasterUtilState extends State {
1193             protected final static boolean TRY_TO_SETUP_MOBILE_CONNECTION = true;
1194             protected final static boolean WAIT_FOR_NETWORK_TO_SETTLE     = false;
1195 
1196             @Override
processMessage(Message m)1197             public boolean processMessage(Message m) {
1198                 return false;
1199             }
enableString(int apnType)1200             protected String enableString(int apnType) {
1201                 switch (apnType) {
1202                 case ConnectivityManager.TYPE_MOBILE_DUN:
1203                     return Phone.FEATURE_ENABLE_DUN_ALWAYS;
1204                 case ConnectivityManager.TYPE_MOBILE:
1205                 case ConnectivityManager.TYPE_MOBILE_HIPRI:
1206                     return Phone.FEATURE_ENABLE_HIPRI;
1207                 }
1208                 return null;
1209             }
turnOnUpstreamMobileConnection(int apnType)1210             protected boolean turnOnUpstreamMobileConnection(int apnType) {
1211                 boolean retValue = true;
1212                 if (apnType == ConnectivityManager.TYPE_NONE) return false;
1213                 if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
1214                 int result = PhoneConstants.APN_REQUEST_FAILED;
1215                 String enableString = enableString(apnType);
1216                 if (enableString == null) return false;
1217                 result = getConnectivityManager().startUsingNetworkFeature(
1218                         ConnectivityManager.TYPE_MOBILE, enableString);
1219                 switch (result) {
1220                 case PhoneConstants.APN_ALREADY_ACTIVE:
1221                 case PhoneConstants.APN_REQUEST_STARTED:
1222                     mMobileApnReserved = apnType;
1223                     Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
1224                     m.arg1 = ++mCurrentConnectionSequence;
1225                     sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
1226                     break;
1227                 case PhoneConstants.APN_REQUEST_FAILED:
1228                 default:
1229                     retValue = false;
1230                     break;
1231                 }
1232 
1233                 return retValue;
1234             }
turnOffUpstreamMobileConnection()1235             protected boolean turnOffUpstreamMobileConnection() {
1236                 // ignore pending renewal requests
1237                 ++mCurrentConnectionSequence;
1238                 if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
1239                     getConnectivityManager().stopUsingNetworkFeature(
1240                             ConnectivityManager.TYPE_MOBILE, enableString(mMobileApnReserved));
1241                     mMobileApnReserved = ConnectivityManager.TYPE_NONE;
1242                 }
1243                 return true;
1244             }
turnOnMasterTetherSettings()1245             protected boolean turnOnMasterTetherSettings() {
1246                 try {
1247                     mNMService.setIpForwardingEnabled(true);
1248                 } catch (Exception e) {
1249                     transitionTo(mSetIpForwardingEnabledErrorState);
1250                     return false;
1251                 }
1252                 try {
1253                     mNMService.startTethering(mDhcpRange);
1254                 } catch (Exception e) {
1255                     try {
1256                         mNMService.stopTethering();
1257                         mNMService.startTethering(mDhcpRange);
1258                     } catch (Exception ee) {
1259                         transitionTo(mStartTetheringErrorState);
1260                         return false;
1261                     }
1262                 }
1263                 return true;
1264             }
turnOffMasterTetherSettings()1265             protected boolean turnOffMasterTetherSettings() {
1266                 try {
1267                     mNMService.stopTethering();
1268                 } catch (Exception e) {
1269                     transitionTo(mStopTetheringErrorState);
1270                     return false;
1271                 }
1272                 try {
1273                     mNMService.setIpForwardingEnabled(false);
1274                 } catch (Exception e) {
1275                     transitionTo(mSetIpForwardingDisabledErrorState);
1276                     return false;
1277                 }
1278                 transitionTo(mInitialState);
1279                 return true;
1280             }
1281 
chooseUpstreamType(boolean tryCell)1282             protected void chooseUpstreamType(boolean tryCell) {
1283                 int upType = ConnectivityManager.TYPE_NONE;
1284                 String iface = null;
1285 
1286                 updateConfiguration(); // TODO - remove?
1287 
1288                 synchronized (mPublicSync) {
1289                     if (VDBG) {
1290                         Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1291                         for (Integer netType : mUpstreamIfaceTypes) {
1292                             Log.d(TAG, " " + netType);
1293                         }
1294                     }
1295 
1296                     for (Integer netType : mUpstreamIfaceTypes) {
1297                         NetworkInfo info =
1298                                 getConnectivityManager().getNetworkInfo(netType.intValue());
1299                         if ((info != null) && info.isConnected()) {
1300                             upType = netType.intValue();
1301                             break;
1302                         }
1303                     }
1304                 }
1305 
1306                 if (DBG) {
1307                     Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
1308                             + mPreferredUpstreamMobileApn + ", got type=" + upType);
1309                 }
1310 
1311                 // if we're on DUN, put our own grab on it
1312                 if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
1313                         upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
1314                     turnOnUpstreamMobileConnection(upType);
1315                 } else if (upType != ConnectivityManager.TYPE_NONE) {
1316                     /* If we've found an active upstream connection that's not DUN/HIPRI
1317                      * we should stop any outstanding DUN/HIPRI start requests.
1318                      *
1319                      * If we found NONE we don't want to do this as we want any previous
1320                      * requests to keep trying to bring up something we can use.
1321                      */
1322                     turnOffUpstreamMobileConnection();
1323                 }
1324 
1325                 if (upType == ConnectivityManager.TYPE_NONE) {
1326                     boolean tryAgainLater = true;
1327                     if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
1328                             (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
1329                         // we think mobile should be coming up - don't set a retry
1330                         tryAgainLater = false;
1331                     }
1332                     if (tryAgainLater) {
1333                         sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1334                     }
1335                 } else {
1336                     LinkProperties linkProperties =
1337                             getConnectivityManager().getLinkProperties(upType);
1338                     if (linkProperties != null) {
1339                         // Find the interface with the default IPv4 route. It may be the
1340                         // interface described by linkProperties, or one of the interfaces
1341                         // stacked on top of it.
1342                         Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1343                         RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1344                             linkProperties.getAllRoutes(), Inet4Address.ANY);
1345                         if (ipv4Default != null) {
1346                             iface = ipv4Default.getInterface();
1347                             Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1348                         } else {
1349                             Log.i(TAG, "No IPv4 upstream interface, giving up.");
1350                         }
1351                     }
1352 
1353                     if (iface != null) {
1354                         String[] dnsServers = mDefaultDnsServers;
1355                         Collection<InetAddress> dnses = linkProperties.getDnsServers();
1356                         if (dnses != null) {
1357                             // we currently only handle IPv4
1358                             ArrayList<InetAddress> v4Dnses =
1359                                     new ArrayList<InetAddress>(dnses.size());
1360                             for (InetAddress dnsAddress : dnses) {
1361                                 if (dnsAddress instanceof Inet4Address) {
1362                                     v4Dnses.add(dnsAddress);
1363                                 }
1364                             }
1365                             if (v4Dnses.size() > 0) {
1366                                 dnsServers = NetworkUtils.makeStrings(v4Dnses);
1367                             }
1368                         }
1369                         try {
1370                             Network network = getConnectivityManager().getNetworkForType(upType);
1371                             if (network == null) {
1372                                 Log.e(TAG, "No Network for upstream type " + upType + "!");
1373                             }
1374                             if (VDBG) {
1375                                 Log.d(TAG, "Setting DNS forwarders: Network=" + network +
1376                                        ", dnsServers=" + Arrays.toString(dnsServers));
1377                             }
1378                             mNMService.setDnsForwarders(network, dnsServers);
1379                         } catch (Exception e) {
1380                             Log.e(TAG, "Setting DNS forwarders failed!");
1381                             transitionTo(mSetDnsForwardersErrorState);
1382                         }
1383                     }
1384                 }
1385                 notifyTetheredOfNewUpstreamIface(iface);
1386             }
1387 
notifyTetheredOfNewUpstreamIface(String ifaceName)1388             protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
1389                 if (DBG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
1390                 mUpstreamIfaceName = ifaceName;
1391                 for (TetherInterfaceSM sm : mNotifyList) {
1392                     sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1393                             ifaceName);
1394                 }
1395             }
1396         }
1397 
1398         private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
1399         private SimChangeBroadcastReceiver mBroadcastReceiver = null;
1400 
1401         // keep consts in sync with packages/apps/Settings TetherSettings.java
1402         private static final int WIFI_TETHERING      = 0;
1403         private static final int USB_TETHERING       = 1;
1404         private static final int BLUETOOTH_TETHERING = 2;
1405 
1406         // keep consts in sync with packages/apps/Settings TetherService.java
1407         private static final String EXTRA_ADD_TETHER_TYPE = "extraAddTetherType";
1408         private static final String EXTRA_RUN_PROVISION = "extraRunProvision";
1409 
startListeningForSimChanges()1410         private void startListeningForSimChanges() {
1411             if (DBG) Log.d(TAG, "startListeningForSimChanges");
1412             if (mBroadcastReceiver == null) {
1413                 mBroadcastReceiver = new SimChangeBroadcastReceiver(
1414                         mSimBcastGenerationNumber.incrementAndGet());
1415                 final IntentFilter filter = new IntentFilter();
1416                 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
1417 
1418                 mContext.registerReceiver(mBroadcastReceiver, filter);
1419             }
1420         }
1421 
stopListeningForSimChanges()1422         private void stopListeningForSimChanges() {
1423             if (DBG) Log.d(TAG, "stopListeningForSimChanges");
1424             if (mBroadcastReceiver != null) {
1425                 mSimBcastGenerationNumber.incrementAndGet();
1426                 mContext.unregisterReceiver(mBroadcastReceiver);
1427                 mBroadcastReceiver = null;
1428             }
1429         }
1430 
1431         class SimChangeBroadcastReceiver extends BroadcastReceiver {
1432             // used to verify this receiver is still current
1433             final private int mGenerationNumber;
1434 
1435             // we're interested in edge-triggered LOADED notifications, so
1436             // ignore LOADED unless we saw an ABSENT state first
1437             private boolean mSimAbsentSeen = false;
1438 
SimChangeBroadcastReceiver(int generationNumber)1439             public SimChangeBroadcastReceiver(int generationNumber) {
1440                 super();
1441                 mGenerationNumber = generationNumber;
1442             }
1443 
1444             @Override
onReceive(Context context, Intent intent)1445             public void onReceive(Context context, Intent intent) {
1446                 if (DBG) {
1447                     Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
1448                             ", current generationNumber=" + mSimBcastGenerationNumber.get());
1449                 }
1450                 if (mGenerationNumber != mSimBcastGenerationNumber.get()) return;
1451 
1452                 final String state =
1453                         intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
1454 
1455                 Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" +
1456                         mSimAbsentSeen);
1457                 if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
1458                     mSimAbsentSeen = true;
1459                 }
1460 
1461                 if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
1462                     mSimAbsentSeen = false;
1463                     try {
1464                         if (mContext.getResources().getString(com.android.internal.R.string.
1465                                 config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) {
1466                             final String tetherService = mContext.getResources().getString(
1467                                     com.android.internal.R.string.config_wifi_tether_enable);
1468                             ArrayList<Integer> tethered = new ArrayList<Integer>();
1469                             synchronized (mPublicSync) {
1470                                 Set ifaces = mIfaces.keySet();
1471                                 for (Object iface : ifaces) {
1472                                     TetherInterfaceSM sm = mIfaces.get(iface);
1473                                     if (sm != null && sm.isTethered()) {
1474                                         if (isUsb((String)iface)) {
1475                                             tethered.add(new Integer(USB_TETHERING));
1476                                         } else if (isWifi((String)iface)) {
1477                                             tethered.add(new Integer(WIFI_TETHERING));
1478                                         } else if (isBluetooth((String)iface)) {
1479                                             tethered.add(new Integer(BLUETOOTH_TETHERING));
1480                                         }
1481                                     }
1482                                 }
1483                             }
1484                             for (int tetherType : tethered) {
1485                                 Intent startProvIntent = new Intent();
1486                                 startProvIntent.putExtra(EXTRA_ADD_TETHER_TYPE, tetherType);
1487                                 startProvIntent.putExtra(EXTRA_RUN_PROVISION, true);
1488                                 startProvIntent.setComponent(
1489                                         ComponentName.unflattenFromString(tetherService));
1490                                 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
1491                             }
1492                             Log.d(TAG, "re-evaluate provisioning");
1493                         } else {
1494                             Log.d(TAG, "no prov-check needed for new SIM");
1495                         }
1496                     } catch (Resources.NotFoundException e) {
1497                         Log.d(TAG, "no prov-check needed for new SIM");
1498                         // not defined, do nothing
1499                     }
1500                 }
1501             }
1502         }
1503 
1504         class InitialState extends TetherMasterUtilState {
1505             @Override
enter()1506             public void enter() {
1507             }
1508             @Override
processMessage(Message message)1509             public boolean processMessage(Message message) {
1510                 if (DBG) Log.d(TAG, "MasterInitialState.processMessage what=" + message.what);
1511                 boolean retValue = true;
1512                 switch (message.what) {
1513                     case CMD_TETHER_MODE_REQUESTED:
1514                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1515                         if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1516                         mNotifyList.add(who);
1517                         transitionTo(mTetherModeAliveState);
1518                         break;
1519                     case CMD_TETHER_MODE_UNREQUESTED:
1520                         who = (TetherInterfaceSM)message.obj;
1521                         if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1522                         int index = mNotifyList.indexOf(who);
1523                         if (index != -1) {
1524                             mNotifyList.remove(who);
1525                         }
1526                         break;
1527                     default:
1528                         retValue = false;
1529                         break;
1530                 }
1531                 return retValue;
1532             }
1533         }
1534 
1535         class TetherModeAliveState extends TetherMasterUtilState {
1536             boolean mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
1537             @Override
enter()1538             public void enter() {
1539                 turnOnMasterTetherSettings(); // may transition us out
1540                 startListeningForSimChanges();
1541 
1542                 mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE; // better try something first pass
1543                                                         // or crazy tests cases will fail
1544                 chooseUpstreamType(mTryCell);
1545                 mTryCell = !mTryCell;
1546             }
1547             @Override
exit()1548             public void exit() {
1549                 turnOffUpstreamMobileConnection();
1550                 stopListeningForSimChanges();
1551                 notifyTetheredOfNewUpstreamIface(null);
1552             }
1553             @Override
processMessage(Message message)1554             public boolean processMessage(Message message) {
1555                 if (DBG) Log.d(TAG, "TetherModeAliveState.processMessage what=" + message.what);
1556                 boolean retValue = true;
1557                 switch (message.what) {
1558                     case CMD_TETHER_MODE_REQUESTED:
1559                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1560                         if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1561                         mNotifyList.add(who);
1562                         who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1563                                 mUpstreamIfaceName);
1564                         break;
1565                     case CMD_TETHER_MODE_UNREQUESTED:
1566                         who = (TetherInterfaceSM)message.obj;
1567                         if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1568                         int index = mNotifyList.indexOf(who);
1569                         if (index != -1) {
1570                             if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
1571                             mNotifyList.remove(index);
1572                             if (mNotifyList.isEmpty()) {
1573                                 turnOffMasterTetherSettings(); // transitions appropriately
1574                             } else {
1575                                 if (DBG) {
1576                                     Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1577                                             " live requests:");
1578                                     for (Object o : mNotifyList) Log.d(TAG, "  " + o);
1579                                 }
1580                             }
1581                         } else {
1582                            Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
1583                         }
1584                         break;
1585                     case CMD_UPSTREAM_CHANGED:
1586                         // need to try DUN immediately if Wifi goes down
1587                         mTryCell = !WAIT_FOR_NETWORK_TO_SETTLE;
1588                         chooseUpstreamType(mTryCell);
1589                         mTryCell = !mTryCell;
1590                         break;
1591                     case CMD_CELL_CONNECTION_RENEW:
1592                         // make sure we're still using a requested connection - may have found
1593                         // wifi or something since then.
1594                         if (mCurrentConnectionSequence == message.arg1) {
1595                             if (VDBG) {
1596                                 Log.d(TAG, "renewing mobile connection - requeuing for another " +
1597                                         CELL_CONNECTION_RENEW_MS + "ms");
1598                             }
1599                             turnOnUpstreamMobileConnection(mMobileApnReserved);
1600                         }
1601                         break;
1602                     case CMD_RETRY_UPSTREAM:
1603                         chooseUpstreamType(mTryCell);
1604                         mTryCell = !mTryCell;
1605                         break;
1606                     default:
1607                         retValue = false;
1608                         break;
1609                 }
1610                 return retValue;
1611             }
1612         }
1613 
1614         class ErrorState extends State {
1615             int mErrorNotification;
1616             @Override
processMessage(Message message)1617             public boolean processMessage(Message message) {
1618                 boolean retValue = true;
1619                 switch (message.what) {
1620                     case CMD_TETHER_MODE_REQUESTED:
1621                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1622                         who.sendMessage(mErrorNotification);
1623                         break;
1624                     default:
1625                        retValue = false;
1626                 }
1627                 return retValue;
1628             }
notify(int msgType)1629             void notify(int msgType) {
1630                 mErrorNotification = msgType;
1631                 for (Object o : mNotifyList) {
1632                     TetherInterfaceSM sm = (TetherInterfaceSM)o;
1633                     sm.sendMessage(msgType);
1634                 }
1635             }
1636 
1637         }
1638         class SetIpForwardingEnabledErrorState extends ErrorState {
1639             @Override
enter()1640             public void enter() {
1641                 Log.e(TAG, "Error in setIpForwardingEnabled");
1642                 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
1643             }
1644         }
1645 
1646         class SetIpForwardingDisabledErrorState extends ErrorState {
1647             @Override
enter()1648             public void enter() {
1649                 Log.e(TAG, "Error in setIpForwardingDisabled");
1650                 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
1651             }
1652         }
1653 
1654         class StartTetheringErrorState extends ErrorState {
1655             @Override
enter()1656             public void enter() {
1657                 Log.e(TAG, "Error in startTethering");
1658                 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
1659                 try {
1660                     mNMService.setIpForwardingEnabled(false);
1661                 } catch (Exception e) {}
1662             }
1663         }
1664 
1665         class StopTetheringErrorState extends ErrorState {
1666             @Override
enter()1667             public void enter() {
1668                 Log.e(TAG, "Error in stopTethering");
1669                 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
1670                 try {
1671                     mNMService.setIpForwardingEnabled(false);
1672                 } catch (Exception e) {}
1673             }
1674         }
1675 
1676         class SetDnsForwardersErrorState extends ErrorState {
1677             @Override
enter()1678             public void enter() {
1679                 Log.e(TAG, "Error in setDnsForwarders");
1680                 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
1681                 try {
1682                     mNMService.stopTethering();
1683                 } catch (Exception e) {}
1684                 try {
1685                     mNMService.setIpForwardingEnabled(false);
1686                 } catch (Exception e) {}
1687             }
1688         }
1689     }
1690 
dump(FileDescriptor fd, PrintWriter writer, String[] args)1691     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
1692         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
1693 
1694         if (mContext.checkCallingOrSelfPermission(
1695                 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
1696             pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
1697                     "from from pid=" + Binder.getCallingPid() + ", uid=" +
1698                     Binder.getCallingUid());
1699                     return;
1700         }
1701 
1702         pw.println("Tethering:");
1703         pw.increaseIndent();
1704         pw.print("mUpstreamIfaceTypes:");
1705         synchronized (mPublicSync) {
1706             for (Integer netType : mUpstreamIfaceTypes) {
1707                 pw.print(" " + ConnectivityManager.getNetworkTypeName(netType));
1708             }
1709             pw.println();
1710 
1711             pw.println("Tether state:");
1712             pw.increaseIndent();
1713             for (Object o : mIfaces.values()) {
1714                 pw.println(o);
1715             }
1716             pw.decreaseIndent();
1717         }
1718         pw.decreaseIndent();
1719         return;
1720     }
1721 }
1722