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