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