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