Home | History | Annotate | Download | only in wifi
      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 
     17 package com.android.settings.wifi;
     18 
     19 import android.app.Activity;
     20 import android.content.Context;
     21 import android.content.Intent;
     22 import android.content.pm.ActivityInfo;
     23 import android.net.NetworkInfo.DetailedState;
     24 import android.net.wifi.WifiConfiguration;
     25 import android.net.wifi.WifiManager;
     26 import android.os.Bundle;
     27 import android.os.Handler;
     28 import android.os.Message;
     29 import android.preference.PreferenceScreen;
     30 import android.text.TextUtils;
     31 import android.util.Log;
     32 import android.view.View;
     33 import android.view.View.OnClickListener;
     34 import android.view.ViewGroup;
     35 import android.view.Window;
     36 import android.view.inputmethod.InputMethodManager;
     37 import android.widget.Button;
     38 import android.widget.ProgressBar;
     39 import android.widget.TextView;
     40 
     41 import com.android.internal.util.AsyncChannel;
     42 import com.android.settings.R;
     43 
     44 import java.util.Collection;
     45 import java.util.EnumMap;
     46 import java.util.List;
     47 
     48 /**
     49  * WifiSetings Activity specific for SetupWizard with X-Large screen size.
     50  */
     51 public class WifiSettingsForSetupWizardXL extends Activity implements OnClickListener {
     52     private static final String TAG = "SetupWizard";
     53     private static final boolean DEBUG = true;
     54 
     55     // lock orientation into landscape or portrait
     56     private static final String EXTRA_PREFS_LANDSCAPE_LOCK = "extra_prefs_landscape_lock";
     57     private static final String EXTRA_PREFS_PORTRAIT_LOCK = "extra_prefs_portrait_lock";
     58 
     59     private static final EnumMap<DetailedState, DetailedState> sNetworkStateMap =
     60             new EnumMap<DetailedState, DetailedState>(DetailedState.class);
     61 
     62     static {
     63         sNetworkStateMap.put(DetailedState.IDLE, DetailedState.DISCONNECTED);
     64         sNetworkStateMap.put(DetailedState.SCANNING, DetailedState.SCANNING);
     65         sNetworkStateMap.put(DetailedState.CONNECTING, DetailedState.CONNECTING);
     66         sNetworkStateMap.put(DetailedState.AUTHENTICATING, DetailedState.CONNECTING);
     67         sNetworkStateMap.put(DetailedState.OBTAINING_IPADDR, DetailedState.CONNECTING);
     68         sNetworkStateMap.put(DetailedState.CONNECTED, DetailedState.CONNECTED);
     69         sNetworkStateMap.put(DetailedState.SUSPENDED, DetailedState.SUSPENDED);  // ?
     70         sNetworkStateMap.put(DetailedState.DISCONNECTING, DetailedState.DISCONNECTED);
     71         sNetworkStateMap.put(DetailedState.DISCONNECTED, DetailedState.DISCONNECTED);
     72         sNetworkStateMap.put(DetailedState.FAILED, DetailedState.FAILED);
     73     }
     74 
     75     private WifiSettings mWifiSettings;
     76     private WifiManager mWifiManager;
     77 
     78     /** Used for resizing a padding above title. Hiden when software keyboard is shown. */
     79     private View mTopPadding;
     80 
     81     /** Used for resizing a padding of main content. Hiden when software keyboard is shown. */
     82     private View mContentPadding;
     83 
     84     private TextView mTitleView;
     85     /**
     86      * The name of a network currently connecting, or trying to connect.
     87      * This may be empty ("") at first, and updated when configuration is changed.
     88      */
     89     private CharSequence mNetworkName = "";
     90     private CharSequence mEditingTitle;
     91 
     92     private ProgressBar mProgressBar;
     93     private View mTopDividerNoProgress;
     94     /**
     95      * Used for resizing a padding between WifiSettings preference and bottom bar when
     96      * ProgressBar is visible as a top divider.
     97      */
     98     private View mBottomPadding;
     99 
    100     private Button mAddNetworkButton;
    101     private Button mRefreshButton;
    102     private Button mSkipOrNextButton;
    103     private Button mBackButton;
    104 
    105     private Button mConnectButton;
    106 
    107     /**
    108      * View enclosing {@link WifiSettings}.
    109      */
    110     private View mWifiSettingsFragmentLayout;
    111     private View mConnectingStatusLayout;
    112     private TextView mConnectingStatusView;
    113 
    114     /*
    115      * States of current screen, which should be saved and restored when Activity is relaunched
    116      * with orientation change, etc.
    117      */
    118     private static final int SCREEN_STATE_DISCONNECTED = 0;
    119     private static final int SCREEN_STATE_EDITING = 1;
    120     private static final int SCREEN_STATE_CONNECTING = 2;
    121     private static final int SCREEN_STATE_CONNECTED = 3;
    122 
    123     /** Current screen state. */
    124     private int mScreenState = SCREEN_STATE_DISCONNECTED;
    125 
    126     private WifiConfigUiForSetupWizardXL mWifiConfig;
    127 
    128     private InputMethodManager mInputMethodManager;
    129 
    130     /**
    131      * Previous network connection state reported by main Wifi module.
    132      *
    133      * Note that we don't use original {@link DetailedState} object but simplified one translated
    134      * using sNetworkStateMap.
    135      */
    136     private DetailedState mPreviousNetworkState = DetailedState.DISCONNECTED;
    137 
    138     @Override
    139     public void onCreate(Bundle savedInstanceState) {
    140         super.onCreate(savedInstanceState);
    141         requestWindowFeature(Window.FEATURE_NO_TITLE);
    142         setContentView(R.layout.wifi_settings_for_setup_wizard_xl);
    143 
    144         mWifiManager = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    145         // There's no button here enabling wifi network, so we need to enable it without
    146         // users' request.
    147         mWifiManager.setWifiEnabled(true);
    148         mWifiManager.asyncConnect(this, new WifiServiceHandler());
    149 
    150         mWifiSettings =
    151                 (WifiSettings)getFragmentManager().findFragmentById(R.id.wifi_setup_fragment);
    152         mInputMethodManager = (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
    153 
    154         initViews();
    155 
    156         // At first, Wifi module doesn't return SCANNING state (it's too early), so we manually
    157         // show it.
    158         showScanningState();
    159     }
    160 
    161     private void initViews() {
    162         Intent intent = getIntent();
    163 
    164         if (intent.getBooleanExtra("firstRun", false)) {
    165             final View layoutRoot = findViewById(R.id.layout_root);
    166             layoutRoot.setSystemUiVisibility(View.STATUS_BAR_DISABLE_BACK);
    167         }
    168         if (intent.getBooleanExtra(EXTRA_PREFS_LANDSCAPE_LOCK, false)) {
    169             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE);
    170         }
    171         if (intent.getBooleanExtra(EXTRA_PREFS_PORTRAIT_LOCK, false)) {
    172             setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT);
    173         }
    174 
    175         mTitleView = (TextView)findViewById(R.id.wifi_setup_title);
    176         mProgressBar = (ProgressBar)findViewById(R.id.scanning_progress_bar);
    177         mProgressBar.setMax(2);
    178         mTopDividerNoProgress = findViewById(R.id.top_divider_no_progress);
    179         mBottomPadding = findViewById(R.id.bottom_padding);
    180 
    181         mProgressBar.setVisibility(View.VISIBLE);
    182         mProgressBar.setIndeterminate(true);
    183         mTopDividerNoProgress.setVisibility(View.GONE);
    184 
    185         mAddNetworkButton = (Button)findViewById(R.id.wifi_setup_add_network);
    186         mAddNetworkButton.setOnClickListener(this);
    187         mRefreshButton = (Button)findViewById(R.id.wifi_setup_refresh_list);
    188         mRefreshButton.setOnClickListener(this);
    189         mSkipOrNextButton = (Button)findViewById(R.id.wifi_setup_skip_or_next);
    190         mSkipOrNextButton.setOnClickListener(this);
    191         mConnectButton = (Button)findViewById(R.id.wifi_setup_connect);
    192         mConnectButton.setOnClickListener(this);
    193         mBackButton = (Button)findViewById(R.id.wifi_setup_cancel);
    194         mBackButton.setOnClickListener(this);
    195 
    196         mTopPadding = findViewById(R.id.top_padding);
    197         mContentPadding = findViewById(R.id.content_padding);
    198 
    199         mWifiSettingsFragmentLayout = findViewById(R.id.wifi_settings_fragment_layout);
    200         mConnectingStatusLayout = findViewById(R.id.connecting_status_layout);
    201         mConnectingStatusView = (TextView) findViewById(R.id.connecting_status);
    202     }
    203 
    204     private class WifiServiceHandler extends Handler {
    205         @Override
    206         public void handleMessage(Message msg) {
    207             switch (msg.what) {
    208                 case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
    209                     if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
    210                         //AsyncChannel in msg.obj
    211                     } else {
    212                         //AsyncChannel set up failure, ignore
    213                         Log.e(TAG, "Failed to establish AsyncChannel connection");
    214                     }
    215                     break;
    216                 default:
    217                     //Ignore
    218                     break;
    219             }
    220         }
    221     }
    222 
    223     private void restoreFirstVisibilityState() {
    224         showDefaultTitle();
    225         mAddNetworkButton.setVisibility(View.VISIBLE);
    226         mRefreshButton.setVisibility(View.VISIBLE);
    227         mSkipOrNextButton.setVisibility(View.VISIBLE);
    228         mConnectButton.setVisibility(View.GONE);
    229         mBackButton.setVisibility(View.GONE);
    230         setPaddingVisibility(View.VISIBLE);
    231     }
    232 
    233     @Override
    234     public void onClick(View view) {
    235         hideSoftwareKeyboard();
    236         if (view == mAddNetworkButton) {
    237             if (DEBUG) Log.d(TAG, "AddNetwork button pressed");
    238             onAddNetworkButtonPressed();
    239         } else if (view == mRefreshButton) {
    240             if (DEBUG) Log.d(TAG, "Refresh button pressed");
    241             refreshAccessPoints(true);
    242         } else if (view == mSkipOrNextButton) {
    243             if (DEBUG) Log.d(TAG, "Skip/Next button pressed");
    244             if (TextUtils.equals(getString(R.string.wifi_setup_skip), ((Button)view).getText())) {
    245                 // We don't want to let Wifi enabled when a user press skip without choosing
    246                 // any access point.
    247                 mWifiManager.setWifiEnabled(false);
    248                 // Notify "skip"
    249                 setResult(RESULT_FIRST_USER);
    250             } else {
    251                 setResult(RESULT_OK);
    252             }
    253             finish();
    254         } else if (view == mConnectButton) {
    255             if (DEBUG) Log.d(TAG, "Connect button pressed");
    256             onConnectButtonPressed();
    257         } else if (view == mBackButton) {
    258             if (DEBUG) Log.d(TAG, "Back button pressed");
    259             onBackButtonPressed();
    260         }
    261     }
    262 
    263     private void hideSoftwareKeyboard() {
    264         if (DEBUG) Log.i(TAG, "Hiding software keyboard.");
    265         final View focusedView = getCurrentFocus();
    266         if (focusedView != null) {
    267             mInputMethodManager.hideSoftInputFromWindow(focusedView.getWindowToken(), 0);
    268         }
    269     }
    270 
    271     // Called from WifiSettings
    272     /* package */ void updateConnectionState(DetailedState originalState) {
    273         final DetailedState state = sNetworkStateMap.get(originalState);
    274 
    275         if (originalState == DetailedState.FAILED) {
    276             // We clean up the current connectivity status and let users select another network
    277             // if they want.
    278             refreshAccessPoints(true);
    279         }
    280 
    281         switch (state) {
    282         case SCANNING: {
    283             if (mScreenState == SCREEN_STATE_DISCONNECTED) {
    284                 if (mWifiSettings.getAccessPointsCount() == 0) {
    285                     showScanningState();
    286                 } else {
    287                     showDisconnectedProgressBar();
    288                     mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE);
    289                     mBottomPadding.setVisibility(View.GONE);
    290                 }
    291             } else {
    292                 showDisconnectedProgressBar();
    293             }
    294             break;
    295         }
    296         case CONNECTING: {
    297             if (mScreenState == SCREEN_STATE_CONNECTING) {
    298                 showConnectingState();
    299             }
    300             break;
    301         }
    302         case CONNECTED: {
    303             showConnectedState();
    304             break;
    305         }
    306         default:  // DISCONNECTED, FAILED
    307             if (mScreenState != SCREEN_STATE_CONNECTED &&
    308                     mWifiSettings.getAccessPointsCount() > 0) {
    309                 showDisconnectedState(Summary.get(this, state));
    310             }
    311             break;
    312         }
    313         mPreviousNetworkState = state;
    314     }
    315 
    316     private void showDisconnectedState(String stateString) {
    317         showDisconnectedProgressBar();
    318         if (mScreenState == SCREEN_STATE_DISCONNECTED &&
    319                 mWifiSettings.getAccessPointsCount() > 0) {
    320             mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE);
    321             mBottomPadding.setVisibility(View.GONE);
    322         }
    323         mAddNetworkButton.setEnabled(true);
    324         mRefreshButton.setEnabled(true);
    325     }
    326 
    327     private void showConnectingState() {
    328         mScreenState = SCREEN_STATE_CONNECTING;
    329 
    330         mBackButton.setVisibility(View.VISIBLE);
    331         // We save this title and show it when authentication failed.
    332         mEditingTitle = mTitleView.getText();
    333         showConnectingTitle();
    334         showConnectingProgressBar();
    335 
    336         setPaddingVisibility(View.VISIBLE);
    337     }
    338 
    339     private void showConnectedState() {
    340         // Once we show "connected" screen, we won't change it even when the device becomes
    341         // disconnected afterwards. We keep the state unless a user explicitly cancel it
    342         // (by pressing "back" button).
    343         mScreenState = SCREEN_STATE_CONNECTED;
    344 
    345         hideSoftwareKeyboard();
    346         setPaddingVisibility(View.VISIBLE);
    347 
    348         showConnectedTitle();
    349         showConnectedProgressBar();
    350 
    351         mWifiSettingsFragmentLayout.setVisibility(View.GONE);
    352         mConnectingStatusLayout.setVisibility(View.VISIBLE);
    353 
    354         mConnectingStatusView.setText(R.string.wifi_setup_description_connected);
    355         mConnectButton.setVisibility(View.GONE);
    356         mAddNetworkButton.setVisibility(View.GONE);
    357         mRefreshButton.setVisibility(View.GONE);
    358         mBackButton.setVisibility(View.VISIBLE);
    359         mBackButton.setText(R.string.wifi_setup_back);
    360         mSkipOrNextButton.setVisibility(View.VISIBLE);
    361         mSkipOrNextButton.setEnabled(true);
    362     }
    363 
    364     private void showDefaultTitle() {
    365         mTitleView.setText(getString(R.string.wifi_setup_title));
    366     }
    367 
    368     private void showAddNetworkTitle() {
    369         mNetworkName = "";
    370         mTitleView.setText(R.string.wifi_setup_title_add_network);
    371     }
    372 
    373     private void showEditingTitle() {
    374         if (TextUtils.isEmpty(mNetworkName) && mWifiConfig != null) {
    375             if (mWifiConfig.getController() != null &&
    376                 mWifiConfig.getController().getConfig() != null) {
    377                 mNetworkName = mWifiConfig.getController().getConfig().SSID;
    378             } else {
    379                 Log.w(TAG, "Unexpected null found (WifiController or WifiConfig is null). " +
    380                         "Ignore them.");
    381             }
    382         }
    383         mTitleView.setText(getString(R.string.wifi_setup_title_editing_network, mNetworkName));
    384     }
    385 
    386     private void showConnectingTitle() {
    387         if (TextUtils.isEmpty(mNetworkName) && mWifiConfig != null) {
    388             if (mWifiConfig.getController() != null &&
    389                     mWifiConfig.getController().getConfig() != null) {
    390                 mNetworkName = mWifiConfig.getController().getConfig().SSID;
    391             } else {
    392                 Log.w(TAG, "Unexpected null found (WifiController or WifiConfig is null). " +
    393                         "Ignore them.");
    394             }
    395         }
    396         mTitleView.setText(getString(R.string.wifi_setup_title_connecting_network, mNetworkName));
    397     }
    398 
    399     private void showConnectedTitle() {
    400         if (TextUtils.isEmpty(mNetworkName) && mWifiConfig != null) {
    401             if (mWifiConfig.getController() != null &&
    402                     mWifiConfig.getController().getConfig() != null) {
    403                 mNetworkName = mWifiConfig.getController().getConfig().SSID;
    404             } else {
    405                 Log.w(TAG, "Unexpected null found (WifiController or WifiConfig is null). " +
    406                         "Ignore them.");
    407             }
    408         }
    409         mTitleView.setText(getString(R.string.wifi_setup_title_connected_network, mNetworkName));
    410     }
    411 
    412     /**
    413      * Shows top divider with ProgressBar without defining the state of the ProgressBar.
    414      *
    415      * @see #showScanningProgressBar()
    416      * @see #showConnectedProgressBar()
    417      * @see #showConnectingProgressBar()
    418      */
    419     private void showTopDividerWithProgressBar() {
    420         mProgressBar.setVisibility(View.VISIBLE);
    421         mTopDividerNoProgress.setVisibility(View.GONE);
    422         mBottomPadding.setVisibility(View.GONE);
    423     }
    424 
    425     private void showScanningState() {
    426         setPaddingVisibility(View.VISIBLE);
    427         mWifiSettingsFragmentLayout.setVisibility(View.GONE);
    428         showScanningProgressBar();
    429     }
    430 
    431     private void onAddNetworkButtonPressed() {
    432         mWifiSettings.onAddNetworkPressed();
    433     }
    434 
    435     /**
    436      * Called when the screen enters wifi configuration UI. UI widget for configuring network
    437      * (a.k.a. ConfigPreference) should be taken care of by caller side.
    438      * This method should handle buttons' visibility/enabled.
    439      * @param selectedAccessPoint AccessPoint object being selected. null when a user pressed
    440      * "Add network" button, meaning there's no selected access point.
    441      */
    442     /* package */ void showConfigUi(AccessPoint selectedAccessPoint, boolean edit) {
    443         mScreenState = SCREEN_STATE_EDITING;
    444 
    445         if (selectedAccessPoint != null &&
    446                 (selectedAccessPoint.security == AccessPoint.SECURITY_WEP ||
    447                         selectedAccessPoint.security == AccessPoint.SECURITY_PSK)) {
    448             // We forcibly set edit as true so that users can modify every field if they want,
    449             // while config UI doesn't allow them to edit some of them when edit is false
    450             // (e.g. password field is hiden when edit==false).
    451             edit = true;
    452         }
    453 
    454         // We don't want to keep scanning Wifi networks during users' configuring a network.
    455         mWifiSettings.pauseWifiScan();
    456 
    457         mWifiSettingsFragmentLayout.setVisibility(View.GONE);
    458         mConnectingStatusLayout.setVisibility(View.GONE);
    459         final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui);
    460         parent.setVisibility(View.VISIBLE);
    461         parent.removeAllViews();
    462         mWifiConfig = new WifiConfigUiForSetupWizardXL(this, parent, selectedAccessPoint, edit);
    463 
    464         if (selectedAccessPoint == null) {  // "Add network" flow
    465             showAddNetworkTitle();
    466             mConnectButton.setVisibility(View.VISIBLE);
    467 
    468             showDisconnectedProgressBar();
    469             showEditingButtonState();
    470         } else if (selectedAccessPoint.security == AccessPoint.SECURITY_NONE) {
    471             mNetworkName = selectedAccessPoint.getTitle().toString();
    472 
    473             // onConnectButtonPressed() will change visibility status.
    474             mConnectButton.performClick();
    475         } else {
    476             mNetworkName = selectedAccessPoint.getTitle().toString();
    477             showEditingTitle();
    478             showDisconnectedProgressBar();
    479             showEditingButtonState();
    480             if (selectedAccessPoint.security == AccessPoint.SECURITY_EAP) {
    481                 onEapNetworkSelected();
    482             } else {
    483                 mConnectButton.setVisibility(View.VISIBLE);
    484 
    485                 // WifiConfigController shows Connect button as "Save" when edit==true and a user
    486                 // tried to connect the network.
    487                 // In SetupWizard, we just show the button as "Connect" instead.
    488                 mConnectButton.setText(R.string.wifi_connect);
    489                 mBackButton.setText(R.string.wifi_setup_cancel);
    490             }
    491         }
    492     }
    493 
    494     /**
    495      * Called before security fields are correctly set by {@link WifiConfigController}.
    496      *
    497      * @param view security field view
    498      * @param accessPointSecurity type of security. e.g. AccessPoint.SECURITY_NONE
    499      * @return true when it is ok for the caller to init security fields. false when
    500      * all security fields are managed by this method, and thus the caller shouldn't touch them.
    501      */
    502     /* package */ boolean initSecurityFields(View view, int accessPointSecurity) {
    503         // Reset all states tweaked below.
    504         view.findViewById(R.id.eap_not_supported).setVisibility(View.GONE);
    505         view.findViewById(R.id.eap_not_supported_for_add_network).setVisibility(View.GONE);
    506         view.findViewById(R.id.ssid_text).setVisibility(View.VISIBLE);
    507         view.findViewById(R.id.ssid_layout).setVisibility(View.VISIBLE);
    508 
    509         if (accessPointSecurity == AccessPoint.SECURITY_EAP) {
    510             setPaddingVisibility(View.VISIBLE);
    511             hideSoftwareKeyboard();
    512 
    513             // In SetupWizard for XLarge screen, we don't have enough space for showing
    514             // configurations needed for EAP. We instead disable the whole feature there and let
    515             // users configure those networks after the setup.
    516             if (view.findViewById(R.id.type_ssid).getVisibility() == View.VISIBLE) {
    517                 view.findViewById(R.id.eap_not_supported_for_add_network)
    518                         .setVisibility(View.VISIBLE);
    519             } else {
    520                 view.findViewById(R.id.eap_not_supported).setVisibility(View.VISIBLE);
    521             }
    522             view.findViewById(R.id.security_fields).setVisibility(View.GONE);
    523             view.findViewById(R.id.ssid_text).setVisibility(View.GONE);
    524             view.findViewById(R.id.ssid_layout).setVisibility(View.GONE);
    525             onEapNetworkSelected();
    526 
    527             // This method did init security fields by itself. The caller must not do it.
    528             return false;
    529         }
    530 
    531         mConnectButton.setVisibility(View.VISIBLE);
    532         setPaddingVisibility(View.GONE);
    533 
    534         // In "add network" flow, we'll see multiple initSecurityFields() calls with different
    535         // accessPointSecurity variable. We want to show software keyboard conditionally everytime
    536         // when this method is called.
    537         if (mWifiConfig != null) {
    538             if (accessPointSecurity == AccessPoint.SECURITY_PSK ||
    539                     accessPointSecurity == AccessPoint.SECURITY_WEP) {
    540                 mWifiConfig.requestFocusAndShowKeyboard(R.id.password);
    541             } else {
    542                 mWifiConfig.requestFocusAndShowKeyboard(R.id.ssid);
    543             }
    544         }
    545 
    546         // Let the caller init security fields.
    547         return true;
    548     }
    549 
    550     private void onEapNetworkSelected() {
    551         mConnectButton.setVisibility(View.GONE);
    552         mBackButton.setText(R.string.wifi_setup_back);
    553     }
    554 
    555     private void showEditingButtonState() {
    556         mSkipOrNextButton.setVisibility(View.GONE);
    557         mAddNetworkButton.setVisibility(View.GONE);
    558         mRefreshButton.setVisibility(View.GONE);
    559         mBackButton.setVisibility(View.VISIBLE);
    560     }
    561 
    562     // May be called when user press "connect" button in WifiDialog
    563     /* package */ void onConnectButtonPressed() {
    564         mScreenState = SCREEN_STATE_CONNECTING;
    565 
    566         mWifiSettings.submit(mWifiConfig.getController());
    567 
    568         // updateConnectionState() isn't called soon by the main Wifi module after the user's
    569         // "connect" request, and the user still sees "not connected" message for a while, which
    570         // looks strange for users though legitimate from the view of the module.
    571         //
    572         // We instead manually show "connecting" message before the system gets actual
    573         // "connecting" message from Wifi module.
    574         showConnectingState();
    575 
    576         // Might be better to delay showing this button.
    577         mBackButton.setVisibility(View.VISIBLE);
    578         mBackButton.setText(R.string.wifi_setup_back);
    579 
    580         final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui);
    581         parent.setVisibility(View.GONE);
    582         mConnectingStatusLayout.setVisibility(View.VISIBLE);
    583         mConnectingStatusView.setText(R.string.wifi_setup_description_connecting);
    584 
    585         mSkipOrNextButton.setVisibility(View.VISIBLE);
    586         mSkipOrNextButton.setEnabled(false);
    587         mConnectButton.setVisibility(View.GONE);
    588         mAddNetworkButton.setVisibility(View.GONE);
    589         mRefreshButton.setVisibility(View.GONE);
    590     }
    591 
    592     private void onBackButtonPressed() {
    593 
    594         if (mScreenState == SCREEN_STATE_CONNECTING || mScreenState == SCREEN_STATE_CONNECTED) {
    595             if (DEBUG) Log.d(TAG, "Back button pressed after connect action.");
    596             mScreenState = SCREEN_STATE_DISCONNECTED;
    597 
    598             // When a user press "Back" button after pressing "Connect" button, we want to cancel
    599             // the "Connect" request and refresh the whole Wifi status.
    600             restoreFirstVisibilityState();
    601 
    602             mSkipOrNextButton.setEnabled(true);
    603             changeNextButtonState(false);  // Skip
    604 
    605             // Wifi list becomes empty for a moment. We show "scanning" effect to a user so that
    606             // he/she won't be astonished there. This stops once the scan finishes.
    607             showScanningState();
    608 
    609             // Remembered networks may be re-used during SetupWizard, which confuse users.
    610             // We force the module to forget them to reduce UX complexity
    611             final List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
    612             for (WifiConfiguration config : configs) {
    613                 if (DEBUG) {
    614                     Log.d(TAG, String.format("forgeting Wi-Fi network \"%s\" (id: %d)",
    615                             config.SSID, config.networkId));
    616                 }
    617                 mWifiManager.forgetNetwork(config.networkId);
    618             }
    619 
    620             mWifiSettingsFragmentLayout.setVisibility(View.GONE);
    621             refreshAccessPoints(true);
    622         } else { // During user's Wifi configuration.
    623             mScreenState = SCREEN_STATE_DISCONNECTED;
    624             mWifiSettings.resumeWifiScan();
    625 
    626             restoreFirstVisibilityState();
    627 
    628             mAddNetworkButton.setEnabled(true);
    629             mRefreshButton.setEnabled(true);
    630             mSkipOrNextButton.setEnabled(true);
    631             showDisconnectedProgressBar();
    632             mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE);
    633             mBottomPadding.setVisibility(View.GONE);
    634         }
    635 
    636         setPaddingVisibility(View.VISIBLE);
    637         mConnectingStatusLayout.setVisibility(View.GONE);
    638         final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui);
    639         parent.removeAllViews();
    640         parent.setVisibility(View.GONE);
    641         mWifiConfig = null;
    642     }
    643 
    644     /**
    645      * @param connected true when the device is connected to a specific network.
    646      */
    647     /* package */ void changeNextButtonState(boolean connected) {
    648         if (connected) {
    649             mSkipOrNextButton.setText(R.string.wifi_setup_next);
    650         } else {
    651             mSkipOrNextButton.setText(R.string.wifi_setup_skip);
    652         }
    653     }
    654 
    655     /**
    656      * Called when the list of AccessPoints are modified and this Activity needs to refresh
    657      * the list.
    658      * @param preferenceScreen
    659      */
    660     /* package */ void onAccessPointsUpdated(
    661             PreferenceScreen preferenceScreen, Collection<AccessPoint> accessPoints) {
    662         // If we already show some of access points but the bar still shows "scanning" state, it
    663         // should be stopped.
    664         if (mProgressBar.isIndeterminate() && accessPoints.size() > 0) {
    665             showDisconnectedProgressBar();
    666             if (mScreenState == SCREEN_STATE_DISCONNECTED) {
    667                 mWifiSettingsFragmentLayout.setVisibility(View.VISIBLE);
    668                 mBottomPadding.setVisibility(View.GONE);
    669             }
    670             mAddNetworkButton.setEnabled(true);
    671             mRefreshButton.setEnabled(true);
    672         }
    673 
    674         for (AccessPoint accessPoint : accessPoints) {
    675             accessPoint.setLayoutResource(R.layout.custom_preference);
    676             preferenceScreen.addPreference(accessPoint);
    677         }
    678     }
    679 
    680     private void refreshAccessPoints(boolean disconnectNetwork) {
    681         showScanningState();
    682 
    683         if (disconnectNetwork) {
    684             mWifiManager.disconnect();
    685         }
    686 
    687         mWifiSettings.refreshAccessPoints();
    688     }
    689 
    690     /**
    691      * Called when {@link WifiSettings} received
    692      * {@link WifiManager#SUPPLICANT_STATE_CHANGED_ACTION}.
    693      */
    694     /* package */ void onSupplicantStateChanged(Intent intent) {
    695         final int errorCode = intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, -1);
    696         if (errorCode == WifiManager.ERROR_AUTHENTICATING) {
    697             Log.i(TAG, "Received authentication error event.");
    698             onAuthenticationFailure();
    699         }
    700     }
    701 
    702     /**
    703      * Called once when Authentication failed.
    704      */
    705     private void onAuthenticationFailure() {
    706         mScreenState = SCREEN_STATE_EDITING;
    707 
    708         mSkipOrNextButton.setVisibility(View.GONE);
    709         mConnectButton.setVisibility(View.VISIBLE);
    710         mConnectButton.setEnabled(true);
    711 
    712         if (!TextUtils.isEmpty(mEditingTitle)) {
    713             mTitleView.setText(mEditingTitle);
    714         } else {
    715             Log.w(TAG, "Title during editing/adding a network was empty.");
    716             showEditingTitle();
    717         }
    718 
    719         final ViewGroup parent = (ViewGroup)findViewById(R.id.wifi_config_ui);
    720         parent.setVisibility(View.VISIBLE);
    721         mConnectingStatusLayout.setVisibility(View.GONE);
    722 
    723         showDisconnectedProgressBar();
    724         setPaddingVisibility(View.GONE);
    725     }
    726 
    727     // Used by WifiConfigUiForSetupWizardXL
    728     /* package */ void setPaddingVisibility(int visibility) {
    729         mTopPadding.setVisibility(visibility);
    730         mContentPadding.setVisibility(visibility);
    731     }
    732 
    733     private void showDisconnectedProgressBar() {
    734         // The device may report DISCONNECTED during connecting to a network, at which we don't
    735         // want to lose bottom padding of top divider implicitly added by ProgressBar.
    736         if (mScreenState == SCREEN_STATE_DISCONNECTED) {
    737             mProgressBar.setVisibility(View.GONE);
    738             mProgressBar.setIndeterminate(false);
    739             mTopDividerNoProgress.setVisibility(View.VISIBLE);
    740         } else {
    741             mProgressBar.setVisibility(View.VISIBLE);
    742             mProgressBar.setIndeterminate(false);
    743             mProgressBar.setProgress(0);
    744             mTopDividerNoProgress.setVisibility(View.GONE);
    745         }
    746     }
    747 
    748     /**
    749      * Shows top divider with ProgressBar, whose state is intermediate.
    750      */
    751     private void showScanningProgressBar() {
    752         showTopDividerWithProgressBar();
    753         mProgressBar.setIndeterminate(true);
    754     }
    755 
    756     /**
    757      * Shows top divider with ProgressBar, showing "connecting" state.
    758      */
    759     private void showConnectingProgressBar() {
    760         showTopDividerWithProgressBar();
    761         mProgressBar.setIndeterminate(false);
    762         mProgressBar.setProgress(1);
    763     }
    764 
    765     private void showConnectedProgressBar() {
    766         showTopDividerWithProgressBar();
    767         mProgressBar.setIndeterminate(false);
    768         mProgressBar.setProgress(2);
    769     }
    770 
    771     /**
    772      * Called when WifiManager is requested to save a network.
    773      */
    774     /* package */ void onSaveNetwork(WifiConfiguration config) {
    775         // We want to both save and connect a network. connectNetwork() does both.
    776         mWifiManager.connectNetwork(config);
    777     }
    778 }
    779