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.bluetooth.BluetoothAdapter;
23 import android.bluetooth.BluetoothPan;
24 import android.bluetooth.BluetoothProfile;
25 import android.bluetooth.BluetoothProfile.ServiceListener;
26 import android.content.BroadcastReceiver;
27 import android.content.ComponentName;
28 import android.content.Context;
29 import android.content.Intent;
30 import android.content.IntentFilter;
31 import android.content.pm.PackageManager;
32 import android.content.res.Resources;
33 import android.hardware.usb.UsbManager;
34 import android.net.ConnectivityManager;
35 import android.net.ConnectivityManager.NetworkCallback;
36 import android.net.INetworkStatsService;
37 import android.net.InterfaceConfiguration;
38 import android.net.LinkAddress;
39 import android.net.LinkProperties;
40 import android.net.Network;
41 import android.net.NetworkCapabilities;
42 import android.net.NetworkInfo;
43 import android.net.NetworkRequest;
44 import android.net.NetworkState;
45 import android.net.NetworkUtils;
46 import android.net.RouteInfo;
47 import android.net.wifi.WifiManager;
48 import android.os.Binder;
49 import android.os.Bundle;
50 import android.os.INetworkManagementService;
51 import android.os.Looper;
52 import android.os.Message;
53 import android.os.Parcel;
54 import android.os.ResultReceiver;
55 import android.os.SystemProperties;
56 import android.os.UserHandle;
57 import android.provider.Settings;
58 import android.telephony.CarrierConfigManager;
59 import android.telephony.TelephonyManager;
60 import android.text.TextUtils;
61 import android.util.Log;
62 import android.util.SparseArray;
63 
64 import com.android.internal.telephony.IccCardConstants;
65 import com.android.internal.telephony.TelephonyIntents;
66 import com.android.internal.util.IState;
67 import com.android.internal.util.IndentingPrintWriter;
68 import com.android.internal.util.MessageUtils;
69 import com.android.internal.util.Protocol;
70 import com.android.internal.util.State;
71 import com.android.internal.util.StateMachine;
72 import com.android.server.IoThread;
73 import com.android.server.net.BaseNetworkObserver;
74 
75 import java.io.FileDescriptor;
76 import java.io.PrintWriter;
77 import java.net.Inet4Address;
78 import java.net.InetAddress;
79 import java.util.ArrayList;
80 import java.util.Arrays;
81 import java.util.Collection;
82 import java.util.HashMap;
83 import java.util.Iterator;
84 import java.util.Set;
85 import java.util.concurrent.atomic.AtomicInteger;
86 
87 
88 /**
89  * @hide
90  *
91  * Timeout
92  *
93  * TODO - look for parent classes and code sharing
94  */
95 public class Tethering extends BaseNetworkObserver {
96 
97     private final Context mContext;
98     private final static String TAG = "Tethering";
99     private final static boolean DBG = false;
100     private final static boolean VDBG = false;
101 
102     private static final Class[] messageClasses = {
103             Tethering.class, TetherMasterSM.class, TetherInterfaceSM.class
104     };
105     private static final SparseArray<String> sMagicDecoderRing =
106             MessageUtils.findMessageNames(messageClasses);
107 
108     // TODO - remove both of these - should be part of interface inspection/selection stuff
109     private String[] mTetherableUsbRegexs;
110     private String[] mTetherableWifiRegexs;
111     private String[] mTetherableBluetoothRegexs;
112     private Collection<Integer> mUpstreamIfaceTypes;
113 
114     // used to synchronize public access to members
115     private final Object mPublicSync;
116 
117     private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
118     private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
119     private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);
120 
121     // if we have to connect to mobile, what APN type should we use?  Calculated by examining the
122     // upstream type list and the DUN_REQUIRED secure-setting
123     private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;
124 
125     private final INetworkManagementService mNMService;
126     private final INetworkStatsService mStatsService;
127     private final Looper mLooper;
128 
129     private HashMap<String, TetherInterfaceSM> mIfaces; // all tethered/tetherable ifaces
130 
131     private BroadcastReceiver mStateReceiver;
132 
133     // {@link ComponentName} of the Service used to run tether provisioning.
134     private static final ComponentName TETHER_SERVICE = ComponentName.unflattenFromString(Resources
135             .getSystem().getString(com.android.internal.R.string.config_wifi_tether_enable));
136 
137     private static final String USB_NEAR_IFACE_ADDR      = "192.168.42.129";
138     private static final int USB_PREFIX_LENGTH        = 24;
139 
140     // USB is  192.168.42.1 and 255.255.255.0
141     // Wifi is 192.168.43.1 and 255.255.255.0
142     // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1
143     // with 255.255.255.0
144     // P2P is 192.168.49.1 and 255.255.255.0
145 
146     private String[] mDhcpRange;
147     private static final String[] DHCP_DEFAULT_RANGE = {
148         "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254",
149         "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254",
150         "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254",
151         "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254",
152     };
153 
154     private String[] mDefaultDnsServers;
155     private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
156     private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";
157 
158     private final StateMachine mTetherMasterSM;
159     private final UpstreamNetworkMonitor mUpstreamNetworkMonitor;
160     private String mCurrentUpstreamIface;
161 
162     private Notification.Builder mTetheredNotificationBuilder;
163     private int mLastNotificationId;
164 
165     private boolean mRndisEnabled;       // track the RNDIS function enabled state
166     private boolean mUsbTetherRequested; // true if USB tethering should be started
167                                          // when RNDIS is enabled
168 
Tethering(Context context, INetworkManagementService nmService, INetworkStatsService statsService)169     public Tethering(Context context, INetworkManagementService nmService,
170             INetworkStatsService statsService) {
171         mContext = context;
172         mNMService = nmService;
173         mStatsService = statsService;
174 
175         mPublicSync = new Object();
176 
177         mIfaces = new HashMap<String, TetherInterfaceSM>();
178 
179         // make our own thread so we don't anr the system
180         mLooper = IoThread.get().getLooper();
181         mTetherMasterSM = new TetherMasterSM("TetherMaster", mLooper);
182         mTetherMasterSM.start();
183 
184         mUpstreamNetworkMonitor = new UpstreamNetworkMonitor();
185 
186         mStateReceiver = new StateReceiver();
187         IntentFilter filter = new IntentFilter();
188         filter.addAction(UsbManager.ACTION_USB_STATE);
189         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
190         filter.addAction(Intent.ACTION_CONFIGURATION_CHANGED);
191         mContext.registerReceiver(mStateReceiver, filter);
192 
193         filter = new IntentFilter();
194         filter.addAction(Intent.ACTION_MEDIA_SHARED);
195         filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
196         filter.addDataScheme("file");
197         mContext.registerReceiver(mStateReceiver, filter);
198 
199         mDhcpRange = context.getResources().getStringArray(
200                 com.android.internal.R.array.config_tether_dhcp_range);
201         if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
202             mDhcpRange = DHCP_DEFAULT_RANGE;
203         }
204 
205         // load device config info
206         updateConfiguration();
207 
208         // TODO - remove and rely on real notifications of the current iface
209         mDefaultDnsServers = new String[2];
210         mDefaultDnsServers[0] = DNS_DEFAULT_SERVER1;
211         mDefaultDnsServers[1] = DNS_DEFAULT_SERVER2;
212     }
213 
214     // We can't do this once in the Tethering() constructor and cache the value, because the
215     // CONNECTIVITY_SERVICE is registered only after the Tethering() constructor has completed.
getConnectivityManager()216     private ConnectivityManager getConnectivityManager() {
217         return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
218     }
219 
updateConfiguration()220     void updateConfiguration() {
221         String[] tetherableUsbRegexs = mContext.getResources().getStringArray(
222                 com.android.internal.R.array.config_tether_usb_regexs);
223         String[] tetherableWifiRegexs = mContext.getResources().getStringArray(
224                 com.android.internal.R.array.config_tether_wifi_regexs);
225         String[] tetherableBluetoothRegexs = mContext.getResources().getStringArray(
226                 com.android.internal.R.array.config_tether_bluetooth_regexs);
227 
228         int ifaceTypes[] = mContext.getResources().getIntArray(
229                 com.android.internal.R.array.config_tether_upstream_types);
230         Collection<Integer> upstreamIfaceTypes = new ArrayList();
231         for (int i : ifaceTypes) {
232             upstreamIfaceTypes.add(new Integer(i));
233         }
234 
235         synchronized (mPublicSync) {
236             mTetherableUsbRegexs = tetherableUsbRegexs;
237             mTetherableWifiRegexs = tetherableWifiRegexs;
238             mTetherableBluetoothRegexs = tetherableBluetoothRegexs;
239             mUpstreamIfaceTypes = upstreamIfaceTypes;
240         }
241 
242         // check if the upstream type list needs to be modified due to secure-settings
243         checkDunRequired();
244     }
245 
246     @Override
interfaceStatusChanged(String iface, boolean up)247     public void interfaceStatusChanged(String iface, boolean up) {
248         // Never called directly: only called from interfaceLinkStateChanged.
249         // See NetlinkHandler.cpp:71.
250         if (VDBG) Log.d(TAG, "interfaceStatusChanged " + iface + ", " + up);
251         boolean found = false;
252         boolean usb = false;
253         synchronized (mPublicSync) {
254             if (isWifi(iface)) {
255                 found = true;
256             } else if (isUsb(iface)) {
257                 found = true;
258                 usb = true;
259             } else if (isBluetooth(iface)) {
260                 found = true;
261             }
262             if (found == false) return;
263 
264             TetherInterfaceSM sm = mIfaces.get(iface);
265             if (up) {
266                 if (sm == null) {
267                     sm = new TetherInterfaceSM(iface, mLooper, usb);
268                     mIfaces.put(iface, sm);
269                     sm.start();
270                 }
271             } else {
272                 if (isUsb(iface)) {
273                     // ignore usb0 down after enabling RNDIS
274                     // we will handle disconnect in interfaceRemoved instead
275                     if (VDBG) Log.d(TAG, "ignore interface down for " + iface);
276                 } else if (sm != null) {
277                     sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
278                     mIfaces.remove(iface);
279                 }
280             }
281         }
282     }
283 
284     @Override
interfaceLinkStateChanged(String iface, boolean up)285     public void interfaceLinkStateChanged(String iface, boolean up) {
286         interfaceStatusChanged(iface, up);
287     }
288 
isUsb(String iface)289     private boolean isUsb(String iface) {
290         synchronized (mPublicSync) {
291             for (String regex : mTetherableUsbRegexs) {
292                 if (iface.matches(regex)) return true;
293             }
294             return false;
295         }
296     }
297 
isWifi(String iface)298     public boolean isWifi(String iface) {
299         synchronized (mPublicSync) {
300             for (String regex : mTetherableWifiRegexs) {
301                 if (iface.matches(regex)) return true;
302             }
303             return false;
304         }
305     }
306 
isBluetooth(String iface)307     public boolean isBluetooth(String iface) {
308         synchronized (mPublicSync) {
309             for (String regex : mTetherableBluetoothRegexs) {
310                 if (iface.matches(regex)) return true;
311             }
312             return false;
313         }
314     }
315 
316     @Override
interfaceAdded(String iface)317     public void interfaceAdded(String iface) {
318         if (VDBG) Log.d(TAG, "interfaceAdded " + iface);
319         boolean found = false;
320         boolean usb = false;
321         synchronized (mPublicSync) {
322             if (isWifi(iface)) {
323                 found = true;
324             }
325             if (isUsb(iface)) {
326                 found = true;
327                 usb = true;
328             }
329             if (isBluetooth(iface)) {
330                 found = true;
331             }
332             if (found == false) {
333                 if (VDBG) Log.d(TAG, iface + " is not a tetherable iface, ignoring");
334                 return;
335             }
336 
337             TetherInterfaceSM sm = mIfaces.get(iface);
338             if (sm != null) {
339                 if (VDBG) Log.d(TAG, "active iface (" + iface + ") reported as added, ignoring");
340                 return;
341             }
342             sm = new TetherInterfaceSM(iface, mLooper, usb);
343             mIfaces.put(iface, sm);
344             sm.start();
345         }
346     }
347 
348     @Override
interfaceRemoved(String iface)349     public void interfaceRemoved(String iface) {
350         if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
351         synchronized (mPublicSync) {
352             TetherInterfaceSM sm = mIfaces.get(iface);
353             if (sm == null) {
354                 if (VDBG) {
355                     Log.e(TAG, "attempting to remove unknown iface (" + iface + "), ignoring");
356                 }
357                 return;
358             }
359             sm.sendMessage(TetherInterfaceSM.CMD_INTERFACE_DOWN);
360             mIfaces.remove(iface);
361         }
362     }
363 
startTethering(int type, ResultReceiver receiver, boolean showProvisioningUi)364     public void startTethering(int type, ResultReceiver receiver,
365             boolean showProvisioningUi) {
366         if (!isTetherProvisioningRequired()) {
367             enableTetheringInternal(type, true, receiver);
368             return;
369         }
370 
371         if (showProvisioningUi) {
372             runUiTetherProvisioningAndEnable(type, receiver);
373         } else {
374             runSilentTetherProvisioningAndEnable(type, receiver);
375         }
376     }
377 
stopTethering(int type)378     public void stopTethering(int type) {
379         enableTetheringInternal(type, false, null);
380         if (isTetherProvisioningRequired()) {
381             cancelTetherProvisioningRechecks(type);
382         }
383     }
384 
385     /**
386      * Check if the device requires a provisioning check in order to enable tethering.
387      *
388      * @return a boolean - {@code true} indicating tether provisioning is required by the carrier.
389      */
isTetherProvisioningRequired()390     private boolean isTetherProvisioningRequired() {
391         String[] provisionApp = mContext.getResources().getStringArray(
392                 com.android.internal.R.array.config_mobile_hotspot_provision_app);
393         if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
394                 || provisionApp == null) {
395             return false;
396         }
397 
398         // Check carrier config for entitlement checks
399         final CarrierConfigManager configManager = (CarrierConfigManager) mContext
400              .getSystemService(Context.CARRIER_CONFIG_SERVICE);
401         boolean isEntitlementCheckRequired = configManager.getConfig().getBoolean(
402              CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL);
403 
404         if (!isEntitlementCheckRequired) {
405             return false;
406         }
407         return (provisionApp.length == 2);
408     }
409 
410     /**
411      * Enables or disables tethering for the given type. This should only be called once
412      * provisioning has succeeded or is not necessary. It will also schedule provisioning rechecks
413      * for the specified interface.
414      */
enableTetheringInternal(int type, boolean enable, ResultReceiver receiver)415     private void enableTetheringInternal(int type, boolean enable, ResultReceiver receiver) {
416         boolean isProvisioningRequired = isTetherProvisioningRequired();
417         switch (type) {
418             case ConnectivityManager.TETHERING_WIFI:
419                 final WifiManager wifiManager =
420                         (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
421                 if (wifiManager.setWifiApEnabled(null, enable)) {
422                     sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_NO_ERROR);
423                     if (enable && isProvisioningRequired) {
424                         scheduleProvisioningRechecks(type);
425                     }
426                 } else{
427                     sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
428                 }
429                 break;
430             case ConnectivityManager.TETHERING_USB:
431                 int result = setUsbTethering(enable);
432                 if (enable && isProvisioningRequired &&
433                         result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
434                     scheduleProvisioningRechecks(type);
435                 }
436                 sendTetherResult(receiver, result);
437                 break;
438             case ConnectivityManager.TETHERING_BLUETOOTH:
439                 setBluetoothTethering(enable, receiver);
440                 break;
441             default:
442                 Log.w(TAG, "Invalid tether type.");
443                 sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE);
444         }
445     }
446 
sendTetherResult(ResultReceiver receiver, int result)447     private void sendTetherResult(ResultReceiver receiver, int result) {
448         if (receiver != null) {
449             receiver.send(result, null);
450         }
451     }
452 
setBluetoothTethering(final boolean enable, final ResultReceiver receiver)453     private void setBluetoothTethering(final boolean enable, final ResultReceiver receiver) {
454         final BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
455         if (adapter == null || !adapter.isEnabled()) {
456             Log.w(TAG, "Tried to enable bluetooth tethering with null or disabled adapter. null: " +
457                     (adapter == null));
458             sendTetherResult(receiver, ConnectivityManager.TETHER_ERROR_SERVICE_UNAVAIL);
459             return;
460         }
461 
462         adapter.getProfileProxy(mContext, new ServiceListener() {
463             @Override
464             public void onServiceDisconnected(int profile) { }
465 
466             @Override
467             public void onServiceConnected(int profile, BluetoothProfile proxy) {
468                 ((BluetoothPan) proxy).setBluetoothTethering(enable);
469                 // TODO: Enabling bluetooth tethering can fail asynchronously here.
470                 // We should figure out a way to bubble up that failure instead of sending success.
471                 int result = ((BluetoothPan) proxy).isTetheringOn() == enable ?
472                         ConnectivityManager.TETHER_ERROR_NO_ERROR :
473                         ConnectivityManager.TETHER_ERROR_MASTER_ERROR;
474                 sendTetherResult(receiver, result);
475                 if (enable && isTetherProvisioningRequired()) {
476                     scheduleProvisioningRechecks(ConnectivityManager.TETHERING_BLUETOOTH);
477                 }
478                 adapter.closeProfileProxy(BluetoothProfile.PAN, proxy);
479             }
480         }, BluetoothProfile.PAN);
481     }
482 
runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver)483     private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
484         ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
485         sendUiTetherProvisionIntent(type, proxyReceiver);
486     }
487 
sendUiTetherProvisionIntent(int type, ResultReceiver receiver)488     private void sendUiTetherProvisionIntent(int type, ResultReceiver receiver) {
489         Intent intent = new Intent(Settings.ACTION_TETHER_PROVISIONING);
490         intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
491         intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
492         final long ident = Binder.clearCallingIdentity();
493         try {
494             mContext.startActivityAsUser(intent, UserHandle.CURRENT);
495         } finally {
496             Binder.restoreCallingIdentity(ident);
497         }
498     }
499 
500     /**
501      * Creates a proxy {@link ResultReceiver} which enables tethering if the provsioning result is
502      * successful before firing back up to the wrapped receiver.
503      *
504      * @param type The type of tethering being enabled.
505      * @param receiver A ResultReceiver which will be called back with an int resultCode.
506      * @return The proxy receiver.
507      */
getProxyReceiver(final int type, final ResultReceiver receiver)508     private ResultReceiver getProxyReceiver(final int type, final ResultReceiver receiver) {
509         ResultReceiver rr = new ResultReceiver(null) {
510             @Override
511             protected void onReceiveResult(int resultCode, Bundle resultData) {
512                 // If provisioning is successful, enable tethering, otherwise just send the error.
513                 if (resultCode == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
514                     enableTetheringInternal(type, true, receiver);
515                 } else {
516                     sendTetherResult(receiver, resultCode);
517                 }
518             }
519         };
520 
521         // The following is necessary to avoid unmarshalling issues when sending the receiver
522         // across processes.
523         Parcel parcel = Parcel.obtain();
524         rr.writeToParcel(parcel,0);
525         parcel.setDataPosition(0);
526         ResultReceiver receiverForSending = ResultReceiver.CREATOR.createFromParcel(parcel);
527         parcel.recycle();
528         return receiverForSending;
529     }
530 
scheduleProvisioningRechecks(int type)531     private void scheduleProvisioningRechecks(int type) {
532         Intent intent = new Intent();
533         intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
534         intent.putExtra(ConnectivityManager.EXTRA_SET_ALARM, true);
535         intent.setComponent(TETHER_SERVICE);
536         final long ident = Binder.clearCallingIdentity();
537         try {
538             mContext.startServiceAsUser(intent, UserHandle.CURRENT);
539         } finally {
540             Binder.restoreCallingIdentity(ident);
541         }
542     }
543 
runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver)544     private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
545         ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
546         sendSilentTetherProvisionIntent(type, proxyReceiver);
547     }
548 
sendSilentTetherProvisionIntent(int type, ResultReceiver receiver)549     private void sendSilentTetherProvisionIntent(int type, ResultReceiver receiver) {
550         Intent intent = new Intent();
551         intent.putExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, type);
552         intent.putExtra(ConnectivityManager.EXTRA_RUN_PROVISION, true);
553         intent.putExtra(ConnectivityManager.EXTRA_PROVISION_CALLBACK, receiver);
554         intent.setComponent(TETHER_SERVICE);
555         final long ident = Binder.clearCallingIdentity();
556         try {
557             mContext.startServiceAsUser(intent, UserHandle.CURRENT);
558         } finally {
559             Binder.restoreCallingIdentity(ident);
560         }
561     }
562 
cancelTetherProvisioningRechecks(int type)563     private void cancelTetherProvisioningRechecks(int type) {
564         if (getConnectivityManager().isTetheringSupported()) {
565             Intent intent = new Intent();
566             intent.putExtra(ConnectivityManager.EXTRA_REM_TETHER_TYPE, type);
567             intent.setComponent(TETHER_SERVICE);
568             final long ident = Binder.clearCallingIdentity();
569             try {
570                 mContext.startServiceAsUser(intent, UserHandle.CURRENT);
571             } finally {
572                 Binder.restoreCallingIdentity(ident);
573             }
574         }
575     }
576 
tether(String iface)577     public int tether(String iface) {
578         if (DBG) Log.d(TAG, "Tethering " + iface);
579         TetherInterfaceSM sm = null;
580         synchronized (mPublicSync) {
581             sm = mIfaces.get(iface);
582         }
583         if (sm == null) {
584             Log.e(TAG, "Tried to Tether an unknown iface :" + iface + ", ignoring");
585             return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
586         }
587         if (!sm.isAvailable() && !sm.isErrored()) {
588             Log.e(TAG, "Tried to Tether an unavailable iface :" + iface + ", ignoring");
589             return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
590         }
591         sm.sendMessage(TetherInterfaceSM.CMD_TETHER_REQUESTED);
592         return ConnectivityManager.TETHER_ERROR_NO_ERROR;
593     }
594 
untether(String iface)595     public int untether(String iface) {
596         if (DBG) Log.d(TAG, "Untethering " + iface);
597         TetherInterfaceSM sm = null;
598         synchronized (mPublicSync) {
599             sm = mIfaces.get(iface);
600         }
601         if (sm == null) {
602             Log.e(TAG, "Tried to Untether an unknown iface :" + iface + ", ignoring");
603             return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
604         }
605         if (sm.isErrored()) {
606             Log.e(TAG, "Tried to Untethered an errored iface :" + iface + ", ignoring");
607             return ConnectivityManager.TETHER_ERROR_UNAVAIL_IFACE;
608         }
609         sm.sendMessage(TetherInterfaceSM.CMD_TETHER_UNREQUESTED);
610         return ConnectivityManager.TETHER_ERROR_NO_ERROR;
611     }
612 
untetherAll()613     public void untetherAll() {
614         if (DBG) Log.d(TAG, "Untethering " + mIfaces);
615         for (String iface : mIfaces.keySet()) {
616             untether(iface);
617         }
618     }
619 
getLastTetherError(String iface)620     public int getLastTetherError(String iface) {
621         TetherInterfaceSM sm = null;
622         synchronized (mPublicSync) {
623             sm = mIfaces.get(iface);
624             if (sm == null) {
625                 Log.e(TAG, "Tried to getLastTetherError on an unknown iface :" + iface +
626                         ", ignoring");
627                 return ConnectivityManager.TETHER_ERROR_UNKNOWN_IFACE;
628             }
629             return sm.getLastError();
630         }
631     }
632 
633     // TODO - move all private methods used only by the state machine into the state machine
634     // to clarify what needs synchronized protection.
sendTetherStateChangedBroadcast()635     private void sendTetherStateChangedBroadcast() {
636         if (!getConnectivityManager().isTetheringSupported()) return;
637 
638         ArrayList<String> availableList = new ArrayList<String>();
639         ArrayList<String> activeList = new ArrayList<String>();
640         ArrayList<String> erroredList = new ArrayList<String>();
641 
642         boolean wifiTethered = false;
643         boolean usbTethered = false;
644         boolean bluetoothTethered = false;
645 
646         synchronized (mPublicSync) {
647             Set ifaces = mIfaces.keySet();
648             for (Object iface : ifaces) {
649                 TetherInterfaceSM sm = mIfaces.get(iface);
650                 if (sm != null) {
651                     if (sm.isErrored()) {
652                         erroredList.add((String)iface);
653                     } else if (sm.isAvailable()) {
654                         availableList.add((String)iface);
655                     } else if (sm.isTethered()) {
656                         if (isUsb((String)iface)) {
657                             usbTethered = true;
658                         } else if (isWifi((String)iface)) {
659                             wifiTethered = true;
660                       } else if (isBluetooth((String)iface)) {
661                             bluetoothTethered = true;
662                         }
663                         activeList.add((String)iface);
664                     }
665                 }
666             }
667         }
668         Intent broadcast = new Intent(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
669         broadcast.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
670                 Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
671         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_AVAILABLE_TETHER,
672                 availableList);
673         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ACTIVE_TETHER, activeList);
674         broadcast.putStringArrayListExtra(ConnectivityManager.EXTRA_ERRORED_TETHER,
675                 erroredList);
676         mContext.sendStickyBroadcastAsUser(broadcast, UserHandle.ALL);
677         if (DBG) {
678             Log.d(TAG, String.format(
679                     "sendTetherStateChangedBroadcast avail=[%s] active=[%s] error=[%s]",
680                     TextUtils.join(",", availableList),
681                     TextUtils.join(",", activeList),
682                     TextUtils.join(",", erroredList)));
683         }
684 
685         if (usbTethered) {
686             if (wifiTethered || bluetoothTethered) {
687                 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
688             } else {
689                 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_usb);
690             }
691         } else if (wifiTethered) {
692             if (bluetoothTethered) {
693                 showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_general);
694             } else {
695                 /* We now have a status bar icon for WifiTethering, so drop the notification */
696                 clearTetheredNotification();
697             }
698         } else if (bluetoothTethered) {
699             showTetheredNotification(com.android.internal.R.drawable.stat_sys_tether_bluetooth);
700         } else {
701             clearTetheredNotification();
702         }
703     }
704 
showTetheredNotification(int icon)705     private void showTetheredNotification(int icon) {
706         NotificationManager notificationManager =
707                 (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
708         if (notificationManager == null) {
709             return;
710         }
711 
712         if (mLastNotificationId != 0) {
713             if (mLastNotificationId == icon) {
714                 return;
715             }
716             notificationManager.cancelAsUser(null, mLastNotificationId,
717                     UserHandle.ALL);
718             mLastNotificationId = 0;
719         }
720 
721         Intent intent = new Intent();
722         intent.setClassName("com.android.settings", "com.android.settings.TetherSettings");
723         intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
724 
725         PendingIntent pi = PendingIntent.getActivityAsUser(mContext, 0, intent, 0,
726                 null, UserHandle.CURRENT);
727 
728         Resources r = Resources.getSystem();
729         CharSequence title = r.getText(com.android.internal.R.string.tethered_notification_title);
730         CharSequence message = r.getText(com.android.internal.R.string.
731                 tethered_notification_message);
732 
733         if (mTetheredNotificationBuilder == null) {
734             mTetheredNotificationBuilder = new Notification.Builder(mContext);
735             mTetheredNotificationBuilder.setWhen(0)
736                     .setOngoing(true)
737                     .setColor(mContext.getColor(
738                             com.android.internal.R.color.system_notification_accent_color))
739                     .setVisibility(Notification.VISIBILITY_PUBLIC)
740                     .setCategory(Notification.CATEGORY_STATUS);
741         }
742         mTetheredNotificationBuilder.setSmallIcon(icon)
743                 .setContentTitle(title)
744                 .setContentText(message)
745                 .setContentIntent(pi);
746         mLastNotificationId = icon;
747 
748         notificationManager.notifyAsUser(null, mLastNotificationId,
749                 mTetheredNotificationBuilder.build(), UserHandle.ALL);
750     }
751 
clearTetheredNotification()752     private void clearTetheredNotification() {
753         NotificationManager notificationManager =
754             (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
755         if (notificationManager != null && mLastNotificationId != 0) {
756             notificationManager.cancelAsUser(null, mLastNotificationId,
757                     UserHandle.ALL);
758             mLastNotificationId = 0;
759         }
760     }
761 
762     private class StateReceiver extends BroadcastReceiver {
763         @Override
onReceive(Context content, Intent intent)764         public void onReceive(Context content, Intent intent) {
765             String action = intent.getAction();
766             if (action == null) { return; }
767             if (action.equals(UsbManager.ACTION_USB_STATE)) {
768                 synchronized (Tethering.this.mPublicSync) {
769                     boolean usbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
770                     mRndisEnabled = intent.getBooleanExtra(UsbManager.USB_FUNCTION_RNDIS, false);
771                     // start tethering if we have a request pending
772                     if (usbConnected && mRndisEnabled && mUsbTetherRequested) {
773                         tetherUsb(true);
774                     }
775                     mUsbTetherRequested = false;
776                 }
777             } else if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
778                 NetworkInfo networkInfo = (NetworkInfo)intent.getParcelableExtra(
779                         ConnectivityManager.EXTRA_NETWORK_INFO);
780                 if (networkInfo != null &&
781                         networkInfo.getDetailedState() != NetworkInfo.DetailedState.FAILED) {
782                     if (VDBG) Log.d(TAG, "Tethering got CONNECTIVITY_ACTION");
783                     mTetherMasterSM.sendMessage(TetherMasterSM.CMD_UPSTREAM_CHANGED);
784                 }
785             } else if (action.equals(Intent.ACTION_CONFIGURATION_CHANGED)) {
786                 updateConfiguration();
787             }
788         }
789     }
790 
tetherUsb(boolean enable)791     private void tetherUsb(boolean enable) {
792         if (VDBG) Log.d(TAG, "tetherUsb " + enable);
793 
794         String[] ifaces = new String[0];
795         try {
796             ifaces = mNMService.listInterfaces();
797         } catch (Exception e) {
798             Log.e(TAG, "Error listing Interfaces", e);
799             return;
800         }
801         for (String iface : ifaces) {
802             if (isUsb(iface)) {
803                 int result = (enable ? tether(iface) : untether(iface));
804                 if (result == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
805                     return;
806                 }
807             }
808         }
809         Log.e(TAG, "unable start or stop USB tethering");
810     }
811 
812     // configured when we start tethering and unconfig'd on error or conclusion
configureUsbIface(boolean enabled)813     private boolean configureUsbIface(boolean enabled) {
814         if (VDBG) Log.d(TAG, "configureUsbIface(" + enabled + ")");
815 
816         // toggle the USB interfaces
817         String[] ifaces = new String[0];
818         try {
819             ifaces = mNMService.listInterfaces();
820         } catch (Exception e) {
821             Log.e(TAG, "Error listing Interfaces", e);
822             return false;
823         }
824         for (String iface : ifaces) {
825             if (isUsb(iface)) {
826                 InterfaceConfiguration ifcg = null;
827                 try {
828                     ifcg = mNMService.getInterfaceConfig(iface);
829                     if (ifcg != null) {
830                         InetAddress addr = NetworkUtils.numericToInetAddress(USB_NEAR_IFACE_ADDR);
831                         ifcg.setLinkAddress(new LinkAddress(addr, USB_PREFIX_LENGTH));
832                         if (enabled) {
833                             ifcg.setInterfaceUp();
834                         } else {
835                             ifcg.setInterfaceDown();
836                         }
837                         ifcg.clearFlag("running");
838                         mNMService.setInterfaceConfig(iface, ifcg);
839                     }
840                 } catch (Exception e) {
841                     Log.e(TAG, "Error configuring interface " + iface, e);
842                     return false;
843                 }
844             }
845          }
846 
847         return true;
848     }
849 
850     // TODO - return copies so people can't tamper
getTetherableUsbRegexs()851     public String[] getTetherableUsbRegexs() {
852         return mTetherableUsbRegexs;
853     }
854 
getTetherableWifiRegexs()855     public String[] getTetherableWifiRegexs() {
856         return mTetherableWifiRegexs;
857     }
858 
getTetherableBluetoothRegexs()859     public String[] getTetherableBluetoothRegexs() {
860         return mTetherableBluetoothRegexs;
861     }
862 
setUsbTethering(boolean enable)863     public int setUsbTethering(boolean enable) {
864         if (VDBG) Log.d(TAG, "setUsbTethering(" + enable + ")");
865         UsbManager usbManager = (UsbManager)mContext.getSystemService(Context.USB_SERVICE);
866 
867         synchronized (mPublicSync) {
868             if (enable) {
869                 if (mRndisEnabled) {
870                     final long ident = Binder.clearCallingIdentity();
871                     try {
872                         tetherUsb(true);
873                     } finally {
874                         Binder.restoreCallingIdentity(ident);
875                     }
876                 } else {
877                     mUsbTetherRequested = true;
878                     usbManager.setCurrentFunction(UsbManager.USB_FUNCTION_RNDIS);
879                 }
880             } else {
881                 final long ident = Binder.clearCallingIdentity();
882                 try {
883                     tetherUsb(false);
884                 } finally {
885                     Binder.restoreCallingIdentity(ident);
886                 }
887                 if (mRndisEnabled) {
888                     usbManager.setCurrentFunction(null);
889                 }
890                 mUsbTetherRequested = false;
891             }
892         }
893         return ConnectivityManager.TETHER_ERROR_NO_ERROR;
894     }
895 
getUpstreamIfaceTypes()896     public int[] getUpstreamIfaceTypes() {
897         int values[];
898         synchronized (mPublicSync) {
899             updateConfiguration();  // TODO - remove?
900             values = new int[mUpstreamIfaceTypes.size()];
901             Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
902             for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
903                 values[i] = iterator.next();
904             }
905         }
906         return values;
907     }
908 
checkDunRequired()909     private void checkDunRequired() {
910         int secureSetting = 2;
911         TelephonyManager tm = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
912         if (tm != null) {
913             secureSetting = tm.getTetherApnRequired();
914         }
915         synchronized (mPublicSync) {
916             // 2 = not set, 0 = DUN not required, 1 = DUN required
917             if (secureSetting != 2) {
918                 int requiredApn = (secureSetting == 1 ?
919                         ConnectivityManager.TYPE_MOBILE_DUN :
920                         ConnectivityManager.TYPE_MOBILE_HIPRI);
921                 if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
922                     while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
923                         mUpstreamIfaceTypes.remove(MOBILE_TYPE);
924                     }
925                     while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
926                         mUpstreamIfaceTypes.remove(HIPRI_TYPE);
927                     }
928                     if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
929                         mUpstreamIfaceTypes.add(DUN_TYPE);
930                     }
931                 } else {
932                     while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
933                         mUpstreamIfaceTypes.remove(DUN_TYPE);
934                     }
935                     if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
936                         mUpstreamIfaceTypes.add(MOBILE_TYPE);
937                     }
938                     if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
939                         mUpstreamIfaceTypes.add(HIPRI_TYPE);
940                     }
941                 }
942             }
943             if (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
944                 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_DUN;
945             } else {
946                 mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_MOBILE_HIPRI;
947             }
948         }
949     }
950 
951     // TODO review API - maybe return ArrayList<String> here and below?
getTetheredIfaces()952     public String[] getTetheredIfaces() {
953         ArrayList<String> list = new ArrayList<String>();
954         synchronized (mPublicSync) {
955             Set keys = mIfaces.keySet();
956             for (Object key : keys) {
957                 TetherInterfaceSM sm = mIfaces.get(key);
958                 if (sm.isTethered()) {
959                     list.add((String)key);
960                 }
961             }
962         }
963         String[] retVal = new String[list.size()];
964         for (int i=0; i < list.size(); i++) {
965             retVal[i] = list.get(i);
966         }
967         return retVal;
968     }
969 
getTetherableIfaces()970     public String[] getTetherableIfaces() {
971         ArrayList<String> list = new ArrayList<String>();
972         synchronized (mPublicSync) {
973             Set keys = mIfaces.keySet();
974             for (Object key : keys) {
975                 TetherInterfaceSM sm = mIfaces.get(key);
976                 if (sm.isAvailable()) {
977                     list.add((String)key);
978                 }
979             }
980         }
981         String[] retVal = new String[list.size()];
982         for (int i=0; i < list.size(); i++) {
983             retVal[i] = list.get(i);
984         }
985         return retVal;
986     }
987 
getTetheredDhcpRanges()988     public String[] getTetheredDhcpRanges() {
989         return mDhcpRange;
990     }
991 
getErroredIfaces()992     public String[] getErroredIfaces() {
993         ArrayList<String> list = new ArrayList<String>();
994         synchronized (mPublicSync) {
995             Set keys = mIfaces.keySet();
996             for (Object key : keys) {
997                 TetherInterfaceSM sm = mIfaces.get(key);
998                 if (sm.isErrored()) {
999                     list.add((String)key);
1000                 }
1001             }
1002         }
1003         String[] retVal = new String[list.size()];
1004         for (int i= 0; i< list.size(); i++) {
1005             retVal[i] = list.get(i);
1006         }
1007         return retVal;
1008     }
1009 
maybeLogMessage(State state, int what)1010     private void maybeLogMessage(State state, int what) {
1011         if (DBG) {
1012             Log.d(TAG, state.getName() + " got " +
1013                     sMagicDecoderRing.get(what, Integer.toString(what)));
1014         }
1015     }
1016 
1017     class TetherInterfaceSM extends StateMachine {
1018         private static final int BASE_IFACE              = Protocol.BASE_TETHERING + 100;
1019         // notification from the master SM that it's not in tether mode
1020         static final int CMD_TETHER_MODE_DEAD            = BASE_IFACE + 1;
1021         // request from the user that it wants to tether
1022         static final int CMD_TETHER_REQUESTED            = BASE_IFACE + 2;
1023         // request from the user that it wants to untether
1024         static final int CMD_TETHER_UNREQUESTED          = BASE_IFACE + 3;
1025         // notification that this interface is down
1026         static final int CMD_INTERFACE_DOWN              = BASE_IFACE + 4;
1027         // notification that this interface is up
1028         static final int CMD_INTERFACE_UP                = BASE_IFACE + 5;
1029         // notification from the master SM that it had an error turning on cellular dun
1030         static final int CMD_CELL_DUN_ERROR              = BASE_IFACE + 6;
1031         // notification from the master SM that it had trouble enabling IP Forwarding
1032         static final int CMD_IP_FORWARDING_ENABLE_ERROR  = BASE_IFACE + 7;
1033         // notification from the master SM that it had trouble disabling IP Forwarding
1034         static final int CMD_IP_FORWARDING_DISABLE_ERROR = BASE_IFACE + 8;
1035         // notification from the master SM that it had trouble starting tethering
1036         static final int CMD_START_TETHERING_ERROR       = BASE_IFACE + 9;
1037         // notification from the master SM that it had trouble stopping tethering
1038         static final int CMD_STOP_TETHERING_ERROR        = BASE_IFACE + 10;
1039         // notification from the master SM that it had trouble setting the DNS forwarders
1040         static final int CMD_SET_DNS_FORWARDERS_ERROR    = BASE_IFACE + 11;
1041         // the upstream connection has changed
1042         static final int CMD_TETHER_CONNECTION_CHANGED   = BASE_IFACE + 12;
1043 
1044         private State mDefaultState;
1045 
1046         private State mInitialState;
1047         private State mStartingState;
1048         private State mTetheredState;
1049 
1050         private State mUnavailableState;
1051 
1052         private boolean mAvailable;
1053         private boolean mTethered;
1054         int mLastError;
1055 
1056         String mIfaceName;
1057         String mMyUpstreamIfaceName;  // may change over time
1058 
1059         boolean mUsb;
1060 
TetherInterfaceSM(String name, Looper looper, boolean usb)1061         TetherInterfaceSM(String name, Looper looper, boolean usb) {
1062             super(name, looper);
1063             mIfaceName = name;
1064             mUsb = usb;
1065             setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
1066 
1067             mInitialState = new InitialState();
1068             addState(mInitialState);
1069             mStartingState = new StartingState();
1070             addState(mStartingState);
1071             mTetheredState = new TetheredState();
1072             addState(mTetheredState);
1073             mUnavailableState = new UnavailableState();
1074             addState(mUnavailableState);
1075 
1076             setInitialState(mInitialState);
1077         }
1078 
toString()1079         public String toString() {
1080             String res = new String();
1081             res += mIfaceName + " - ";
1082             IState current = getCurrentState();
1083             if (current == mInitialState) res += "InitialState";
1084             if (current == mStartingState) res += "StartingState";
1085             if (current == mTetheredState) res += "TetheredState";
1086             if (current == mUnavailableState) res += "UnavailableState";
1087             if (mAvailable) res += " - Available";
1088             if (mTethered) res += " - Tethered";
1089             res += " - lastError =" + mLastError;
1090             return res;
1091         }
1092 
getLastError()1093         public int getLastError() {
1094             synchronized (Tethering.this.mPublicSync) {
1095                 return mLastError;
1096             }
1097         }
1098 
setLastError(int error)1099         private void setLastError(int error) {
1100             synchronized (Tethering.this.mPublicSync) {
1101                 mLastError = error;
1102 
1103                 if (isErrored()) {
1104                     if (mUsb) {
1105                         // note everything's been unwound by this point so nothing to do on
1106                         // further error..
1107                         Tethering.this.configureUsbIface(false);
1108                     }
1109                 }
1110             }
1111         }
1112 
isAvailable()1113         public boolean isAvailable() {
1114             synchronized (Tethering.this.mPublicSync) {
1115                 return mAvailable;
1116             }
1117         }
1118 
setAvailable(boolean available)1119         private void setAvailable(boolean available) {
1120             synchronized (Tethering.this.mPublicSync) {
1121                 mAvailable = available;
1122             }
1123         }
1124 
isTethered()1125         public boolean isTethered() {
1126             synchronized (Tethering.this.mPublicSync) {
1127                 return mTethered;
1128             }
1129         }
1130 
setTethered(boolean tethered)1131         private void setTethered(boolean tethered) {
1132             synchronized (Tethering.this.mPublicSync) {
1133                 mTethered = tethered;
1134             }
1135         }
1136 
isErrored()1137         public boolean isErrored() {
1138             synchronized (Tethering.this.mPublicSync) {
1139                 return (mLastError != ConnectivityManager.TETHER_ERROR_NO_ERROR);
1140             }
1141         }
1142 
1143         class InitialState extends State {
1144             @Override
enter()1145             public void enter() {
1146                 setAvailable(true);
1147                 setTethered(false);
1148                 sendTetherStateChangedBroadcast();
1149             }
1150 
1151             @Override
processMessage(Message message)1152             public boolean processMessage(Message message) {
1153                 maybeLogMessage(this, message.what);
1154                 boolean retValue = true;
1155                 switch (message.what) {
1156                     case CMD_TETHER_REQUESTED:
1157                         setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
1158                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_REQUESTED,
1159                                 TetherInterfaceSM.this);
1160                         transitionTo(mStartingState);
1161                         break;
1162                     case CMD_INTERFACE_DOWN:
1163                         transitionTo(mUnavailableState);
1164                         break;
1165                     default:
1166                         retValue = false;
1167                         break;
1168                 }
1169                 return retValue;
1170             }
1171         }
1172 
1173         class StartingState extends State {
1174             @Override
enter()1175             public void enter() {
1176                 setAvailable(false);
1177                 if (mUsb) {
1178                     if (!Tethering.this.configureUsbIface(true)) {
1179                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1180                                 TetherInterfaceSM.this);
1181                         setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
1182 
1183                         transitionTo(mInitialState);
1184                         return;
1185                     }
1186                 }
1187                 sendTetherStateChangedBroadcast();
1188 
1189                 // Skipping StartingState
1190                 transitionTo(mTetheredState);
1191             }
1192             @Override
processMessage(Message message)1193             public boolean processMessage(Message message) {
1194                 maybeLogMessage(this, message.what);
1195                 boolean retValue = true;
1196                 switch (message.what) {
1197                     // maybe a parent class?
1198                     case CMD_TETHER_UNREQUESTED:
1199                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1200                                 TetherInterfaceSM.this);
1201                         if (mUsb) {
1202                             if (!Tethering.this.configureUsbIface(false)) {
1203                                 setLastErrorAndTransitionToInitialState(
1204                                     ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
1205                                 break;
1206                             }
1207                         }
1208                         transitionTo(mInitialState);
1209                         break;
1210                     case CMD_CELL_DUN_ERROR:
1211                     case CMD_IP_FORWARDING_ENABLE_ERROR:
1212                     case CMD_IP_FORWARDING_DISABLE_ERROR:
1213                     case CMD_START_TETHERING_ERROR:
1214                     case CMD_STOP_TETHERING_ERROR:
1215                     case CMD_SET_DNS_FORWARDERS_ERROR:
1216                         setLastErrorAndTransitionToInitialState(
1217                                 ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
1218                         break;
1219                     case CMD_INTERFACE_DOWN:
1220                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1221                                 TetherInterfaceSM.this);
1222                         transitionTo(mUnavailableState);
1223                         break;
1224                     default:
1225                         retValue = false;
1226                 }
1227                 return retValue;
1228             }
1229         }
1230 
1231         class TetheredState extends State {
1232             @Override
enter()1233             public void enter() {
1234                 try {
1235                     mNMService.tetherInterface(mIfaceName);
1236                 } catch (Exception e) {
1237                     Log.e(TAG, "Error Tethering: " + e.toString());
1238                     setLastError(ConnectivityManager.TETHER_ERROR_TETHER_IFACE_ERROR);
1239 
1240                     try {
1241                         mNMService.untetherInterface(mIfaceName);
1242                     } catch (Exception ee) {
1243                         Log.e(TAG, "Error untethering after failure!" + ee.toString());
1244                     }
1245                     transitionTo(mInitialState);
1246                     return;
1247                 }
1248                 if (DBG) Log.d(TAG, "Tethered " + mIfaceName);
1249                 setAvailable(false);
1250                 setTethered(true);
1251                 sendTetherStateChangedBroadcast();
1252             }
1253 
cleanupUpstream()1254             private void cleanupUpstream() {
1255                 if (mMyUpstreamIfaceName != null) {
1256                     // note that we don't care about errors here.
1257                     // sometimes interfaces are gone before we get
1258                     // to remove their rules, which generates errors.
1259                     // just do the best we can.
1260                     try {
1261                         // about to tear down NAT; gather remaining statistics
1262                         mStatsService.forceUpdate();
1263                     } catch (Exception e) {
1264                         if (VDBG) Log.e(TAG, "Exception in forceUpdate: " + e.toString());
1265                     }
1266                     try {
1267                         mNMService.stopInterfaceForwarding(mIfaceName, mMyUpstreamIfaceName);
1268                     } catch (Exception e) {
1269                         if (VDBG) Log.e(
1270                                 TAG, "Exception in removeInterfaceForward: " + e.toString());
1271                     }
1272                     try {
1273                         mNMService.disableNat(mIfaceName, mMyUpstreamIfaceName);
1274                     } catch (Exception e) {
1275                         if (VDBG) Log.e(TAG, "Exception in disableNat: " + e.toString());
1276                     }
1277                     mMyUpstreamIfaceName = null;
1278                 }
1279                 return;
1280             }
1281 
1282             @Override
processMessage(Message message)1283             public boolean processMessage(Message message) {
1284                 maybeLogMessage(this, message.what);
1285                 boolean retValue = true;
1286                 boolean error = false;
1287                 switch (message.what) {
1288                     case CMD_TETHER_UNREQUESTED:
1289                     case CMD_INTERFACE_DOWN:
1290                         cleanupUpstream();
1291                         try {
1292                             mNMService.untetherInterface(mIfaceName);
1293                         } catch (Exception e) {
1294                             setLastErrorAndTransitionToInitialState(
1295                                     ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
1296                             break;
1297                         }
1298                         mTetherMasterSM.sendMessage(TetherMasterSM.CMD_TETHER_MODE_UNREQUESTED,
1299                                 TetherInterfaceSM.this);
1300                         if (message.what == CMD_TETHER_UNREQUESTED) {
1301                             if (mUsb) {
1302                                 if (!Tethering.this.configureUsbIface(false)) {
1303                                     setLastError(
1304                                             ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
1305                                 }
1306                             }
1307                             transitionTo(mInitialState);
1308                         } else if (message.what == CMD_INTERFACE_DOWN) {
1309                             transitionTo(mUnavailableState);
1310                         }
1311                         if (DBG) Log.d(TAG, "Untethered " + mIfaceName);
1312                         break;
1313                     case CMD_TETHER_CONNECTION_CHANGED:
1314                         String newUpstreamIfaceName = (String)(message.obj);
1315                         if ((mMyUpstreamIfaceName == null && newUpstreamIfaceName == null) ||
1316                                 (mMyUpstreamIfaceName != null &&
1317                                 mMyUpstreamIfaceName.equals(newUpstreamIfaceName))) {
1318                             if (VDBG) Log.d(TAG, "Connection changed noop - dropping");
1319                             break;
1320                         }
1321                         cleanupUpstream();
1322                         if (newUpstreamIfaceName != null) {
1323                             try {
1324                                 mNMService.enableNat(mIfaceName, newUpstreamIfaceName);
1325                                 mNMService.startInterfaceForwarding(mIfaceName,
1326                                         newUpstreamIfaceName);
1327                             } catch (Exception e) {
1328                                 Log.e(TAG, "Exception enabling Nat: " + e.toString());
1329                                 try {
1330                                     mNMService.disableNat(mIfaceName, newUpstreamIfaceName);
1331                                 } catch (Exception ee) {}
1332                                 try {
1333                                     mNMService.untetherInterface(mIfaceName);
1334                                 } catch (Exception ee) {}
1335 
1336                                 setLastError(ConnectivityManager.TETHER_ERROR_ENABLE_NAT_ERROR);
1337                                 transitionTo(mInitialState);
1338                                 return true;
1339                             }
1340                         }
1341                         mMyUpstreamIfaceName = newUpstreamIfaceName;
1342                         break;
1343                     case CMD_CELL_DUN_ERROR:
1344                     case CMD_IP_FORWARDING_ENABLE_ERROR:
1345                     case CMD_IP_FORWARDING_DISABLE_ERROR:
1346                     case CMD_START_TETHERING_ERROR:
1347                     case CMD_STOP_TETHERING_ERROR:
1348                     case CMD_SET_DNS_FORWARDERS_ERROR:
1349                         error = true;
1350                         // fall through
1351                     case CMD_TETHER_MODE_DEAD:
1352                         cleanupUpstream();
1353                         try {
1354                             mNMService.untetherInterface(mIfaceName);
1355                         } catch (Exception e) {
1356                             setLastErrorAndTransitionToInitialState(
1357                                     ConnectivityManager.TETHER_ERROR_UNTETHER_IFACE_ERROR);
1358                             break;
1359                         }
1360                         if (error) {
1361                             setLastErrorAndTransitionToInitialState(
1362                                     ConnectivityManager.TETHER_ERROR_MASTER_ERROR);
1363                             break;
1364                         }
1365                         if (DBG) Log.d(TAG, "Tether lost upstream connection " + mIfaceName);
1366                         sendTetherStateChangedBroadcast();
1367                         if (mUsb) {
1368                             if (!Tethering.this.configureUsbIface(false)) {
1369                                 setLastError(ConnectivityManager.TETHER_ERROR_IFACE_CFG_ERROR);
1370                             }
1371                         }
1372                         transitionTo(mInitialState);
1373                         break;
1374                     default:
1375                         retValue = false;
1376                         break;
1377                 }
1378                 return retValue;
1379             }
1380         }
1381 
1382         class UnavailableState extends State {
1383             @Override
enter()1384             public void enter() {
1385                 setAvailable(false);
1386                 setLastError(ConnectivityManager.TETHER_ERROR_NO_ERROR);
1387                 setTethered(false);
1388                 sendTetherStateChangedBroadcast();
1389             }
1390             @Override
processMessage(Message message)1391             public boolean processMessage(Message message) {
1392                 boolean retValue = true;
1393                 switch (message.what) {
1394                     case CMD_INTERFACE_UP:
1395                         transitionTo(mInitialState);
1396                         break;
1397                     default:
1398                         retValue = false;
1399                         break;
1400                 }
1401                 return retValue;
1402             }
1403         }
1404 
setLastErrorAndTransitionToInitialState(int error)1405         void setLastErrorAndTransitionToInitialState(int error) {
1406             setLastError(error);
1407             transitionTo(mInitialState);
1408         }
1409 
1410     }
1411 
1412     /**
1413      * A NetworkCallback class that relays information of interest to the
1414      * tethering master state machine thread for subsequent processing.
1415      */
1416     class UpstreamNetworkCallback extends NetworkCallback {
1417         @Override
onLinkPropertiesChanged(Network network, LinkProperties newLp)1418         public void onLinkPropertiesChanged(Network network, LinkProperties newLp) {
1419             mTetherMasterSM.sendMessage(
1420                     TetherMasterSM.EVENT_UPSTREAM_LINKPROPERTIES_CHANGED,
1421                     new NetworkState(null, newLp, null, network, null, null));
1422         }
1423 
1424         @Override
onLost(Network network)1425         public void onLost(Network network) {
1426             mTetherMasterSM.sendMessage(TetherMasterSM.EVENT_UPSTREAM_LOST, network);
1427         }
1428     }
1429 
1430     /**
1431      * A class to centralize all the network and link properties information
1432      * pertaining to the current and any potential upstream network.
1433      *
1434      * Calling #start() registers two callbacks: one to track the system default
1435      * network and a second to specifically observe TYPE_MOBILE_DUN networks.
1436      *
1437      * The methods and data members of this class are only to be accessed and
1438      * modified from the tethering master state machine thread. Any other
1439      * access semantics would necessitate the addition of locking.
1440      *
1441      * TODO: Investigate whether more "upstream-specific" logic/functionality
1442      * could/should be moved here.
1443      */
1444     class UpstreamNetworkMonitor {
1445         final HashMap<Network, NetworkState> mNetworkMap = new HashMap();
1446         NetworkCallback mDefaultNetworkCallback;
1447         NetworkCallback mDunTetheringCallback;
1448 
start()1449         void start() {
1450             stop();
1451 
1452             mDefaultNetworkCallback = new UpstreamNetworkCallback();
1453             getConnectivityManager().registerDefaultNetworkCallback(mDefaultNetworkCallback);
1454 
1455             final NetworkRequest dunTetheringRequest = new NetworkRequest.Builder()
1456                     .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
1457                     .removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
1458                     .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN)
1459                     .build();
1460             mDunTetheringCallback = new UpstreamNetworkCallback();
1461             getConnectivityManager().registerNetworkCallback(
1462                     dunTetheringRequest, mDunTetheringCallback);
1463         }
1464 
stop()1465         void stop() {
1466             if (mDefaultNetworkCallback != null) {
1467                 getConnectivityManager().unregisterNetworkCallback(mDefaultNetworkCallback);
1468                 mDefaultNetworkCallback = null;
1469             }
1470 
1471             if (mDunTetheringCallback != null) {
1472                 getConnectivityManager().unregisterNetworkCallback(mDunTetheringCallback);
1473                 mDunTetheringCallback = null;
1474             }
1475 
1476             mNetworkMap.clear();
1477         }
1478 
1479         // Returns true if these updated LinkProperties pertain to the current
1480         // upstream network interface, false otherwise (or if there is not
1481         // currently any upstream tethering interface).
processLinkPropertiesChanged(NetworkState networkState)1482         boolean processLinkPropertiesChanged(NetworkState networkState) {
1483             if (networkState == null ||
1484                     networkState.network == null ||
1485                     networkState.linkProperties == null) {
1486                 return false;
1487             }
1488 
1489             mNetworkMap.put(networkState.network, networkState);
1490 
1491             if (mCurrentUpstreamIface != null) {
1492                 for (String ifname : networkState.linkProperties.getAllInterfaceNames()) {
1493                     if (mCurrentUpstreamIface.equals(ifname)) {
1494                         return true;
1495                     }
1496                 }
1497             }
1498             return false;
1499         }
1500 
processNetworkLost(Network network)1501         void processNetworkLost(Network network) {
1502             if (network != null) {
1503                 mNetworkMap.remove(network);
1504             }
1505         }
1506     }
1507 
1508     class TetherMasterSM extends StateMachine {
1509         private static final int BASE_MASTER                    = Protocol.BASE_TETHERING;
1510         // an interface SM has requested Tethering
1511         static final int CMD_TETHER_MODE_REQUESTED              = BASE_MASTER + 1;
1512         // an interface SM has unrequested Tethering
1513         static final int CMD_TETHER_MODE_UNREQUESTED            = BASE_MASTER + 2;
1514         // upstream connection change - do the right thing
1515         static final int CMD_UPSTREAM_CHANGED                   = BASE_MASTER + 3;
1516         // we don't have a valid upstream conn, check again after a delay
1517         static final int CMD_RETRY_UPSTREAM                     = BASE_MASTER + 4;
1518         // Events from NetworkCallbacks that we process on the master state
1519         // machine thread on behalf of the UpstreamNetworkMonitor.
1520         static final int EVENT_UPSTREAM_LINKPROPERTIES_CHANGED  = BASE_MASTER + 5;
1521         static final int EVENT_UPSTREAM_LOST                    = BASE_MASTER + 6;
1522 
1523         // This indicates what a timeout event relates to.  A state that
1524         // sends itself a delayed timeout event and handles incoming timeout events
1525         // should inc this when it is entered and whenever it sends a new timeout event.
1526         // We do not flush the old ones.
1527         private int mSequenceNumber;
1528 
1529         private State mInitialState;
1530         private State mTetherModeAliveState;
1531 
1532         private State mSetIpForwardingEnabledErrorState;
1533         private State mSetIpForwardingDisabledErrorState;
1534         private State mStartTetheringErrorState;
1535         private State mStopTetheringErrorState;
1536         private State mSetDnsForwardersErrorState;
1537 
1538         private ArrayList<TetherInterfaceSM> mNotifyList;
1539 
1540         private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;
1541         private NetworkCallback mMobileUpstreamCallback;
1542 
1543         private static final int UPSTREAM_SETTLE_TIME_MS     = 10000;
1544 
TetherMasterSM(String name, Looper looper)1545         TetherMasterSM(String name, Looper looper) {
1546             super(name, looper);
1547 
1548             //Add states
1549             mInitialState = new InitialState();
1550             addState(mInitialState);
1551             mTetherModeAliveState = new TetherModeAliveState();
1552             addState(mTetherModeAliveState);
1553 
1554             mSetIpForwardingEnabledErrorState = new SetIpForwardingEnabledErrorState();
1555             addState(mSetIpForwardingEnabledErrorState);
1556             mSetIpForwardingDisabledErrorState = new SetIpForwardingDisabledErrorState();
1557             addState(mSetIpForwardingDisabledErrorState);
1558             mStartTetheringErrorState = new StartTetheringErrorState();
1559             addState(mStartTetheringErrorState);
1560             mStopTetheringErrorState = new StopTetheringErrorState();
1561             addState(mStopTetheringErrorState);
1562             mSetDnsForwardersErrorState = new SetDnsForwardersErrorState();
1563             addState(mSetDnsForwardersErrorState);
1564 
1565             mNotifyList = new ArrayList<TetherInterfaceSM>();
1566             setInitialState(mInitialState);
1567         }
1568 
1569         class TetherMasterUtilState extends State {
1570             @Override
processMessage(Message m)1571             public boolean processMessage(Message m) {
1572                 return false;
1573             }
1574 
turnOnUpstreamMobileConnection(int apnType)1575             protected boolean turnOnUpstreamMobileConnection(int apnType) {
1576                 if (apnType == ConnectivityManager.TYPE_NONE) { return false; }
1577 
1578                 if (apnType != mMobileApnReserved) {
1579                     // Unregister any previous mobile upstream callback because
1580                     // this request, if any, will be different.
1581                     turnOffUpstreamMobileConnection();
1582                 }
1583 
1584                 if (mMobileUpstreamCallback != null) {
1585                     // Looks like we already filed a request for this apnType.
1586                     return true;
1587                 }
1588 
1589                 switch (apnType) {
1590                     case ConnectivityManager.TYPE_MOBILE_DUN:
1591                     case ConnectivityManager.TYPE_MOBILE:
1592                     case ConnectivityManager.TYPE_MOBILE_HIPRI:
1593                         mMobileApnReserved = apnType;
1594                         break;
1595                     default:
1596                         return false;
1597                 }
1598 
1599                 final NetworkRequest.Builder builder = new NetworkRequest.Builder()
1600                         .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
1601                 if (apnType == ConnectivityManager.TYPE_MOBILE_DUN) {
1602                     builder.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED)
1603                            .addCapability(NetworkCapabilities.NET_CAPABILITY_DUN);
1604                 } else {
1605                     builder.addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
1606                 }
1607                 final NetworkRequest mobileUpstreamRequest = builder.build();
1608 
1609                 // The UpstreamNetworkMonitor's callback will be notified.
1610                 // Therefore, to avoid duplicate notifications, we only register a no-op.
1611                 mMobileUpstreamCallback = new NetworkCallback();
1612 
1613                 // TODO: Change the timeout from 0 (no onUnavailable callback) to use some
1614                 // moderate callback time (once timeout callbacks are implemented). This might
1615                 // be useful for updating some UI. Additionally, we should definitely log a
1616                 // message to aid in any subsequent debugging
1617                 if (DBG) Log.d(TAG, "requesting mobile upstream network: " + mobileUpstreamRequest);
1618                 getConnectivityManager().requestNetwork(
1619                         mobileUpstreamRequest, mMobileUpstreamCallback, 0, apnType);
1620                 return true;
1621             }
1622 
turnOffUpstreamMobileConnection()1623             protected void turnOffUpstreamMobileConnection() {
1624                 if (mMobileUpstreamCallback != null) {
1625                     getConnectivityManager().unregisterNetworkCallback(mMobileUpstreamCallback);
1626                     mMobileUpstreamCallback = null;
1627                 }
1628                 mMobileApnReserved = ConnectivityManager.TYPE_NONE;
1629             }
1630 
turnOnMasterTetherSettings()1631             protected boolean turnOnMasterTetherSettings() {
1632                 try {
1633                     mNMService.setIpForwardingEnabled(true);
1634                 } catch (Exception e) {
1635                     transitionTo(mSetIpForwardingEnabledErrorState);
1636                     return false;
1637                 }
1638                 try {
1639                     mNMService.startTethering(mDhcpRange);
1640                 } catch (Exception e) {
1641                     try {
1642                         mNMService.stopTethering();
1643                         mNMService.startTethering(mDhcpRange);
1644                     } catch (Exception ee) {
1645                         transitionTo(mStartTetheringErrorState);
1646                         return false;
1647                     }
1648                 }
1649                 return true;
1650             }
1651 
turnOffMasterTetherSettings()1652             protected boolean turnOffMasterTetherSettings() {
1653                 try {
1654                     mNMService.stopTethering();
1655                 } catch (Exception e) {
1656                     transitionTo(mStopTetheringErrorState);
1657                     return false;
1658                 }
1659                 try {
1660                     mNMService.setIpForwardingEnabled(false);
1661                 } catch (Exception e) {
1662                     transitionTo(mSetIpForwardingDisabledErrorState);
1663                     return false;
1664                 }
1665                 transitionTo(mInitialState);
1666                 return true;
1667             }
1668 
chooseUpstreamType(boolean tryCell)1669             protected void chooseUpstreamType(boolean tryCell) {
1670                 int upType = ConnectivityManager.TYPE_NONE;
1671                 String iface = null;
1672 
1673                 updateConfiguration(); // TODO - remove?
1674 
1675                 synchronized (mPublicSync) {
1676                     if (VDBG) {
1677                         Log.d(TAG, "chooseUpstreamType has upstream iface types:");
1678                         for (Integer netType : mUpstreamIfaceTypes) {
1679                             Log.d(TAG, " " + netType);
1680                         }
1681                     }
1682 
1683                     for (Integer netType : mUpstreamIfaceTypes) {
1684                         NetworkInfo info =
1685                                 getConnectivityManager().getNetworkInfo(netType.intValue());
1686                         if ((info != null) && info.isConnected()) {
1687                             upType = netType.intValue();
1688                             break;
1689                         }
1690                     }
1691                 }
1692 
1693                 if (DBG) {
1694                     Log.d(TAG, "chooseUpstreamType(" + tryCell + "),"
1695                             + " preferredApn="
1696                             + ConnectivityManager.getNetworkTypeName(mPreferredUpstreamMobileApn)
1697                             + ", got type="
1698                             + ConnectivityManager.getNetworkTypeName(upType));
1699                 }
1700 
1701                 switch (upType) {
1702                     case ConnectivityManager.TYPE_MOBILE_DUN:
1703                     case ConnectivityManager.TYPE_MOBILE_HIPRI:
1704                         // If we're on DUN, put our own grab on it.
1705                         turnOnUpstreamMobileConnection(upType);
1706                         break;
1707                     case ConnectivityManager.TYPE_NONE:
1708                         if (tryCell &&
1709                                 turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn)) {
1710                             // We think mobile should be coming up; don't set a retry.
1711                         } else {
1712                             sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
1713                         }
1714                         break;
1715                     default:
1716                         /* If we've found an active upstream connection that's not DUN/HIPRI
1717                          * we should stop any outstanding DUN/HIPRI start requests.
1718                          *
1719                          * If we found NONE we don't want to do this as we want any previous
1720                          * requests to keep trying to bring up something we can use.
1721                          */
1722                         turnOffUpstreamMobileConnection();
1723                         break;
1724                 }
1725 
1726                 if (upType != ConnectivityManager.TYPE_NONE) {
1727                     LinkProperties linkProperties =
1728                             getConnectivityManager().getLinkProperties(upType);
1729                     if (linkProperties != null) {
1730                         // Find the interface with the default IPv4 route. It may be the
1731                         // interface described by linkProperties, or one of the interfaces
1732                         // stacked on top of it.
1733                         Log.i(TAG, "Finding IPv4 upstream interface on: " + linkProperties);
1734                         RouteInfo ipv4Default = RouteInfo.selectBestRoute(
1735                             linkProperties.getAllRoutes(), Inet4Address.ANY);
1736                         if (ipv4Default != null) {
1737                             iface = ipv4Default.getInterface();
1738                             Log.i(TAG, "Found interface " + ipv4Default.getInterface());
1739                         } else {
1740                             Log.i(TAG, "No IPv4 upstream interface, giving up.");
1741                         }
1742                     }
1743 
1744                     if (iface != null) {
1745                         Network network = getConnectivityManager().getNetworkForType(upType);
1746                         if (network == null) {
1747                             Log.e(TAG, "No Network for upstream type " + upType + "!");
1748                         }
1749                         setDnsForwarders(network, linkProperties);
1750                     }
1751                 }
1752                 notifyTetheredOfNewUpstreamIface(iface);
1753             }
1754 
setDnsForwarders(final Network network, final LinkProperties lp)1755             protected void setDnsForwarders(final Network network, final LinkProperties lp) {
1756                 String[] dnsServers = mDefaultDnsServers;
1757                 final Collection<InetAddress> dnses = lp.getDnsServers();
1758                 // TODO: Properly support the absence of DNS servers.
1759                 if (dnses != null && !dnses.isEmpty()) {
1760                     // TODO: remove this invocation of NetworkUtils.makeStrings().
1761                     dnsServers = NetworkUtils.makeStrings(dnses);
1762                 }
1763                 if (VDBG) {
1764                     Log.d(TAG, "Setting DNS forwarders: Network=" + network +
1765                            ", dnsServers=" + Arrays.toString(dnsServers));
1766                 }
1767                 try {
1768                     mNMService.setDnsForwarders(network, dnsServers);
1769                 } catch (Exception e) {
1770                     // TODO: Investigate how this can fail and what exactly
1771                     // happens if/when such failures occur.
1772                     Log.e(TAG, "Setting DNS forwarders failed!");
1773                     transitionTo(mSetDnsForwardersErrorState);
1774                 }
1775             }
1776 
notifyTetheredOfNewUpstreamIface(String ifaceName)1777             protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
1778                 if (DBG) Log.d(TAG, "Notifying tethered with upstream=" + ifaceName);
1779                 mCurrentUpstreamIface = ifaceName;
1780                 for (TetherInterfaceSM sm : mNotifyList) {
1781                     sm.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1782                             ifaceName);
1783                 }
1784             }
1785         }
1786 
1787         private final AtomicInteger mSimBcastGenerationNumber = new AtomicInteger(0);
1788         private SimChangeBroadcastReceiver mBroadcastReceiver = null;
1789 
startListeningForSimChanges()1790         private void startListeningForSimChanges() {
1791             if (DBG) Log.d(TAG, "startListeningForSimChanges");
1792             if (mBroadcastReceiver == null) {
1793                 mBroadcastReceiver = new SimChangeBroadcastReceiver(
1794                         mSimBcastGenerationNumber.incrementAndGet());
1795                 final IntentFilter filter = new IntentFilter();
1796                 filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
1797 
1798                 mContext.registerReceiver(mBroadcastReceiver, filter);
1799             }
1800         }
1801 
stopListeningForSimChanges()1802         private void stopListeningForSimChanges() {
1803             if (DBG) Log.d(TAG, "stopListeningForSimChanges");
1804             if (mBroadcastReceiver != null) {
1805                 mSimBcastGenerationNumber.incrementAndGet();
1806                 mContext.unregisterReceiver(mBroadcastReceiver);
1807                 mBroadcastReceiver = null;
1808             }
1809         }
1810 
1811         class SimChangeBroadcastReceiver extends BroadcastReceiver {
1812             // used to verify this receiver is still current
1813             final private int mGenerationNumber;
1814 
1815             // we're interested in edge-triggered LOADED notifications, so
1816             // ignore LOADED unless we saw an ABSENT state first
1817             private boolean mSimAbsentSeen = false;
1818 
SimChangeBroadcastReceiver(int generationNumber)1819             public SimChangeBroadcastReceiver(int generationNumber) {
1820                 super();
1821                 mGenerationNumber = generationNumber;
1822             }
1823 
1824             @Override
onReceive(Context context, Intent intent)1825             public void onReceive(Context context, Intent intent) {
1826                 if (DBG) {
1827                     Log.d(TAG, "simchange mGenerationNumber=" + mGenerationNumber +
1828                             ", current generationNumber=" + mSimBcastGenerationNumber.get());
1829                 }
1830                 if (mGenerationNumber != mSimBcastGenerationNumber.get()) return;
1831 
1832                 final String state =
1833                         intent.getStringExtra(IccCardConstants.INTENT_KEY_ICC_STATE);
1834 
1835                 Log.d(TAG, "got Sim changed to state " + state + ", mSimAbsentSeen=" +
1836                         mSimAbsentSeen);
1837                 if (!mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_ABSENT.equals(state)) {
1838                     mSimAbsentSeen = true;
1839                 }
1840 
1841                 if (mSimAbsentSeen && IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state)) {
1842                     mSimAbsentSeen = false;
1843                     try {
1844                         if (mContext.getResources().getString(com.android.internal.R.string.
1845                                 config_mobile_hotspot_provision_app_no_ui).isEmpty() == false) {
1846                             ArrayList<Integer> tethered = new ArrayList<Integer>();
1847                             synchronized (mPublicSync) {
1848                                 Set ifaces = mIfaces.keySet();
1849                                 for (Object iface : ifaces) {
1850                                     TetherInterfaceSM sm = mIfaces.get(iface);
1851                                     if (sm != null && sm.isTethered()) {
1852                                         if (isUsb((String)iface)) {
1853                                             tethered.add(new Integer(
1854                                                     ConnectivityManager.TETHERING_USB));
1855                                         } else if (isWifi((String)iface)) {
1856                                             tethered.add(new Integer(
1857                                                     ConnectivityManager.TETHERING_WIFI));
1858                                         } else if (isBluetooth((String)iface)) {
1859                                             tethered.add(new Integer(
1860                                                     ConnectivityManager.TETHERING_BLUETOOTH));
1861                                         }
1862                                     }
1863                                 }
1864                             }
1865                             for (int tetherType : tethered) {
1866                                 Intent startProvIntent = new Intent();
1867                                 startProvIntent.putExtra(
1868                                         ConnectivityManager.EXTRA_ADD_TETHER_TYPE, tetherType);
1869                                 startProvIntent.putExtra(
1870                                         ConnectivityManager.EXTRA_RUN_PROVISION, true);
1871                                 startProvIntent.setComponent(TETHER_SERVICE);
1872                                 mContext.startServiceAsUser(startProvIntent, UserHandle.CURRENT);
1873                             }
1874                             Log.d(TAG, "re-evaluate provisioning");
1875                         } else {
1876                             Log.d(TAG, "no prov-check needed for new SIM");
1877                         }
1878                     } catch (Resources.NotFoundException e) {
1879                         Log.d(TAG, "no prov-check needed for new SIM");
1880                         // not defined, do nothing
1881                     }
1882                 }
1883             }
1884         }
1885 
1886         class InitialState extends TetherMasterUtilState {
1887             @Override
enter()1888             public void enter() {
1889             }
1890             @Override
processMessage(Message message)1891             public boolean processMessage(Message message) {
1892                 maybeLogMessage(this, message.what);
1893                 boolean retValue = true;
1894                 switch (message.what) {
1895                     case CMD_TETHER_MODE_REQUESTED:
1896                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1897                         if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1898                         mNotifyList.add(who);
1899                         transitionTo(mTetherModeAliveState);
1900                         break;
1901                     case CMD_TETHER_MODE_UNREQUESTED:
1902                         who = (TetherInterfaceSM)message.obj;
1903                         if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1904                         int index = mNotifyList.indexOf(who);
1905                         if (index != -1) {
1906                             mNotifyList.remove(who);
1907                         }
1908                         break;
1909                     default:
1910                         retValue = false;
1911                         break;
1912                 }
1913                 return retValue;
1914             }
1915         }
1916 
1917         class TetherModeAliveState extends TetherMasterUtilState {
1918             boolean mTryCell = true;
1919             @Override
enter()1920             public void enter() {
1921                 // TODO: examine if we should check the return value.
1922                 turnOnMasterTetherSettings(); // may transition us out
1923                 startListeningForSimChanges();
1924                 mUpstreamNetworkMonitor.start();
1925 
1926                 mTryCell = true;  // better try something first pass or crazy tests cases will fail
1927                 chooseUpstreamType(mTryCell);
1928                 mTryCell = !mTryCell;
1929             }
1930             @Override
exit()1931             public void exit() {
1932                 // TODO: examine if we should check the return value.
1933                 turnOffUpstreamMobileConnection();
1934                 mUpstreamNetworkMonitor.stop();
1935                 stopListeningForSimChanges();
1936                 notifyTetheredOfNewUpstreamIface(null);
1937             }
1938             @Override
processMessage(Message message)1939             public boolean processMessage(Message message) {
1940                 maybeLogMessage(this, message.what);
1941                 boolean retValue = true;
1942                 switch (message.what) {
1943                     case CMD_TETHER_MODE_REQUESTED:
1944                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
1945                         if (VDBG) Log.d(TAG, "Tether Mode requested by " + who);
1946                         mNotifyList.add(who);
1947                         who.sendMessage(TetherInterfaceSM.CMD_TETHER_CONNECTION_CHANGED,
1948                                 mCurrentUpstreamIface);
1949                         break;
1950                     case CMD_TETHER_MODE_UNREQUESTED:
1951                         who = (TetherInterfaceSM)message.obj;
1952                         if (VDBG) Log.d(TAG, "Tether Mode unrequested by " + who);
1953                         int index = mNotifyList.indexOf(who);
1954                         if (index != -1) {
1955                             if (DBG) Log.d(TAG, "TetherModeAlive removing notifyee " + who);
1956                             mNotifyList.remove(index);
1957                             if (mNotifyList.isEmpty()) {
1958                                 turnOffMasterTetherSettings(); // transitions appropriately
1959                             } else {
1960                                 if (DBG) {
1961                                     Log.d(TAG, "TetherModeAlive still has " + mNotifyList.size() +
1962                                             " live requests:");
1963                                     for (Object o : mNotifyList) Log.d(TAG, "  " + o);
1964                                 }
1965                             }
1966                         } else {
1967                            Log.e(TAG, "TetherModeAliveState UNREQUESTED has unknown who: " + who);
1968                         }
1969                         break;
1970                     case CMD_UPSTREAM_CHANGED:
1971                         // need to try DUN immediately if Wifi goes down
1972                         mTryCell = true;
1973                         chooseUpstreamType(mTryCell);
1974                         mTryCell = !mTryCell;
1975                         break;
1976                     case CMD_RETRY_UPSTREAM:
1977                         chooseUpstreamType(mTryCell);
1978                         mTryCell = !mTryCell;
1979                         break;
1980                     case EVENT_UPSTREAM_LINKPROPERTIES_CHANGED:
1981                         NetworkState state = (NetworkState) message.obj;
1982                         if (mUpstreamNetworkMonitor.processLinkPropertiesChanged(state)) {
1983                             setDnsForwarders(state.network, state.linkProperties);
1984                         } else if (mCurrentUpstreamIface == null) {
1985                             // If we have no upstream interface, try to run through upstream
1986                             // selection again.  If, for example, IPv4 connectivity has shown up
1987                             // after IPv6 (e.g., 464xlat became available) we want the chance to
1988                             // notice and act accordingly.
1989                             chooseUpstreamType(false);
1990                         }
1991                         break;
1992                     case EVENT_UPSTREAM_LOST:
1993                         // TODO: Re-evaluate possible upstreams. Currently upstream reevaluation
1994                         // is triggered via received CONNECTIVITY_ACTION broadcasts that result
1995                         // in being passed a TetherMasterSM.CMD_UPSTREAM_CHANGED.
1996                         mUpstreamNetworkMonitor.processNetworkLost((Network) message.obj);
1997                         break;
1998                     default:
1999                         retValue = false;
2000                         break;
2001                 }
2002                 return retValue;
2003             }
2004         }
2005 
2006         class ErrorState extends State {
2007             int mErrorNotification;
2008             @Override
processMessage(Message message)2009             public boolean processMessage(Message message) {
2010                 boolean retValue = true;
2011                 switch (message.what) {
2012                     case CMD_TETHER_MODE_REQUESTED:
2013                         TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
2014                         who.sendMessage(mErrorNotification);
2015                         break;
2016                     default:
2017                        retValue = false;
2018                 }
2019                 return retValue;
2020             }
notify(int msgType)2021             void notify(int msgType) {
2022                 mErrorNotification = msgType;
2023                 for (Object o : mNotifyList) {
2024                     TetherInterfaceSM sm = (TetherInterfaceSM)o;
2025                     sm.sendMessage(msgType);
2026                 }
2027             }
2028 
2029         }
2030         class SetIpForwardingEnabledErrorState extends ErrorState {
2031             @Override
enter()2032             public void enter() {
2033                 Log.e(TAG, "Error in setIpForwardingEnabled");
2034                 notify(TetherInterfaceSM.CMD_IP_FORWARDING_ENABLE_ERROR);
2035             }
2036         }
2037 
2038         class SetIpForwardingDisabledErrorState extends ErrorState {
2039             @Override
enter()2040             public void enter() {
2041                 Log.e(TAG, "Error in setIpForwardingDisabled");
2042                 notify(TetherInterfaceSM.CMD_IP_FORWARDING_DISABLE_ERROR);
2043             }
2044         }
2045 
2046         class StartTetheringErrorState extends ErrorState {
2047             @Override
enter()2048             public void enter() {
2049                 Log.e(TAG, "Error in startTethering");
2050                 notify(TetherInterfaceSM.CMD_START_TETHERING_ERROR);
2051                 try {
2052                     mNMService.setIpForwardingEnabled(false);
2053                 } catch (Exception e) {}
2054             }
2055         }
2056 
2057         class StopTetheringErrorState extends ErrorState {
2058             @Override
enter()2059             public void enter() {
2060                 Log.e(TAG, "Error in stopTethering");
2061                 notify(TetherInterfaceSM.CMD_STOP_TETHERING_ERROR);
2062                 try {
2063                     mNMService.setIpForwardingEnabled(false);
2064                 } catch (Exception e) {}
2065             }
2066         }
2067 
2068         class SetDnsForwardersErrorState extends ErrorState {
2069             @Override
enter()2070             public void enter() {
2071                 Log.e(TAG, "Error in setDnsForwarders");
2072                 notify(TetherInterfaceSM.CMD_SET_DNS_FORWARDERS_ERROR);
2073                 try {
2074                     mNMService.stopTethering();
2075                 } catch (Exception e) {}
2076                 try {
2077                     mNMService.setIpForwardingEnabled(false);
2078                 } catch (Exception e) {}
2079             }
2080         }
2081     }
2082 
dump(FileDescriptor fd, PrintWriter writer, String[] args)2083     public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
2084         final IndentingPrintWriter pw = new IndentingPrintWriter(writer, "  ");
2085 
2086         if (mContext.checkCallingOrSelfPermission(
2087                 android.Manifest.permission.DUMP) != PackageManager.PERMISSION_GRANTED) {
2088             pw.println("Permission Denial: can't dump ConnectivityService.Tether " +
2089                     "from from pid=" + Binder.getCallingPid() + ", uid=" +
2090                     Binder.getCallingUid());
2091                     return;
2092         }
2093 
2094         pw.println("Tethering:");
2095         pw.increaseIndent();
2096         pw.print("mUpstreamIfaceTypes:");
2097         synchronized (mPublicSync) {
2098             for (Integer netType : mUpstreamIfaceTypes) {
2099                 pw.print(" " + ConnectivityManager.getNetworkTypeName(netType));
2100             }
2101             pw.println();
2102 
2103             pw.println("Tether state:");
2104             pw.increaseIndent();
2105             for (Object o : mIfaces.values()) {
2106                 pw.println(o);
2107             }
2108             pw.decreaseIndent();
2109         }
2110         pw.decreaseIndent();
2111         return;
2112     }
2113 }
2114