2 * Copyright (C) 2010 The Android Open Source Project
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 package com.android.settings.wifi;
19 import com.android.settings.ProgressCategory;
20 import com.android.settings.R;
22 import android.content.BroadcastReceiver;
23 import android.content.Context;
24 import android.content.DialogInterface;
25 import android.content.Intent;
26 import android.content.IntentFilter;
27 import android.net.NetworkInfo;
28 import android.net.wifi.ScanResult;
29 import android.net.wifi.SupplicantState;
30 import android.net.wifi.WifiConfiguration;
31 import android.net.wifi.WifiConfiguration.KeyMgmt;
32 import android.net.wifi.WifiConfiguration.Status;
33 import android.net.wifi.WifiInfo;
34 import android.net.wifi.WifiManager;
35 import android.os.Bundle;
36 import android.os.Handler;
37 import android.os.Message;
38 import android.preference.CheckBoxPreference;
39 import android.preference.Preference;
40 import android.preference.PreferenceActivity;
41 import android.preference.PreferenceScreen;
42 import android.provider.Settings.Secure;
43 import android.security.Credentials;
44 import android.security.KeyStore;
45 import android.text.TextUtils;
46 import android.view.ContextMenu;
47 import android.view.ContextMenu.ContextMenuInfo;
48 import android.view.Menu;
49 import android.view.MenuItem;
50 import android.view.View;
51 import android.widget.AdapterView.AdapterContextMenuInfo;
52 import android.widget.Toast;
54 import java.util.ArrayList;
55 import java.util.List;
57 public class WifiSettings2 extends PreferenceActivity implements DialogInterface.OnClickListener {
58 private static final int MENU_ID_SCAN = Menu.FIRST;
59 private static final int MENU_ID_ADVANCED = Menu.FIRST + 1;
60 private static final int MENU_ID_CONNECT = Menu.FIRST + 2;
61 private static final int MENU_ID_FORGET = Menu.FIRST + 3;
62 private static final int MENU_ID_MODIFY = Menu.FIRST + 4;
64 private final IntentFilter mFilter;
65 private final BroadcastReceiver mReceiver;
66 private final Scanner mScanner;
68 private WifiManager mWifiManager;
69 private WifiEnabler mWifiEnabler;
70 private CheckBoxPreference mNotifyOpenNetworks;
71 private ProgressCategory mAccessPoints;
72 private Preference mAddNetwork;
74 private NetworkInfo.DetailedState mLastState;
75 private WifiInfo mLastInfo;
76 private int mLastPriority;
78 private boolean mResetNetworks = false;
79 private int mKeyStoreNetworkId = -1;
81 private AccessPoint mSelected;
82 private WifiDialog mDialog;
84 public WifiSettings2() {
85 mFilter = new IntentFilter();
86 mFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
87 mFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
88 mFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
89 mFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
90 mFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
91 mFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
93 mReceiver = new BroadcastReceiver() {
95 public void onReceive(Context context, Intent intent) {
100 mScanner = new Scanner();
104 protected void onCreate(Bundle savedInstanceState) {
105 super.onCreate(savedInstanceState);
107 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
109 if (getIntent().getBooleanExtra("only_access_points", false)) {
110 addPreferencesFromResource(R.xml.wifi_access_points2);
112 addPreferencesFromResource(R.xml.wifi_settings2);
113 mWifiEnabler = new WifiEnabler(this, mWifiManager,
114 (CheckBoxPreference) findPreference("enable_wifi"));
115 mNotifyOpenNetworks =
116 (CheckBoxPreference) findPreference("notify_open_networks");
117 mNotifyOpenNetworks.setChecked(Secure.getInt(getContentResolver(),
118 Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON, 0) == 1);
121 mAccessPoints = (ProgressCategory) findPreference("access_points");
122 mAccessPoints.setOrderingAsAdded(false);
123 mAddNetwork = findPreference("add_network");
125 registerForContextMenu(getListView());
129 protected void onResume() {
131 registerReceiver(mReceiver, mFilter);
132 if (mWifiEnabler != null) {
133 mWifiEnabler.resume();
135 if (mKeyStoreNetworkId != -1 && KeyStore.getInstance().test() == KeyStore.NO_ERROR) {
136 connect(mKeyStoreNetworkId);
138 mKeyStoreNetworkId = -1;
142 protected void onPause() {
144 unregisterReceiver(mReceiver);
145 if (mWifiEnabler != null) {
146 mWifiEnabler.pause();
149 if (mDialog != null) {
153 if (mResetNetworks) {
159 public boolean onCreateOptionsMenu(Menu menu) {
160 menu.add(Menu.NONE, MENU_ID_SCAN, 0, R.string.wifi_menu_scan)
161 .setIcon(R.drawable.ic_menu_scan_network);
162 menu.add(Menu.NONE, MENU_ID_ADVANCED, 0, R.string.wifi_menu_advanced)
163 .setIcon(android.R.drawable.ic_menu_manage);
164 return super.onCreateOptionsMenu(menu);
168 public boolean onOptionsItemSelected(MenuItem item) {
169 switch (item.getItemId()) {
173 case MENU_ID_ADVANCED:
174 startActivity(new Intent(this, AdvancedSettings.class));
177 return super.onOptionsItemSelected(item);
181 public void onCreateContextMenu(ContextMenu menu, View view, ContextMenuInfo info) {
182 if (info instanceof AdapterContextMenuInfo) {
183 Preference preference = (Preference) getListView().getItemAtPosition(
184 ((AdapterContextMenuInfo) info).position);
186 if (preference instanceof AccessPoint) {
187 mSelected = (AccessPoint) preference;
188 menu.setHeaderTitle(mSelected.ssid);
189 if (mSelected.getLevel() != -1 && mSelected.getState() == null) {
190 menu.add(Menu.NONE, MENU_ID_CONNECT, 0, R.string.wifi_menu_connect);
192 if (mSelected.networkId != -1) {
193 menu.add(Menu.NONE, MENU_ID_FORGET, 0, R.string.wifi_menu_forget);
194 if (mSelected.security != AccessPoint.SECURITY_NONE) {
195 menu.add(Menu.NONE, MENU_ID_MODIFY, 0, R.string.wifi_menu_modify);
203 public boolean onContextItemSelected(MenuItem item) {
204 if (mSelected == null) {
205 return super.onContextItemSelected(item);
207 switch (item.getItemId()) {
208 case MENU_ID_CONNECT:
209 if (mSelected.networkId != -1) {
210 if (!requireKeyStore(mSelected.getConfig())) {
211 connect(mSelected.networkId);
213 } else if (mSelected.security == AccessPoint.SECURITY_NONE) {
214 // Shortcut for open networks.
215 WifiConfiguration config = new WifiConfiguration();
216 config.SSID = mSelected.ssid;
217 config.allowedKeyManagement.set(KeyMgmt.NONE);
218 int networkId = mWifiManager.addNetwork(config);
219 mWifiManager.enableNetwork(networkId, false);
222 showDialog(mSelected, false);
226 forget(mSelected.networkId);
229 showDialog(mSelected, true);
232 return super.onContextItemSelected(item);
236 public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) {
237 if (preference instanceof AccessPoint) {
238 mSelected = (AccessPoint) preference;
239 showDialog(mSelected, false);
240 } else if (preference == mAddNetwork) {
242 showDialog(null, true);
243 } else if (preference == mNotifyOpenNetworks) {
244 Secure.putInt(getContentResolver(),
245 Secure.WIFI_NETWORKS_AVAILABLE_NOTIFICATION_ON,
246 mNotifyOpenNetworks.isChecked() ? 1 : 0);
248 return super.onPreferenceTreeClick(screen, preference);
253 public void onClick(DialogInterface dialogInterface, int button) {
254 if (button == WifiDialog.BUTTON_FORGET && mSelected != null) {
255 forget(mSelected.networkId);
256 } else if (button == WifiDialog.BUTTON_SUBMIT) {
257 WifiConfiguration config = mDialog.getConfig();
259 if (config == null) {
260 if (mSelected != null && !requireKeyStore(mSelected.getConfig())) {
261 connect(mSelected.networkId);
263 } else if (config.networkId != -1) {
264 if (mSelected != null) {
265 mWifiManager.updateNetwork(config);
269 int networkId = mWifiManager.addNetwork(config);
270 if (networkId != -1) {
271 mWifiManager.enableNetwork(networkId, false);
272 config.networkId = networkId;
273 if (mDialog.edit || requireKeyStore(config)) {
283 private void showDialog(AccessPoint accessPoint, boolean edit) {
284 if (mDialog != null) {
287 mDialog = new WifiDialog(this, this, accessPoint, edit);
291 private boolean requireKeyStore(WifiConfiguration config) {
292 if (WifiDialog.requireKeyStore(config) &&
293 KeyStore.getInstance().test() != KeyStore.NO_ERROR) {
294 mKeyStoreNetworkId = config.networkId;
295 Credentials.getInstance().unlock(this);
301 private void forget(int networkId) {
302 mWifiManager.removeNetwork(networkId);
306 private void connect(int networkId) {
307 if (networkId == -1) {
311 // Reset the priority of each network if it goes too high.
312 if (mLastPriority > 1000000) {
313 for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
314 AccessPoint accessPoint = (AccessPoint) mAccessPoints.getPreference(i);
315 if (accessPoint.networkId != -1) {
316 WifiConfiguration config = new WifiConfiguration();
317 config.networkId = accessPoint.networkId;
319 mWifiManager.updateNetwork(config);
325 // Set to the highest priority and save the configuration.
326 WifiConfiguration config = new WifiConfiguration();
327 config.networkId = networkId;
328 config.priority = ++mLastPriority;
329 mWifiManager.updateNetwork(config);
332 // Connect to network by disabling others.
333 mWifiManager.enableNetwork(networkId, true);
334 mWifiManager.reconnect();
335 mResetNetworks = true;
338 private void enableNetworks() {
339 for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
340 WifiConfiguration config = ((AccessPoint) mAccessPoints.getPreference(i)).getConfig();
341 if (config != null && config.status != Status.ENABLED) {
342 mWifiManager.enableNetwork(config.networkId, false);
345 mResetNetworks = false;
348 private void saveNetworks() {
349 // Always save the configuration with all networks enabled.
351 mWifiManager.saveConfiguration();
352 updateAccessPoints();
355 private void updateAccessPoints() {
356 List<AccessPoint> accessPoints = new ArrayList<AccessPoint>();
358 List<WifiConfiguration> configs = mWifiManager.getConfiguredNetworks();
359 if (configs != null) {
361 for (WifiConfiguration config : configs) {
362 if (config.priority > mLastPriority) {
363 mLastPriority = config.priority;
366 // Shift the status to make enableNetworks() more efficient.
367 if (config.status == Status.CURRENT) {
368 config.status = Status.ENABLED;
369 } else if (mResetNetworks && config.status == Status.DISABLED) {
370 config.status = Status.CURRENT;
373 AccessPoint accessPoint = new AccessPoint(this, config);
374 accessPoint.update(mLastInfo, mLastState);
375 accessPoints.add(accessPoint);
379 List<ScanResult> results = mWifiManager.getScanResults();
380 if (results != null) {
381 for (ScanResult result : results) {
382 // Ignore hidden and ad-hoc networks.
383 if (result.SSID == null || result.SSID.length() == 0 ||
384 result.capabilities.contains("[IBSS]")) {
388 boolean found = false;
389 for (AccessPoint accessPoint : accessPoints) {
390 if (accessPoint.update(result)) {
395 accessPoints.add(new AccessPoint(this, result));
400 mAccessPoints.removeAll();
401 for (AccessPoint accessPoint : accessPoints) {
402 mAccessPoints.addPreference(accessPoint);
406 private void handleEvent(Intent intent) {
407 String action = intent.getAction();
408 if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)) {
409 updateWifiState(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
410 WifiManager.WIFI_STATE_UNKNOWN));
411 } else if (WifiManager.SCAN_RESULTS_AVAILABLE_ACTION.equals(action)) {
412 updateAccessPoints();
413 } else if (WifiManager.NETWORK_IDS_CHANGED_ACTION.equals(action)) {
414 if (mSelected != null && mSelected.networkId != -1) {
417 updateAccessPoints();
418 } else if (WifiManager.SUPPLICANT_STATE_CHANGED_ACTION.equals(action)) {
419 updateConnectionState(WifiInfo.getDetailedStateOf((SupplicantState)
420 intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE)));
421 } else if (WifiManager.NETWORK_STATE_CHANGED_ACTION.equals(action)) {
422 updateConnectionState(((NetworkInfo) intent.getParcelableExtra(
423 WifiManager.EXTRA_NETWORK_INFO)).getDetailedState());
424 } else if (WifiManager.RSSI_CHANGED_ACTION.equals(action)) {
425 updateConnectionState(null);
429 private void updateConnectionState(NetworkInfo.DetailedState state) {
430 if (state == NetworkInfo.DetailedState.OBTAINING_IPADDR) {
436 mLastInfo = mWifiManager.getConnectionInfo();
441 for (int i = mAccessPoints.getPreferenceCount() - 1; i >= 0; --i) {
442 ((AccessPoint) mAccessPoints.getPreference(i)).update(mLastInfo, mLastState);
446 private void updateWifiState(int state) {
447 if (state == WifiManager.WIFI_STATE_ENABLED) {
449 updateAccessPoints();
452 mAccessPoints.removeAll();
456 private class Scanner extends Handler {
457 private int mRetry = 0;
460 if (!hasMessages(0)) {
467 mAccessPoints.setProgress(false);
472 public void handleMessage(Message message) {
473 if (mWifiManager.startScanActive()) {
475 } else if (++mRetry >= 3) {
477 Toast.makeText(WifiSettings2.this, R.string.wifi_fail_to_scan,
478 Toast.LENGTH_LONG).show();
480 mAccessPoints.setProgress(mRetry != 0);
481 sendEmptyMessageDelayed(0, 6000);