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
17package com.android.settings.wifi;
18
19import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID;
20
21import android.content.Context;
22import android.content.res.Resources;
23import android.net.LinkAddress;
24import android.net.LinkProperties;
25import android.net.NetworkInfo.DetailedState;
26import android.net.NetworkUtils;
27import android.net.ProxyProperties;
28import android.net.RouteInfo;
29import android.net.wifi.WifiConfiguration;
30import android.net.wifi.WifiConfiguration.AuthAlgorithm;
31import android.net.wifi.WifiConfiguration.IpAssignment;
32import android.net.wifi.WifiConfiguration.KeyMgmt;
33import android.net.wifi.WifiConfiguration.ProxySettings;
34import android.net.wifi.WifiConfiguration.Status;
35import android.net.wifi.WifiInfo;
36import android.os.Handler;
37import android.security.Credentials;
38import android.security.KeyStore;
39import android.text.Editable;
40import android.text.InputType;
41import android.text.TextWatcher;
42import android.text.TextUtils;
43import android.util.Log;
44import android.view.View;
45import android.view.ViewGroup;
46import android.widget.AdapterView;
47import android.widget.ArrayAdapter;
48import android.widget.Button;
49import android.widget.CheckBox;
50import android.widget.EditText;
51import android.widget.Spinner;
52import android.widget.TextView;
53
54import com.android.settings.ProxySelector;
55import com.android.settings.R;
56
57import java.net.InetAddress;
58import java.util.Iterator;
59
60/**
61 * The class for allowing UIs like {@link WifiDialog} and {@link WifiConfigUiBase} to
62 * share the logic for controlling buttons, text fields, etc.
63 */
64public class WifiConfigController implements TextWatcher,
65        View.OnClickListener, AdapterView.OnItemSelectedListener {
66    private static final String KEYSTORE_SPACE = WifiConfiguration.KEYSTORE_URI;
67
68    private static final String PHASE2_PREFIX = "auth=";
69
70    private final WifiConfigUiBase mConfigUi;
71    private final View mView;
72    private final AccessPoint mAccessPoint;
73
74    private boolean mEdit;
75
76    private TextView mSsidView;
77
78    // e.g. AccessPoint.SECURITY_NONE
79    private int mAccessPointSecurity;
80    private TextView mPasswordView;
81
82    private Spinner mSecuritySpinner;
83    private Spinner mEapMethodSpinner;
84    private Spinner mEapCaCertSpinner;
85    private Spinner mPhase2Spinner;
86    private Spinner mEapUserCertSpinner;
87    private TextView mEapIdentityView;
88    private TextView mEapAnonymousView;
89
90    /* This value comes from "wifi_ip_settings" resource array */
91    private static final int DHCP = 0;
92    private static final int STATIC_IP = 1;
93
94    /* These values come from "wifi_proxy_settings" resource array */
95    public static final int PROXY_NONE = 0;
96    public static final int PROXY_STATIC = 1;
97
98    /* These values from from "wifi_eap_method" resource array */
99    public static final int WIFI_EAP_METHOD_PEAP = 0;
100    public static final int WIFI_EAP_METHOD_TLS  = 1;
101    public static final int WIFI_EAP_METHOD_TTLS = 2;
102    public static final int WIFI_EAP_METHOD_PWD  = 3;
103
104    private static final String TAG = "WifiConfigController";
105
106    private Spinner mIpSettingsSpinner;
107    private TextView mIpAddressView;
108    private TextView mGatewayView;
109    private TextView mNetworkPrefixLengthView;
110    private TextView mDns1View;
111    private TextView mDns2View;
112
113    private Spinner mProxySettingsSpinner;
114    private TextView mProxyHostView;
115    private TextView mProxyPortView;
116    private TextView mProxyExclusionListView;
117
118    private IpAssignment mIpAssignment = IpAssignment.UNASSIGNED;
119    private ProxySettings mProxySettings = ProxySettings.UNASSIGNED;
120    private LinkProperties mLinkProperties = new LinkProperties();
121
122    // True when this instance is used in SetupWizard XL context.
123    private final boolean mInXlSetupWizard;
124
125    private final Handler mTextViewChangedHandler;
126
127    static boolean requireKeyStore(WifiConfiguration config) {
128        if (config == null) {
129            return false;
130        }
131        if (!TextUtils.isEmpty(config.key_id.value())) {
132            return true;
133        }
134        String values[] = { config.ca_cert.value(), config.client_cert.value() };
135        for (String value : values) {
136            if (value != null && value.startsWith(KEYSTORE_SPACE)) {
137                return true;
138            }
139        }
140        return false;
141    }
142
143    public WifiConfigController(
144            WifiConfigUiBase parent, View view, AccessPoint accessPoint, boolean edit) {
145        mConfigUi = parent;
146        mInXlSetupWizard = (parent instanceof WifiConfigUiForSetupWizardXL);
147
148        mView = view;
149        mAccessPoint = accessPoint;
150        mAccessPointSecurity = (accessPoint == null) ? AccessPoint.SECURITY_NONE :
151                accessPoint.security;
152        mEdit = edit;
153
154        mTextViewChangedHandler = new Handler();
155        final Context context = mConfigUi.getContext();
156        final Resources resources = context.getResources();
157
158        mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings);
159        mIpSettingsSpinner.setOnItemSelectedListener(this);
160        mProxySettingsSpinner = (Spinner) mView.findViewById(R.id.proxy_settings);
161        mProxySettingsSpinner.setOnItemSelectedListener(this);
162
163        if (mAccessPoint == null) { // new network
164            mConfigUi.setTitle(R.string.wifi_add_network);
165
166            mSsidView = (TextView) mView.findViewById(R.id.ssid);
167            mSsidView.addTextChangedListener(this);
168            mSecuritySpinner = ((Spinner) mView.findViewById(R.id.security));
169            mSecuritySpinner.setOnItemSelectedListener(this);
170            if (mInXlSetupWizard) {
171                mView.findViewById(R.id.type_ssid).setVisibility(View.VISIBLE);
172                mView.findViewById(R.id.type_security).setVisibility(View.VISIBLE);
173                // We want custom layout. The content must be same as the other cases.
174
175                ArrayAdapter<String> adapter = new ArrayAdapter<String>(context,
176                        R.layout.wifi_setup_custom_list_item_1, android.R.id.text1,
177                        context.getResources().getStringArray(R.array.wifi_security_no_eap));
178                mSecuritySpinner.setAdapter(adapter);
179            } else {
180                mView.findViewById(R.id.type).setVisibility(View.VISIBLE);
181            }
182
183            showIpConfigFields();
184            showProxyFields();
185            mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE);
186            mView.findViewById(R.id.wifi_advanced_togglebox).setOnClickListener(this);
187
188            mConfigUi.setSubmitButton(context.getString(R.string.wifi_save));
189        } else {
190            mConfigUi.setTitle(mAccessPoint.ssid);
191
192            ViewGroup group = (ViewGroup) mView.findViewById(R.id.info);
193
194            DetailedState state = mAccessPoint.getState();
195            if (state != null) {
196                addRow(group, R.string.wifi_status, Summary.get(mConfigUi.getContext(), state));
197            }
198
199            int level = mAccessPoint.getLevel();
200            if (level != -1) {
201                String[] signal = resources.getStringArray(R.array.wifi_signal);
202                addRow(group, R.string.wifi_signal, signal[level]);
203            }
204
205            WifiInfo info = mAccessPoint.getInfo();
206            if (info != null && info.getLinkSpeed() != -1) {
207                addRow(group, R.string.wifi_speed, info.getLinkSpeed() + WifiInfo.LINK_SPEED_UNITS);
208            }
209
210            addRow(group, R.string.wifi_security, mAccessPoint.getSecurityString(false));
211
212            boolean showAdvancedFields = false;
213            if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
214                WifiConfiguration config = mAccessPoint.getConfig();
215                if (config.ipAssignment == IpAssignment.STATIC) {
216                    mIpSettingsSpinner.setSelection(STATIC_IP);
217                    showAdvancedFields = true;
218                } else {
219                    mIpSettingsSpinner.setSelection(DHCP);
220                }
221                //Display IP addresses
222                for(InetAddress a : config.linkProperties.getAddresses()) {
223                    addRow(group, R.string.wifi_ip_address, a.getHostAddress());
224                }
225
226
227                if (config.proxySettings == ProxySettings.STATIC) {
228                    mProxySettingsSpinner.setSelection(PROXY_STATIC);
229                    showAdvancedFields = true;
230                } else {
231                    mProxySettingsSpinner.setSelection(PROXY_NONE);
232                }
233            }
234
235            if (mAccessPoint.networkId == INVALID_NETWORK_ID || mEdit) {
236                showSecurityFields();
237                showIpConfigFields();
238                showProxyFields();
239                mView.findViewById(R.id.wifi_advanced_toggle).setVisibility(View.VISIBLE);
240                mView.findViewById(R.id.wifi_advanced_togglebox).setOnClickListener(this);
241                if (showAdvancedFields) {
242                    ((CheckBox) mView.findViewById(R.id.wifi_advanced_togglebox)).setChecked(true);
243                    mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.VISIBLE);
244                }
245            }
246
247            if (mEdit) {
248                mConfigUi.setSubmitButton(context.getString(R.string.wifi_save));
249            } else {
250                if (state == null && level != -1) {
251                    mConfigUi.setSubmitButton(context.getString(R.string.wifi_connect));
252                } else {
253                    mView.findViewById(R.id.ip_fields).setVisibility(View.GONE);
254                }
255                if (mAccessPoint.networkId != INVALID_NETWORK_ID) {
256                    mConfigUi.setForgetButton(context.getString(R.string.wifi_forget));
257                }
258            }
259        }
260
261
262        mConfigUi.setCancelButton(context.getString(R.string.wifi_cancel));
263        if (mConfigUi.getSubmitButton() != null) {
264            enableSubmitIfAppropriate();
265        }
266    }
267
268    private void addRow(ViewGroup group, int name, String value) {
269        View row = mConfigUi.getLayoutInflater().inflate(R.layout.wifi_dialog_row, group, false);
270        ((TextView) row.findViewById(R.id.name)).setText(name);
271        ((TextView) row.findViewById(R.id.value)).setText(value);
272        group.addView(row);
273    }
274
275    /* show submit button if password, ip and proxy settings are valid */
276    void enableSubmitIfAppropriate() {
277        Button submit = mConfigUi.getSubmitButton();
278        if (submit == null) return;
279
280        boolean enabled = false;
281        boolean passwordInvalid = false;
282
283        if (mPasswordView != null &&
284            ((mAccessPointSecurity == AccessPoint.SECURITY_WEP && mPasswordView.length() == 0) ||
285            (mAccessPointSecurity == AccessPoint.SECURITY_PSK && mPasswordView.length() < 8))) {
286            passwordInvalid = true;
287        }
288
289        if ((mSsidView != null && mSsidView.length() == 0) ||
290            ((mAccessPoint == null || mAccessPoint.networkId == INVALID_NETWORK_ID) &&
291            passwordInvalid)) {
292            enabled = false;
293        } else {
294            if (ipAndProxyFieldsAreValid()) {
295                enabled = true;
296            } else {
297                enabled = false;
298            }
299        }
300        submit.setEnabled(enabled);
301    }
302
303    /* package */ WifiConfiguration getConfig() {
304        if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID && !mEdit) {
305            return null;
306        }
307
308        WifiConfiguration config = new WifiConfiguration();
309
310        if (mAccessPoint == null) {
311            config.SSID = AccessPoint.convertToQuotedString(
312                    mSsidView.getText().toString());
313            // If the user adds a network manually, assume that it is hidden.
314            config.hiddenSSID = true;
315        } else if (mAccessPoint.networkId == INVALID_NETWORK_ID) {
316            config.SSID = AccessPoint.convertToQuotedString(
317                    mAccessPoint.ssid);
318        } else {
319            config.networkId = mAccessPoint.networkId;
320        }
321
322        switch (mAccessPointSecurity) {
323            case AccessPoint.SECURITY_NONE:
324                config.allowedKeyManagement.set(KeyMgmt.NONE);
325                break;
326
327            case AccessPoint.SECURITY_WEP:
328                config.allowedKeyManagement.set(KeyMgmt.NONE);
329                config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
330                config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED);
331                if (mPasswordView.length() != 0) {
332                    int length = mPasswordView.length();
333                    String password = mPasswordView.getText().toString();
334                    // WEP-40, WEP-104, and 256-bit WEP (WEP-232?)
335                    if ((length == 10 || length == 26 || length == 58) &&
336                            password.matches("[0-9A-Fa-f]*")) {
337                        config.wepKeys[0] = password;
338                    } else {
339                        config.wepKeys[0] = '"' + password + '"';
340                    }
341                }
342                break;
343
344            case AccessPoint.SECURITY_PSK:
345                config.allowedKeyManagement.set(KeyMgmt.WPA_PSK);
346                if (mPasswordView.length() != 0) {
347                    String password = mPasswordView.getText().toString();
348                    if (password.matches("[0-9A-Fa-f]{64}")) {
349                        config.preSharedKey = password;
350                    } else {
351                        config.preSharedKey = '"' + password + '"';
352                    }
353                }
354                break;
355
356            case AccessPoint.SECURITY_EAP:
357                config.allowedKeyManagement.set(KeyMgmt.WPA_EAP);
358                config.allowedKeyManagement.set(KeyMgmt.IEEE8021X);
359                config.eap.setValue((String) mEapMethodSpinner.getSelectedItem());
360
361                config.phase2.setValue((mPhase2Spinner.getSelectedItemPosition() == 0) ? "" :
362                        PHASE2_PREFIX + mPhase2Spinner.getSelectedItem());
363                config.ca_cert.setValue((mEapCaCertSpinner.getSelectedItemPosition() == 0) ? "" :
364                        KEYSTORE_SPACE + Credentials.CA_CERTIFICATE +
365                        (String) mEapCaCertSpinner.getSelectedItem());
366                config.client_cert.setValue((mEapUserCertSpinner.getSelectedItemPosition() == 0) ?
367                        "" : KEYSTORE_SPACE + Credentials.USER_CERTIFICATE +
368                        (String) mEapUserCertSpinner.getSelectedItem());
369                final boolean isEmptyKeyId = (mEapUserCertSpinner.getSelectedItemPosition() == 0);
370                config.key_id.setValue(isEmptyKeyId ? "" : Credentials.USER_PRIVATE_KEY +
371                        (String) mEapUserCertSpinner.getSelectedItem());
372                config.engine.setValue(isEmptyKeyId ? WifiConfiguration.ENGINE_DISABLE :
373                        WifiConfiguration.ENGINE_ENABLE);
374                config.engine_id.setValue(isEmptyKeyId ? "" : WifiConfiguration.KEYSTORE_ENGINE_ID);
375                config.identity.setValue((mEapIdentityView.length() == 0) ? "" :
376                        mEapIdentityView.getText().toString());
377                config.anonymous_identity.setValue((mEapAnonymousView.length() == 0) ? "" :
378                        mEapAnonymousView.getText().toString());
379                if (mPasswordView.length() != 0) {
380                    config.password.setValue(mPasswordView.getText().toString());
381                }
382                break;
383
384            default:
385                    return null;
386        }
387
388        config.proxySettings = mProxySettings;
389        config.ipAssignment = mIpAssignment;
390        config.linkProperties = new LinkProperties(mLinkProperties);
391
392        return config;
393    }
394
395    private boolean ipAndProxyFieldsAreValid() {
396        mLinkProperties.clear();
397        mIpAssignment = (mIpSettingsSpinner != null &&
398                mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) ?
399                IpAssignment.STATIC : IpAssignment.DHCP;
400
401        if (mIpAssignment == IpAssignment.STATIC) {
402            int result = validateIpConfigFields(mLinkProperties);
403            if (result != 0) {
404                return false;
405            }
406        }
407
408        mProxySettings = (mProxySettingsSpinner != null &&
409                mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) ?
410                ProxySettings.STATIC : ProxySettings.NONE;
411
412        if (mProxySettings == ProxySettings.STATIC && mProxyHostView != null) {
413            String host = mProxyHostView.getText().toString();
414            String portStr = mProxyPortView.getText().toString();
415            String exclusionList = mProxyExclusionListView.getText().toString();
416            int port = 0;
417            int result = 0;
418            try {
419                port = Integer.parseInt(portStr);
420                result = ProxySelector.validate(host, portStr, exclusionList);
421            } catch (NumberFormatException e) {
422                result = R.string.proxy_error_invalid_port;
423            }
424            if (result == 0) {
425                ProxyProperties proxyProperties= new ProxyProperties(host, port, exclusionList);
426                mLinkProperties.setHttpProxy(proxyProperties);
427            } else {
428                return false;
429            }
430        }
431        return true;
432    }
433
434    private int validateIpConfigFields(LinkProperties linkProperties) {
435        if (mIpAddressView == null) return 0;
436
437        String ipAddr = mIpAddressView.getText().toString();
438        if (TextUtils.isEmpty(ipAddr)) return R.string.wifi_ip_settings_invalid_ip_address;
439
440        InetAddress inetAddr = null;
441        try {
442            inetAddr = NetworkUtils.numericToInetAddress(ipAddr);
443        } catch (IllegalArgumentException e) {
444            return R.string.wifi_ip_settings_invalid_ip_address;
445        }
446
447        int networkPrefixLength = -1;
448        try {
449            networkPrefixLength = Integer.parseInt(mNetworkPrefixLengthView.getText().toString());
450            if (networkPrefixLength < 0 || networkPrefixLength > 32) {
451                return R.string.wifi_ip_settings_invalid_network_prefix_length;
452            }
453            linkProperties.addLinkAddress(new LinkAddress(inetAddr, networkPrefixLength));
454        } catch (NumberFormatException e) {
455            // Set the hint as default after user types in ip address
456            mNetworkPrefixLengthView.setText(mConfigUi.getContext().getString(
457                    R.string.wifi_network_prefix_length_hint));
458        }
459
460        String gateway = mGatewayView.getText().toString();
461        if (TextUtils.isEmpty(gateway)) {
462            try {
463                //Extract a default gateway from IP address
464                InetAddress netPart = NetworkUtils.getNetworkPart(inetAddr, networkPrefixLength);
465                byte[] addr = netPart.getAddress();
466                addr[addr.length-1] = 1;
467                mGatewayView.setText(InetAddress.getByAddress(addr).getHostAddress());
468            } catch (RuntimeException ee) {
469            } catch (java.net.UnknownHostException u) {
470            }
471        } else {
472            InetAddress gatewayAddr = null;
473            try {
474                gatewayAddr = NetworkUtils.numericToInetAddress(gateway);
475            } catch (IllegalArgumentException e) {
476                return R.string.wifi_ip_settings_invalid_gateway;
477            }
478            linkProperties.addRoute(new RouteInfo(gatewayAddr));
479        }
480
481        String dns = mDns1View.getText().toString();
482        InetAddress dnsAddr = null;
483
484        if (TextUtils.isEmpty(dns)) {
485            //If everything else is valid, provide hint as a default option
486            mDns1View.setText(mConfigUi.getContext().getString(R.string.wifi_dns1_hint));
487        } else {
488            try {
489                dnsAddr = NetworkUtils.numericToInetAddress(dns);
490            } catch (IllegalArgumentException e) {
491                return R.string.wifi_ip_settings_invalid_dns;
492            }
493            linkProperties.addDns(dnsAddr);
494        }
495
496        if (mDns2View.length() > 0) {
497            dns = mDns2View.getText().toString();
498            try {
499                dnsAddr = NetworkUtils.numericToInetAddress(dns);
500            } catch (IllegalArgumentException e) {
501                return R.string.wifi_ip_settings_invalid_dns;
502            }
503            linkProperties.addDns(dnsAddr);
504        }
505        return 0;
506    }
507
508    private void showSecurityFields() {
509        if (mInXlSetupWizard) {
510            // Note: XL SetupWizard won't hide "EAP" settings here.
511            if (!((WifiSettingsForSetupWizardXL)mConfigUi.getContext()).initSecurityFields(mView,
512                        mAccessPointSecurity)) {
513                return;
514            }
515        }
516        if (mAccessPointSecurity == AccessPoint.SECURITY_NONE) {
517            mView.findViewById(R.id.security_fields).setVisibility(View.GONE);
518            return;
519        }
520        mView.findViewById(R.id.security_fields).setVisibility(View.VISIBLE);
521
522        if (mPasswordView == null) {
523            mPasswordView = (TextView) mView.findViewById(R.id.password);
524            mPasswordView.addTextChangedListener(this);
525            ((CheckBox) mView.findViewById(R.id.show_password)).setOnClickListener(this);
526
527            if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
528                mPasswordView.setHint(R.string.wifi_unchanged);
529            }
530        }
531
532        if (mAccessPointSecurity != AccessPoint.SECURITY_EAP) {
533            mView.findViewById(R.id.eap).setVisibility(View.GONE);
534            return;
535        }
536        mView.findViewById(R.id.eap).setVisibility(View.VISIBLE);
537
538        if (mEapMethodSpinner == null) {
539            mEapMethodSpinner = (Spinner) mView.findViewById(R.id.method);
540            mEapMethodSpinner.setOnItemSelectedListener(this);
541            mPhase2Spinner = (Spinner) mView.findViewById(R.id.phase2);
542            mEapCaCertSpinner = (Spinner) mView.findViewById(R.id.ca_cert);
543            mEapUserCertSpinner = (Spinner) mView.findViewById(R.id.user_cert);
544            mEapIdentityView = (TextView) mView.findViewById(R.id.identity);
545            mEapAnonymousView = (TextView) mView.findViewById(R.id.anonymous);
546
547            loadCertificates(mEapCaCertSpinner, Credentials.CA_CERTIFICATE);
548            loadCertificates(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY);
549
550            if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
551                WifiConfiguration config = mAccessPoint.getConfig();
552                setSelection(mEapMethodSpinner, config.eap.value());
553
554                final String phase2Method = config.phase2.value();
555                if (phase2Method != null && phase2Method.startsWith(PHASE2_PREFIX)) {
556                    setSelection(mPhase2Spinner, phase2Method.substring(PHASE2_PREFIX.length()));
557                } else {
558                    setSelection(mPhase2Spinner, phase2Method);
559                }
560
561                setCertificate(mEapCaCertSpinner, KEYSTORE_SPACE + Credentials.CA_CERTIFICATE,
562                        config.ca_cert.value());
563                setCertificate(mEapUserCertSpinner, Credentials.USER_PRIVATE_KEY,
564                        config.key_id.value());
565                mEapIdentityView.setText(config.identity.value());
566                mEapAnonymousView.setText(config.anonymous_identity.value());
567            }
568        }
569
570        mView.findViewById(R.id.l_method).setVisibility(View.VISIBLE);
571        mView.findViewById(R.id.l_identity).setVisibility(View.VISIBLE);
572
573        if (mEapMethodSpinner.getSelectedItemPosition() == WIFI_EAP_METHOD_PWD){
574            mView.findViewById(R.id.l_phase2).setVisibility(View.GONE);
575            mView.findViewById(R.id.l_ca_cert).setVisibility(View.GONE);
576            mView.findViewById(R.id.l_user_cert).setVisibility(View.GONE);
577            mView.findViewById(R.id.l_anonymous).setVisibility(View.GONE);
578        } else {
579            mView.findViewById(R.id.l_phase2).setVisibility(View.VISIBLE);
580            mView.findViewById(R.id.l_ca_cert).setVisibility(View.VISIBLE);
581            mView.findViewById(R.id.l_user_cert).setVisibility(View.VISIBLE);
582            mView.findViewById(R.id.l_anonymous).setVisibility(View.VISIBLE);
583        }
584    }
585
586    private void showIpConfigFields() {
587        WifiConfiguration config = null;
588
589        mView.findViewById(R.id.ip_fields).setVisibility(View.VISIBLE);
590
591        if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
592            config = mAccessPoint.getConfig();
593        }
594
595        if (mIpSettingsSpinner.getSelectedItemPosition() == STATIC_IP) {
596            mView.findViewById(R.id.staticip).setVisibility(View.VISIBLE);
597            if (mIpAddressView == null) {
598                mIpAddressView = (TextView) mView.findViewById(R.id.ipaddress);
599                mIpAddressView.addTextChangedListener(this);
600                mGatewayView = (TextView) mView.findViewById(R.id.gateway);
601                mGatewayView.addTextChangedListener(this);
602                mNetworkPrefixLengthView = (TextView) mView.findViewById(
603                        R.id.network_prefix_length);
604                mNetworkPrefixLengthView.addTextChangedListener(this);
605                mDns1View = (TextView) mView.findViewById(R.id.dns1);
606                mDns1View.addTextChangedListener(this);
607                mDns2View = (TextView) mView.findViewById(R.id.dns2);
608                mDns2View.addTextChangedListener(this);
609            }
610            if (config != null) {
611                LinkProperties linkProperties = config.linkProperties;
612                Iterator<LinkAddress> iterator = linkProperties.getLinkAddresses().iterator();
613                if (iterator.hasNext()) {
614                    LinkAddress linkAddress = iterator.next();
615                    mIpAddressView.setText(linkAddress.getAddress().getHostAddress());
616                    mNetworkPrefixLengthView.setText(Integer.toString(linkAddress
617                            .getNetworkPrefixLength()));
618                }
619
620                for (RouteInfo route : linkProperties.getRoutes()) {
621                    if (route.isDefaultRoute()) {
622                        mGatewayView.setText(route.getGateway().getHostAddress());
623                        break;
624                    }
625                }
626
627                Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator();
628                if (dnsIterator.hasNext()) {
629                    mDns1View.setText(dnsIterator.next().getHostAddress());
630                }
631                if (dnsIterator.hasNext()) {
632                    mDns2View.setText(dnsIterator.next().getHostAddress());
633                }
634            }
635        } else {
636            mView.findViewById(R.id.staticip).setVisibility(View.GONE);
637        }
638    }
639
640    private void showProxyFields() {
641        WifiConfiguration config = null;
642
643        mView.findViewById(R.id.proxy_settings_fields).setVisibility(View.VISIBLE);
644
645        if (mAccessPoint != null && mAccessPoint.networkId != INVALID_NETWORK_ID) {
646            config = mAccessPoint.getConfig();
647        }
648
649        if (mProxySettingsSpinner.getSelectedItemPosition() == PROXY_STATIC) {
650            mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.VISIBLE);
651            mView.findViewById(R.id.proxy_fields).setVisibility(View.VISIBLE);
652            if (mProxyHostView == null) {
653                mProxyHostView = (TextView) mView.findViewById(R.id.proxy_hostname);
654                mProxyHostView.addTextChangedListener(this);
655                mProxyPortView = (TextView) mView.findViewById(R.id.proxy_port);
656                mProxyPortView.addTextChangedListener(this);
657                mProxyExclusionListView = (TextView) mView.findViewById(R.id.proxy_exclusionlist);
658                mProxyExclusionListView.addTextChangedListener(this);
659            }
660            if (config != null) {
661                ProxyProperties proxyProperties = config.linkProperties.getHttpProxy();
662                if (proxyProperties != null) {
663                    mProxyHostView.setText(proxyProperties.getHost());
664                    mProxyPortView.setText(Integer.toString(proxyProperties.getPort()));
665                    mProxyExclusionListView.setText(proxyProperties.getExclusionList());
666                }
667            }
668        } else {
669            mView.findViewById(R.id.proxy_warning_limited_support).setVisibility(View.GONE);
670            mView.findViewById(R.id.proxy_fields).setVisibility(View.GONE);
671        }
672    }
673
674
675
676    private void loadCertificates(Spinner spinner, String prefix) {
677        final Context context = mConfigUi.getContext();
678        final String unspecified = context.getString(R.string.wifi_unspecified);
679
680        String[] certs = KeyStore.getInstance().saw(prefix);
681        if (certs == null || certs.length == 0) {
682            certs = new String[] {unspecified};
683        } else {
684            final String[] array = new String[certs.length + 1];
685            array[0] = unspecified;
686            System.arraycopy(certs, 0, array, 1, certs.length);
687            certs = array;
688        }
689
690        final ArrayAdapter<String> adapter = new ArrayAdapter<String>(
691                context, android.R.layout.simple_spinner_item, certs);
692        adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
693        spinner.setAdapter(adapter);
694    }
695
696    private void setCertificate(Spinner spinner, String prefix, String cert) {
697        if (cert != null && cert.startsWith(prefix)) {
698            setSelection(spinner, cert.substring(prefix.length()));
699        }
700    }
701
702    private void setSelection(Spinner spinner, String value) {
703        if (value != null) {
704            @SuppressWarnings("unchecked")
705            ArrayAdapter<String> adapter = (ArrayAdapter<String>) spinner.getAdapter();
706            for (int i = adapter.getCount() - 1; i >= 0; --i) {
707                if (value.equals(adapter.getItem(i))) {
708                    spinner.setSelection(i);
709                    break;
710                }
711            }
712        }
713    }
714
715    public boolean isEdit() {
716        return mEdit;
717    }
718
719    @Override
720    public void afterTextChanged(Editable s) {
721        mTextViewChangedHandler.post(new Runnable() {
722                public void run() {
723                    enableSubmitIfAppropriate();
724                }
725            });
726    }
727
728    @Override
729    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
730        // work done in afterTextChanged
731    }
732
733    @Override
734    public void onTextChanged(CharSequence s, int start, int before, int count) {
735        // work done in afterTextChanged
736    }
737
738    @Override
739    public void onClick(View view) {
740        if (view.getId() == R.id.show_password) {
741            int pos = mPasswordView.getSelectionEnd();
742            mPasswordView.setInputType(
743                    InputType.TYPE_CLASS_TEXT | (((CheckBox) view).isChecked() ?
744                            InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
745                                InputType.TYPE_TEXT_VARIATION_PASSWORD));
746            if (pos >= 0) {
747                ((EditText)mPasswordView).setSelection(pos);
748            }
749        } else if (view.getId() == R.id.wifi_advanced_togglebox) {
750            if (((CheckBox) view).isChecked()) {
751                mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.VISIBLE);
752            } else {
753                mView.findViewById(R.id.wifi_advanced_fields).setVisibility(View.GONE);
754            }
755        }
756    }
757
758    @Override
759    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
760        if (parent == mSecuritySpinner) {
761            mAccessPointSecurity = position;
762            showSecurityFields();
763        } else if (parent == mEapMethodSpinner) {
764            showSecurityFields();
765        } else if (parent == mProxySettingsSpinner) {
766            showProxyFields();
767        } else {
768            showIpConfigFields();
769        }
770        enableSubmitIfAppropriate();
771    }
772
773    @Override
774    public void onNothingSelected(AdapterView<?> parent) {
775        //
776    }
777}
778