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 
WifiConfigController(WifiConfigUiBase parent, View view, AccessPoint accessPoint, int mode)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 
addRow(ViewGroup group, int name, String value)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 
getSignalString()353     private String getSignalString() {
354         final int level = mAccessPoint.getLevel();
355 
356         return (level > -1 && level < mLevels.length) ? mLevels[level] : null;
357     }
358 
hideForgetButton()359     void hideForgetButton() {
360         Button forget = mConfigUi.getForgetButton();
361         if (forget == null) return;
362 
363         forget.setVisibility(View.GONE);
364     }
365 
hideSubmitButton()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 */
enableSubmitIfAppropriate()374     void enableSubmitIfAppropriate() {
375         Button submit = mConfigUi.getSubmitButton();
376         if (submit == null) return;
377 
378         submit.setEnabled(isSubmittable());
379     }
380 
isSubmittable()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 
showWarningMessagesIfAppropriate()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 
getConfig()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 
ipAndProxyFieldsAreValid()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 
getIPv4Address(String text)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 
validateIpConfigFields(StaticIpConfiguration staticIpConfiguration)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 
showSecurityFields()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      */
showEapFieldsByMethod(int eapMethod)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 
setIdentityInvisible()970     private void setIdentityInvisible() {
971         mView.findViewById(R.id.l_identity).setVisibility(View.GONE);
972         mPhase2Spinner.setSelection(Phase2.NONE);
973     }
974 
setPhase2Invisible()975     private void setPhase2Invisible() {
976         mView.findViewById(R.id.l_phase2).setVisibility(View.GONE);
977         mPhase2Spinner.setSelection(Phase2.NONE);
978     }
979 
setCaCertInvisible()980     private void setCaCertInvisible() {
981         mView.findViewById(R.id.l_ca_cert).setVisibility(View.GONE);
982         setSelection(mEapCaCertSpinner, mUnspecifiedCertString);
983     }
984 
setDomainInvisible()985     private void setDomainInvisible() {
986         mView.findViewById(R.id.l_domain).setVisibility(View.GONE);
987         mEapDomainView.setText("");
988     }
989 
setUserCertInvisible()990     private void setUserCertInvisible() {
991         mView.findViewById(R.id.l_user_cert).setVisibility(View.GONE);
992         setSelection(mEapUserCertSpinner, mUnspecifiedCertString);
993     }
994 
setAnonymousIdentInvisible()995     private void setAnonymousIdentInvisible() {
996         mView.findViewById(R.id.l_anonymous).setVisibility(View.GONE);
997         mEapAnonymousView.setText("");
998     }
999 
setPasswordInvisible()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 
showIpConfigFields()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 
showProxyFields()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 
setVisibility(int id, int visibility)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 
loadCertificates( Spinner spinner, String prefix, String noCertificateString, boolean showMultipleCerts, boolean showUsePreinstalledCertOption)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 
setSelection(Spinner spinner, String value)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 
getMode()1156     public int getMode() {
1157         return mMode;
1158     }
1159 
1160     @Override
afterTextChanged(Editable s)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
beforeTextChanged(CharSequence s, int start, int count, int after)1171     public void beforeTextChanged(CharSequence s, int start, int count, int after) {
1172         // work done in afterTextChanged
1173     }
1174 
1175     @Override
onTextChanged(CharSequence s, int start, int before, int count)1176     public void onTextChanged(CharSequence s, int start, int before, int count) {
1177         // work done in afterTextChanged
1178     }
1179 
1180     @Override
onEditorAction(TextView textView, int id, KeyEvent keyEvent)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
onKey(View view, int keyCode, KeyEvent keyEvent)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
onCheckedChanged(CompoundButton view, boolean isChecked)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
onItemSelected(AdapterView<?> parent, View view, int position, long id)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
onNothingSelected(AdapterView<?> parent)1238     public void onNothingSelected(AdapterView<?> parent) {
1239         //
1240     }
1241 
1242     /**
1243      * Make the characters of the password visible if show_password is checked.
1244      */
updatePassword()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 
getAccessPoint()1253     public AccessPoint getAccessPoint() {
1254         return mAccessPoint;
1255     }
1256 }
1257