OSDN Git Service

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