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