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