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