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