• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onCreate(Bundle icicle)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
onSaveInstanceState(Bundle savedInstanceState)190     public void onSaveInstanceState(Bundle savedInstanceState) {
191         savedInstanceState.putInt(TETHER_CHOICE, mTetherChoice);
192         super.onSaveInstanceState(savedInstanceState);
193     }
194 
initWifiTethering()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
onCreateDialog(int id)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
onReceive(Context content, Intent intent)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
onStart()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
onStop()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 
updateState()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 
updateState(String[] available, String[] tethered, String[] errored)355     private void updateState(String[] available, String[] tethered,
356             String[] errored) {
357         updateUsbState(available, tethered, errored);
358         updateBluetoothState(available, tethered, errored);
359     }
360 
361 
updateUsbState(String[] available, String[] tethered, String[] errored)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 
updateBluetoothState(String[] available, String[] tethered, String[] errored)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 
onPreferenceChange(Preference preference, Object value)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 
isProvisioningNeededButUnavailable(Context context)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 
isIntentAvailable(Context context, String[] provisionApp)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 
isProvisioningNeeded(String[] provisionApp)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 
startProvisioningIfNecessary(int choice)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 
onActivityResult(int requestCode, int resultCode, Intent intent)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 
startTethering()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 
setUsbTethering(boolean enabled)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
onPreferenceTreeClick(PreferenceScreen screen, Preference preference)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 
findIface(String[] ifaces, String[] regexes)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 
onClick(DialogInterface dialogInterface, int button)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
getHelpResource()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      */
showInShortcuts(Context context)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