WifiSettings.java revision 1ad4824d848d67e185f06b4fdce86f1caeb0d95e
1/* 2 * Copyright (C) 2010 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 17package com.android.settings.wifi; 18 19import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; 20 21import android.app.Activity; 22import android.app.AlertDialog; 23import android.content.BroadcastReceiver; 24import android.content.Context; 25import android.content.DialogInterface; 26import android.content.Intent; 27import android.content.IntentFilter; 28import android.net.ConnectivityManager; 29import android.net.NetworkInfo; 30import android.net.NetworkInfo.DetailedState; 31import android.net.wifi.ScanResult; 32import android.net.wifi.SupplicantState; 33import android.net.wifi.WifiConfiguration; 34import android.net.wifi.WifiInfo; 35import android.net.wifi.WifiManager; 36import android.net.wifi.WpsResult; 37import android.net.wifi.WifiConfiguration.KeyMgmt; 38import android.net.wifi.WpsConfiguration; 39import android.os.Bundle; 40import android.os.Handler; 41import android.os.Message; 42import android.preference.CheckBoxPreference; 43import android.preference.Preference; 44import android.preference.ListPreference; 45import android.preference.PreferenceActivity; 46import android.preference.PreferenceScreen; 47import android.provider.Settings.Secure; 48import android.provider.Settings; 49import android.security.Credentials; 50import android.security.KeyStore; 51import android.util.Log; 52import android.view.ContextMenu; 53import android.view.LayoutInflater; 54import android.view.Menu; 55import android.view.MenuInflater; 56import android.view.MenuItem; 57import android.view.View; 58import android.view.ViewGroup; 59import android.view.ContextMenu.ContextMenuInfo; 60import android.widget.Toast; 61import android.widget.AdapterView.AdapterContextMenuInfo; 62 63import com.android.internal.util.AsyncChannel; 64import com.android.settings.ProgressCategoryBase; 65import com.android.settings.R; 66import com.android.settings.SettingsPreferenceFragment; 67import com.android.settings.Utils; 68 69import java.util.ArrayList; 70import java.util.Collection; 71import java.util.List; 72import java.util.concurrent.atomic.AtomicBoolean; 73 74/** 75 * This currently provides three types of UI. 76 * 77 * Two are for phones with relatively small screens: "for SetupWizard" and "for usual Settings". 78 * Users just need to launch WifiSettings Activity as usual. The request will be appropriately 79 * handled by ActivityManager, and they will have appropriate look-and-feel with this fragment. 80 * 81 * Third type is for Setup Wizard with X-Large, landscape UI. Users need to launch 82 * {@link WifiSettingsForSetupWizardXL} Activity, which contains this fragment but also has 83 * other decorations specific to that screen. 84 */ 85public class WifiSettings extends SettingsPreferenceFragment 86 implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener { 87 private static final String TAG = "WifiSettings"; 88 private static final int MENU_ID_SCAN = Menu.FIRST; 89 private static final int MENU_ID_ADVANCED = Menu.FIRST + 1; 90 private static final int MENU_ID_CONNECT = Menu.FIRST + 2; 91 private static final int MENU_ID_FORGET = Menu.FIRST + 3; 92 private static final int MENU_ID_MODIFY = Menu.FIRST + 4; 93 private static final String KEY_SLEEP_POLICY = "sleep_policy"; 94 95 private final IntentFilter mFilter; 96 private final BroadcastReceiver mReceiver; 97 private final Scanner mScanner; 98 99 private WifiManager mWifiManager; 100 private WifiEnabler mWifiEnabler; 101 private CheckBoxPreference mNotifyOpenNetworks; 102 private ProgressCategoryBase mAccessPoints; 103 private Preference mAddNetwork; 104 // An access point being editted is stored here. 105 private AccessPoint mSelectedAccessPoint; 106 private boolean mEdit; 107 108 private DetailedState mLastState; 109 private WifiInfo mLastInfo; 110 111 private AtomicBoolean mConnected = new AtomicBoolean(false); 112 113 private int mKeyStoreNetworkId = INVALID_NETWORK_ID; 114 115 private WifiDialog mDialog; 116 117 /* Used in Wifi Setup context */ 118 119 // this boolean extra specifies whether to disable the Next button when not connected 120 private static final String EXTRA_ENABLE_NEXT_ON_CONNECT = "wifi_enable_next_on_connect"; 121 122 // should Next button only be enabled when we have a connection? 123 private boolean mEnableNextOnConnection; 124 private boolean mInXlSetupWizard; 125 126 /* End of "used in Wifi Setup context" */ 127 128 public WifiSettings() { 129 mFilter = new IntentFilter(); 130 mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 131 mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 132 mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION); 133 mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 134 mFilter.addAction(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); 135 mFilter.addAction(WifiManager.LINK_CONFIGURATION_CHANGED_ACTION); 136 mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 137 mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 138 mFilter.addAction(WifiManager.ERROR_ACTION); 139 140 mReceiver = new BroadcastReceiver() { 141 @Override 142 public void onReceive(Context context, Intent intent) { 143 handleEvent(context, intent); 144 } 145 }; 146 147 mScanner = new Scanner(); 148 } 149 150 @Override 151 public void onAttach(Activity activity) { 152 super.onAttach(activity); 153 154 mInXlSetupWizard = (activity instanceof WifiSettingsForSetupWizardXL); 155 } 156 157 @Override 158 public View onCreateView(LayoutInflater inflater, ViewGroup container, 159 Bundle savedInstanceState) { 160 if (mInXlSetupWizard) { 161 return inflater.inflate(R.layout.custom_preference_list_fragment, container, false); 162 } else { 163 return super.onCreateView(inflater, container, savedInstanceState); 164 } 165 } 166 167 @Override 168 public void onActivityCreated(Bundle savedInstanceState) { 169 // We don't call super.onActivityCreated() here, since it assumes we already set up 170 // Preference (probably in onCreate()), while WifiSettings exceptionally set it up in 171 // this method. 172 173 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 174 mWifiManager.asyncConnect(getActivity(), new WifiServiceHandler()); 175 176 final Activity activity = getActivity(); 177 final Intent intent = activity.getIntent(); 178 179 // if we're supposed to enable/disable the Next button based on our current connection 180 // state, start it off in the right state 181 mEnableNextOnConnection = intent.getBooleanExtra(EXTRA_ENABLE_NEXT_ON_CONNECT, false); 182 183 // Avoid re-adding on returning from an overlapping activity/fragment. 184 if (getPreferenceScreen() == null || getPreferenceScreen().getPreferenceCount() < 2) { 185 if (mEnableNextOnConnection) { 186 if (hasNextButton()) { 187 final ConnectivityManager connectivity = (ConnectivityManager) 188 getActivity().getSystemService(Context.CONNECTIVITY_SERVICE); 189 if (connectivity != null) { 190 NetworkInfo info = connectivity.getNetworkInfo( 191 ConnectivityManager.TYPE_WIFI); 192 changeNextButtonState(info.isConnected()); 193 } 194 } 195 } 196 197 if (mInXlSetupWizard) { 198 addPreferencesFromResource(R.xml.wifi_access_points_for_wifi_setup_xl); 199 } else if (intent.getBooleanExtra("only_access_points", false)) { 200 addPreferencesFromResource(R.xml.wifi_access_points); 201 } else { 202 addPreferencesFromResource(R.xml.wifi_settings); 203 mWifiEnabler = new WifiEnabler(activity, 204 (CheckBoxPreference) findPreference("enable_wifi")); 205 mNotifyOpenNetworks = 206 (CheckBoxPreference) findPreference("notify_open_networks"); 207 mNotifyOpenNetworks.setChecked(Secure.getInt(getContentResolver(), 208 Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1); 209 } 210 // This may be either ProgressCategory or AccessPointCategoryForXL. 211 final ProgressCategoryBase preference = 212 (ProgressCategoryBase) findPreference("access_points"); 213 mAccessPoints = preference; 214 mAccessPoints.setOrderingAsAdded(false); 215 mAddNetwork = findPreference("add_network"); 216 217 ListPreference pref = (ListPreference) findPreference(KEY_SLEEP_POLICY); 218 if (pref != null) { 219 if (Utils.isWifiOnly()) { 220 pref.setEntries(R.array.wifi_sleep_policy_entries_wifi_only); 221 pref.setSummary(R.string.wifi_setting_sleep_policy_summary_wifi_only); 222 } 223 pref.setOnPreferenceChangeListener(this); 224 int value = Settings.System.getInt(getContentResolver(), 225 Settings.System.WIFI_SLEEP_POLICY, 226 Settings.System.WIFI_SLEEP_POLICY_NEVER); 227 pref.setValue(String.valueOf(value)); 228 } 229 230 registerForContextMenu(getListView()); 231 setHasOptionsMenu(true); 232 } 233 234 // After confirming PreferenceScreen is available, we call super. 235 super.onActivityCreated(savedInstanceState); 236 237 } 238 239 @Override 240 public void onResume() { 241 super.onResume(); 242 if (mWifiEnabler != null) { 243 mWifiEnabler.resume(); 244 } 245 246 getActivity().registerReceiver(mReceiver, mFilter); 247 if (mKeyStoreNetworkId != INVALID_NETWORK_ID && 248 KeyStore.getInstance().test() == KeyStore.NO_ERROR) { 249 mWifiManager.connectNetwork(mKeyStoreNetworkId); 250 } 251 mKeyStoreNetworkId = INVALID_NETWORK_ID; 252 updateAccessPoints(); 253 } 254 255 @Override 256 public void onPause() { 257 super.onPause(); 258 if (mWifiEnabler != null) { 259 mWifiEnabler.pause(); 260 } 261 getActivity().unregisterReceiver(mReceiver); 262 mScanner.pause(); 263 if (mDialog != null) { 264 mDialog.dismiss(); 265 mDialog = null; 266 } 267 } 268 269 @Override 270 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { 271 // We don't want menus in Setup Wizard XL. 272 if (!mInXlSetupWizard) { 273 menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan) 274 .setIcon(R.drawable.ic_menu_scan_network); 275 menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced) 276 .setIcon(android.R.drawable.ic_menu_manage); 277 } 278 super.onCreateOptionsMenu(menu, inflater); 279 } 280 281 @Override 282 public boolean onOptionsItemSelected(MenuItem item) { 283 switch (item.getItemId()) { 284 case MENU_ID_SCAN: 285 if (mWifiManager.isWifiEnabled()) { 286 mScanner.forceScan(); 287 } 288 return true; 289 case MENU_ID_ADVANCED: 290 if (getActivity() instanceof PreferenceActivity) { 291 ((PreferenceActivity) getActivity()).startPreferencePanel( 292 AdvancedSettings.class.getCanonicalName(), 293 null, 294 R.string.wifi_advanced_titlebar, null, 295 this, 0); 296 } else { 297 startFragment(this, AdvancedSettings.class.getCanonicalName(), -1, null); 298 } 299 return true; 300 } 301 return super.onOptionsItemSelected(item); 302 } 303 304 @Override 305 public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) { 306 if (mInXlSetupWizard) { 307 ((WifiSettingsForSetupWizardXL)getActivity()).onCreateContextMenu(menu, view, info); 308 } else if (info instanceof AdapterContextMenuInfo) { 309 Preference preference = (Preference) getListView().getItemAtPosition( 310 ((AdapterContextMenuInfo) info).position); 311 312 if (preference instanceof AccessPoint) { 313 mSelectedAccessPoint = (AccessPoint) preference; 314 menu.setHeaderTitle(mSelectedAccessPoint.ssid); 315 if (mSelectedAccessPoint.getLevel() != -1 316 && mSelectedAccessPoint.getState() == null) { 317 menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect); 318 } 319 if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) { 320 menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget); 321 menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify); 322 } 323 } 324 } 325 } 326 327 @Override 328 public boolean onContextItemSelected(MenuItem item) { 329 if (mSelectedAccessPoint == null) { 330 return super.onContextItemSelected(item); 331 } 332 switch (item.getItemId()) { 333 case MENU_ID_CONNECT: { 334 if (mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) { 335 if (!requireKeyStore(mSelectedAccessPoint.getConfig())) { 336 mWifiManager.connectNetwork(mSelectedAccessPoint.networkId); 337 } 338 } else if (mSelectedAccessPoint.security == AccessPoint.SECURITY_NONE) { 339 // Shortcut for open networks. 340 WifiConfiguration config = new WifiConfiguration(); 341 config.SSID = AccessPoint.convertToQuotedString(mSelectedAccessPoint.ssid); 342 config.allowedKeyManagement.set(KeyMgmt.NONE); 343 mWifiManager.connectNetwork(config); 344 } else { 345 showConfigUi(mSelectedAccessPoint, true); 346 } 347 return true; 348 } 349 case MENU_ID_FORGET: { 350 mWifiManager.forgetNetwork(mSelectedAccessPoint.networkId); 351 return true; 352 } 353 case MENU_ID_MODIFY: { 354 showConfigUi(mSelectedAccessPoint, true); 355 return true; 356 } 357 } 358 return super.onContextItemSelected(item); 359 } 360 361 @Override 362 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { 363 if (preference instanceof AccessPoint) { 364 mSelectedAccessPoint = (AccessPoint) preference; 365 showConfigUi(mSelectedAccessPoint, false); 366 } else if (preference == mAddNetwork) { 367 onAddNetworkPressed(); 368 } else if (preference == mNotifyOpenNetworks) { 369 Secure.putInt(getContentResolver(), 370 Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 371 mNotifyOpenNetworks.isChecked() ? 1 : 0); 372 } else { 373 return super.onPreferenceTreeClick(screen, preference); 374 } 375 return true; 376 } 377 378 public boolean onPreferenceChange(Preference preference, Object newValue) { 379 String key = preference.getKey(); 380 if (key == null) return true; 381 382 if (key.equals(KEY_SLEEP_POLICY)) { 383 try { 384 Settings.System.putInt(getContentResolver(), 385 Settings.System.WIFI_SLEEP_POLICY, Integer.parseInt(((String) newValue))); 386 } catch (NumberFormatException e) { 387 Toast.makeText(getActivity(), R.string.wifi_setting_sleep_policy_error, 388 Toast.LENGTH_SHORT).show(); 389 return false; 390 } 391 } 392 393 return true; 394 } 395 396 397 /** 398 * Shows an appropriate Wifi configuration component. 399 * Called when a user clicks "Add network" preference or one of available networks is selected. 400 */ 401 private void showConfigUi(AccessPoint accessPoint, boolean edit) { 402 mEdit = edit; 403 if (mInXlSetupWizard) { 404 ((WifiSettingsForSetupWizardXL)getActivity()).showConfigUi(accessPoint, edit); 405 } else { 406 showDialog(accessPoint, edit); 407 } 408 } 409 410 private void showDialog(AccessPoint accessPoint, boolean edit) { 411 if (mDialog != null) { 412 mDialog.dismiss(); 413 } 414 mDialog = new WifiDialog(getActivity(), this, accessPoint, edit); 415 mDialog.show(); 416 } 417 418 private boolean requireKeyStore(WifiConfiguration config) { 419 if (WifiConfigController.requireKeyStore(config) && 420 KeyStore.getInstance().test() != KeyStore.NO_ERROR) { 421 mKeyStoreNetworkId = config.networkId; 422 Credentials.getInstance().unlock(getActivity()); 423 return true; 424 } 425 return false; 426 } 427 428 /** 429 * Shows the latest access points available with supplimental information like 430 * the strength of network and the security for it. 431 */ 432 private void updateAccessPoints() { 433 mAccessPoints.removeAll(); 434 435 // AccessPoints are automatically sorted with TreeSet. 436 final Collection<AccessPoint> accessPoints = constructAccessPoints(); 437 if (mInXlSetupWizard) { 438 ((WifiSettingsForSetupWizardXL)getActivity()).onAccessPointsUpdated( 439 mAccessPoints, accessPoints); 440 } else { 441 for (AccessPoint accessPoint : accessPoints) { 442 mAccessPoints.addPreference(accessPoint); 443 } 444 } 445 } 446 447 private Collection<AccessPoint> constructAccessPoints() { 448 Collection<AccessPoint> accessPoints = new ArrayList<AccessPoint>(); 449 450 final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks(); 451 if (configs != null) { 452 for (WifiConfiguration config : configs) { 453 AccessPoint accessPoint = new AccessPoint(getActivity(), config); 454 accessPoint.update(mLastInfo, mLastState); 455 accessPoints.add(accessPoint); 456 } 457 } 458 459 final List<ScanResult> results = mWifiManager.getScanResults(); 460 if (results != null) { 461 for (ScanResult result : results) { 462 // Ignore hidden and ad-hoc networks. 463 if (result.SSID == null || result.SSID.length() == 0 || 464 result.capabilities.contains("[IBSS]")) { 465 continue; 466 } 467 468 boolean found = false; 469 for (AccessPoint accessPoint : accessPoints) { 470 if (accessPoint.update(result)) { 471 found = true; 472 } 473 } 474 if (!found) { 475 accessPoints.add(new AccessPoint(getActivity(), result)); 476 } 477 } 478 } 479 480 return accessPoints; 481 } 482 483 private void handleEvent(Context context, Intent intent) { 484 String action = intent.getAction(); 485 if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) { 486 updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 487 WifiManager.WIFI_STATE_UNKNOWN)); 488 } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action) || 489 WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION.equals(action) || 490 WifiManager.LINK_CONFIGURATION_CHANGED_ACTION.equals(action)) { 491 updateAccessPoints(); 492 } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) { 493 //Ignore supplicant state changes when network is connected 494 //TODO: we should deprecate SUPPLICANT_STATE_CHANGED_ACTION and 495 //introduce a broadcast that combines the supplicant and network 496 //network state change events so the apps dont have to worry about 497 //ignoring supplicant state change when network is connected 498 //to get more fine grained information. 499 if (!mConnected.get()) { 500 updateConnectionState(WifiInfo.getDetailedStateOf((SupplicantState) 501 intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE))); 502 } 503 504 if (mInXlSetupWizard) { 505 ((WifiSettingsForSetupWizardXL)getActivity()).onSupplicantStateChanged(intent); 506 } 507 } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) { 508 NetworkInfo info = (NetworkInfo) intent.getParcelableExtra( 509 WifiManager.EXTRA_NETWORK_INFO); 510 mConnected.set(info.isConnected()); 511 changeNextButtonState(info.isConnected()); 512 updateConnectionState(info.getDetailedState()); 513 } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) { 514 updateConnectionState(null); 515 } else if (WifiManager.ERROR_ACTION.equals(action)) { 516 int errorCode = intent.getIntExtra(WifiManager.EXTRA_ERROR_CODE, 0); 517 switch (errorCode) { 518 case WifiManager.WPS_OVERLAP_ERROR: 519 Toast.makeText(context, R.string.wifi_wps_overlap_error, 520 Toast.LENGTH_SHORT).show(); 521 break; 522 } 523 } 524 } 525 526 private void updateConnectionState(DetailedState state) { 527 /* sticky broadcasts can call this when wifi is disabled */ 528 if (!mWifiManager.isWifiEnabled()) { 529 mScanner.pause(); 530 return; 531 } 532 533 if (state == DetailedState.OBTAINING_IPADDR) { 534 mScanner.pause(); 535 } else { 536 mScanner.resume(); 537 } 538 539 mLastInfo = mWifiManager.getConnectionInfo(); 540 if (state != null) { 541 mLastState = state; 542 } 543 544 for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) { 545 // Maybe there's a WifiConfigPreference 546 Preference preference = mAccessPoints.getPreference(i); 547 if (preference instanceof AccessPoint) { 548 final AccessPoint accessPoint = (AccessPoint) preference; 549 accessPoint.update(mLastInfo, mLastState); 550 } 551 } 552 553 if (mInXlSetupWizard) { 554 ((WifiSettingsForSetupWizardXL)getActivity()).updateConnectionState(mLastState); 555 } 556 } 557 558 private void updateWifiState(int state) { 559 if (state == WifiManager.WIFI_STATE_ENABLED) { 560 mScanner.resume(); 561 } else { 562 mScanner.pause(); 563 mAccessPoints.removeAll(); 564 } 565 } 566 567 private class Scanner extends Handler { 568 private int mRetry = 0; 569 570 void resume() { 571 if (!hasMessages(0)) { 572 sendEmptyMessage(0); 573 } 574 } 575 576 void forceScan() { 577 sendEmptyMessage(0); 578 } 579 580 void pause() { 581 mRetry = 0; 582 mAccessPoints.setProgress(false); 583 removeMessages(0); 584 } 585 586 @Override 587 public void handleMessage(Message message) { 588 if (mWifiManager.startScanActive()) { 589 mRetry = 0; 590 } else if (++mRetry >= 3) { 591 mRetry = 0; 592 Toast.makeText(getActivity(), R.string.wifi_fail_to_scan, 593 Toast.LENGTH_LONG).show(); 594 return; 595 } 596 mAccessPoints.setProgress(mRetry != 0); 597 // Combo scans can take 5-6s to complete. Increase interval to 10s. 598 sendEmptyMessageDelayed(0, 10000); 599 } 600 } 601 602 private class WifiServiceHandler extends Handler { 603 604 @Override 605 public void handleMessage(Message msg) { 606 switch (msg.what) { 607 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED: 608 if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) { 609 //AsyncChannel in msg.obj 610 } else { 611 //AsyncChannel set up failure, ignore 612 Log.e(TAG, "Failed to establish AsyncChannel connection"); 613 } 614 break; 615 case WifiManager.CMD_WPS_COMPLETED: 616 WpsResult result = (WpsResult) msg.obj; 617 if (result == null) break; 618 AlertDialog.Builder dialog = new AlertDialog.Builder(getActivity()) 619 .setTitle(R.string.wifi_wps_setup_title) 620 .setPositiveButton(android.R.string.ok, null); 621 switch (result.status) { 622 case FAILURE: 623 dialog.setMessage(R.string.wifi_wps_failed); 624 dialog.show(); 625 break; 626 case IN_PROGRESS: 627 dialog.setMessage(R.string.wifi_wps_in_progress); 628 dialog.show(); 629 break; 630 default: 631 if (result.pin != null) { 632 dialog.setMessage(getResources().getString( 633 R.string.wifi_wps_pin_output, result.pin)); 634 dialog.show(); 635 } 636 break; 637 } 638 //TODO: more connectivity feedback 639 default: 640 //Ignore 641 break; 642 } 643 } 644 } 645 646 /** 647 * Renames/replaces "Next" button when appropriate. "Next" button usually exists in 648 * Wifi setup screens, not in usual wifi settings screen. 649 * 650 * @param connected true when the device is connected to a wifi network. 651 */ 652 private void changeNextButtonState(boolean connected) { 653 if (mInXlSetupWizard) { 654 ((WifiSettingsForSetupWizardXL)getActivity()).changeNextButtonState(connected); 655 } else if (mEnableNextOnConnection && hasNextButton()) { 656 getNextButton().setEnabled(connected); 657 } 658 } 659 660 public void onClick(DialogInterface dialogInterface, int button) { 661 if (mInXlSetupWizard) { 662 if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) { 663 forget(); 664 } else if (button == WifiDialog.BUTTON_SUBMIT) { 665 ((WifiSettingsForSetupWizardXL)getActivity()).onConnectButtonPressed(); 666 } 667 } else { 668 if (button == WifiDialog.BUTTON_FORGET && mSelectedAccessPoint != null) { 669 forget(); 670 } else if (button == WifiDialog.BUTTON_SUBMIT) { 671 submit(mDialog.getController()); 672 } 673 } 674 675 } 676 677 /* package */ void submit(WifiConfigController configController) { 678 int networkSetup = configController.chosenNetworkSetupMethod(); 679 switch(networkSetup) { 680 case WifiConfigController.WPS_PBC: 681 case WifiConfigController.WPS_PIN_FROM_ACCESS_POINT: 682 case WifiConfigController.WPS_PIN_FROM_DEVICE: 683 mWifiManager.startWps(configController.getWpsConfig()); 684 break; 685 case WifiConfigController.MANUAL: 686 final WifiConfiguration config = configController.getConfig(); 687 688 if (config == null) { 689 if (mSelectedAccessPoint != null 690 && !requireKeyStore(mSelectedAccessPoint.getConfig()) 691 && mSelectedAccessPoint.networkId != INVALID_NETWORK_ID) { 692 mWifiManager.connectNetwork(mSelectedAccessPoint.networkId); 693 } 694 } else if (config.networkId != INVALID_NETWORK_ID) { 695 if (mSelectedAccessPoint != null) { 696 saveNetwork(config); 697 } 698 } else { 699 if (configController.isEdit() || requireKeyStore(config)) { 700 saveNetwork(config); 701 } else { 702 mWifiManager.connectNetwork(config); 703 } 704 } 705 break; 706 } 707 708 if (mWifiManager.isWifiEnabled()) { 709 mScanner.resume(); 710 } 711 updateAccessPoints(); 712 } 713 714 private void saveNetwork(WifiConfiguration config) { 715 if (mInXlSetupWizard) { 716 ((WifiSettingsForSetupWizardXL)getActivity()).onSaveNetwork(config); 717 } else { 718 mWifiManager.saveNetwork(config); 719 } 720 } 721 722 /* package */ void forget() { 723 mWifiManager.forgetNetwork(mSelectedAccessPoint.networkId); 724 725 if (mWifiManager.isWifiEnabled()) { 726 mScanner.resume(); 727 } 728 updateAccessPoints(); 729 730 // We need to rename/replace "Next" button in wifi setup context. 731 changeNextButtonState(false); 732 } 733 734 /** 735 * Refreshes acccess points and ask Wifi module to scan networks again. 736 */ 737 /* package */ void refreshAccessPoints() { 738 if (mWifiManager.isWifiEnabled()) { 739 mScanner.resume(); 740 } 741 742 mAccessPoints.removeAll(); 743 } 744 745 /** 746 * Called when "add network" button is pressed. 747 */ 748 /* package */ void onAddNetworkPressed() { 749 // No exact access point is selected. 750 mSelectedAccessPoint = null; 751 showConfigUi(null, true); 752 } 753 754 /* package */ int getAccessPointsCount() { 755 if (mAccessPoints != null) { 756 return mAccessPoints.getPreferenceCount(); 757 } else { 758 return 0; 759 } 760 } 761 762 /** 763 * Requests wifi module to pause wifi scan. May be ignored when the module is disabled. 764 */ 765 /* package */ void pauseWifiScan() { 766 if (mWifiManager.isWifiEnabled()) { 767 mScanner.pause(); 768 } 769 } 770 771 /** 772 * Requests wifi module to resume wifi scan. May be ignored when the module is disabled. 773 */ 774 /* package */ void resumeWifiScan() { 775 if (mWifiManager.isWifiEnabled()) { 776 mScanner.resume(); 777 } 778 } 779} 780