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