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