Home | History | Annotate | Download | only in wifi
      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