Home | History | Annotate | Download | only in settings
      1 /*
      2  * Copyright (C) 2008 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.settings;
     18 
     19 import com.android.settings.wifi.WifiApEnabler;
     20 import com.android.settings.wifi.WifiApDialog;
     21 
     22 import android.app.Activity;
     23 import android.app.AlertDialog;
     24 import android.app.Dialog;
     25 import android.bluetooth.BluetoothAdapter;
     26 import android.bluetooth.BluetoothPan;
     27 import android.bluetooth.BluetoothProfile;
     28 import android.content.BroadcastReceiver;
     29 import android.content.Context;
     30 import android.content.DialogInterface;
     31 import android.content.Intent;
     32 import android.content.IntentFilter;
     33 import android.content.pm.PackageManager;
     34 import android.content.res.AssetManager;
     35 import android.hardware.usb.UsbManager;
     36 import android.net.ConnectivityManager;
     37 import android.net.wifi.WifiConfiguration;
     38 import android.net.wifi.WifiManager;
     39 import android.os.Bundle;
     40 import android.os.Environment;
     41 import android.os.SystemProperties;
     42 import android.os.UserHandle;
     43 import android.os.UserManager;
     44 import android.preference.Preference;
     45 import android.preference.PreferenceScreen;
     46 import android.preference.SwitchPreference;
     47 import android.text.TextUtils;
     48 import android.view.ViewGroup;
     49 import android.view.ViewParent;
     50 import android.webkit.WebView;
     51 import android.widget.TextView;
     52 
     53 import java.io.InputStream;
     54 import java.util.ArrayList;
     55 import java.util.concurrent.atomic.AtomicReference;
     56 import java.util.Locale;
     57 
     58 /*
     59  * Displays preferences for Tethering.
     60  */
     61 public class TetherSettings extends SettingsPreferenceFragment
     62         implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener {
     63     private static final String TAG = "TetherSettings";
     64 
     65     private static final String USB_TETHER_SETTINGS = "usb_tether_settings";
     66     private static final String ENABLE_WIFI_AP = "enable_wifi_ap";
     67     private static final String ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering";
     68     private static final String TETHER_CHOICE = "TETHER_TYPE";
     69 
     70     private static final int DIALOG_AP_SETTINGS = 1;
     71 
     72     private WebView mView;
     73     private SwitchPreference mUsbTether;
     74 
     75     private WifiApEnabler mWifiApEnabler;
     76     private SwitchPreference mEnableWifiAp;
     77 
     78     private SwitchPreference mBluetoothTether;
     79 
     80     private BroadcastReceiver mTetherChangeReceiver;
     81 
     82     private String[] mUsbRegexs;
     83 
     84     private String[] mWifiRegexs;
     85 
     86     private String[] mBluetoothRegexs;
     87     private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<BluetoothPan>();
     88 
     89     private static final String WIFI_AP_SSID_AND_SECURITY = "wifi_ap_ssid_and_security";
     90     private static final int CONFIG_SUBTEXT = R.string.wifi_tether_configure_subtext;
     91 
     92     private String[] mSecurityType;
     93     private Preference mCreateNetwork;
     94 
     95     private WifiApDialog mDialog;
     96     private WifiManager mWifiManager;
     97     private WifiConfiguration mWifiConfig = null;
     98     private UserManager mUm;
     99 
    100     private boolean mUsbConnected;
    101     private boolean mMassStorageActive;
    102 
    103     private boolean mBluetoothEnableForTether;
    104 
    105     private static final int INVALID             = -1;
    106     private static final int WIFI_TETHERING      = 0;
    107     private static final int USB_TETHERING       = 1;
    108     private static final int BLUETOOTH_TETHERING = 2;
    109 
    110     /* One of INVALID, WIFI_TETHERING, USB_TETHERING or BLUETOOTH_TETHERING */
    111     private int mTetherChoice = INVALID;
    112 
    113     /* Stores the package name and the class name of the provisioning app */
    114     private String[] mProvisionApp;
    115     private static final int PROVISION_REQUEST = 0;
    116 
    117     private boolean mUnavailable;
    118 
    119     @Override
    120     public void onCreate(Bundle icicle) {
    121         super.onCreate(icicle);
    122 
    123         if(icicle != null) {
    124             mTetherChoice = icicle.getInt(TETHER_CHOICE);
    125         }
    126         addPreferencesFromResource(R.xml.tether_prefs);
    127 
    128         mUm = (UserManager) getSystemService(Context.USER_SERVICE);
    129 
    130         if (mUm.hasUserRestriction(UserManager.DISALLOW_CONFIG_TETHERING)) {
    131             mUnavailable = true;
    132             setPreferenceScreen(new PreferenceScreen(getActivity(), null));
    133             return;
    134         }
    135 
    136         final Activity activity = getActivity();
    137         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    138         if (adapter != null) {
    139             adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener,
    140                     BluetoothProfile.PAN);
    141         }
    142 
    143         mEnableWifiAp =
    144                 (SwitchPreference) findPreference(ENABLE_WIFI_AP);
    145         Preference wifiApSettings = findPreference(WIFI_AP_SSID_AND_SECURITY);
    146         mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS);
    147         mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING);
    148 
    149         ConnectivityManager cm =
    150                 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    151 
    152         mUsbRegexs = cm.getTetherableUsbRegexs();
    153         mWifiRegexs = cm.getTetherableWifiRegexs();
    154         mBluetoothRegexs = cm.getTetherableBluetoothRegexs();
    155 
    156         final boolean usbAvailable = mUsbRegexs.length != 0;
    157         final boolean wifiAvailable = mWifiRegexs.length != 0;
    158         final boolean bluetoothAvailable = mBluetoothRegexs.length != 0;
    159 
    160         if (!usbAvailable || Utils.isMonkeyRunning()) {
    161             getPreferenceScreen().removePreference(mUsbTether);
    162         }
    163 
    164         if (wifiAvailable && !Utils.isMonkeyRunning()) {
    165             mWifiApEnabler = new WifiApEnabler(activity, mEnableWifiAp);
    166             initWifiTethering();
    167         } else {
    168             getPreferenceScreen().removePreference(mEnableWifiAp);
    169             getPreferenceScreen().removePreference(wifiApSettings);
    170         }
    171 
    172         if (!bluetoothAvailable) {
    173             getPreferenceScreen().removePreference(mBluetoothTether);
    174         } else {
    175             BluetoothPan pan = mBluetoothPan.get();
    176             if (pan != null && pan.isTetheringOn()) {
    177                 mBluetoothTether.setChecked(true);
    178             } else {
    179                 mBluetoothTether.setChecked(false);
    180             }
    181         }
    182 
    183         mProvisionApp = getResources().getStringArray(
    184                 com.android.internal.R.array.config_mobile_hotspot_provision_app);
    185 
    186         mView = new WebView(activity);
    187     }
    188 
    189     @Override
    190     public void onSaveInstanceState(Bundle savedInstanceState) {
    191         savedInstanceState.putInt(TETHER_CHOICE, mTetherChoice);
    192         super.onSaveInstanceState(savedInstanceState);
    193     }
    194 
    195     private void initWifiTethering() {
    196         final Activity activity = getActivity();
    197         mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
    198         mWifiConfig = mWifiManager.getWifiApConfiguration();
    199         mSecurityType = getResources().getStringArray(R.array.wifi_ap_security);
    200 
    201         mCreateNetwork = findPreference(WIFI_AP_SSID_AND_SECURITY);
    202 
    203         if (mWifiConfig == null) {
    204             final String s = activity.getString(
    205                     com.android.internal.R.string.wifi_tether_configure_ssid_default);
    206             mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT),
    207                     s, mSecurityType[WifiApDialog.OPEN_INDEX]));
    208         } else {
    209             int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig);
    210             mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT),
    211                     mWifiConfig.SSID,
    212                     mSecurityType[index]));
    213         }
    214     }
    215 
    216     private BluetoothProfile.ServiceListener mProfileServiceListener =
    217         new BluetoothProfile.ServiceListener() {
    218         public void onServiceConnected(int profile, BluetoothProfile proxy) {
    219             mBluetoothPan.set((BluetoothPan) proxy);
    220         }
    221         public void onServiceDisconnected(int profile) {
    222             mBluetoothPan.set(null);
    223         }
    224     };
    225 
    226     @Override
    227     public Dialog onCreateDialog(int id) {
    228         if (id == DIALOG_AP_SETTINGS) {
    229             final Activity activity = getActivity();
    230             mDialog = new WifiApDialog(activity, this, mWifiConfig);
    231             return mDialog;
    232         }
    233 
    234         return null;
    235     }
    236 
    237     private class TetherChangeReceiver extends BroadcastReceiver {
    238         @Override
    239         public void onReceive(Context content, Intent intent) {
    240             String action = intent.getAction();
    241             if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
    242                 // TODO - this should understand the interface types
    243                 ArrayList<String> available = intent.getStringArrayListExtra(
    244                         ConnectivityManager.EXTRA_AVAILABLE_TETHER);
    245                 ArrayList<String> active = intent.getStringArrayListExtra(
    246                         ConnectivityManager.EXTRA_ACTIVE_TETHER);
    247                 ArrayList<String> errored = intent.getStringArrayListExtra(
    248                         ConnectivityManager.EXTRA_ERRORED_TETHER);
    249                 updateState(available.toArray(new String[available.size()]),
    250                         active.toArray(new String[active.size()]),
    251                         errored.toArray(new String[errored.size()]));
    252             } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) {
    253                 mMassStorageActive = true;
    254                 updateState();
    255             } else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) {
    256                 mMassStorageActive = false;
    257                 updateState();
    258             } else if (action.equals(UsbManager.ACTION_USB_STATE)) {
    259                 mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false);
    260                 updateState();
    261             } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
    262                 if (mBluetoothEnableForTether) {
    263                     switch (intent
    264                             .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) {
    265                         case BluetoothAdapter.STATE_ON:
    266                             BluetoothPan bluetoothPan = mBluetoothPan.get();
    267                             if (bluetoothPan != null) {
    268                                 bluetoothPan.setBluetoothTethering(true);
    269                                 mBluetoothEnableForTether = false;
    270                             }
    271                             break;
    272 
    273                         case BluetoothAdapter.STATE_OFF:
    274                         case BluetoothAdapter.ERROR:
    275                             mBluetoothEnableForTether = false;
    276                             break;
    277 
    278                         default:
    279                             // ignore transition states
    280                     }
    281                 }
    282                 updateState();
    283             }
    284         }
    285     }
    286 
    287     @Override
    288     public void onStart() {
    289         super.onStart();
    290 
    291         if (mUnavailable) {
    292             TextView emptyView = (TextView) getView().findViewById(android.R.id.empty);
    293             getListView().setEmptyView(emptyView);
    294             if (emptyView != null) {
    295                 emptyView.setText(R.string.tethering_settings_not_available);
    296             }
    297             return;
    298         }
    299 
    300         final Activity activity = getActivity();
    301 
    302         mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
    303         mTetherChangeReceiver = new TetherChangeReceiver();
    304         IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
    305         Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter);
    306 
    307         filter = new IntentFilter();
    308         filter.addAction(UsbManager.ACTION_USB_STATE);
    309         activity.registerReceiver(mTetherChangeReceiver, filter);
    310 
    311         filter = new IntentFilter();
    312         filter.addAction(Intent.ACTION_MEDIA_SHARED);
    313         filter.addAction(Intent.ACTION_MEDIA_UNSHARED);
    314         filter.addDataScheme("file");
    315         activity.registerReceiver(mTetherChangeReceiver, filter);
    316 
    317         filter = new IntentFilter();
    318         filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
    319         activity.registerReceiver(mTetherChangeReceiver, filter);
    320 
    321         if (intent != null) mTetherChangeReceiver.onReceive(activity, intent);
    322         if (mWifiApEnabler != null) {
    323             mEnableWifiAp.setOnPreferenceChangeListener(this);
    324             mWifiApEnabler.resume();
    325         }
    326 
    327         updateState();
    328     }
    329 
    330     @Override
    331     public void onStop() {
    332         super.onStop();
    333 
    334         if (mUnavailable) {
    335             return;
    336         }
    337         getActivity().unregisterReceiver(mTetherChangeReceiver);
    338         mTetherChangeReceiver = null;
    339         if (mWifiApEnabler != null) {
    340             mEnableWifiAp.setOnPreferenceChangeListener(null);
    341             mWifiApEnabler.pause();
    342         }
    343     }
    344 
    345     private void updateState() {
    346         ConnectivityManager cm =
    347                 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    348 
    349         String[] available = cm.getTetherableIfaces();
    350         String[] tethered = cm.getTetheredIfaces();
    351         String[] errored = cm.getTetheringErroredIfaces();
    352         updateState(available, tethered, errored);
    353     }
    354 
    355     private void updateState(String[] available, String[] tethered,
    356             String[] errored) {
    357         updateUsbState(available, tethered, errored);
    358         updateBluetoothState(available, tethered, errored);
    359     }
    360 
    361 
    362     private void updateUsbState(String[] available, String[] tethered,
    363             String[] errored) {
    364         ConnectivityManager cm =
    365                 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    366         boolean usbAvailable = mUsbConnected && !mMassStorageActive;
    367         int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR;
    368         for (String s : available) {
    369             for (String regex : mUsbRegexs) {
    370                 if (s.matches(regex)) {
    371                     if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
    372                         usbError = cm.getLastTetherError(s);
    373                     }
    374                 }
    375             }
    376         }
    377         boolean usbTethered = false;
    378         for (String s : tethered) {
    379             for (String regex : mUsbRegexs) {
    380                 if (s.matches(regex)) usbTethered = true;
    381             }
    382         }
    383         boolean usbErrored = false;
    384         for (String s: errored) {
    385             for (String regex : mUsbRegexs) {
    386                 if (s.matches(regex)) usbErrored = true;
    387             }
    388         }
    389 
    390         if (usbTethered) {
    391             mUsbTether.setSummary(R.string.usb_tethering_active_subtext);
    392             mUsbTether.setEnabled(true);
    393             mUsbTether.setChecked(true);
    394         } else if (usbAvailable) {
    395             if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) {
    396                 mUsbTether.setSummary(R.string.usb_tethering_available_subtext);
    397             } else {
    398                 mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
    399             }
    400             mUsbTether.setEnabled(true);
    401             mUsbTether.setChecked(false);
    402         } else if (usbErrored) {
    403             mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
    404             mUsbTether.setEnabled(false);
    405             mUsbTether.setChecked(false);
    406         } else if (mMassStorageActive) {
    407             mUsbTether.setSummary(R.string.usb_tethering_storage_active_subtext);
    408             mUsbTether.setEnabled(false);
    409             mUsbTether.setChecked(false);
    410         } else {
    411             mUsbTether.setSummary(R.string.usb_tethering_unavailable_subtext);
    412             mUsbTether.setEnabled(false);
    413             mUsbTether.setChecked(false);
    414         }
    415     }
    416 
    417     private void updateBluetoothState(String[] available, String[] tethered,
    418             String[] errored) {
    419         boolean bluetoothErrored = false;
    420         for (String s: errored) {
    421             for (String regex : mBluetoothRegexs) {
    422                 if (s.matches(regex)) bluetoothErrored = true;
    423             }
    424         }
    425 
    426         BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    427         if (adapter == null)
    428             return;
    429         int btState = adapter.getState();
    430         if (btState == BluetoothAdapter.STATE_TURNING_OFF) {
    431             mBluetoothTether.setEnabled(false);
    432             mBluetoothTether.setSummary(R.string.bluetooth_turning_off);
    433         } else if (btState == BluetoothAdapter.STATE_TURNING_ON) {
    434             mBluetoothTether.setEnabled(false);
    435             mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
    436         } else {
    437             BluetoothPan bluetoothPan = mBluetoothPan.get();
    438             if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null &&
    439                     bluetoothPan.isTetheringOn()) {
    440                 mBluetoothTether.setChecked(true);
    441                 mBluetoothTether.setEnabled(true);
    442                 int bluetoothTethered = bluetoothPan.getConnectedDevices().size();
    443                 if (bluetoothTethered > 1) {
    444                     String summary = getString(
    445                             R.string.bluetooth_tethering_devices_connected_subtext,
    446                             bluetoothTethered);
    447                     mBluetoothTether.setSummary(summary);
    448                 } else if (bluetoothTethered == 1) {
    449                     mBluetoothTether.setSummary(
    450                             R.string.bluetooth_tethering_device_connected_subtext);
    451                 } else if (bluetoothErrored) {
    452                     mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
    453                 } else {
    454                     mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
    455                 }
    456             } else {
    457                 mBluetoothTether.setEnabled(true);
    458                 mBluetoothTether.setChecked(false);
    459                 mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext);
    460             }
    461         }
    462     }
    463 
    464     public boolean onPreferenceChange(Preference preference, Object value) {
    465         boolean enable = (Boolean) value;
    466 
    467         if (enable) {
    468             startProvisioningIfNecessary(WIFI_TETHERING);
    469         } else {
    470             mWifiApEnabler.setSoftapEnabled(false);
    471         }
    472         return false;
    473     }
    474 
    475     public static boolean isProvisioningNeededButUnavailable(Context context) {
    476         String[] provisionApp = context.getResources().getStringArray(
    477                 com.android.internal.R.array.config_mobile_hotspot_provision_app);
    478         return (isProvisioningNeeded(provisionApp)
    479                 && !isIntentAvailable(context, provisionApp));
    480     }
    481 
    482     private static boolean isIntentAvailable(Context context, String[] provisionApp) {
    483         if (provisionApp.length <  2) {
    484             throw new IllegalArgumentException("provisionApp length should at least be 2");
    485         }
    486         final PackageManager packageManager = context.getPackageManager();
    487         Intent intent = new Intent(Intent.ACTION_MAIN);
    488         intent.setClassName(provisionApp[0], provisionApp[1]);
    489 
    490         return (packageManager.queryIntentActivities(intent,
    491                 PackageManager.MATCH_DEFAULT_ONLY).size() > 0);
    492     }
    493 
    494 
    495     private static boolean isProvisioningNeeded(String[] provisionApp) {
    496         if (SystemProperties.getBoolean("net.tethering.noprovisioning", false)
    497                 || provisionApp == null) {
    498             return false;
    499         }
    500         return (provisionApp.length == 2);
    501     }
    502 
    503     private void startProvisioningIfNecessary(int choice) {
    504         mTetherChoice = choice;
    505         if (isProvisioningNeeded(mProvisionApp)) {
    506             Intent intent = new Intent(Intent.ACTION_MAIN);
    507             intent.setClassName(mProvisionApp[0], mProvisionApp[1]);
    508             intent.putExtra(TETHER_CHOICE, mTetherChoice);
    509             startActivityForResult(intent, PROVISION_REQUEST);
    510         } else {
    511             startTethering();
    512         }
    513     }
    514 
    515     public void onActivityResult(int requestCode, int resultCode, Intent intent) {
    516         super.onActivityResult(requestCode, resultCode, intent);
    517         if (requestCode == PROVISION_REQUEST) {
    518             if (resultCode == Activity.RESULT_OK) {
    519                 startTethering();
    520             } else {
    521                 //BT and USB need switch turned off on failure
    522                 //Wifi tethering is never turned on until afterwards
    523                 switch (mTetherChoice) {
    524                     case BLUETOOTH_TETHERING:
    525                         mBluetoothTether.setChecked(false);
    526                         break;
    527                     case USB_TETHERING:
    528                         mUsbTether.setChecked(false);
    529                         break;
    530                 }
    531                 mTetherChoice = INVALID;
    532             }
    533         }
    534     }
    535 
    536     private void startTethering() {
    537         switch (mTetherChoice) {
    538             case WIFI_TETHERING:
    539                 mWifiApEnabler.setSoftapEnabled(true);
    540                 break;
    541             case BLUETOOTH_TETHERING:
    542                 // turn on Bluetooth first
    543                 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    544                 if (adapter.getState() == BluetoothAdapter.STATE_OFF) {
    545                     mBluetoothEnableForTether = true;
    546                     adapter.enable();
    547                     mBluetoothTether.setSummary(R.string.bluetooth_turning_on);
    548                     mBluetoothTether.setEnabled(false);
    549                 } else {
    550                     BluetoothPan bluetoothPan = mBluetoothPan.get();
    551                     if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(true);
    552                     mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext);
    553                 }
    554                 break;
    555             case USB_TETHERING:
    556                 setUsbTethering(true);
    557                 break;
    558             default:
    559                 //should not happen
    560                 break;
    561         }
    562     }
    563 
    564     private void setUsbTethering(boolean enabled) {
    565         ConnectivityManager cm =
    566             (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    567         mUsbTether.setChecked(false);
    568         if (cm.setUsbTethering(enabled) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
    569             mUsbTether.setSummary(R.string.usb_tethering_errored_subtext);
    570             return;
    571         }
    572         mUsbTether.setSummary("");
    573     }
    574 
    575     @Override
    576     public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
    577         ConnectivityManager cm =
    578                 (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
    579 
    580         if (preference == mUsbTether) {
    581             boolean newState = mUsbTether.isChecked();
    582 
    583             if (newState) {
    584                 startProvisioningIfNecessary(USB_TETHERING);
    585             } else {
    586                 setUsbTethering(newState);
    587             }
    588         } else if (preference == mBluetoothTether) {
    589             boolean bluetoothTetherState = mBluetoothTether.isChecked();
    590 
    591             if (bluetoothTetherState) {
    592                 startProvisioningIfNecessary(BLUETOOTH_TETHERING);
    593             } else {
    594                 boolean errored = false;
    595 
    596                 String [] tethered = cm.getTetheredIfaces();
    597                 String bluetoothIface = findIface(tethered, mBluetoothRegexs);
    598                 if (bluetoothIface != null &&
    599                         cm.untether(bluetoothIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) {
    600                     errored = true;
    601                 }
    602 
    603                 BluetoothPan bluetoothPan = mBluetoothPan.get();
    604                 if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(false);
    605                 if (errored) {
    606                     mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext);
    607                 } else {
    608                     mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext);
    609                 }
    610             }
    611         } else if (preference == mCreateNetwork) {
    612             showDialog(DIALOG_AP_SETTINGS);
    613         }
    614 
    615         return super.onPreferenceTreeClick(screen, preference);
    616     }
    617 
    618     private static String findIface(String[] ifaces, String[] regexes) {
    619         for (String iface : ifaces) {
    620             for (String regex : regexes) {
    621                 if (iface.matches(regex)) {
    622                     return iface;
    623                 }
    624             }
    625         }
    626         return null;
    627     }
    628 
    629     public void onClick(DialogInterface dialogInterface, int button) {
    630         if (button == DialogInterface.BUTTON_POSITIVE) {
    631             mWifiConfig = mDialog.getConfig();
    632             if (mWifiConfig != null) {
    633                 /**
    634                  * if soft AP is stopped, bring up
    635                  * else restart with new config
    636                  * TODO: update config on a running access point when framework support is added
    637                  */
    638                 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) {
    639                     mWifiManager.setWifiApEnabled(null, false);
    640                     mWifiManager.setWifiApEnabled(mWifiConfig, true);
    641                 } else {
    642                     mWifiManager.setWifiApConfiguration(mWifiConfig);
    643                 }
    644                 int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig);
    645                 mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT),
    646                         mWifiConfig.SSID,
    647                         mSecurityType[index]));
    648             }
    649         }
    650     }
    651 
    652     @Override
    653     public int getHelpResource() {
    654         return R.string.help_url_tether;
    655     }
    656 
    657     /**
    658      * Checks whether this screen will have anything to show on this device. This is called by
    659      * the shortcut picker for Settings shortcuts (home screen widget).
    660      * @param context a context object for getting a system service.
    661      * @return whether Tether & portable hotspot should be shown in the shortcuts picker.
    662      */
    663     public static boolean showInShortcuts(Context context) {
    664         final ConnectivityManager cm =
    665                 (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
    666         final boolean isSecondaryUser = UserHandle.myUserId() != UserHandle.USER_OWNER;
    667         return !isSecondaryUser && cm.isTetheringSupported();
    668     }
    669 }
    670