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