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.Handler; 37 import android.os.UserManager; 38 import android.support.v14.preference.SwitchPreference; 39 import android.support.v7.preference.Preference; 40 import android.util.Log; 41 42 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 43 import com.android.settings.datausage.DataSaverBackend; 44 import com.android.settings.wifi.WifiApDialog; 45 import com.android.settings.wifi.WifiApEnabler; 46 import com.android.settingslib.TetherUtil; 47 48 import java.lang.ref.WeakReference; 49 import java.util.ArrayList; 50 import java.util.concurrent.atomic.AtomicReference; 51 52 import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; 53 import static android.net.ConnectivityManager.TETHERING_USB; 54 import static android.net.ConnectivityManager.TETHERING_WIFI; 55 56 /* 57 * Displays preferences for Tethering. 58 */ 59 public class TetherSettings extends RestrictedSettingsFragment 60 implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener, 61 DataSaverBackend.Listener { 62 63 private static final String USB_TETHER_SETTINGS = "usb_tether_settings"; 64 private static final String ENABLE_WIFI_AP = "enable_wifi_ap"; 65 private static final String ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering"; 66 private static final String TETHER_CHOICE = "TETHER_TYPE"; 67 private static final String DATA_SAVER_FOOTER = "disabled_on_data_saver"; 68 69 private static final int DIALOG_AP_SETTINGS = 1; 70 71 private static final String TAG = "TetheringSettings"; 72 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 Handler mHandler = new Handler(); 90 private OnStartTetheringCallback mStartTetheringCallback; 91 92 private static final String WIFI_AP_SSID_AND_SECURITY = "wifi_ap_ssid_and_security"; 93 private static final int CONFIG_SUBTEXT = R.string.wifi_tether_configure_subtext; 94 95 private String[] mSecurityType; 96 private Preference mCreateNetwork; 97 98 private WifiApDialog mDialog; 99 private WifiManager mWifiManager; 100 private WifiConfiguration mWifiConfig = null; 101 private ConnectivityManager mCm; 102 103 private boolean mRestartWifiApAfterConfigChange; 104 105 private boolean mUsbConnected; 106 private boolean mMassStorageActive; 107 108 private boolean mBluetoothEnableForTether; 109 110 /* Stores the package name and the class name of the provisioning app */ 111 private String[] mProvisionApp; 112 private static final int PROVISION_REQUEST = 0; 113 114 private boolean mUnavailable; 115 116 private DataSaverBackend mDataSaverBackend; 117 private boolean mDataSaverEnabled; 118 private Preference mDataSaverFooter; 119 120 @Override getMetricsCategory()121 public int getMetricsCategory() { 122 return MetricsEvent.TETHER; 123 } 124 TetherSettings()125 public TetherSettings() { 126 super(UserManager.DISALLOW_CONFIG_TETHERING); 127 } 128 129 @Override onCreate(Bundle icicle)130 public void onCreate(Bundle icicle) { 131 super.onCreate(icicle); 132 133 addPreferencesFromResource(R.xml.tether_prefs); 134 mFooterPreferenceMixin.createFooterPreference() 135 .setTitle(R.string.tethering_footer_info); 136 137 mDataSaverBackend = new DataSaverBackend(getContext()); 138 mDataSaverEnabled = mDataSaverBackend.isDataSaverEnabled(); 139 mDataSaverFooter = findPreference(DATA_SAVER_FOOTER); 140 141 setIfOnlyAvailableForAdmins(true); 142 if (isUiRestricted()) { 143 mUnavailable = true; 144 getPreferenceScreen().removeAll(); 145 return; 146 } 147 148 final Activity activity = getActivity(); 149 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 150 if (adapter != null) { 151 adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener, 152 BluetoothProfile.PAN); 153 } 154 155 mEnableWifiAp = 156 (SwitchPreference) findPreference(ENABLE_WIFI_AP); 157 Preference wifiApSettings = findPreference(WIFI_AP_SSID_AND_SECURITY); 158 mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS); 159 mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING); 160 161 mDataSaverBackend.addListener(this); 162 163 mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); 164 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 165 166 mUsbRegexs = mCm.getTetherableUsbRegexs(); 167 mWifiRegexs = mCm.getTetherableWifiRegexs(); 168 mBluetoothRegexs = mCm.getTetherableBluetoothRegexs(); 169 170 final boolean usbAvailable = mUsbRegexs.length != 0; 171 final boolean wifiAvailable = mWifiRegexs.length != 0; 172 final boolean bluetoothAvailable = mBluetoothRegexs.length != 0; 173 174 if (!usbAvailable || Utils.isMonkeyRunning()) { 175 getPreferenceScreen().removePreference(mUsbTether); 176 } 177 178 if (wifiAvailable && !Utils.isMonkeyRunning()) { 179 mWifiApEnabler = new WifiApEnabler(activity, mDataSaverBackend, mEnableWifiAp); 180 initWifiTethering(); 181 } else { 182 getPreferenceScreen().removePreference(mEnableWifiAp); 183 getPreferenceScreen().removePreference(wifiApSettings); 184 } 185 186 if (!bluetoothAvailable) { 187 getPreferenceScreen().removePreference(mBluetoothTether); 188 } else { 189 BluetoothPan pan = mBluetoothPan.get(); 190 if (pan != null && pan.isTetheringOn()) { 191 mBluetoothTether.setChecked(true); 192 } else { 193 mBluetoothTether.setChecked(false); 194 } 195 } 196 // Set initial state based on Data Saver mode. 197 onDataSaverChanged(mDataSaverBackend.isDataSaverEnabled()); 198 } 199 200 @Override onDestroy()201 public void onDestroy() { 202 mDataSaverBackend.remListener(this); 203 204 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 205 BluetoothProfile profile = mBluetoothPan.getAndSet(null); 206 if (profile != null && adapter != null) { 207 adapter.closeProfileProxy(BluetoothProfile.PAN, profile); 208 } 209 210 super.onDestroy(); 211 } 212 213 @Override onDataSaverChanged(boolean isDataSaving)214 public void onDataSaverChanged(boolean isDataSaving) { 215 mDataSaverEnabled = isDataSaving; 216 mEnableWifiAp.setEnabled(!mDataSaverEnabled); 217 mUsbTether.setEnabled(!mDataSaverEnabled); 218 mBluetoothTether.setEnabled(!mDataSaverEnabled); 219 mDataSaverFooter.setVisible(mDataSaverEnabled); 220 } 221 222 @Override onWhitelistStatusChanged(int uid, boolean isWhitelisted)223 public void onWhitelistStatusChanged(int uid, boolean isWhitelisted) { 224 } 225 226 @Override onBlacklistStatusChanged(int uid, boolean isBlacklisted)227 public void onBlacklistStatusChanged(int uid, boolean isBlacklisted) { 228 } 229 initWifiTethering()230 private void initWifiTethering() { 231 final Activity activity = getActivity(); 232 mWifiConfig = mWifiManager.getWifiApConfiguration(); 233 mSecurityType = getResources().getStringArray(R.array.wifi_ap_security); 234 235 mCreateNetwork = findPreference(WIFI_AP_SSID_AND_SECURITY); 236 237 mRestartWifiApAfterConfigChange = false; 238 239 if (mWifiConfig == null) { 240 final String s = activity.getString( 241 com.android.internal.R.string.wifi_tether_configure_ssid_default); 242 mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT), 243 s, mSecurityType[WifiApDialog.OPEN_INDEX])); 244 } else { 245 int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig); 246 mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT), 247 mWifiConfig.SSID, 248 mSecurityType[index])); 249 } 250 } 251 252 @Override onCreateDialog(int id)253 public Dialog onCreateDialog(int id) { 254 if (id == DIALOG_AP_SETTINGS) { 255 final Activity activity = getActivity(); 256 mDialog = new WifiApDialog(activity, this, mWifiConfig); 257 return mDialog; 258 } 259 260 return null; 261 } 262 263 @Override getDialogMetricsCategory(int dialogId)264 public int getDialogMetricsCategory(int dialogId) { 265 if (dialogId == DIALOG_AP_SETTINGS) { 266 return MetricsEvent.DIALOG_AP_SETTINGS; 267 } 268 return 0; 269 } 270 271 private class TetherChangeReceiver extends BroadcastReceiver { 272 @Override onReceive(Context content, Intent intent)273 public void onReceive(Context content, Intent intent) { 274 String action = intent.getAction(); 275 if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) { 276 // TODO - this should understand the interface types 277 ArrayList<String> available = intent.getStringArrayListExtra( 278 ConnectivityManager.EXTRA_AVAILABLE_TETHER); 279 ArrayList<String> active = intent.getStringArrayListExtra( 280 ConnectivityManager.EXTRA_ACTIVE_TETHER); 281 ArrayList<String> errored = intent.getStringArrayListExtra( 282 ConnectivityManager.EXTRA_ERRORED_TETHER); 283 updateState(available.toArray(new String[available.size()]), 284 active.toArray(new String[active.size()]), 285 errored.toArray(new String[errored.size()])); 286 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_DISABLED 287 && mRestartWifiApAfterConfigChange) { 288 mRestartWifiApAfterConfigChange = false; 289 Log.d(TAG, "Restarting WifiAp due to prior config change."); 290 startTethering(TETHERING_WIFI); 291 } 292 } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) { 293 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 0); 294 if (state == WifiManager.WIFI_AP_STATE_DISABLED 295 && mRestartWifiApAfterConfigChange) { 296 mRestartWifiApAfterConfigChange = false; 297 Log.d(TAG, "Restarting WifiAp due to prior config change."); 298 startTethering(TETHERING_WIFI); 299 } 300 } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) { 301 mMassStorageActive = true; 302 updateState(); 303 } else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) { 304 mMassStorageActive = false; 305 updateState(); 306 } else if (action.equals(UsbManager.ACTION_USB_STATE)) { 307 mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 308 updateState(); 309 } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 310 if (mBluetoothEnableForTether) { 311 switch (intent 312 .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { 313 case BluetoothAdapter.STATE_ON: 314 startTethering(TETHERING_BLUETOOTH); 315 mBluetoothEnableForTether = false; 316 break; 317 318 case BluetoothAdapter.STATE_OFF: 319 case BluetoothAdapter.ERROR: 320 mBluetoothEnableForTether = false; 321 break; 322 323 default: 324 // ignore transition states 325 } 326 } 327 updateState(); 328 } 329 } 330 } 331 332 @Override onStart()333 public void onStart() { 334 super.onStart(); 335 336 if (mUnavailable) { 337 if (!isUiRestrictedByOnlyAdmin()) { 338 getEmptyTextView().setText(R.string.tethering_settings_not_available); 339 } 340 getPreferenceScreen().removeAll(); 341 return; 342 } 343 344 final Activity activity = getActivity(); 345 346 mStartTetheringCallback = new OnStartTetheringCallback(this); 347 348 mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); 349 mTetherChangeReceiver = new TetherChangeReceiver(); 350 IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 351 filter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 352 Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter); 353 354 filter = new IntentFilter(); 355 filter.addAction(UsbManager.ACTION_USB_STATE); 356 activity.registerReceiver(mTetherChangeReceiver, filter); 357 358 filter = new IntentFilter(); 359 filter.addAction(Intent.ACTION_MEDIA_SHARED); 360 filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 361 filter.addDataScheme("file"); 362 activity.registerReceiver(mTetherChangeReceiver, filter); 363 364 filter = new IntentFilter(); 365 filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 366 activity.registerReceiver(mTetherChangeReceiver, filter); 367 368 if (intent != null) mTetherChangeReceiver.onReceive(activity, intent); 369 if (mWifiApEnabler != null) { 370 mEnableWifiAp.setOnPreferenceChangeListener(this); 371 mWifiApEnabler.resume(); 372 } 373 374 updateState(); 375 } 376 377 @Override onStop()378 public void onStop() { 379 super.onStop(); 380 381 if (mUnavailable) { 382 return; 383 } 384 getActivity().unregisterReceiver(mTetherChangeReceiver); 385 mTetherChangeReceiver = null; 386 mStartTetheringCallback = null; 387 if (mWifiApEnabler != null) { 388 mEnableWifiAp.setOnPreferenceChangeListener(null); 389 mWifiApEnabler.pause(); 390 } 391 } 392 updateState()393 private void updateState() { 394 String[] available = mCm.getTetherableIfaces(); 395 String[] tethered = mCm.getTetheredIfaces(); 396 String[] errored = mCm.getTetheringErroredIfaces(); 397 updateState(available, tethered, errored); 398 } 399 updateState(String[] available, String[] tethered, String[] errored)400 private void updateState(String[] available, String[] tethered, 401 String[] errored) { 402 updateUsbState(available, tethered, errored); 403 updateBluetoothState(available, tethered, errored); 404 } 405 406 updateUsbState(String[] available, String[] tethered, String[] errored)407 private void updateUsbState(String[] available, String[] tethered, 408 String[] errored) { 409 boolean usbAvailable = mUsbConnected && !mMassStorageActive; 410 int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 411 for (String s : available) { 412 for (String regex : mUsbRegexs) { 413 if (s.matches(regex)) { 414 if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 415 usbError = mCm.getLastTetherError(s); 416 } 417 } 418 } 419 } 420 boolean usbTethered = false; 421 for (String s : tethered) { 422 for (String regex : mUsbRegexs) { 423 if (s.matches(regex)) usbTethered = true; 424 } 425 } 426 boolean usbErrored = false; 427 for (String s: errored) { 428 for (String regex : mUsbRegexs) { 429 if (s.matches(regex)) usbErrored = true; 430 } 431 } 432 433 if (usbTethered) { 434 mUsbTether.setSummary(R.string.usb_tethering_active_subtext); 435 mUsbTether.setEnabled(!mDataSaverEnabled); 436 mUsbTether.setChecked(true); 437 } else if (usbAvailable) { 438 if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 439 mUsbTether.setSummary(R.string.usb_tethering_available_subtext); 440 } else { 441 mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); 442 } 443 mUsbTether.setEnabled(!mDataSaverEnabled); 444 mUsbTether.setChecked(false); 445 } else if (usbErrored) { 446 mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); 447 mUsbTether.setEnabled(false); 448 mUsbTether.setChecked(false); 449 } else if (mMassStorageActive) { 450 mUsbTether.setSummary(R.string.usb_tethering_storage_active_subtext); 451 mUsbTether.setEnabled(false); 452 mUsbTether.setChecked(false); 453 } else { 454 mUsbTether.setSummary(R.string.usb_tethering_unavailable_subtext); 455 mUsbTether.setEnabled(false); 456 mUsbTether.setChecked(false); 457 } 458 } 459 updateBluetoothState(String[] available, String[] tethered, String[] errored)460 private void updateBluetoothState(String[] available, String[] tethered, 461 String[] errored) { 462 boolean bluetoothErrored = false; 463 for (String s: errored) { 464 for (String regex : mBluetoothRegexs) { 465 if (s.matches(regex)) bluetoothErrored = true; 466 } 467 } 468 469 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 470 if (adapter == null) { 471 return; 472 } 473 int btState = adapter.getState(); 474 if (btState == BluetoothAdapter.STATE_TURNING_OFF) { 475 mBluetoothTether.setEnabled(false); 476 mBluetoothTether.setSummary(R.string.bluetooth_turning_off); 477 } else if (btState == BluetoothAdapter.STATE_TURNING_ON) { 478 mBluetoothTether.setEnabled(false); 479 mBluetoothTether.setSummary(R.string.bluetooth_turning_on); 480 } else { 481 BluetoothPan bluetoothPan = mBluetoothPan.get(); 482 if (btState == BluetoothAdapter.STATE_ON && bluetoothPan != null 483 && bluetoothPan.isTetheringOn()) { 484 mBluetoothTether.setChecked(true); 485 mBluetoothTether.setEnabled(!mDataSaverEnabled); 486 int bluetoothTethered = bluetoothPan.getConnectedDevices().size(); 487 if (bluetoothTethered > 1) { 488 String summary = getString( 489 R.string.bluetooth_tethering_devices_connected_subtext, 490 bluetoothTethered); 491 mBluetoothTether.setSummary(summary); 492 } else if (bluetoothTethered == 1) { 493 mBluetoothTether.setSummary( 494 R.string.bluetooth_tethering_device_connected_subtext); 495 } else if (bluetoothErrored) { 496 mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); 497 } else { 498 mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); 499 } 500 } else { 501 mBluetoothTether.setEnabled(!mDataSaverEnabled); 502 mBluetoothTether.setChecked(false); 503 mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); 504 } 505 } 506 } 507 508 @Override onPreferenceChange(Preference preference, Object value)509 public boolean onPreferenceChange(Preference preference, Object value) { 510 boolean enable = (Boolean) value; 511 512 if (enable) { 513 startTethering(TETHERING_WIFI); 514 } else { 515 mCm.stopTethering(TETHERING_WIFI); 516 } 517 return false; 518 } 519 isProvisioningNeededButUnavailable(Context context)520 public static boolean isProvisioningNeededButUnavailable(Context context) { 521 return (TetherUtil.isProvisioningNeeded(context) 522 && !isIntentAvailable(context)); 523 } 524 isIntentAvailable(Context context)525 private static boolean isIntentAvailable(Context context) { 526 String[] provisionApp = context.getResources().getStringArray( 527 com.android.internal.R.array.config_mobile_hotspot_provision_app); 528 if (provisionApp.length < 2) { 529 return false; 530 } 531 final PackageManager packageManager = context.getPackageManager(); 532 Intent intent = new Intent(Intent.ACTION_MAIN); 533 intent.setClassName(provisionApp[0], provisionApp[1]); 534 535 return (packageManager.queryIntentActivities(intent, 536 PackageManager.MATCH_DEFAULT_ONLY).size() > 0); 537 } 538 startTethering(int choice)539 private void startTethering(int choice) { 540 if (choice == TETHERING_BLUETOOTH) { 541 // Turn on Bluetooth first. 542 BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 543 if (adapter.getState() == BluetoothAdapter.STATE_OFF) { 544 mBluetoothEnableForTether = true; 545 adapter.enable(); 546 mBluetoothTether.setSummary(R.string.bluetooth_turning_on); 547 mBluetoothTether.setEnabled(false); 548 return; 549 } 550 } 551 552 mCm.startTethering(choice, true, mStartTetheringCallback, mHandler); 553 } 554 555 @Override onPreferenceTreeClick(Preference preference)556 public boolean onPreferenceTreeClick(Preference preference) { 557 if (preference == mUsbTether) { 558 if (mUsbTether.isChecked()) { 559 startTethering(TETHERING_USB); 560 } else { 561 mCm.stopTethering(TETHERING_USB); 562 } 563 } else if (preference == mBluetoothTether) { 564 if (mBluetoothTether.isChecked()) { 565 startTethering(TETHERING_BLUETOOTH); 566 } else { 567 mCm.stopTethering(TETHERING_BLUETOOTH); 568 // No ACTION_TETHER_STATE_CHANGED is fired or bluetooth unless a device is 569 // connected. Need to update state manually. 570 updateState(); 571 } 572 } else if (preference == mCreateNetwork) { 573 showDialog(DIALOG_AP_SETTINGS); 574 } 575 576 return super.onPreferenceTreeClick(preference); 577 } 578 onClick(DialogInterface dialogInterface, int button)579 public void onClick(DialogInterface dialogInterface, int button) { 580 if (button == DialogInterface.BUTTON_POSITIVE) { 581 mWifiConfig = mDialog.getConfig(); 582 if (mWifiConfig != null) { 583 /** 584 * if soft AP is stopped, bring up 585 * else restart with new config 586 * TODO: update config on a running access point when framework support is added 587 */ 588 if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) { 589 Log.d("TetheringSettings", 590 "Wifi AP config changed while enabled, stop and restart"); 591 mRestartWifiApAfterConfigChange = true; 592 mCm.stopTethering(TETHERING_WIFI); 593 } 594 mWifiManager.setWifiApConfiguration(mWifiConfig); 595 int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig); 596 mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT), 597 mWifiConfig.SSID, 598 mSecurityType[index])); 599 } 600 } 601 } 602 603 @Override getHelpResource()604 public int getHelpResource() { 605 return R.string.help_url_tether; 606 } 607 608 private BluetoothProfile.ServiceListener mProfileServiceListener = 609 new BluetoothProfile.ServiceListener() { 610 public void onServiceConnected(int profile, BluetoothProfile proxy) { 611 mBluetoothPan.set((BluetoothPan) proxy); 612 } 613 public void onServiceDisconnected(int profile) { 614 mBluetoothPan.set(null); 615 } 616 }; 617 618 private static final class OnStartTetheringCallback extends 619 ConnectivityManager.OnStartTetheringCallback { 620 final WeakReference<TetherSettings> mTetherSettings; 621 OnStartTetheringCallback(TetherSettings settings)622 OnStartTetheringCallback(TetherSettings settings) { 623 mTetherSettings = new WeakReference<TetherSettings>(settings); 624 } 625 626 @Override onTetheringStarted()627 public void onTetheringStarted() { 628 update(); 629 } 630 631 @Override onTetheringFailed()632 public void onTetheringFailed() { 633 update(); 634 } 635 update()636 private void update() { 637 TetherSettings settings = mTetherSettings.get(); 638 if (settings != null) { 639 settings.updateState(); 640 } 641 } 642 } 643 } 644