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