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