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