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