1/* 2 * Copyright (C) 2014 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.tv.settings.connectivity.setup; 18 19import android.animation.Animator; 20import android.animation.ObjectAnimator; 21import android.app.Fragment; 22import android.app.FragmentManager; 23import android.app.FragmentTransaction; 24import android.content.Context; 25import android.content.Intent; 26import android.net.ConnectivityManager; 27import android.net.NetworkInfo; 28import android.net.wifi.ScanResult; 29import android.net.wifi.WifiConfiguration; 30import android.net.wifi.WifiInfo; 31import android.net.wifi.WifiManager; 32import android.os.Bundle; 33import android.os.Handler; 34import android.os.Message; 35import android.text.TextUtils; 36import android.util.Pair; 37 38import com.android.tv.settings.R; 39import com.android.tv.settings.connectivity.AdvancedWifiOptionsFlow; 40import com.android.tv.settings.connectivity.ConnectToWifiFragment; 41import com.android.tv.settings.connectivity.FormPageDisplayer; 42import com.android.tv.settings.connectivity.TimedMessageWizardFragment; 43import com.android.tv.settings.connectivity.WifiConfigHelper; 44import com.android.tv.settings.connectivity.WifiFormPageType; 45import com.android.tv.settings.connectivity.WifiMultiPagedFormActivity; 46import com.android.tv.settings.connectivity.WifiSecurity; 47import com.android.tv.settings.connectivity.WpsConnectionActivity; 48import com.android.tv.settings.connectivity.setup.SelectFromListWizardFragment.ListItem; 49import com.android.tv.settings.form.FormPage; 50import com.android.tv.settings.form.FormPageResultListener; 51import com.android.tv.settings.util.ThemeHelper; 52import com.android.tv.settings.util.TransitionUtils; 53 54import java.util.ArrayList; 55import java.util.Collections; 56import java.util.HashMap; 57import java.util.List; 58 59/** 60 * Wi-Fi settings during initial setup for a large no-touch device 61 */ 62public class WifiSetupActivity extends WifiMultiPagedFormActivity 63 implements ConnectToWifiFragment.Listener, TimedMessageWizardFragment.Listener { 64 65 private static final String TAG = "WifiSetupActivity"; 66 private static final int MSG_NETWORK_REFRESH = 1; 67 private static final int NETWORK_REFRESH_TIMEOUT = 5000; 68 private static final String EXTRA_SHOW_SUMMARY = "extra_show_summary"; 69 private static final String EXTRA_SHOW_SKIP_NETWORK = "extra_show_skip_network"; 70 private static final String EXTRA_SHOW_WPS_AT_TOP = "extra_show_wps_at_top"; 71 // If you change this constant, make sure to change the constant in setup wizard 72 private static final int RESULT_NETWORK_SKIPPED = 3; 73 74 private boolean mShowSkipNetwork; 75 private boolean mShowWpsAtTop; 76 private AdvancedWifiOptionsFlow mAdvancedWifiOptionsFlow; 77 private WifiManager mWifiManager; 78 private WifiConfiguration mConfiguration; 79 private String mConnectedNetwork; 80 private WifiSecurity mWifiSecurity; 81 private Handler mHandler; 82 private FormPageDisplayer.UserActivityListener mUserActivityListener; 83 private FormPage mChooseNetworkPage; 84 private FormPage mSsidPage; 85 private FormPage mSecurityPage; 86 private FormPage mPasswordPage; 87 private SelectFromListWizardFragment mNetworkListFragment; 88 private FormPage mConnectPage; 89 private FormPage mSuccessPage; 90 91 @Override 92 protected void onCreate(Bundle savedInstanceState) { 93 setTheme(ThemeHelper.getThemeResource(getIntent())); 94 95 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 96 mConfiguration = new WifiConfiguration(); 97 98 mHandler = new Handler() { 99 @Override 100 public void handleMessage(Message msg) { 101 if (mNetworkListFragment != null) { 102 mNetworkListFragment.update(WifiFormPageType.CHOOSE_NETWORK.getChoices( 103 WifiSetupActivity.this, getNetworks())); 104 mHandler.sendEmptyMessageDelayed(MSG_NETWORK_REFRESH, NETWORK_REFRESH_TIMEOUT); 105 } 106 } 107 }; 108 mUserActivityListener = new FormPageDisplayer.UserActivityListener() { 109 @Override 110 public void onUserActivity() { 111 mHandler.removeMessages(MSG_NETWORK_REFRESH); 112 mHandler.sendEmptyMessageDelayed(MSG_NETWORK_REFRESH, NETWORK_REFRESH_TIMEOUT); 113 } 114 }; 115 116 boolean showSummary = getIntent().getBooleanExtra(EXTRA_SHOW_SUMMARY, false); 117 mShowSkipNetwork = getIntent().getBooleanExtra(EXTRA_SHOW_SKIP_NETWORK, false); 118 mShowWpsAtTop = getIntent().getBooleanExtra(EXTRA_SHOW_WPS_AT_TOP, false); 119 120 if (showSummary) { 121 addSummaryPage(); 122 } else { 123 addPage(WifiFormPageType.CHOOSE_NETWORK); 124 } 125 126 super.onCreate(savedInstanceState); 127 128 // fade in 129 ObjectAnimator animator = TransitionUtils.createActivityFadeInAnimator(getResources(), 130 true); 131 animator.setTarget(getContentView()); 132 animator.start(); 133 } 134 135 @Override 136 public void finish() { 137 // fade out and really finish when we're done 138 ObjectAnimator animator = TransitionUtils.createActivityFadeOutAnimator(getResources(), 139 true); 140 animator.setTarget(getContentView()); 141 animator.addListener(new Animator.AnimatorListener() { 142 143 @Override 144 public void onAnimationStart(Animator animation) { 145 } 146 147 @Override 148 public void onAnimationRepeat(Animator animation) { 149 } 150 151 @Override 152 public void onAnimationEnd(Animator animation) { 153 doFinish(); 154 } 155 156 @Override 157 public void onAnimationCancel(Animator animation) { 158 } 159 }); 160 animator.start(); 161 } 162 163 @Override 164 public void onConnectToWifiCompleted(int reason) { 165 Bundle result = new Bundle(); 166 result.putString(FormPage.DATA_KEY_SUMMARY_STRING, Integer.toString(reason)); 167 onBundlePageResult(mConnectPage, result); 168 } 169 170 @Override 171 public void onTimedMessageCompleted() { 172 Bundle result = new Bundle(); 173 result.putString(FormPage.DATA_KEY_SUMMARY_STRING, ""); 174 onBundlePageResult(mSuccessPage, result); 175 } 176 177 @Override 178 public void addPage(WifiFormPageType formPageType) { 179 for (int i = mFormPages.size() - 1; i >= 0; i--) { 180 if (getFormPageType(mFormPages.get (i)) == formPageType) { 181 for (int j = mFormPages.size() - 1; j >= i; j--) { 182 mFormPages.remove(j); 183 } 184 break; 185 } 186 } 187 addPage(formPageType.create()); 188 } 189 190 @Override 191 protected boolean onPageComplete(WifiFormPageType formPageType, FormPage formPage) { 192 193 switch (formPageType) { 194 case KNOWN_NETWORK: 195 if (choiceChosen(formPage, R.string.wifi_connect)) { 196 addStartPage(); 197 } else if (choiceChosen(formPage, R.string.wifi_forget_network)) { 198 ((WifiManager) getSystemService(Context.WIFI_SERVICE)).forget( 199 mConfiguration.networkId, null); 200 addPage(WifiFormPageType.CHOOSE_NETWORK); 201 } 202 break; 203 case CHOOSE_NETWORK: 204 if (choiceChosen(formPage, R.string.skip_network)) { 205 WifiConfigHelper.forgetWifiNetwork(this); 206 setResult(RESULT_NETWORK_SKIPPED); 207 } else { 208 mHandler.removeMessages(MSG_NETWORK_REFRESH); 209 mNetworkListFragment = null; 210 mChooseNetworkPage = formPage; 211 addPageBasedOnNetworkChoice(mChooseNetworkPage); 212 } 213 break; 214 case ENTER_SSID: 215 mSsidPage = formPage; 216 String ssid = formPage.getDataSummary(); 217 WifiConfigHelper.setConfigSsid(mConfiguration, ssid); 218 addPage(WifiFormPageType.CHOOSE_SECURITY); 219 break; 220 case CHOOSE_SECURITY: 221 mSecurityPage = formPage; 222 if (choiceChosen(formPage, R.string.wifi_security_type_none)) { 223 mWifiSecurity = WifiSecurity.NONE; 224 } else if (choiceChosen(formPage, R.string.wifi_security_type_wep)) { 225 mWifiSecurity = WifiSecurity.WEP; 226 } else if (choiceChosen(formPage, R.string.wifi_security_type_wpa)) { 227 mWifiSecurity = WifiSecurity.PSK; 228 } else if (choiceChosen(formPage, R.string.wifi_security_type_eap)) { 229 mWifiSecurity = WifiSecurity.EAP; 230 } 231 WifiConfigHelper.setConfigKeyManagementBySecurity(mConfiguration, mWifiSecurity); 232 if (mWifiSecurity == WifiSecurity.NONE) { 233 optionsOrConnect(); 234 } else { 235 addPage(WifiFormPageType.ENTER_PASSWORD); 236 } 237 break; 238 case ENTER_PASSWORD: 239 mPasswordPage = formPage; 240 String password = formPage.getDataSummary(); 241 setWifiConfigurationPassword(mConfiguration, mWifiSecurity, password); 242 optionsOrConnect(); 243 break; 244 case CONNECT: 245 switch (Integer.valueOf(formPage.getDataSummary())) { 246 case ConnectToWifiFragment.RESULT_REJECTED_BY_AP: 247 addPage(WifiFormPageType.CONNECT_REJECTED_BY_AP); 248 break; 249 case ConnectToWifiFragment.RESULT_UNKNOWN_ERROR: 250 addPage(WifiFormPageType.CONNECT_FAILED); 251 break; 252 case ConnectToWifiFragment.RESULT_TIMEOUT: 253 addPage(WifiFormPageType.CONNECT_TIMEOUT); 254 break; 255 case ConnectToWifiFragment.RESULT_BAD_AUTHENTICATION: 256 WifiConfigHelper.forgetConfiguration(this, mConfiguration); 257 addPage(WifiFormPageType.CONNECT_AUTHENTICATION_FAILURE); 258 break; 259 case ConnectToWifiFragment.RESULT_SUCCESS: 260 WifiConfigHelper.saveConfiguration(this, mConfiguration); 261 addPage(WifiFormPageType.SUCCESS); 262 break; 263 default: 264 break; 265 } 266 break; 267 case CONNECT_TIMEOUT: 268 mAdvancedWifiOptionsFlow = new AdvancedWifiOptionsFlow(this, this, true, null); 269 // fall through 270 case CONNECT_REJECTED_BY_AP: 271 if (choiceChosen(formPage, R.string.wifi_action_try_again)) { 272 optionsOrConnect(); 273 } else { 274 mSsidPage = null; 275 mSecurityPage = null; 276 mPasswordPage = null; 277 addPage(WifiFormPageType.CHOOSE_NETWORK); 278 } 279 break; 280 case CONNECT_FAILED: 281 // fall through 282 case CONNECT_AUTHENTICATION_FAILURE: 283 if (choiceChosen(formPage, R.string.wifi_action_try_again)) { 284 addPageBasedOnNetworkChoice(mChooseNetworkPage); 285 } else { 286 mSsidPage = null; 287 mSecurityPage = null; 288 mPasswordPage = null; 289 addPage(WifiFormPageType.CHOOSE_NETWORK); 290 } 291 break; 292 case SUMMARY_CONNECTED_WIFI: 293 if (choiceChosen(formPage, R.string.wifi_action_dont_change_network)) { 294 setResult(RESULT_OK); 295 finish(); 296 } else if (choiceChosen(formPage, R.string.wifi_action_change_network)) { 297 addPage(WifiFormPageType.CHOOSE_NETWORK); 298 } 299 break; 300 case SUMMARY_CONNECTED_NON_WIFI: 301 setResult(RESULT_OK); 302 finish(); 303 break; 304 case SUMMARY_NOT_CONNECTED: 305 addPage(WifiFormPageType.CHOOSE_NETWORK); 306 break; 307 case SUCCESS: 308 setResult(RESULT_OK); 309 break; 310 case WPS: 311 setResult(RESULT_OK); 312 break; 313 default: 314 if (mAdvancedWifiOptionsFlow != null) { 315 switch (mAdvancedWifiOptionsFlow.handlePageComplete(formPageType, formPage)) { 316 case AdvancedWifiOptionsFlow.RESULT_ALL_PAGES_COMPLETE: 317 connect(); 318 break; 319 case AdvancedWifiOptionsFlow.RESULT_UNKNOWN_PAGE: 320 case AdvancedWifiOptionsFlow.RESULT_PAGE_HANDLED: 321 default: 322 break; 323 } 324 } 325 break; 326 } 327 return true; 328 } 329 330 @Override 331 protected void displayPage(FormPage formPage, FormPageResultListener listener, 332 boolean forward) { 333 WifiFormPageType formPageType = getFormPageType(formPage); 334 335 if (formPageType == WifiFormPageType.CONNECT) { 336 mConnectPage = formPage; 337 Fragment fragment = ConnectToWifiFragment.newInstance( 338 getString(formPageType.getTitleResourceId(), mConfiguration.getPrintableSsid()), 339 true, mConfiguration); 340 displayFragment(fragment, forward); 341 } else if (formPageType == WifiFormPageType.SUCCESS) { 342 mSuccessPage = formPage; 343 Fragment fragment = TimedMessageWizardFragment.newInstance( 344 getString(formPageType.getTitleResourceId())); 345 displayFragment(fragment, forward); 346 } else if (formPageType == WifiFormPageType.WPS) { 347 displayFragment(MessageWizardFragment.newInstance("", true), forward); 348 } else { 349 Fragment fragment = displayPage(formPageType, mConfiguration.getPrintableSsid(), 350 formPageType == WifiFormPageType.SUMMARY_CONNECTED_WIFI ? mConnectedNetwork 351 : null, 352 formPageType == WifiFormPageType.CHOOSE_NETWORK ? getNetworks() : null, 353 getLastPage(formPageType), 354 formPageType == WifiFormPageType.CHOOSE_NETWORK ? mUserActivityListener : null, 355 formPageType != WifiFormPageType.SUCCESS, formPage, listener, forward, 356 (mAdvancedWifiOptionsFlow != null) ? mAdvancedWifiOptionsFlow 357 .isEmptyTextAllowed(formPageType) : false); 358 if (formPageType == WifiFormPageType.CHOOSE_NETWORK) { 359 mNetworkListFragment = (SelectFromListWizardFragment) fragment; 360 mHandler.sendEmptyMessageDelayed(MSG_NETWORK_REFRESH, NETWORK_REFRESH_TIMEOUT); 361 } 362 } 363 } 364 365 @Override 366 protected void undisplayCurrentPage() { 367 FragmentManager fragMan = getFragmentManager(); 368 Fragment target = fragMan.findFragmentById(R.id.content); 369 FragmentTransaction transaction = fragMan.beginTransaction(); 370 transaction.remove(target); 371 transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_CLOSE); 372 transaction.commit(); 373 } 374 375 private void doFinish() { 376 super.finish(); 377 } 378 379 private void connect() { 380 if (!WifiConfigHelper.isNetworkSaved(mConfiguration) && 381 mAdvancedWifiOptionsFlow != null) { 382 mAdvancedWifiOptionsFlow.updateConfiguration(mConfiguration); 383 } 384 addPage(WifiFormPageType.CONNECT); 385 } 386 387 private void optionsOrConnect() { 388 if (mAdvancedWifiOptionsFlow != null) { 389 addPage(mAdvancedWifiOptionsFlow.getInitialPage()); 390 } else { 391 connect(); 392 } 393 } 394 395 private FormPage getLastPage(WifiFormPageType formPageType) { 396 switch (formPageType) { 397 case CHOOSE_NETWORK: 398 return mChooseNetworkPage; 399 case CHOOSE_SECURITY: 400 return mSecurityPage; 401 case ENTER_PASSWORD: 402 return mPasswordPage; 403 case ENTER_SSID: 404 return mSsidPage; 405 default: 406 return (mAdvancedWifiOptionsFlow != null) ? mAdvancedWifiOptionsFlow 407 .getPreviousPage(formPageType) 408 : null; 409 } 410 } 411 412 private ArrayList<ListItem> getNetworks() { 413 ArrayList<SelectFromListWizardFragment.ListItem> listItems = new ArrayList< 414 SelectFromListWizardFragment.ListItem>(); 415 final List<ScanResult> results = mWifiManager.getScanResults(); 416 final HashMap<Pair<String, WifiSecurity>, ScanResult> consolidatedScanResults = new HashMap< 417 Pair<String, WifiSecurity>, ScanResult>(); 418 for (ScanResult result : results) { 419 if (TextUtils.isEmpty(result.SSID)) { 420 continue; 421 } 422 423 Pair<String, WifiSecurity> key = new Pair<String, WifiSecurity>( 424 result.SSID, WifiSecurity.getSecurity(result)); 425 ScanResult existing = consolidatedScanResults.get(key); 426 if (existing == null || existing.level < result.level) { 427 consolidatedScanResults.put(key, result); 428 } 429 } 430 for (ScanResult result : consolidatedScanResults.values()) { 431 listItems.add(new SelectFromListWizardFragment.ListItem(result)); 432 } 433 Collections.sort(listItems, new SelectFromListWizardFragment.ListItemComparator()); 434 435 SelectFromListWizardFragment.ListItem wpsItem = new SelectFromListWizardFragment.ListItem( 436 getString(R.string.wps_network).toUpperCase(), R.drawable.ic_setup_wps); 437 if (mShowWpsAtTop) { 438 listItems.add(0, wpsItem); 439 } else { 440 listItems.add(wpsItem); 441 } 442 443 if (mShowSkipNetwork) { 444 listItems.add(new SelectFromListWizardFragment.ListItem( 445 getString(R.string.skip_network).toUpperCase(), 0)); 446 } 447 448 return listItems; 449 } 450 451 private void addPageBasedOnNetworkChoice(FormPage chooseNetworkPage) { 452 if (choiceChosen(chooseNetworkPage, R.string.other_network)) { 453 mConfiguration.hiddenSSID = true; 454 addPage(WifiFormPageType.ENTER_SSID); 455 } else if (choiceChosen(chooseNetworkPage, R.string.wps_network)) { 456 addPage(WifiFormPageType.WPS, new Intent(this, WpsConnectionActivity.class) 457 .putExtras(getIntent().getExtras())); 458 } else { 459 ScanResult scanResult = getListItem(chooseNetworkPage).getScanResult(); 460 mConfiguration = WifiConfigHelper.getConfigurationForNetwork(this, scanResult); 461 mWifiSecurity = WifiSecurity.getSecurity(scanResult); 462 463 if (WifiConfigHelper.isNetworkSaved(mConfiguration)) { 464 addPage(WifiFormPageType.KNOWN_NETWORK); 465 } else { 466 addStartPage(); 467 } 468 } 469 } 470 471 private void addStartPage() { 472 if ((mWifiSecurity == WifiSecurity.WEP && TextUtils.isEmpty(mConfiguration.wepKeys[0])) 473 || (!mWifiSecurity.isOpen() && TextUtils.isEmpty(mConfiguration.preSharedKey))) { 474 addPage(WifiFormPageType.ENTER_PASSWORD); 475 } else { 476 connect(); 477 } 478 } 479 480 private void addSummaryPage() { 481 ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService( 482 Context.CONNECTIVITY_SERVICE); 483 NetworkInfo currentConnection = connectivityManager.getActiveNetworkInfo(); 484 boolean isConnected = (currentConnection != null) && currentConnection.isConnected(); 485 if (isConnected) { 486 if (currentConnection.getType() == ConnectivityManager.TYPE_WIFI) { 487 WifiInfo currentWifiConnection = mWifiManager.getConnectionInfo(); 488 mConnectedNetwork = WifiInfo.removeDoubleQuotes( 489 currentWifiConnection.getSSID()); 490 if (mConnectedNetwork == null) { 491 mConnectedNetwork = getString(R.string.wifi_summary_unknown_network); 492 } 493 addPage(WifiFormPageType.SUMMARY_CONNECTED_WIFI); 494 } else { 495 addPage(WifiFormPageType.SUMMARY_CONNECTED_NON_WIFI); 496 } 497 } else { 498 addPage(WifiFormPageType.SUMMARY_NOT_CONNECTED); 499 } 500 } 501} 502