• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 {
sNetworkStateMap.put(DetailedState.IDLE, DetailedState.DISCONNECTED)63         sNetworkStateMap.put(DetailedState.IDLE, DetailedState.DISCONNECTED);
sNetworkStateMap.put(DetailedState.SCANNING, DetailedState.SCANNING)64         sNetworkStateMap.put(DetailedState.SCANNING, DetailedState.SCANNING);
sNetworkStateMap.put(DetailedState.CONNECTING, DetailedState.CONNECTING)65         sNetworkStateMap.put(DetailedState.CONNECTING, DetailedState.CONNECTING);
sNetworkStateMap.put(DetailedState.AUTHENTICATING, DetailedState.CONNECTING)66         sNetworkStateMap.put(DetailedState.AUTHENTICATING, DetailedState.CONNECTING);
sNetworkStateMap.put(DetailedState.OBTAINING_IPADDR, DetailedState.CONNECTING)67         sNetworkStateMap.put(DetailedState.OBTAINING_IPADDR, DetailedState.CONNECTING);
sNetworkStateMap.put(DetailedState.CONNECTED, DetailedState.CONNECTED)68         sNetworkStateMap.put(DetailedState.CONNECTED, DetailedState.CONNECTED);
sNetworkStateMap.put(DetailedState.SUSPENDED, DetailedState.SUSPENDED)69         sNetworkStateMap.put(DetailedState.SUSPENDED, DetailedState.SUSPENDED);  // ?
sNetworkStateMap.put(DetailedState.DISCONNECTING, DetailedState.DISCONNECTED)70         sNetworkStateMap.put(DetailedState.DISCONNECTING, DetailedState.DISCONNECTED);
sNetworkStateMap.put(DetailedState.DISCONNECTED, DetailedState.DISCONNECTED)71         sNetworkStateMap.put(DetailedState.DISCONNECTED, DetailedState.DISCONNECTED);
sNetworkStateMap.put(DetailedState.FAILED, DetailedState.FAILED)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
onCreate(Bundle savedInstanceState)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 
initViews()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
handleMessage(Message msg)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 
restoreFirstVisibilityState()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
onClick(View view)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 
hideSoftwareKeyboard()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
updateConnectionState(DetailedState originalState)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 
showDisconnectedState(String stateString)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 
showConnectingState()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 
showConnectedState()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 
showDefaultTitle()364     private void showDefaultTitle() {
365         mTitleView.setText(getString(R.string.wifi_setup_title));
366     }
367 
showAddNetworkTitle()368     private void showAddNetworkTitle() {
369         mNetworkName = "";
370         mTitleView.setText(R.string.wifi_setup_title_add_network);
371     }
372 
showEditingTitle()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 
showConnectingTitle()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 
showConnectedTitle()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      */
showTopDividerWithProgressBar()419     private void showTopDividerWithProgressBar() {
420         mProgressBar.setVisibility(View.VISIBLE);
421         mTopDividerNoProgress.setVisibility(View.GONE);
422         mBottomPadding.setVisibility(View.GONE);
423     }
424 
showScanningState()425     private void showScanningState() {
426         setPaddingVisibility(View.VISIBLE);
427         mWifiSettingsFragmentLayout.setVisibility(View.GONE);
428         showScanningProgressBar();
429     }
430 
onAddNetworkButtonPressed()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      */
showConfigUi(AccessPoint selectedAccessPoint, boolean edit)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      */
initSecurityFields(View view, int accessPointSecurity)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 
onEapNetworkSelected()550     private void onEapNetworkSelected() {
551         mConnectButton.setVisibility(View.GONE);
552         mBackButton.setText(R.string.wifi_setup_back);
553     }
554 
showEditingButtonState()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
onConnectButtonPressed()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 
onBackButtonPressed()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      */
changeNextButtonState(boolean connected)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      */
onAccessPointsUpdated( PreferenceScreen preferenceScreen, Collection<AccessPoint> accessPoints)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 
refreshAccessPoints(boolean disconnectNetwork)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      */
onSupplicantStateChanged(Intent intent)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      */
onAuthenticationFailure()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
setPaddingVisibility(int visibility)728     /* package */ void setPaddingVisibility(int visibility) {
729         mTopPadding.setVisibility(visibility);
730         mContentPadding.setVisibility(visibility);
731     }
732 
showDisconnectedProgressBar()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      */
showScanningProgressBar()751     private void showScanningProgressBar() {
752         showTopDividerWithProgressBar();
753         mProgressBar.setIndeterminate(true);
754     }
755 
756     /**
757      * Shows top divider with ProgressBar, showing "connecting" state.
758      */
showConnectingProgressBar()759     private void showConnectingProgressBar() {
760         showTopDividerWithProgressBar();
761         mProgressBar.setIndeterminate(false);
762         mProgressBar.setProgress(1);
763     }
764 
showConnectedProgressBar()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      */
onSaveNetwork(WifiConfiguration config)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