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