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 android.app.AlertDialog;
20import android.content.Context;
21import android.content.DialogInterface;
22import android.net.wifi.WifiConfiguration;
23import android.net.wifi.WifiConfiguration.AuthAlgorithm;
24import android.net.wifi.WifiConfiguration.KeyMgmt;
25import android.net.wifi.WifiManager;
26import android.os.Bundle;
27import android.text.Editable;
28import android.text.InputType;
29import android.text.TextWatcher;
30import android.util.Log;
31import android.view.View;
32import android.widget.AdapterView;
33import android.widget.ArrayAdapter;
34import android.widget.CheckBox;
35import android.widget.EditText;
36import android.widget.Spinner;
37import android.widget.TextView;
38
39import com.android.settings.R;
40
41import java.nio.charset.Charset;
42
43/**
44 * Dialog to configure the SSID and security settings
45 * for Access Point operation
46 */
47public class WifiApDialog extends AlertDialog implements View.OnClickListener,
48        TextWatcher, AdapterView.OnItemSelectedListener {
49
50    static final int BUTTON_SUBMIT = DialogInterface.BUTTON_POSITIVE;
51
52    private final DialogInterface.OnClickListener mListener;
53
54    public static final int OPEN_INDEX = 0;
55    public static final int WPA2_INDEX = 1;
56
57    private View mView;
58    private TextView mSsid;
59    private int mSecurityTypeIndex = OPEN_INDEX;
60    private EditText mPassword;
61    private int mBandIndex = OPEN_INDEX;
62
63    WifiConfiguration mWifiConfig;
64    WifiManager mWifiManager;
65    private Context mContext;
66
67    private static final String TAG = "WifiApDialog";
68
69    public WifiApDialog(Context context, DialogInterface.OnClickListener listener,
70            WifiConfiguration wifiConfig) {
71        super(context);
72        mListener = listener;
73        mWifiConfig = wifiConfig;
74        if (wifiConfig != null) {
75            mSecurityTypeIndex = getSecurityTypeIndex(wifiConfig);
76        }
77        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
78        mContext =  context;
79    }
80
81    public static int getSecurityTypeIndex(WifiConfiguration wifiConfig) {
82        if (wifiConfig.allowedKeyManagement.get(KeyMgmt.WPA2_PSK)) {
83            return WPA2_INDEX;
84        }
85        return OPEN_INDEX;
86    }
87
88    public WifiConfiguration getConfig() {
89
90        WifiConfiguration config = new WifiConfiguration();
91
92        /**
93         * TODO: SSID in WifiConfiguration for soft ap
94         * is being stored as a raw string without quotes.
95         * This is not the case on the client side. We need to
96         * make things consistent and clean it up
97         */
98        config.SSID = mSsid.getText().toString();
99
100        config.apBand = mBandIndex;
101
102        switch (mSecurityTypeIndex) {
103            case OPEN_INDEX:
104                config.allowedKeyManagement.set(KeyMgmt.NONE);
105                return config;
106
107            case WPA2_INDEX:
108                config.allowedKeyManagement.set(KeyMgmt.WPA2_PSK);
109                config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN);
110                if (mPassword.length() != 0) {
111                    String password = mPassword.getText().toString();
112                    config.preSharedKey = password;
113                }
114                return config;
115        }
116        return null;
117    }
118
119    @Override
120    protected void onCreate(Bundle savedInstanceState) {
121        boolean mInit = true;
122        mView = getLayoutInflater().inflate(R.layout.wifi_ap_dialog, null);
123        Spinner mSecurity = ((Spinner) mView.findViewById(R.id.security));
124        final Spinner mChannel = (Spinner) mView.findViewById(R.id.choose_channel);
125
126        setView(mView);
127        setInverseBackgroundForced(true);
128
129        Context context = getContext();
130
131        setTitle(R.string.wifi_tether_configure_ap_text);
132        mView.findViewById(R.id.type).setVisibility(View.VISIBLE);
133        mSsid = (TextView) mView.findViewById(R.id.ssid);
134        mPassword = (EditText) mView.findViewById(R.id.password);
135
136        ArrayAdapter <CharSequence> channelAdapter;
137        String countryCode = mWifiManager.getCountryCode();
138        if (!mWifiManager.isDualBandSupported() || countryCode == null) {
139            //If no country code, 5GHz AP is forbidden
140            Log.i(TAG,(!mWifiManager.isDualBandSupported() ? "Device do not support 5GHz " :"")
141                    + (countryCode == null ? " NO country code" :"") +  " forbid 5GHz");
142            channelAdapter = ArrayAdapter.createFromResource(mContext,
143                    R.array.wifi_ap_band_config_2G_only, android.R.layout.simple_spinner_item);
144            mWifiConfig.apBand = 0;
145        } else {
146            channelAdapter = ArrayAdapter.createFromResource(mContext,
147                    R.array.wifi_ap_band_config_full, android.R.layout.simple_spinner_item);
148        }
149
150        channelAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
151
152        setButton(BUTTON_SUBMIT, context.getString(R.string.wifi_save), mListener);
153        setButton(DialogInterface.BUTTON_NEGATIVE,
154        context.getString(R.string.wifi_cancel), mListener);
155
156        if (mWifiConfig != null) {
157            mSsid.setText(mWifiConfig.SSID);
158            if (mWifiConfig.apBand == 0) {
159               mBandIndex = 0;
160            } else {
161               mBandIndex = 1;
162            }
163
164            mSecurity.setSelection(mSecurityTypeIndex);
165            if (mSecurityTypeIndex == WPA2_INDEX) {
166                mPassword.setText(mWifiConfig.preSharedKey);
167            }
168        }
169
170        mChannel.setAdapter(channelAdapter);
171        mChannel.setOnItemSelectedListener(
172                new AdapterView.OnItemSelectedListener() {
173                    boolean mInit = true;
174                    @Override
175                    public void onItemSelected(AdapterView<?> adapterView, View view, int position,
176                                               long id) {
177                        if (!mInit) {
178                            mBandIndex = position;
179                            mWifiConfig.apBand = mBandIndex;
180                            Log.i(TAG, "config on channelIndex : " + mBandIndex + " Band: " +
181                                    mWifiConfig.apBand);
182                        } else {
183                            mInit = false;
184                            mChannel.setSelection(mBandIndex);
185                        }
186
187                    }
188
189                    @Override
190                    public void onNothingSelected(AdapterView<?> adapterView) {
191
192                    }
193                }
194        );
195
196        mSsid.addTextChangedListener(this);
197        mPassword.addTextChangedListener(this);
198        ((CheckBox) mView.findViewById(R.id.show_password)).setOnClickListener(this);
199        mSecurity.setOnItemSelectedListener(this);
200
201        super.onCreate(savedInstanceState);
202
203        showSecurityFields();
204        validate();
205    }
206
207    public void onRestoreInstanceState(Bundle savedInstanceState) {
208        super.onRestoreInstanceState(savedInstanceState);
209        mPassword.setInputType(
210                InputType.TYPE_CLASS_TEXT |
211                (((CheckBox) mView.findViewById(R.id.show_password)).isChecked() ?
212                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
213                InputType.TYPE_TEXT_VARIATION_PASSWORD));
214    }
215
216    private void validate() {
217        String mSsidString = mSsid.getText().toString();
218        if ((mSsid != null && mSsid.length() == 0)
219                || ((mSecurityTypeIndex == WPA2_INDEX) && mPassword.length() < 8)
220                || (mSsid != null &&
221                Charset.forName("UTF-8").encode(mSsidString).limit() > 32)) {
222            getButton(BUTTON_SUBMIT).setEnabled(false);
223        } else {
224            getButton(BUTTON_SUBMIT).setEnabled(true);
225        }
226    }
227
228    public void onClick(View view) {
229        mPassword.setInputType(
230                InputType.TYPE_CLASS_TEXT | (((CheckBox) view).isChecked() ?
231                InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD :
232                InputType.TYPE_TEXT_VARIATION_PASSWORD));
233    }
234
235    public void onTextChanged(CharSequence s, int start, int before, int count) {
236    }
237
238    public void beforeTextChanged(CharSequence s, int start, int count, int after) {
239    }
240
241    public void afterTextChanged(Editable editable) {
242        validate();
243    }
244
245    @Override
246    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
247        mSecurityTypeIndex = position;
248        showSecurityFields();
249        validate();
250    }
251
252    @Override
253    public void onNothingSelected(AdapterView<?> parent) {
254    }
255
256    private void showSecurityFields() {
257        if (mSecurityTypeIndex == OPEN_INDEX) {
258            mView.findViewById(R.id.fields).setVisibility(View.GONE);
259            return;
260        }
261        mView.findViewById(R.id.fields).setVisibility(View.VISIBLE);
262    }
263}
264