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.content.Context; 20 import android.content.res.Resources; 21 import android.net.IpConfiguration; 22 import android.net.IpConfiguration.IpAssignment; 23 import android.net.IpConfiguration.ProxySettings; 24 import android.net.LinkAddress; 25 import android.net.NetworkInfo.DetailedState; 26 import android.net.NetworkUtils; 27 import android.net.ProxyInfo; 28 import android.net.StaticIpConfiguration; 29 import android.net.Uri; 30 import android.net.wifi.WifiConfiguration; 31 import android.net.wifi.WifiConfiguration.AuthAlgorithm; 32 import android.net.wifi.WifiConfiguration.KeyMgmt; 33 import android.net.wifi.WifiEnterpriseConfig; 34 import android.net.wifi.WifiEnterpriseConfig.Eap; 35 import android.net.wifi.WifiEnterpriseConfig.Phase2; 36 import android.net.wifi.WifiInfo; 37 import android.os.Handler; 38 import android.os.UserManager; 39 import android.security.Credentials; 40 import android.security.KeyStore; 41 import android.text.Editable; 42 import android.text.InputType; 43 import android.text.TextUtils; 44 import android.text.TextWatcher; 45 import android.util.Log; 46 import android.view.KeyEvent; 47 import android.view.View; 48 import android.view.ViewGroup; 49 import android.view.inputmethod.EditorInfo; 50 import android.widget.AdapterView; 51 import android.widget.ArrayAdapter; 52 import android.widget.Button; 53 import android.widget.CheckBox; 54 import android.widget.CompoundButton; 55 import android.widget.CompoundButton.OnCheckedChangeListener; 56 import android.widget.EditText; 57 import android.widget.LinearLayout; 58 import android.widget.Spinner; 59 import android.widget.TextView; 60 61 import com.android.settings.ProxySelector; 62 import com.android.settings.R; 63 import com.android.settings.Utils; 64 import com.android.settingslib.wifi.AccessPoint; 65 66 import java.net.Inet4Address; 67 import java.net.InetAddress; 68 import java.util.ArrayList; 69 import java.util.Arrays; 70 import java.util.Iterator; 71 72 /** 73 * The class for allowing UIs like {@link WifiDialog} and {@link WifiConfigUiBase} to 74 * share the logic for controlling buttons, text fields, etc. 75 */ 76 public class WifiConfigController implements TextWatcher, 77 AdapterView.OnItemSelectedListener, OnCheckedChangeListener, 78 TextView.OnEditorActionListener, View.OnKeyListener{ 79 private static final String TAG = "WifiConfigController"; 80 81 private static final String SYSTEM_CA_STORE_PATH = "/system/etc/security/cacerts"; 82 83 private final WifiConfigUiBase mConfigUi; 84 private final View mView; 85 private final AccessPoint mAccessPoint; 86 87 /* This value comes from "wifi_ip_settings" resource array */ 88 private static final int DHCP = 0; 89 private static final int STATIC_IP = 1; 90 91 /* These values come from "wifi_proxy_settings" resource array */ 92 public static final int PROXY_NONE = 0; 93 public static final int PROXY_STATIC = 1; 94 public static final int PROXY_PAC = 2; 95 96 /* These values come from "wifi_eap_method" resource array */ 97 public static final int WIFI_EAP_METHOD_PEAP = 0; 98 public static final int WIFI_EAP_METHOD_TLS = 1; 99 public static final int WIFI_EAP_METHOD_TTLS = 2; 100 public static final int WIFI_EAP_METHOD_PWD = 3; 101 public static final int WIFI_EAP_METHOD_SIM = 4; 102 public static final int WIFI_EAP_METHOD_AKA = 5; 103 public static final int WIFI_EAP_METHOD_AKA_PRIME = 6; 104 105 /* These values come from "wifi_peap_phase2_entries" resource array */ 106 public static final int WIFI_PEAP_PHASE2_NONE = 0; 107 public static final int WIFI_PEAP_PHASE2_MSCHAPV2 = 1; 108 public static final int WIFI_PEAP_PHASE2_GTC = 2; 109 110 /* Phase2 methods supported by PEAP are limited */ 111 private final ArrayAdapter<String> mPhase2PeapAdapter; 112 /* Full list of phase2 methods */ 113 private final ArrayAdapter<String> mPhase2FullAdapter; 114 115 private final Handler mTextViewChangedHandler; 116 117 // e.g. AccessPoint.SECURITY_NONE 118 private int mAccessPointSecurity; 119 private TextView mPasswordView; 120 121 private String mUnspecifiedCertString; 122 private String mMultipleCertSetString; 123 private String mUseSystemCertsString; 124 private String mDoNotProvideEapUserCertString; 125 private String mDoNotValidateEapServerString; 126 127 private Spinner mSecuritySpinner; 128 private Spinner mEapMethodSpinner; 129 private Spinner mEapCaCertSpinner; 130 private TextView mEapDomainView; 131 private Spinner mPhase2Spinner; 132 // Associated with mPhase2Spinner, one of mPhase2FullAdapter or mPhase2PeapAdapter 133 private ArrayAdapter<String> mPhase2Adapter; 134 private Spinner mEapUserCertSpinner; 135 private TextView mEapIdentityView; 136 private TextView mEapAnonymousView; 137 138 private Spinner mIpSettingsSpinner; 139 private TextView mIpAddressView; 140 private TextView mGatewayView; 141 private TextView mNetworkPrefixLengthView; 142 private TextView mDns1View; 143 private TextView mDns2View; 144 145 private Spinner mProxySettingsSpinner; 146 private TextView mProxyHostView; 147 private TextView mProxyPortView; 148 private TextView mProxyExclusionListView; 149 private TextView mProxyPacView; 150 151 private CheckBox mSharedCheckBox; 152 153 private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED; 154 private ProxySettings mProxySettings = ProxySettings.UNASSIGNED; 155 private ProxyInfo mHttpProxy = null; 156 private StaticIpConfiguration mStaticIpConfiguration = null; 157 158 private String[] mLevels; 159 private int mMode; 160 private TextView mSsidView; 161 162 private Context mContext; 163 164 public WifiConfigController(WifiConfigUiBase parent, View view, AccessPoint accessPoint, 165 int mode) { 166 mConfigUi = parent; 167 168 mView = view; 169 mAccessPoint = accessPoint; 170 mAccessPointSecurity = (accessPoint == null) ? AccessPoint.SECURITY_NONE : 171 accessPoint.getSecurity(); 172 mMode = mode; 173 174 mTextViewChangedHandler = new Handler(); 175 mContext = mConfigUi.getContext(); 176 final Resources res = mContext.getResources(); 177 178 mLevels = res.getStringArray(R.array.wifi_signal); 179 mPhase2PeapAdapter = new ArrayAdapter<String>( 180 mContext, android.R.layout.simple_spinner_item, 181 res.getStringArray(R.array.wifi_peap_phase2_entries)); 182 mPhase2PeapAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 183 184 mPhase2FullAdapter = new ArrayAdapter<String>( 185 mContext, android.R.layout.simple_spinner_item, 186 res.getStringArray(R.array.wifi_phase2_entries)); 187 mPhase2FullAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 188 189 mUnspecifiedCertString = mContext.getString(R.string.wifi_unspecified); 190 mMultipleCertSetString = mContext.getString(R.string.wifi_multiple_cert_added); 191 mUseSystemCertsString = mContext.getString(R.string.wifi_use_system_certs); 192 mDoNotProvideEapUserCertString = 193 mContext.getString(R.string.wifi_do_not_provide_eap_user_cert); 194 mDoNotValidateEapServerString = 195 mContext.getString(R.string.wifi_do_not_validate_eap_server); 196 197 mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings); 198 mIpSettingsSpinner.setOnItemSelectedListener(this); 199 mProxySettingsSpinner = (Spinner) mView.findViewById(R.id.proxy_settings); 200 mProxySettingsSpinner.setOnItemSelectedListener(this); 201 mSharedCheckBox = (CheckBox) mView.findViewById(R.id.shared); 202 203 if (mAccessPoint == null) { // new network 204 mConfigUi.setTitle(R.string.wifi_add_network); 205 206 mSsidView = (TextView) mView.findViewById(R.id.ssid); 207 mSsidView.addTextChangedListener(this); 208 mSecuritySpinner = ((Spinner) mView.findViewById(R.id.security)); 209 mSecuritySpinner.setOnItemSelectedListener(this); 210 mView.findViewById(R.id.type).setVisibility(View.VISIBLE); 211 212 showIpConfigFields(); 213 showProxyFields(); 214 mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE); 215 ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox)) 216 .setOnCheckedChangeListener(this); 217 218 mConfigUi.setSubmitButton(res.getString(R.string.wifi_save)); 219 } else { 220 mConfigUi.setTitle(mAccessPoint.getSsid()); 221 222 ViewGroup group = (ViewGroup) mView.findViewById(R.id.info); 223 224 boolean showAdvancedFields = false; 225 if (mAccessPoint.isSaved()) { 226 WifiConfiguration config = mAccessPoint.getConfig(); 227 if (config.getIpAssignment() == IpAssignment.STATIC) { 228 mIpSettingsSpinner.setSelection(STATIC_IP); 229 showAdvancedFields = true; 230 // Display IP address. 231 StaticIpConfiguration staticConfig = config.getStaticIpConfiguration(); 232 if (staticConfig != null && staticConfig.ipAddress != null) { 233 addRow(group, R.string.wifi_ip_address, 234 staticConfig.ipAddress.getAddress().getHostAddress()); 235 } 236 } else { 237 mIpSettingsSpinner.setSelection(DHCP); 238 } 239 240 mSharedCheckBox.setEnabled(config.shared); 241 if (!config.shared) { 242 showAdvancedFields = true; 243 } 244 245 if (config.getProxySettings() == ProxySettings.STATIC) { 246 mProxySettingsSpinner.setSelection(PROXY_STATIC); 247 showAdvancedFields = true; 248 } else if (config.getProxySettings() == ProxySettings.PAC) { 249 mProxySettingsSpinner.setSelection(PROXY_PAC); 250 showAdvancedFields = true; 251 } else { 252 mProxySettingsSpinner.setSelection(PROXY_NONE); 253 } 254 if (config != null && config.isPasspoint()) { 255 addRow(group, R.string.passpoint_label, 256 String.format(mContext.getString(R.string.passpoint_content), 257 config.providerFriendlyName)); 258 } 259 } 260 261 if ((!mAccessPoint.isSaved() && !mAccessPoint.isActive()) 262 || mMode != WifiConfigUiBase.MODE_VIEW) { 263 showSecurityFields(); 264 showIpConfigFields(); 265 showProxyFields(); 266 final CheckBox advancedTogglebox = 267 (CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox); 268 mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE); 269 advancedTogglebox.setOnCheckedChangeListener(this); 270 advancedTogglebox.setChecked(showAdvancedFields); 271 mView.findViewById(R.id.wifi_advanced_fields) 272 .setVisibility(showAdvancedFields ? View.VISIBLE : View.GONE); 273 } 274 275 if (mMode == WifiConfigUiBase.MODE_MODIFY) { 276 mConfigUi.setSubmitButton(res.getString(R.string.wifi_save)); 277 } else if (mMode == WifiConfigUiBase.MODE_CONNECT) { 278 mConfigUi.setSubmitButton(res.getString(R.string.wifi_connect)); 279 } else { 280 final DetailedState state = mAccessPoint.getDetailedState(); 281 final String signalLevel = getSignalString(); 282 283 if (state == null && signalLevel != null) { 284 mConfigUi.setSubmitButton(res.getString(R.string.wifi_connect)); 285 } else { 286 if (state != null) { 287 boolean isEphemeral = mAccessPoint.isEphemeral(); 288 WifiConfiguration config = mAccessPoint.getConfig(); 289 String providerFriendlyName = null; 290 if (config != null && config.isPasspoint()) { 291 providerFriendlyName = config.providerFriendlyName; 292 } 293 String summary = AccessPoint.getSummary( 294 mConfigUi.getContext(), state, isEphemeral, providerFriendlyName); 295 addRow(group, R.string.wifi_status, summary); 296 } 297 298 if (signalLevel != null) { 299 addRow(group, R.string.wifi_signal, signalLevel); 300 } 301 302 WifiInfo info = mAccessPoint.getInfo(); 303 if (info != null && info.getLinkSpeed() != -1) { 304 addRow(group, R.string.wifi_speed, String.format( 305 res.getString(R.string.link_speed), info.getLinkSpeed())); 306 } 307 308 if (info != null && info.getFrequency() != -1) { 309 final int frequency = info.getFrequency(); 310 String band = null; 311 312 if (frequency >= AccessPoint.LOWER_FREQ_24GHZ 313 && frequency < AccessPoint.HIGHER_FREQ_24GHZ) { 314 band = res.getString(R.string.wifi_band_24ghz); 315 } else if (frequency >= AccessPoint.LOWER_FREQ_5GHZ 316 && frequency < AccessPoint.HIGHER_FREQ_5GHZ) { 317 band = res.getString(R.string.wifi_band_5ghz); 318 } else { 319 Log.e(TAG, "Unexpected frequency " + frequency); 320 } 321 if (band != null) { 322 addRow(group, R.string.wifi_frequency, band); 323 } 324 } 325 326 addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false)); 327 mView.findViewById(R.id.ip_fields).setVisibility(View.GONE); 328 } 329 if (mAccessPoint.isSaved() || mAccessPoint.isActive()) { 330 mConfigUi.setForgetButton(res.getString(R.string.wifi_forget)); 331 } 332 } 333 } 334 335 final UserManager userManager = 336 (UserManager) mContext.getSystemService(Context.USER_SERVICE); 337 if (!userManager.isSplitSystemUser()) { 338 mSharedCheckBox.setVisibility(View.GONE); 339 } 340 341 mConfigUi.setCancelButton(res.getString(R.string.wifi_cancel)); 342 if (mConfigUi.getSubmitButton() != null) { 343 enableSubmitIfAppropriate(); 344 } 345 } 346 347 private void addRow(ViewGroup group, int name, String value) { 348 View row = mConfigUi.getLayoutInflater().inflate(R.layout.wifi_dialog_row, group, false); 349 ((TextView) row.findViewById(R.id.name)).setText(name); 350 ((TextView) row.findViewById(R.id.value)).setText(value); 351 group.addView(row); 352 } 353 354 private String getSignalString() { 355 final int level = mAccessPoint.getLevel(); 356 357 return (level > -1 && level < mLevels.length) ? mLevels[level] : null; 358 } 359 360 void hideForgetButton() { 361 Button forget = mConfigUi.getForgetButton(); 362 if (forget == null) return; 363 364 forget.setVisibility(View.GONE); 365 } 366 367 void hideSubmitButton() { 368 Button submit = mConfigUi.getSubmitButton(); 369 if (submit == null) return; 370 371 submit.setVisibility(View.GONE); 372 } 373 374 /* show submit button if password, ip and proxy settings are valid */ 375 void enableSubmitIfAppropriate() { 376 Button submit = mConfigUi.getSubmitButton(); 377 if (submit == null) return; 378 379 submit.setEnabled(isSubmittable()); 380 } 381 382 boolean isSubmittable() { 383 boolean enabled = false; 384 boolean passwordInvalid = false; 385 386 if (mPasswordView != null 387 && ((mAccessPointSecurity == AccessPoint.SECURITY_WEP 388 && mPasswordView.length() == 0) 389 || (mAccessPointSecurity == AccessPoint.SECURITY_PSK 390 && mPasswordView.length() < 8))) { 391 passwordInvalid = true; 392 } 393 394 if ((mSsidView != null && mSsidView.length() == 0) 395 || ((mAccessPoint == null || !mAccessPoint.isSaved()) && passwordInvalid)) { 396 enabled = false; 397 } else { 398 enabled = ipAndProxyFieldsAreValid(); 399 } 400 if (mEapCaCertSpinner != null 401 && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) { 402 String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem(); 403 if (caCertSelection.equals(mUnspecifiedCertString)) { 404 // Disallow submit if the user has not selected a CA certificate for an EAP network 405 // configuration. 406 enabled = false; 407 } 408 if (caCertSelection.equals(mUseSystemCertsString) 409 && mEapDomainView != null 410 && mView.findViewById(R.id.l_domain).getVisibility() != View.GONE 411 && TextUtils.isEmpty(mEapDomainView.getText().toString())) { 412 // Disallow submit if the user chooses to use system certificates for EAP server 413 // validation, but does not provide a domain. 414 enabled = false; 415 } 416 } 417 if (mEapUserCertSpinner != null 418 && mView.findViewById(R.id.l_user_cert).getVisibility() != View.GONE 419 && ((String) mEapUserCertSpinner.getSelectedItem()) 420 .equals(mUnspecifiedCertString)) { 421 // Disallow submit if the user has not selected a user certificate for an EAP network 422 // configuration. 423 enabled = false; 424 } 425 return enabled; 426 } 427 428 void showWarningMessagesIfAppropriate() { 429 mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.GONE); 430 mView.findViewById(R.id.no_domain_warning).setVisibility(View.GONE); 431 432 if (mEapCaCertSpinner != null 433 && mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) { 434 String caCertSelection = (String) mEapCaCertSpinner.getSelectedItem(); 435 if (caCertSelection.equals(mDoNotValidateEapServerString)) { 436 // Display warning if user chooses not to validate the EAP server with a 437 // user-supplied CA certificate in an EAP network configuration. 438 mView.findViewById(R.id.no_ca_cert_warning).setVisibility(View.VISIBLE); 439 } 440 if (caCertSelection.equals(mUseSystemCertsString) 441 && mEapDomainView != null 442 && mView.findViewById(R.id.l_domain).getVisibility() != View.GONE 443 && TextUtils.isEmpty(mEapDomainView.getText().toString())) { 444 // Display warning if user chooses to use pre-installed public CA certificates 445 // without restricting the server domain that these certificates can be used to 446 // validate. 447 mView.findViewById(R.id.no_domain_warning).setVisibility(View.VISIBLE); 448 } 449 } 450 } 451 452 /* package */ WifiConfiguration getConfig() { 453 if (mMode == WifiConfigUiBase.MODE_VIEW) { 454 return null; 455 } 456 457 WifiConfiguration config = new WifiConfiguration(); 458 459 if (mAccessPoint == null) { 460 config.SSID = AccessPoint.convertToQuotedString( 461 mSsidView.getText().toString()); 462 // If the user adds a network manually, assume that it is hidden. 463 config.hiddenSSID = true; 464 } else if (!mAccessPoint.isSaved()) { 465 config.SSID = AccessPoint.convertToQuotedString( 466 mAccessPoint.getSsidStr()); 467 } else { 468 config.networkId = mAccessPoint.getConfig().networkId; 469 } 470 471 config.shared = mSharedCheckBox.isChecked(); 472 473 switch (mAccessPointSecurity) { 474 case AccessPoint.SECURITY_NONE: 475 config.allowedKeyManagement.set(KeyMgmt.NONE); 476 break; 477 478 case AccessPoint.SECURITY_WEP: 479 config.allowedKeyManagement.set(KeyMgmt.NONE); 480 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); 481 config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); 482 if (mPasswordView.length() != 0) { 483 int length = mPasswordView.length(); 484 String password = mPasswordView.getText().toString(); 485 // WEP-40, WEP-104, and 256-bit WEP (WEP-232?) 486 if ((length == 10 || length == 26 || length == 58) 487 && password.matches("[0-9A-Fa-f]*")) { 488 config.wepKeys[0] = password; 489 } else { 490 config.wepKeys[0] = '"' + password + '"'; 491 } 492 } 493 break; 494 495 case AccessPoint.SECURITY_PSK: 496 config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 497 if (mPasswordView.length() != 0) { 498 String password = mPasswordView.getText().toString(); 499 if (password.matches("[0-9A-Fa-f]{64}")) { 500 config.preSharedKey = password; 501 } else { 502 config.preSharedKey = '"' + password + '"'; 503 } 504 } 505 break; 506 507 case AccessPoint.SECURITY_EAP: 508 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 509 config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); 510 config.enterpriseConfig = new WifiEnterpriseConfig(); 511 int eapMethod = mEapMethodSpinner.getSelectedItemPosition(); 512 int phase2Method = mPhase2Spinner.getSelectedItemPosition(); 513 config.enterpriseConfig.setEapMethod(eapMethod); 514 switch (eapMethod) { 515 case Eap.PEAP: 516 // PEAP supports limited phase2 values 517 // Map the index from the mPhase2PeapAdapter to the one used 518 // by the API which has the full list of PEAP methods. 519 switch(phase2Method) { 520 case WIFI_PEAP_PHASE2_NONE: 521 config.enterpriseConfig.setPhase2Method(Phase2.NONE); 522 break; 523 case WIFI_PEAP_PHASE2_MSCHAPV2: 524 config.enterpriseConfig.setPhase2Method(Phase2.MSCHAPV2); 525 break; 526 case WIFI_PEAP_PHASE2_GTC: 527 config.enterpriseConfig.setPhase2Method(Phase2.GTC); 528 break; 529 default: 530 Log.e(TAG, "Unknown phase2 method" + phase2Method); 531 break; 532 } 533 break; 534 default: 535 // The default index from mPhase2FullAdapter maps to the API 536 config.enterpriseConfig.setPhase2Method(phase2Method); 537 break; 538 } 539 540 String caCert = (String) mEapCaCertSpinner.getSelectedItem(); 541 config.enterpriseConfig.setCaCertificateAliases(null); 542 config.enterpriseConfig.setCaPath(null); 543 config.enterpriseConfig.setDomainSuffixMatch(mEapDomainView.getText().toString()); 544 if (caCert.equals(mUnspecifiedCertString) 545 || caCert.equals(mDoNotValidateEapServerString)) { 546 // ca_cert already set to null, so do nothing. 547 } else if (caCert.equals(mUseSystemCertsString)) { 548 config.enterpriseConfig.setCaPath(SYSTEM_CA_STORE_PATH); 549 } else if (caCert.equals(mMultipleCertSetString)) { 550 if (mAccessPoint != null) { 551 if (!mAccessPoint.isSaved()) { 552 Log.e(TAG, "Multiple certs can only be set " 553 + "when editing saved network"); 554 } 555 config.enterpriseConfig.setCaCertificateAliases( 556 mAccessPoint 557 .getConfig() 558 .enterpriseConfig 559 .getCaCertificateAliases()); 560 } 561 } else { 562 config.enterpriseConfig.setCaCertificateAliases(new String[] {caCert}); 563 } 564 565 // ca_cert or ca_path should not both be non-null, since we only intend to let 566 // the use either their own certificate, or the system certificates, not both. 567 // The variable that is not used must explicitly be set to null, so that a 568 // previously-set value on a saved configuration will be erased on an update. 569 if (config.enterpriseConfig.getCaCertificateAliases() != null 570 && config.enterpriseConfig.getCaPath() != null) { 571 Log.e(TAG, "ca_cert (" 572 + config.enterpriseConfig.getCaCertificateAliases() 573 + ") and ca_path (" 574 + config.enterpriseConfig.getCaPath() 575 + ") should not both be non-null"); 576 } 577 578 String clientCert = (String) mEapUserCertSpinner.getSelectedItem(); 579 if (clientCert.equals(mUnspecifiedCertString) 580 || clientCert.equals(mDoNotProvideEapUserCertString)) { 581 // Note: |clientCert| should not be able to take the value |unspecifiedCert|, 582 // since we prevent such configurations from being saved. 583 clientCert = ""; 584 } 585 config.enterpriseConfig.setClientCertificateAlias(clientCert); 586 if (eapMethod == Eap.SIM || eapMethod == Eap.AKA || eapMethod == Eap.AKA_PRIME) { 587 config.enterpriseConfig.setIdentity(""); 588 config.enterpriseConfig.setAnonymousIdentity(""); 589 } else if (eapMethod == Eap.PWD) { 590 config.enterpriseConfig.setIdentity(mEapIdentityView.getText().toString()); 591 config.enterpriseConfig.setAnonymousIdentity(""); 592 } else { 593 config.enterpriseConfig.setIdentity(mEapIdentityView.getText().toString()); 594 config.enterpriseConfig.setAnonymousIdentity( 595 mEapAnonymousView.getText().toString()); 596 } 597 598 if (mPasswordView.isShown()) { 599 // For security reasons, a previous password is not displayed to user. 600 // Update only if it has been changed. 601 if (mPasswordView.length() > 0) { 602 config.enterpriseConfig.setPassword(mPasswordView.getText().toString()); 603 } 604 } else { 605 // clear password 606 config.enterpriseConfig.setPassword(mPasswordView.getText().toString()); 607 } 608 break; 609 default: 610 return null; 611 } 612 613 config.setIpConfiguration( 614 new IpConfiguration(mIpAssignment, mProxySettings, 615 mStaticIpConfiguration, mHttpProxy)); 616 617 return config; 618 } 619 620 private boolean ipAndProxyFieldsAreValid() { 621 mIpAssignment = 622 (mIpSettingsSpinner != null 623 && mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) 624 ? IpAssignment.STATIC 625 : IpAssignment.DHCP; 626 627 if (mIpAssignment == IpAssignment.STATIC) { 628 mStaticIpConfiguration = new StaticIpConfiguration(); 629 int result = validateIpConfigFields(mStaticIpConfiguration); 630 if (result != 0) { 631 return false; 632 } 633 } 634 635 final int selectedPosition = mProxySettingsSpinner.getSelectedItemPosition(); 636 mProxySettings = ProxySettings.NONE; 637 mHttpProxy = null; 638 if (selectedPosition == PROXY_STATIC && mProxyHostView != null) { 639 mProxySettings = ProxySettings.STATIC; 640 String host = mProxyHostView.getText().toString(); 641 String portStr = mProxyPortView.getText().toString(); 642 String exclusionList = mProxyExclusionListView.getText().toString(); 643 int port = 0; 644 int result = 0; 645 try { 646 port = Integer.parseInt(portStr); 647 result = ProxySelector.validate(host, portStr, exclusionList); 648 } catch (NumberFormatException e) { 649 result = R.string.proxy_error_invalid_port; 650 } 651 if (result == 0) { 652 mHttpProxy = new ProxyInfo(host, port, exclusionList); 653 } else { 654 return false; 655 } 656 } else if (selectedPosition == PROXY_PAC && mProxyPacView != null) { 657 mProxySettings = ProxySettings.PAC; 658 CharSequence uriSequence = mProxyPacView.getText(); 659 if (TextUtils.isEmpty(uriSequence)) { 660 return false; 661 } 662 Uri uri = Uri.parse(uriSequence.toString()); 663 if (uri == null) { 664 return false; 665 } 666 mHttpProxy = new ProxyInfo(uri); 667 } 668 return true; 669 } 670 671 private Inet4Address getIPv4Address(String text) { 672 try { 673 return (Inet4Address) NetworkUtils.numericToInetAddress(text); 674 } catch (IllegalArgumentException | ClassCastException e) { 675 return null; 676 } 677 } 678 679 private int validateIpConfigFields(StaticIpConfiguration staticIpConfiguration) { 680 if (mIpAddressView == null) return 0; 681 682 String ipAddr = mIpAddressView.getText().toString(); 683 if (TextUtils.isEmpty(ipAddr)) return R.string.wifi_ip_settings_invalid_ip_address; 684 685 Inet4Address inetAddr = getIPv4Address(ipAddr); 686 if (inetAddr == null || inetAddr.equals(Inet4Address.ANY)) { 687 return R.string.wifi_ip_settings_invalid_ip_address; 688 } 689 690 int networkPrefixLength = -1; 691 try { 692 networkPrefixLength = Integer.parseInt(mNetworkPrefixLengthView.getText().toString()); 693 if (networkPrefixLength < 0 || networkPrefixLength > 32) { 694 return R.string.wifi_ip_settings_invalid_network_prefix_length; 695 } 696 staticIpConfiguration.ipAddress = new LinkAddress(inetAddr, networkPrefixLength); 697 } catch (NumberFormatException e) { 698 // Set the hint as default after user types in ip address 699 mNetworkPrefixLengthView.setText(mConfigUi.getContext().getString( 700 R.string.wifi_network_prefix_length_hint)); 701 } catch (IllegalArgumentException e) { 702 return R.string.wifi_ip_settings_invalid_ip_address; 703 } 704 705 String gateway = mGatewayView.getText().toString(); 706 if (TextUtils.isEmpty(gateway)) { 707 try { 708 //Extract a default gateway from IP address 709 InetAddress netPart = NetworkUtils.getNetworkPart(inetAddr, networkPrefixLength); 710 byte[] addr = netPart.getAddress(); 711 addr[addr.length - 1] = 1; 712 mGatewayView.setText(InetAddress.getByAddress(addr).getHostAddress()); 713 } catch (RuntimeException ee) { 714 } catch (java.net.UnknownHostException u) { 715 } 716 } else { 717 InetAddress gatewayAddr = getIPv4Address(gateway); 718 if (gatewayAddr == null) { 719 return R.string.wifi_ip_settings_invalid_gateway; 720 } 721 if (gatewayAddr.isMulticastAddress()) { 722 return R.string.wifi_ip_settings_invalid_gateway; 723 } 724 staticIpConfiguration.gateway = gatewayAddr; 725 } 726 727 String dns = mDns1View.getText().toString(); 728 InetAddress dnsAddr = null; 729 730 if (TextUtils.isEmpty(dns)) { 731 //If everything else is valid, provide hint as a default option 732 mDns1View.setText(mConfigUi.getContext().getString(R.string.wifi_dns1_hint)); 733 } else { 734 dnsAddr = getIPv4Address(dns); 735 if (dnsAddr == null) { 736 return R.string.wifi_ip_settings_invalid_dns; 737 } 738 staticIpConfiguration.dnsServers.add(dnsAddr); 739 } 740 741 if (mDns2View.length() > 0) { 742 dns = mDns2View.getText().toString(); 743 dnsAddr = getIPv4Address(dns); 744 if (dnsAddr == null) { 745 return R.string.wifi_ip_settings_invalid_dns; 746 } 747 staticIpConfiguration.dnsServers.add(dnsAddr); 748 } 749 return 0; 750 } 751 752 private void showSecurityFields() { 753 if (mAccessPointSecurity == AccessPoint.SECURITY_NONE) { 754 mView.findViewById(R.id.security_fields).setVisibility(View.GONE); 755 return; 756 } 757 mView.findViewById(R.id.security_fields).setVisibility(View.VISIBLE); 758 759 if (mPasswordView == null) { 760 mPasswordView = (TextView) mView.findViewById(R.id.password); 761 mPasswordView.addTextChangedListener(this); 762 mPasswordView.setOnEditorActionListener(this); 763 mPasswordView.setOnKeyListener(this); 764 ((CheckBox) mView.findViewById(R.id.show_password)) 765 .setOnCheckedChangeListener(this); 766 767 if (mAccessPoint != null && mAccessPoint.isSaved()) { 768 mPasswordView.setHint(R.string.wifi_unchanged); 769 } 770 } 771 772 if (mAccessPointSecurity != AccessPoint.SECURITY_EAP) { 773 mView.findViewById(R.id.eap).setVisibility(View.GONE); 774 return; 775 } 776 mView.findViewById(R.id.eap).setVisibility(View.VISIBLE); 777 778 if (mEapMethodSpinner == null) { 779 mEapMethodSpinner = (Spinner) mView.findViewById(R.id.method); 780 mEapMethodSpinner.setOnItemSelectedListener(this); 781 if (Utils.isWifiOnly(mContext) || !mContext.getResources().getBoolean( 782 com.android.internal.R.bool.config_eap_sim_based_auth_supported)) { 783 String[] eapMethods = mContext.getResources().getStringArray( 784 R.array.eap_method_without_sim_auth); 785 ArrayAdapter<String> spinnerAdapter = new ArrayAdapter<String>(mContext, 786 android.R.layout.simple_spinner_item, eapMethods); 787 spinnerAdapter.setDropDownViewResource( 788 android.R.layout.simple_spinner_dropdown_item); 789 mEapMethodSpinner.setAdapter(spinnerAdapter); 790 } 791 mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2); 792 mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert); 793 mEapCaCertSpinner.setOnItemSelectedListener(this); 794 mEapDomainView = (TextView) mView.findViewById(R.id.domain); 795 mEapDomainView.addTextChangedListener(this); 796 mEapUserCertSpinner = (Spinner) mView.findViewById(R.id.user_cert); 797 mEapUserCertSpinner.setOnItemSelectedListener(this); 798 mEapIdentityView = (TextView) mView.findViewById(R.id.identity); 799 mEapAnonymousView = (TextView) mView.findViewById(R.id.anonymous); 800 801 loadCertificates( 802 mEapCaCertSpinner, 803 Credentials.CA_CERTIFICATE, 804 mDoNotValidateEapServerString, 805 false, 806 true); 807 loadCertificates( 808 mEapUserCertSpinner, 809 Credentials.USER_PRIVATE_KEY, 810 mDoNotProvideEapUserCertString, 811 false, 812 false); 813 814 // Modifying an existing network 815 if (mAccessPoint != null && mAccessPoint.isSaved()) { 816 WifiEnterpriseConfig enterpriseConfig = mAccessPoint.getConfig().enterpriseConfig; 817 int eapMethod = enterpriseConfig.getEapMethod(); 818 int phase2Method = enterpriseConfig.getPhase2Method(); 819 mEapMethodSpinner.setSelection(eapMethod); 820 showEapFieldsByMethod(eapMethod); 821 switch (eapMethod) { 822 case Eap.PEAP: 823 switch (phase2Method) { 824 case Phase2.NONE: 825 mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_NONE); 826 break; 827 case Phase2.MSCHAPV2: 828 mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_MSCHAPV2); 829 break; 830 case Phase2.GTC: 831 mPhase2Spinner.setSelection(WIFI_PEAP_PHASE2_GTC); 832 break; 833 default: 834 Log.e(TAG, "Invalid phase 2 method " + phase2Method); 835 break; 836 } 837 break; 838 default: 839 mPhase2Spinner.setSelection(phase2Method); 840 break; 841 } 842 if (!TextUtils.isEmpty(enterpriseConfig.getCaPath())) { 843 setSelection(mEapCaCertSpinner, mUseSystemCertsString); 844 } else { 845 String[] caCerts = enterpriseConfig.getCaCertificateAliases(); 846 if (caCerts == null) { 847 setSelection(mEapCaCertSpinner, mDoNotValidateEapServerString); 848 } else if (caCerts.length == 1) { 849 setSelection(mEapCaCertSpinner, caCerts[0]); 850 } else { 851 // Reload the cert spinner with an extra "multiple certificates added" item. 852 loadCertificates( 853 mEapCaCertSpinner, 854 Credentials.CA_CERTIFICATE, 855 mDoNotValidateEapServerString, 856 true, 857 true); 858 setSelection(mEapCaCertSpinner, mMultipleCertSetString); 859 } 860 } 861 mEapDomainView.setText(enterpriseConfig.getDomainSuffixMatch()); 862 String userCert = enterpriseConfig.getClientCertificateAlias(); 863 if (TextUtils.isEmpty(userCert)) { 864 setSelection(mEapUserCertSpinner, mDoNotProvideEapUserCertString); 865 } else { 866 setSelection(mEapUserCertSpinner, userCert); 867 } 868 mEapIdentityView.setText(enterpriseConfig.getIdentity()); 869 mEapAnonymousView.setText(enterpriseConfig.getAnonymousIdentity()); 870 } else { 871 showEapFieldsByMethod(mEapMethodSpinner.getSelectedItemPosition()); 872 } 873 } else { 874 showEapFieldsByMethod(mEapMethodSpinner.getSelectedItemPosition()); 875 } 876 } 877 878 /** 879 * EAP-PWD valid fields include 880 * identity 881 * password 882 * EAP-PEAP valid fields include 883 * phase2: MSCHAPV2, GTC 884 * ca_cert 885 * identity 886 * anonymous_identity 887 * password 888 * EAP-TLS valid fields include 889 * user_cert 890 * ca_cert 891 * domain 892 * identity 893 * EAP-TTLS valid fields include 894 * phase2: PAP, MSCHAP, MSCHAPV2, GTC 895 * ca_cert 896 * identity 897 * anonymous_identity 898 * password 899 */ 900 private void showEapFieldsByMethod(int eapMethod) { 901 // Common defaults 902 mView.findViewById(R.id.l_method).setVisibility(View.VISIBLE); 903 mView.findViewById(R.id.l_identity).setVisibility(View.VISIBLE); 904 mView.findViewById(R.id.l_domain).setVisibility(View.VISIBLE); 905 906 // Defaults for most of the EAP methods and over-riden by 907 // by certain EAP methods 908 mView.findViewById(R.id.l_ca_cert).setVisibility(View.VISIBLE); 909 mView.findViewById(R.id.password_layout).setVisibility(View.VISIBLE); 910 mView.findViewById(R.id.show_password_layout).setVisibility(View.VISIBLE); 911 912 Context context = mConfigUi.getContext(); 913 switch (eapMethod) { 914 case WIFI_EAP_METHOD_PWD: 915 setPhase2Invisible(); 916 setCaCertInvisible(); 917 setDomainInvisible(); 918 setAnonymousIdentInvisible(); 919 setUserCertInvisible(); 920 break; 921 case WIFI_EAP_METHOD_TLS: 922 mView.findViewById(R.id.l_user_cert).setVisibility(View.VISIBLE); 923 setPhase2Invisible(); 924 setAnonymousIdentInvisible(); 925 setPasswordInvisible(); 926 break; 927 case WIFI_EAP_METHOD_PEAP: 928 // Reset adapter if needed 929 if (mPhase2Adapter != mPhase2PeapAdapter) { 930 mPhase2Adapter = mPhase2PeapAdapter; 931 mPhase2Spinner.setAdapter(mPhase2Adapter); 932 } 933 mView.findViewById(R.id.l_phase2).setVisibility(View.VISIBLE); 934 mView.findViewById(R.id.l_anonymous).setVisibility(View.VISIBLE); 935 setUserCertInvisible(); 936 break; 937 case WIFI_EAP_METHOD_TTLS: 938 // Reset adapter if needed 939 if (mPhase2Adapter != mPhase2FullAdapter) { 940 mPhase2Adapter = mPhase2FullAdapter; 941 mPhase2Spinner.setAdapter(mPhase2Adapter); 942 } 943 mView.findViewById(R.id.l_phase2).setVisibility(View.VISIBLE); 944 mView.findViewById(R.id.l_anonymous).setVisibility(View.VISIBLE); 945 setUserCertInvisible(); 946 break; 947 case WIFI_EAP_METHOD_SIM: 948 case WIFI_EAP_METHOD_AKA: 949 case WIFI_EAP_METHOD_AKA_PRIME: 950 setPhase2Invisible(); 951 setAnonymousIdentInvisible(); 952 setCaCertInvisible(); 953 setDomainInvisible(); 954 setUserCertInvisible(); 955 setPasswordInvisible(); 956 setIdentityInvisible(); 957 break; 958 } 959 960 if (mView.findViewById(R.id.l_ca_cert).getVisibility() != View.GONE) { 961 String eapCertSelection = (String) mEapCaCertSpinner.getSelectedItem(); 962 if (eapCertSelection.equals(mDoNotValidateEapServerString) 963 || eapCertSelection.equals(mUnspecifiedCertString)) { 964 // Domain suffix matching is not relevant if the user hasn't chosen a CA 965 // certificate yet, or chooses not to validate the EAP server. 966 setDomainInvisible(); 967 } 968 } 969 } 970 971 private void setIdentityInvisible() { 972 mView.findViewById(R.id.l_identity).setVisibility(View.GONE); 973 mPhase2Spinner.setSelection(Phase2.NONE); 974 } 975 976 private void setPhase2Invisible() { 977 mView.findViewById(R.id.l_phase2).setVisibility(View.GONE); 978 mPhase2Spinner.setSelection(Phase2.NONE); 979 } 980 981 private void setCaCertInvisible() { 982 mView.findViewById(R.id.l_ca_cert).setVisibility(View.GONE); 983 setSelection(mEapCaCertSpinner, mUnspecifiedCertString); 984 } 985 986 private void setDomainInvisible() { 987 mView.findViewById(R.id.l_domain).setVisibility(View.GONE); 988 mEapDomainView.setText(""); 989 } 990 991 private void setUserCertInvisible() { 992 mView.findViewById(R.id.l_user_cert).setVisibility(View.GONE); 993 setSelection(mEapUserCertSpinner, mUnspecifiedCertString); 994 } 995 996 private void setAnonymousIdentInvisible() { 997 mView.findViewById(R.id.l_anonymous).setVisibility(View.GONE); 998 mEapAnonymousView.setText(""); 999 } 1000 1001 private void setPasswordInvisible() { 1002 mPasswordView.setText(""); 1003 mView.findViewById(R.id.password_layout).setVisibility(View.GONE); 1004 mView.findViewById(R.id.show_password_layout).setVisibility(View.GONE); 1005 } 1006 1007 private void showIpConfigFields() { 1008 WifiConfiguration config = null; 1009 1010 mView.findViewById(R.id.ip_fields).setVisibility(View.VISIBLE); 1011 1012 if (mAccessPoint != null && mAccessPoint.isSaved()) { 1013 config = mAccessPoint.getConfig(); 1014 } 1015 1016 if (mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) { 1017 mView.findViewById(R.id.staticip).setVisibility(View.VISIBLE); 1018 if (mIpAddressView == null) { 1019 mIpAddressView = (TextView) mView.findViewById(R.id.ipaddress); 1020 mIpAddressView.addTextChangedListener(this); 1021 mGatewayView = (TextView) mView.findViewById(R.id.gateway); 1022 mGatewayView.addTextChangedListener(this); 1023 mNetworkPrefixLengthView = (TextView) mView.findViewById( 1024 R.id.network_prefix_length); 1025 mNetworkPrefixLengthView.addTextChangedListener(this); 1026 mDns1View = (TextView) mView.findViewById(R.id.dns1); 1027 mDns1View.addTextChangedListener(this); 1028 mDns2View = (TextView) mView.findViewById(R.id.dns2); 1029 mDns2View.addTextChangedListener(this); 1030 } 1031 if (config != null) { 1032 StaticIpConfiguration staticConfig = config.getStaticIpConfiguration(); 1033 if (staticConfig != null) { 1034 if (staticConfig.ipAddress != null) { 1035 mIpAddressView.setText( 1036 staticConfig.ipAddress.getAddress().getHostAddress()); 1037 mNetworkPrefixLengthView.setText(Integer.toString(staticConfig.ipAddress 1038 .getNetworkPrefixLength())); 1039 } 1040 1041 if (staticConfig.gateway != null) { 1042 mGatewayView.setText(staticConfig.gateway.getHostAddress()); 1043 } 1044 1045 Iterator<InetAddress> dnsIterator = staticConfig.dnsServers.iterator(); 1046 if (dnsIterator.hasNext()) { 1047 mDns1View.setText(dnsIterator.next().getHostAddress()); 1048 } 1049 if (dnsIterator.hasNext()) { 1050 mDns2View.setText(dnsIterator.next().getHostAddress()); 1051 } 1052 } 1053 } 1054 } else { 1055 mView.findViewById(R.id.staticip).setVisibility(View.GONE); 1056 } 1057 } 1058 1059 private void showProxyFields() { 1060 WifiConfiguration config = null; 1061 1062 mView.findViewById(R.id.proxy_settings_fields).setVisibility(View.VISIBLE); 1063 1064 if (mAccessPoint != null && mAccessPoint.isSaved()) { 1065 config = mAccessPoint.getConfig(); 1066 } 1067 1068 if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) { 1069 setVisibility(R.id.proxy_warning_limited_support, View.VISIBLE); 1070 setVisibility(R.id.proxy_fields, View.VISIBLE); 1071 setVisibility(R.id.proxy_pac_field, View.GONE); 1072 if (mProxyHostView == null) { 1073 mProxyHostView = (TextView) mView.findViewById(R.id.proxy_hostname); 1074 mProxyHostView.addTextChangedListener(this); 1075 mProxyPortView = (TextView) mView.findViewById(R.id.proxy_port); 1076 mProxyPortView.addTextChangedListener(this); 1077 mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist); 1078 mProxyExclusionListView.addTextChangedListener(this); 1079 } 1080 if (config != null) { 1081 ProxyInfo proxyProperties = config.getHttpProxy(); 1082 if (proxyProperties != null) { 1083 mProxyHostView.setText(proxyProperties.getHost()); 1084 mProxyPortView.setText(Integer.toString(proxyProperties.getPort())); 1085 mProxyExclusionListView.setText(proxyProperties.getExclusionListAsString()); 1086 } 1087 } 1088 } else if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_PAC) { 1089 setVisibility(R.id.proxy_warning_limited_support, View.GONE); 1090 setVisibility(R.id.proxy_fields, View.GONE); 1091 setVisibility(R.id.proxy_pac_field, View.VISIBLE); 1092 1093 if (mProxyPacView == null) { 1094 mProxyPacView = (TextView) mView.findViewById(R.id.proxy_pac); 1095 mProxyPacView.addTextChangedListener(this); 1096 } 1097 if (config != null) { 1098 ProxyInfo proxyInfo = config.getHttpProxy(); 1099 if (proxyInfo != null) { 1100 mProxyPacView.setText(proxyInfo.getPacFileUrl().toString()); 1101 } 1102 } 1103 } else { 1104 setVisibility(R.id.proxy_warning_limited_support, View.GONE); 1105 setVisibility(R.id.proxy_fields, View.GONE); 1106 setVisibility(R.id.proxy_pac_field, View.GONE); 1107 } 1108 } 1109 1110 private void setVisibility(int id, int visibility) { 1111 final View v = mView.findViewById(id); 1112 if (v != null) { 1113 v.setVisibility(visibility); 1114 } 1115 } 1116 1117 private void loadCertificates( 1118 Spinner spinner, 1119 String prefix, 1120 String noCertificateString, 1121 boolean showMultipleCerts, 1122 boolean showUsePreinstalledCertOption) { 1123 final Context context = mConfigUi.getContext(); 1124 1125 ArrayList<String> certs = new ArrayList<String>(); 1126 certs.add(mUnspecifiedCertString); 1127 if (showMultipleCerts) { 1128 certs.add(mMultipleCertSetString); 1129 } 1130 if (showUsePreinstalledCertOption) { 1131 certs.add(mUseSystemCertsString); 1132 } 1133 certs.addAll( 1134 Arrays.asList(KeyStore.getInstance().list(prefix, android.os.Process.WIFI_UID))); 1135 certs.add(noCertificateString); 1136 1137 final ArrayAdapter<String> adapter = new ArrayAdapter<String>( 1138 context, android.R.layout.simple_spinner_item, 1139 certs.toArray(new String[certs.size()])); 1140 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); 1141 spinner.setAdapter(adapter); 1142 } 1143 1144 private void setSelection(Spinner spinner, String value) { 1145 if (value != null) { 1146 @SuppressWarnings("unchecked") 1147 ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter(); 1148 for (int i = adapter.getCount() - 1; i >= 0; --i) { 1149 if (value.equals(adapter.getItem(i))) { 1150 spinner.setSelection(i); 1151 break; 1152 } 1153 } 1154 } 1155 } 1156 1157 public int getMode() { 1158 return mMode; 1159 } 1160 1161 @Override 1162 public void afterTextChanged(Editable s) { 1163 mTextViewChangedHandler.post(new Runnable() { 1164 public void run() { 1165 showWarningMessagesIfAppropriate(); 1166 enableSubmitIfAppropriate(); 1167 } 1168 }); 1169 } 1170 1171 @Override 1172 public void beforeTextChanged(CharSequence s, int start, int count, int after) { 1173 // work done in afterTextChanged 1174 } 1175 1176 @Override 1177 public void onTextChanged(CharSequence s, int start, int before, int count) { 1178 // work done in afterTextChanged 1179 } 1180 1181 @Override 1182 public boolean onEditorAction(TextView textView, int id, KeyEvent keyEvent) { 1183 if (textView == mPasswordView) { 1184 if (id == EditorInfo.IME_ACTION_DONE && isSubmittable()) { 1185 mConfigUi.dispatchSubmit(); 1186 return true; 1187 } 1188 } 1189 return false; 1190 } 1191 1192 @Override 1193 public boolean onKey(View view, int keyCode, KeyEvent keyEvent) { 1194 if (view == mPasswordView) { 1195 if (keyCode == KeyEvent.KEYCODE_ENTER && isSubmittable()) { 1196 mConfigUi.dispatchSubmit(); 1197 return true; 1198 } 1199 } 1200 return false; 1201 } 1202 1203 @Override 1204 public void onCheckedChanged(CompoundButton view, boolean isChecked) { 1205 if (view.getId() == R.id.show_password) { 1206 int pos = mPasswordView.getSelectionEnd(); 1207 mPasswordView.setInputType(InputType.TYPE_CLASS_TEXT 1208 | (isChecked ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD 1209 : InputType.TYPE_TEXT_VARIATION_PASSWORD)); 1210 if (pos >= 0) { 1211 ((EditText) mPasswordView).setSelection(pos); 1212 } 1213 } else if (view.getId() == R.id.wifi_advanced_togglebox) { 1214 final View advancedToggle = mView.findViewById(R.id.wifi_advanced_toggle); 1215 final int toggleVisibility; 1216 final int stringID; 1217 if (isChecked) { 1218 toggleVisibility = View.VISIBLE; 1219 stringID = R.string.wifi_advanced_toggle_description_expanded; 1220 } else { 1221 toggleVisibility = View.GONE; 1222 stringID = R.string.wifi_advanced_toggle_description_collapsed; 1223 } 1224 mView.findViewById(R.id.wifi_advanced_fields).setVisibility(toggleVisibility); 1225 advancedToggle.setContentDescription(mContext.getString(stringID)); 1226 } 1227 } 1228 1229 @Override 1230 public void onItemSelected(AdapterView<?> parent, View view, int position, long id) { 1231 if (parent == mSecuritySpinner) { 1232 mAccessPointSecurity = position; 1233 showSecurityFields(); 1234 } else if (parent == mEapMethodSpinner || parent == mEapCaCertSpinner) { 1235 showSecurityFields(); 1236 } else if (parent == mProxySettingsSpinner) { 1237 showProxyFields(); 1238 } else { 1239 showIpConfigFields(); 1240 } 1241 showWarningMessagesIfAppropriate(); 1242 enableSubmitIfAppropriate(); 1243 } 1244 1245 @Override 1246 public void onNothingSelected(AdapterView<?> parent) { 1247 // 1248 } 1249 1250 /** 1251 * Make the characters of the password visible if show_password is checked. 1252 */ 1253 public void updatePassword() { 1254 TextView passwdView = (TextView) mView.findViewById(R.id.password); 1255 passwdView.setInputType(InputType.TYPE_CLASS_TEXT 1256 | (((CheckBox) mView.findViewById(R.id.show_password)).isChecked() 1257 ? InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD 1258 : InputType.TYPE_TEXT_VARIATION_PASSWORD)); 1259 } 1260 1261 public AccessPoint getAccessPoint() { 1262 return mAccessPoint; 1263 } 1264 } 1265