Home | History | Annotate | Download | only in connectivity
      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 
    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 
    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 
    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.
    228     private ConnectivityManager getConnectivityManager() {
    229         return (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
    230     }
    231 
    232     private WifiManager getWifiManager() {
    233         return (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
    234     }
    235 
    236     private void updateConfiguration() {
    237         mConfig = new TetheringConfiguration(mContext);
    238     }
    239 
    240     @Override
    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
    263     public void interfaceLinkStateChanged(String iface, boolean up) {
    264         interfaceStatusChanged(iface, up);
    265     }
    266 
    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
    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
    289     public void interfaceRemoved(String iface) {
    290         if (VDBG) Log.d(TAG, "interfaceRemoved " + iface);
    291         synchronized (mPublicSync) {
    292             stopTrackingInterfaceLocked(iface);
    293         }
    294     }
    295 
    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 
    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
    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      */
    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 
    376     private void sendTetherResult(ResultReceiver receiver, int result) {
    377         if (receiver != null) {
    378             receiver.send(result, null);
    379         }
    380     }
    381 
    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 
    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 
    430     private void runUiTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
    431         ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
    432         sendUiTetherProvisionIntent(type, proxyReceiver);
    433     }
    434 
    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      */
    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 
    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 
    491     private void runSilentTetherProvisioningAndEnable(int type, ResultReceiver receiver) {
    492         ResultReceiver proxyReceiver = getProxyReceiver(type, receiver);
    493         sendSilentTetherProvisionIntent(type, proxyReceiver);
    494     }
    495 
    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 
    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 
    524     public int tether(String iface) {
    525         return tether(iface, IControlsTethering.STATE_TETHERED);
    526     }
    527 
    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 
    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 
    571     public void untetherAll() {
    572         stopTethering(ConnectivityManager.TETHERING_WIFI);
    573         stopTethering(ConnectivityManager.TETHERING_USB);
    574         stopTethering(ConnectivityManager.TETHERING_BLUETOOTH);
    575     }
    576 
    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.
    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 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    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
    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 
    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 
    914     public TetheringConfiguration getTetheringConfiguration() {
    915         return mConfig;
    916     }
    917 
    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.
    931     public String[] getTetherableUsbRegexs() {
    932         return copy(mConfig.tetherableUsbRegexs);
    933     }
    934 
    935     public String[] getTetherableWifiRegexs() {
    936         return copy(mConfig.tetherableWifiRegexs);
    937     }
    938 
    939     public String[] getTetherableBluetoothRegexs() {
    940         return copy(mConfig.tetherableBluetoothRegexs);
    941     }
    942 
    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.
    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 
    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 
   1005     public String[] getTetheredDhcpRanges() {
   1006         return mConfig.dhcpRanges;
   1007     }
   1008 
   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 
   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 
   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.
   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 
   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
   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
   1143             public boolean processMessage(Message m) {
   1144                 return false;
   1145             }
   1146 
   1147             protected void requestUpstreamMobileConnection() {
   1148                 mUpstreamNetworkMonitor.updateMobileRequiresDun(mConfig.isDunRequired);
   1149                 mUpstreamNetworkMonitor.registerMobileNetworkRequest();
   1150             }
   1151 
   1152             protected void unrequestUpstreamMobileConnection() {
   1153                 mUpstreamNetworkMonitor.releaseMobileNetworkRequest();
   1154             }
   1155 
   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 
   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 
   1203             protected void chooseUpstreamType(boolean tryCell) {
   1204                 final int upstreamType = findPreferredUpstreamType(tryCell);
   1205                 setUpstreamByType(upstreamType);
   1206             }
   1207 
   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 
   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 
   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 
   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 
   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 
   1357             SimChangeListener(Context ctx) {
   1358                 mContext = ctx;
   1359                 mSimBcastGenerationNumber = new AtomicInteger(0);
   1360             }
   1361 
   1362             public int generationNumber() {
   1363                 return mSimBcastGenerationNumber.get();
   1364             }
   1365 
   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 
   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 
   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 
   1402             private boolean isSimCardLoaded(String state) {
   1403                 return IccCardConstants.INTENT_VALUE_ICC_LOADED.equals(state);
   1404             }
   1405 
   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 
   1421                 public SimChangeBroadcastReceiver(int generationNumber) {
   1422                     mGenerationNumber = generationNumber;
   1423                 }
   1424 
   1425                 @Override
   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 
   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 
   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
   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
   1542             public void exit() {
   1543                 mOffloadController.stop();
   1544                 unrequestUpstreamMobileConnection();
   1545                 mUpstreamNetworkMonitor.stop();
   1546                 simChange.stopListening();
   1547                 notifyTetheredOfNewUpstreamIface(null);
   1548                 handleNewUpstreamNetworkState(null);
   1549             }
   1550 
   1551             private boolean updateUpstreamWanted() {
   1552                 final boolean previousUpstreamWanted = mUpstreamWanted;
   1553                 mUpstreamWanted = upstreamWanted();
   1554                 return previousUpstreamWanted;
   1555             }
   1556 
   1557             @Override
   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
   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 
   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
   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
   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
   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
   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
   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
   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 
   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
   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 
   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 
   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 
   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 
   1910     private static String[] copy(String[] strarray) {
   1911         return Arrays.copyOf(strarray, strarray.length);
   1912     }
   1913 }
   1914