summaryrefslogtreecommitdiffstats
path: root/src/com/android/settings/wifi/WifiLayer.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/com/android/settings/wifi/WifiLayer.java')
-rw-r--r--src/com/android/settings/wifi/WifiLayer.java1302
1 files changed, 0 insertions, 1302 deletions
diff --git a/src/com/android/settings/wifi/WifiLayer.java b/src/com/android/settings/wifi/WifiLayer.java
deleted file mode 100644
index b0857d2..0000000
--- a/src/com/android/settings/wifi/WifiLayer.java
+++ /dev/null
@@ -1,1302 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.wifi;
-
-import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
-import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
-
-import com.android.settings.R;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.net.NetworkInfo;
-import android.net.NetworkInfo.DetailedState;
-import android.net.NetworkInfo.State;
-import android.net.wifi.ScanResult;
-import android.net.wifi.SupplicantState;
-import android.net.wifi.WifiConfiguration;
-import android.net.wifi.WifiInfo;
-import android.net.wifi.WifiManager;
-import android.os.Handler;
-import android.os.Message;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Config;
-import android.util.Log;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-/**
- * Helper class for abstracting Wi-Fi.
- * <p>
- * Client must call {@link #onCreate()}, {@link #onCreatedCallback()},
- * {@link #onPause()}, {@link #onResume()}.
- */
-public class WifiLayer {
-
- private static final String TAG = "SettingsWifiLayer";
- static final boolean LOGV = false || Config.LOGV;
-
- //============================
- // Other member variables
- //============================
-
- private Context mContext;
- private Callback mCallback;
-
- static final int MESSAGE_ATTEMPT_SCAN = 1;
- private Handler mHandler = new MyHandler();
-
- //============================
- // Wifi member variables
- //============================
-
- private WifiManager mWifiManager;
- private IntentFilter mIntentFilter;
- private List<AccessPointState> mApScanList = new ArrayList<AccessPointState>();
- private List<AccessPointState> mApOtherList = new ArrayList<AccessPointState>();
- private AccessPointState mCurrentPrimaryAp;
-
- /** The last access point that we were authenticating with. */
- private AccessPointState mLastAuthenticatingAp;
-
- /** The delay between scans when we're continually scanning. */
- private static final int CONTINUOUS_SCAN_DELAY_MS = 6000;
- /** On failure, the maximum retries for scanning. */
- private static final int SCAN_MAX_RETRY = 5;
- /** On failure, the delay between each scan retry. */
- private static final int SCAN_RETRY_DELAY_MS = 1000;
- /** On failure, the number of retries so far. */
- private int mScanRetryCount = 0;
- /**
- * Whether we're currently obtaining an address. Continuous scanning will be
- * disabled in this state.
- */
- private boolean mIsObtainingAddress;
-
- /**
- * See {@link android.provider.Settings.Secure#WIFI_NUM_OPEN_NETWORKS_KEPT}.
- */
- private int WIFI_NUM_OPEN_NETWORKS_KEPT;
- /**
- * Once the highest priority exceeds this value, all networks will be
- * wrapped around starting at 0. This is so another client of the Wi-Fi
- * API can have access points that aren't managed by us. (If the other
- * client wants lower-priority access points than ours, it can use negative
- * priority.)
- */
- private static final int HIGHEST_PRIORITY_MAX_VALUE = 99999;
- /**
- * Never access directly, only the related methods should.
- */
- private int mNextHighestPriority;
-
- /**
- * This is used to track when the user wants to connect to a specific AP. We
- * disable all other APs, set this to true, and let wpa_supplicant connect.
- * Once we get a network state change, we re-enable the rest of them.
- */
- private boolean mReenableApsOnNetworkStateChange = false;
-
- /**
- * The current supplicant state, as broadcasted.
- */
- private SupplicantState mCurrentSupplicantState;
-
- //============================
- // Inner classes
- //============================
-
- interface Callback {
- void onError(int messageResId);
-
- /**
- * Called when an AP is added or removed.
- *
- * @param ap The AP.
- * @param added {@code true} if added, {@code false} if removed.
- */
- void onAccessPointSetChanged(AccessPointState ap, boolean added);
-
- /**
- * Called when the scanning status changes.
- *
- * @param started {@code true} if the scanning just started,
- * {@code false} if it just ended.
- */
- void onScanningStatusChanged(boolean started);
-
- /**
- * Called when the access points should be enabled or disabled. This is
- * called from both wpa_supplicant being connected/disconnected and Wi-Fi
- * being enabled/disabled.
- *
- * @param enabled {@code true} if they should be enabled, {@code false}
- * if they should be disabled.
- */
- void onAccessPointsStateChanged(boolean enabled);
-
- /**
- * Called when there is trouble authenticating and the retry-password
- * dialog should be shown.
- *
- * @param ap The access point.
- */
- void onRetryPassword(AccessPointState ap);
- }
-
- private BroadcastReceiver mReceiver = new BroadcastReceiver() {
-
- @Override
- public void onReceive(Context context, Intent intent) {
- final String action = intent.getAction();
- if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
- handleNetworkStateChanged(
- (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO),
- intent.getStringExtra(WifiManager.EXTRA_BSSID));
- } else if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
- handleScanResultsAvailable();
- } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) {
- handleSupplicantConnectionChanged(
- intent.getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false));
- } else if (action.equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) {
- handleSupplicantStateChanged(
- (SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE),
- intent.hasExtra(WifiManager.EXTRA_SUPPLICANT_ERROR),
- intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0));
- } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
- handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
- WifiManager.WIFI_STATE_UNKNOWN));
- } else if (action.equals(WifiManager.RSSI_CHANGED_ACTION)) {
- handleSignalChanged(intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, 0));
- } else if (action.equals(WifiManager.NETWORK_IDS_CHANGED_ACTION)) {
- handleNetworkIdsChanged();
- }
- }
- };
-
- /**
- * If using this class, make sure to call the callbacks of this class, such
- * as {@link #onCreate()}, {@link #onCreatedCallback()},
- * {@link #onPause()}, {@link #onResume()}.
- *
- * @param context The context.
- * @param callback The interface that will be invoked when events from this
- * class are generated.
- */
- public WifiLayer(Context context, Callback callback) {
- mContext = context;
- mCallback = callback;
- }
-
- //============================
- // Lifecycle
- //============================
-
- /**
- * The client MUST call this.
- * <p>
- * This shouldn't have any dependency on the callback.
- */
- public void onCreate() {
- mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-
- mIntentFilter = new IntentFilter();
- mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
- mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
- mIntentFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.RSSI_CHANGED_ACTION);
- mIntentFilter.addAction(WifiManager.NETWORK_IDS_CHANGED_ACTION);
-
- WIFI_NUM_OPEN_NETWORKS_KEPT = Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.WIFI_NUM_OPEN_NETWORKS_KEPT, 10);
- }
-
- /**
- * The client MUST call this.
- * <p>
- * Callback is ready, this can do whatever it wants with it.
- */
- public void onCreatedCallback() {
- if (isWifiEnabled()) {
- refreshAll(false);
- }
- }
-
- /**
- * The client MUST call this.
- *
- * @see android.app.Activity#onResume
- */
- public void onResume() {
- mContext.registerReceiver(mReceiver, mIntentFilter);
-
- if (isWifiEnabled()) {
- // Kick start the continual scan
- queueContinuousScan();
- }
- }
-
- /**
- * The client MUST call this.
- *
- * @see android.app.Activity#onPause
- */
- public void onPause() {
- mContext.unregisterReceiver(mReceiver);
-
- attemptReenableAllAps();
-
- removeFutureScans();
- }
-
- //============================
- // "Public" API
- //============================
-
- /**
- * Returns an AccessPointState instance (that we track locally in WifiLayer)
- * for the given state. First, we check if we track the given instance. If
- * not, we find an equal AccessPointState instance that we track.
- *
- * @param state An AccessPointState instance that does not necessarily have
- * to be one that this WifiLayer class tracks. For example, it
- * could be the result of unparceling.
- * @return An AccessPointState instance that this WifiLayer class tracks.
- */
- public AccessPointState getWifiLayerApInstance(AccessPointState state) {
- synchronized (this) {
-
- if (hasApInstanceLocked(state)) {
- return state;
- }
-
- return findApLocked(state.networkId, state.bssid, state.ssid, state.security);
- }
- }
-
- /**
- * Connects to the network, and creates the Wi-Fi API config if necessary.
- *
- * @param state The state of the network to connect to. This MUST be an
- * instance that was given to you by this class. If you
- * constructed the instance yourself (for example, after
- * unparceling it), you should use
- * {@link #getWifiLayerApInstance(AccessPointState)}.
- * @return Whether the operation was successful.
- */
- public boolean connectToNetwork(AccessPointState state) {
- if (LOGV) {
- Log.v(TAG, "Connecting to " + state);
- }
-
- // Need WifiConfiguration for the AP
- WifiConfiguration config = findConfiguredNetwork(state);
-
- if (LOGV) {
- Log.v(TAG, " Found configured network " + config);
- }
-
- if (config == null) {
- /*
- * Connecting for the first time, need to create it. We will enable
- * and save it below (when we set priority).
- */
- config = addConfiguration(state, 0);
-
- if (config == null) {
- Log.e(TAG, "Config is still null, even after attempting to add it.");
- error(R.string.error_connecting);
- return false;
- }
-
- /*
- * We could reload the configured networks, but instead just
- * shortcut and add this state to our list in memory.
- */
- ensureTrackingState(state);
- } else {
- // Make sure the configuration has the latest from the state
- state.updateWifiConfiguration(config);
- }
-
- // Enable this network before we save to storage
- if (!managerEnableNetwork(state, false)) {
- Log.e(TAG, "Could not enable network ID " + state.networkId);
- error(R.string.error_connecting);
- return false;
- }
-
- /*
- * Give it highest priority, this could cause a network ID change, so do
- * it after any modifications to the network we're connecting to
- */
- setHighestPriorityStateAndSave(state, config);
-
- /*
- * We force supplicant to connect to this network by disabling the
- * others. We do this AFTER we save above so this disabled flag isn't
- * persisted.
- */
- mReenableApsOnNetworkStateChange = true;
- if (!managerEnableNetwork(state, true)) {
- Log.e(TAG, "Could not enable network ID " + state.networkId);
- error(R.string.error_connecting);
- return false;
- }
-
- if (LOGV) {
- Log.v(TAG, " Enabled network " + state.networkId);
- }
-
- if (mCurrentSupplicantState == SupplicantState.DISCONNECTED ||
- mCurrentSupplicantState == SupplicantState.SCANNING) {
- mWifiManager.reconnect();
- }
-
- // Check for too many configured open networks
- if (!state.hasSecurity()) {
- checkForExcessOpenNetworks();
- }
-
- return true;
- }
-
- /**
- * Saves a network, and creates the Wi-Fi API config if necessary.
- *
- * @param state The state of the network to save. If you constructed the
- * instance yourself (for example, after unparceling it), you
- * should use {@link #getWifiLayerApInstance(AccessPointState)}.
- * @return Whether the operation was successful.
- */
- public boolean saveNetwork(AccessPointState state) {
- WifiConfiguration config = findConfiguredNetwork(state);
-
- if (config == null) {
- // if the user is adding a new network, assume that it is hidden
- state.setHiddenSsid(true);
-
- config = addConfiguration(state, ADD_CONFIGURATION_ENABLE);
-
- if (config == null) {
- Log.e(TAG, "Could not save configuration, call to addConfiguration failed.");
- error(R.string.error_saving);
- return false;
- }
-
- } else {
- state.updateWifiConfiguration(config);
- if (mWifiManager.updateNetwork(config) == -1) {
- Log.e(TAG, "Could not update configuration, call to WifiManager failed.");
- error(R.string.error_saving);
- return false;
- }
- }
-
- // Successfully added network, go ahead and persist
- if (!managerSaveConfiguration()) {
- Log.e(TAG, "Could not save configuration, call to WifiManager failed.");
- error(R.string.error_saving);
- return false;
- }
-
- /*
- * We could reload the configured networks, but instead just shortcut
- * and add this state to our list in memory
- */
- ensureTrackingState(state);
-
- return true;
- }
-
- /**
- * Forgets a network.
- *
- * @param state The state of the network to forget. If you constructed the
- * instance yourself (for example, after unparceling it), you
- * should use {@link #getWifiLayerApInstance(AccessPointState)}.
- * @return Whether the operation was succesful.
- */
- public boolean forgetNetwork(AccessPointState state) {
- if (!state.configured) {
- Log.w(TAG, "Inconsistent state: Forgetting a network that is not configured.");
- return true;
- }
-
- int oldNetworkId = state.networkId;
- state.forget();
-
- if (!state.seen) {
- // If it is not seen, it should be removed from the UI
- removeApFromUi(state);
- }
-
- synchronized (this) {
- mApOtherList.remove(state);
- // It should not be removed from the scan list, since if it was
- // there that means it's still seen
- }
-
- if (!mWifiManager.removeNetwork(oldNetworkId)) {
- Log.e(TAG, "Removing network " + state.ssid + " (network ID " + oldNetworkId +
- ") failed.");
- return false;
- }
-
- if (!managerSaveConfiguration()) {
- error(R.string.error_saving);
- return false;
- }
-
- return true;
- }
-
- /**
- * This ensures this class is tracking the given state. This means it is in
- * our list of access points, either in the scanned list or in the
- * remembered list.
- *
- * @param state The state that will be checked for tracking, and if not
- * tracking will be added to the remembered list in memory.
- */
- private void ensureTrackingState(AccessPointState state) {
- synchronized (this) {
- if (hasApInstanceLocked(state)) {
- return;
- }
-
- mApOtherList.add(state);
- }
- }
-
- /**
- * Attempts to scan networks. This has a retry mechanism.
- */
- public void attemptScan() {
-
- // Remove any future scans since we're scanning right now
- removeFutureScans();
-
- if (!mWifiManager.isWifiEnabled()) return;
-
- if (!mWifiManager.startScan()) {
- postAttemptScan();
- } else {
- mScanRetryCount = 0;
- }
- }
-
- private void queueContinuousScan() {
- mHandler.removeMessages(MESSAGE_ATTEMPT_SCAN);
-
- if (!mIsObtainingAddress) {
- // Don't do continuous scan while in obtaining IP state
- mHandler.sendEmptyMessageDelayed(MESSAGE_ATTEMPT_SCAN, CONTINUOUS_SCAN_DELAY_MS);
- }
- }
-
- private void removeFutureScans() {
- mHandler.removeMessages(MESSAGE_ATTEMPT_SCAN);
- }
-
- public boolean isWifiEnabled() {
- return mWifiManager.isWifiEnabled();
- }
-
- public void error(int messageResId) {
- Log.e(TAG, mContext.getResources().getString(messageResId));
-
- if (mCallback != null) {
- mCallback.onError(messageResId);
- }
- }
-
- //============================
- // Wifi logic
- //============================
-
- private void refreshAll(boolean attemptScan) {
- loadConfiguredAccessPoints();
- refreshStatus();
-
- if (attemptScan) {
- attemptScan();
- }
- }
-
- private void postAttemptScan() {
- onScanningStarted();
-
- if (++mScanRetryCount < SCAN_MAX_RETRY) {
- // Just in case, remove previous ones first
- removeFutureScans();
- mHandler.sendEmptyMessageDelayed(MESSAGE_ATTEMPT_SCAN, SCAN_RETRY_DELAY_MS);
- } else {
- // Show an error once we run out of attempts
- error(R.string.error_scanning);
- onScanningEnded();
- }
- }
-
- private void onScanningStarted() {
- if (mCallback != null) {
- mCallback.onScanningStatusChanged(true);
- }
- }
-
- private void onScanningEnded() {
- queueContinuousScan();
-
- if (mCallback != null) {
- mCallback.onScanningStatusChanged(false);
- }
- }
-
- private void clearApLists() {
- List<AccessPointState> accessPoints = new ArrayList<AccessPointState>();
-
- synchronized(this) {
- // Clear the logic's list of access points
- accessPoints.addAll(mApScanList);
- accessPoints.addAll(mApOtherList);
- mApScanList.clear();
- mApOtherList.clear();
- }
-
- for (int i = accessPoints.size() - 1; i >= 0; i--) {
- removeApFromUi(accessPoints.get(i));
- }
- }
-
- private boolean managerSaveConfiguration() {
- boolean retValue = mWifiManager.saveConfiguration();
-
- /*
- * We need to assume the network IDs have changed, so handle this. Note:
- * we also have a receiver on the broadcast intent in case another wifi
- * framework client caused the change. In this case, we will handle the
- * possible network ID change twice (but it's not too costly).
- */
- handleNetworkIdsChanged();
-
- return retValue;
- }
-
- private boolean managerEnableNetwork(AccessPointState state, boolean disableOthers) {
- if (!mWifiManager.enableNetwork(state.networkId, disableOthers)) {
- return false;
- }
-
- // Enabling was successful, make sure the state is not disabled
- state.setDisabled(false);
-
- return true;
- }
-
- private static final int ADD_CONFIGURATION_ENABLE = 1;
- private static final int ADD_CONFIGURATION_SAVE = 2;
- private WifiConfiguration addConfiguration(AccessPointState state, int flags) {
- // Create and add
- WifiConfiguration config = new WifiConfiguration();
-
- state.updateWifiConfiguration(config);
-
- final int networkId = mWifiManager.addNetwork(config);
- if (networkId == -1) {
- return null;
- }
-
- state.setNetworkId(networkId);
- state.setConfigured(true);
-
- // If we should, then enable it, since it comes disabled by default
- if ((flags & ADD_CONFIGURATION_ENABLE) != 0
- && !managerEnableNetwork(state, false)) {
- return null;
- }
-
- // If we should, then save it
- if ((flags & ADD_CONFIGURATION_SAVE) != 0 && !managerSaveConfiguration()) {
- return null;
- }
-
- if (mCallback != null) {
- mCallback.onAccessPointSetChanged(state, true);
- }
-
- return config;
- }
-
- private WifiConfiguration findConfiguredNetwork(AccessPointState state) {
- final List<WifiConfiguration> wifiConfigs = getConfiguredNetworks();
-
- for (int i = wifiConfigs.size() - 1; i >= 0; i--) {
- final WifiConfiguration wifiConfig = wifiConfigs.get(i);
- if (state.matchesWifiConfiguration(wifiConfig) >= AccessPointState.MATCH_WEAK) {
- return wifiConfig;
- }
- }
-
- return null;
- }
-
- private List<WifiConfiguration> getConfiguredNetworks() {
- final List<WifiConfiguration> wifiConfigs = mWifiManager.getConfiguredNetworks();
- return wifiConfigs;
- }
-
- /**
- * Must call while holding the lock for the list, which is usually the
- * WifiLayer instance.
- */
- private static AccessPointState findApLocked(List<AccessPointState> list, int networkId,
- String bssid, String ssid, String security) {
- AccessPointState ap;
- for (int i = list.size() - 1; i >= 0; i--) {
- ap = list.get(i);
- if (ap.matches(networkId, bssid, ssid, security) >= AccessPointState.MATCH_WEAK) {
- return ap;
- }
- }
-
- return null;
- }
-
- /**
- * Must call while holding the lock for the lists, which is usually this
- * WifiLayer instance.
- */
- private AccessPointState findApLocked(int networkId, String bssid, String ssid,
- String security) {
- AccessPointState ap = findApLocked(mApScanList, networkId, bssid, ssid, security);
- if (ap == null) {
- ap = findApLocked(mApOtherList, networkId, bssid, ssid, security);
- }
- return ap;
- }
-
- /**
- * Returns whether we have the exact instance of the access point state
- * given. This is useful in cases where an AccessPointState has been
- * parceled by the client and the client is attempting to use it to
- * connect/forget/save.
- * <p>
- * Must call while holding the lock for the lists, which is usually this
- * WifiLayer instance.
- */
- private boolean hasApInstanceLocked(AccessPointState state) {
-
- for (int i = mApScanList.size() - 1; i >= 0; i--) {
- if (mApScanList.get(i) == state) {
- return true;
- }
- }
-
- for (int i = mApOtherList.size() - 1; i >= 0; i--) {
- if (mApOtherList.get(i) == state) {
- return true;
- }
- }
-
- return false;
- }
-
- private void loadConfiguredAccessPoints() {
- final List<WifiConfiguration> configs = getConfiguredNetworks();
-
- for (int i = configs.size() - 1; i >= 0; i--) {
- final WifiConfiguration config = configs.get(i);
-
- AccessPointState ap;
- synchronized(this) {
- ap = findApLocked(config.networkId, config.BSSID, config.SSID,
- AccessPointState.getWifiConfigurationSecurity(config));
-
- if (ap != null) {
- // We already know about this one
- continue;
- }
-
- ap = new AccessPointState(mContext);
- ap.updateFromWifiConfiguration(config);
- if (LOGV) Log.v(TAG, "Created " + ap + " in loadConfiguredAccessPoints");
- mApOtherList.add(ap);
- }
-
- // Make sure our next highest priority is greater than this
- checkNextHighestPriority(ap.priority);
-
- if (mCallback != null) {
- mCallback.onAccessPointSetChanged(ap, true);
- }
- }
- }
-
- private AccessPointState getCurrentAp() {
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
-
- String ssid = wifiInfo.getSSID();
- if (ssid != null) {
- /*
- * We pass null for security since we have a network ID (i.e., it's
- * not a wildcard), and rely on it matching.
- */
- return findApLocked(wifiInfo.getNetworkId(), wifiInfo.getBSSID(), ssid, null);
- } else {
- return null;
- }
- }
-
- private void setPrimaryAp(AccessPointState ap) {
- synchronized (this) {
- // Unset other
- if (mCurrentPrimaryAp != null) {
- mCurrentPrimaryAp.setPrimary(false);
- }
-
- mCurrentPrimaryAp = ap;
- }
-
- if (ap != null) {
- ap.setPrimary(true);
- }
- }
-
- private void attemptReenableAllAps() {
- if (mReenableApsOnNetworkStateChange) {
- mReenableApsOnNetworkStateChange = false;
- enableAllAps();
- }
- }
-
- private void enableAllAps() {
- synchronized(this) {
- if (LOGV) {
- Log.v(TAG, " Enabling all APs");
- }
-
- enableApsLocked(mApOtherList);
- enableApsLocked(mApScanList);
- }
- }
-
- private void enableApsLocked(List<AccessPointState> apList) {
- for (int i = apList.size() - 1; i >= 0; i--) {
- AccessPointState state = apList.get(i);
- int networkId = state.networkId;
- if (networkId != AccessPointState.NETWORK_ID_NOT_SET &&
- networkId != AccessPointState.NETWORK_ID_ANY) {
- managerEnableNetwork(state, false);
- }
- }
- }
-
- private void removeApFromUi(AccessPointState ap) {
- if (mCallback != null) {
- mCallback.onAccessPointSetChanged(ap, false);
- }
- }
-
- /**
- * Sets the access point state to the highest priority.
- * <p>
- * If you have a list of configured networks from WifiManager, you probably
- * shouldn't call this until you're done traversing the list.
- *
- * @param state The state to set as the highest priority.
- * @param reusableConfiguration An optional WifiConfiguration that will be
- * given to the WifiManager as updated data for the network ID.
- * This will be filled with the new priority.
- * @return Whether the operation was successful.
- */
- private boolean setHighestPriorityStateAndSave(AccessPointState state,
- WifiConfiguration reusableConfiguration) {
-
- if (!isConsideredForHighestPriority(state)) {
- Log.e(TAG,
- "Could not set highest priority on state because state is not being considered.");
- return false;
- }
-
- if (reusableConfiguration == null) {
- reusableConfiguration = new WifiConfiguration();
- }
-
- int oldPriority = reusableConfiguration.priority;
- reusableConfiguration.priority = getNextHighestPriority();
- reusableConfiguration.networkId = state.networkId;
-
- if (mWifiManager.updateNetwork(reusableConfiguration) == -1) {
- // Rollback priority
- reusableConfiguration.priority = oldPriority;
- Log.e(TAG,
- "Could not set highest priority on state because updating the supplicant network failed.");
- return false;
- }
-
- if (!managerSaveConfiguration()) {
- reusableConfiguration.priority = oldPriority;
- Log.e(TAG,
- "Could not set highest priority on state because saving config failed.");
- return false;
- }
-
- state.priority = reusableConfiguration.priority;
-
- if (LOGV) {
- Log.v(TAG, " Set highest priority to "
- + state.priority + " from " + oldPriority);
- }
-
- return true;
- }
-
- /**
- * Makes sure the next highest priority is larger than the given priority.
- */
- private void checkNextHighestPriority(int priority) {
- if (priority > HIGHEST_PRIORITY_MAX_VALUE || priority < 0) {
- // This is a priority that we aren't managing
- return;
- }
-
- if (mNextHighestPriority <= priority) {
- mNextHighestPriority = priority + 1;
- }
- }
-
- /**
- * Checks if there are too many open networks, and removes the excess ones.
- */
- private void checkForExcessOpenNetworks() {
- synchronized(this) {
- ArrayList<AccessPointState> allAps = getApsSortedByPriorityLocked();
-
- // Walk from highest to lowest priority
- int openConfiguredCount = 0;
- for (int i = allAps.size() - 1; i >= 0; i--) {
- AccessPointState state = allAps.get(i);
- if (state.configured && !state.hasSecurity()) {
- openConfiguredCount++;
- if (openConfiguredCount > WIFI_NUM_OPEN_NETWORKS_KEPT) {
- // Remove this network
- forgetNetwork(state);
- }
- }
- }
- }
- }
-
- private boolean isConsideredForHighestPriority(AccessPointState state) {
- return state.configured && state.networkId != AccessPointState.NETWORK_ID_ANY &&
- state.networkId != AccessPointState.NETWORK_ID_NOT_SET;
- }
-
- /**
- * Gets the next highest priority. If this value is larger than the max,
- * shift all the priorities so the lowest starts at 0.
- * <p>
- * Only
- * {@link #setHighestPriorityStateAndSave(AccessPointState, WifiConfiguration)}
- * should call this.
- *
- * @return The next highest priority to use.
- */
- private int getNextHighestPriority() {
- if (mNextHighestPriority > HIGHEST_PRIORITY_MAX_VALUE) {
- shiftPriorities();
- }
-
- return mNextHighestPriority++;
- }
-
- /**
- * Shift all the priorities so the lowest starts at 0.
- *
- * @return Whether the operation was successful.
- */
- private boolean shiftPriorities() {
- synchronized(this) {
-
- ArrayList<AccessPointState> allAps = getApsSortedByPriorityLocked();
-
- // Re-usable WifiConfiguration for setting priority
- WifiConfiguration updatePriorityConfig = new WifiConfiguration();
-
- // Set new priorities
- mNextHighestPriority = 0;
- int size = allAps.size();
- for (int i = 0; i < size; i++) {
- AccessPointState state = allAps.get(i);
-
- if (!isConsideredForHighestPriority(state)) {
- continue;
- }
-
- if (!setHighestPriorityStateAndSave(state, updatePriorityConfig)) {
- Log.e(TAG,
- "Could not shift priorities because setting the new priority failed.");
- return false;
- }
- }
-
- return true;
- }
- }
-
- private ArrayList<AccessPointState> getApsSortedByPriorityLocked() {
- // Get all of the access points we have
- ArrayList<AccessPointState> allAps = new ArrayList<AccessPointState>(mApScanList.size()
- + mApOtherList.size());
- allAps.addAll(mApScanList);
- allAps.addAll(mApOtherList);
-
- // Sort them based on priority
- Collections.sort(allAps, new Comparator<AccessPointState>() {
- public int compare(AccessPointState object1, AccessPointState object2) {
- return object1.priority - object2.priority;
- }
- });
-
- return allAps;
- }
-
- //============================
- // Status related
- //============================
-
- private void refreshStatus() {
- refreshStatus(null, null);
- }
-
- private void refreshStatus(AccessPointState ap, NetworkInfo.DetailedState detailedState) {
- final WifiInfo wifiInfo = mWifiManager.getConnectionInfo();
- if (detailedState == null) {
- detailedState = WifiInfo.getDetailedStateOf(wifiInfo.getSupplicantState());
- }
-
- if (ap == null && WifiStatus.isLiveConnection(detailedState)) {
- /*
- * We pass null for security since we have a network ID (i.e., it's
- * not a wildcard), and rely on it matching.
- */
- ap = findApLocked(wifiInfo.getNetworkId(), wifiInfo.getBSSID(), wifiInfo
- .getSSID(), null);
- }
-
- if (ap != null) {
- ap.blockRefresh();
-
- // Let the AP get the latest info from the WifiInfo
- ap.updateFromWifiInfo(wifiInfo, detailedState);
-
- // The detailed state from the Intent has more states than the WifiInfo's detailed
- // state can have (for example, DHCP completion). Set the status using
- // the Intent's detailed state.
- ap.setStatus(detailedState);
- ap.unblockRefresh();
- }
- }
-
- //============================
- // Wifi callbacks
- //============================
-
- private void handleNetworkStateChanged(NetworkInfo info, String bssid) {
- final AccessPointState ap = getCurrentAp();
- NetworkInfo.DetailedState detailedState = info.getDetailedState();
-
- if (LOGV) {
- Log.v(TAG, "State change received " + info.toString() + ", or "
- + detailedState + " on " + bssid + " matched to " + ap);
- }
-
- handleDisablingScanWhileObtainingAddress(detailedState);
-
- // This will update the AP with its new info
- refreshStatus(ap, detailedState);
-
- boolean isDisconnected = info.getState().equals(State.DISCONNECTED);
- if (ap != null && info.isConnectedOrConnecting()) {
- setPrimaryAp(ap);
-
- if (LOGV) {
- Log.v(TAG, " Updated " + ap + " to be primary");
- }
-
- } else if (isDisconnected) {
-
- /*
- * When we drop off a network (for example, the router is powered
- * down when we were connected), we received a DISCONNECT event
- * without a BSSID. We should not have a primary AP anymore.
- */
- setPrimaryAp(null);
-
- if (LOGV) {
- Log.v(TAG, " Cleared primary");
- }
-
- } else if (detailedState.equals(DetailedState.FAILED)) {
-
- /*
- * Doh, failed for whatever reason. Unset the primary AP, but set
- * failed status on the AP that failed.
- */
- setPrimaryAp(null);
- ap.setStatus(DetailedState.FAILED);
-
- // Bring up error dialog
- error(R.string.wifi_generic_connection_error);
-
- } else if (LOGV) {
- Log.v(TAG, " Did not update any AP to primary, could have updated "
- + ap + " but we aren't connected or connecting");
- }
-
- if ((ap != null) && (info.isConnected()
- || (detailedState == DetailedState.OBTAINING_IPADDR))) {
- /*
- * Sometimes the scan results do not contain the AP even though it's
- * clearly connected. This may be because we do passive background
- * scanning that isn't as 'strong' as active scanning, so even
- * though a network is nearby, it won't be seen by the passive
- * scanning. If we are connected (or obtaining IP) then we know it
- * is seen.
- */
- ap.setSeen(true);
- }
-
- attemptReenableAllAps();
- }
-
- private void handleDisablingScanWhileObtainingAddress(DetailedState detailedState) {
-
- if (detailedState == DetailedState.OBTAINING_IPADDR) {
- mIsObtainingAddress = true;
-
- // We will not scan while obtaining an IP address
- removeFutureScans();
-
- } else {
- mIsObtainingAddress = false;
-
- // Start continuous scan
- queueContinuousScan();
- }
- }
-
- private void handleScanResultsAvailable() {
- synchronized(this) {
- // In the end, we'll moved the ones no longer seen into the mApOtherList
- List<AccessPointState> oldScanList = mApScanList;
- List<AccessPointState> newScanList =
- new ArrayList<AccessPointState>(oldScanList.size());
-
- List<ScanResult> list = mWifiManager.getScanResults();
- if (list != null) {
- for (int i = list.size() - 1; i >= 0; i--) {
- final ScanResult scanResult = list.get(i);
-
- if (LOGV) {
-// Log.v(TAG, " " + scanResult);
- }
-
- if (scanResult == null) {
- continue;
- }
-
- /*
- * Ignore adhoc, enterprise-secured, or hidden networks.
- * Hidden networks show up with empty SSID.
- */
- if (AccessPointState.isAdhoc(scanResult)
- || AccessPointState.isEnterprise(scanResult)
- || TextUtils.isEmpty(scanResult.SSID)) {
- continue;
- }
-
- final String ssid = AccessPointState.convertToQuotedString(scanResult.SSID);
- String security = AccessPointState.getScanResultSecurity(scanResult);
-
- // See if this AP is part of a group of APs (e.g., any large
- // wifi network has many APs, we'll only show one) that we've
- // seen in this scan
- AccessPointState ap = findApLocked(newScanList, AccessPointState.NETWORK_ID_ANY,
- AccessPointState.BSSID_ANY, ssid, security);
-
- // Yup, we've seen this network.
- if (ap != null) {
- // Use the better signal
- if (WifiManager.compareSignalLevel(scanResult.level, ap.signal) > 0) {
- ap.setSignal(scanResult.level);
- }
-
- if (LOGV) {
-// Log.v(TAG, " Already seen, continuing..");
- }
-
- continue;
- }
-
- // Find the AP in either our old scan list, or our non-seen
- // configured networks list
- ap = findApLocked(AccessPointState.NETWORK_ID_ANY, AccessPointState.BSSID_ANY,
- ssid, security);
-
- if (ap != null) {
- // Remove the AP from both (no harm if one doesn't contain it)
- oldScanList.remove(ap);
- mApOtherList.remove(ap);
- } else {
- ap = new AccessPointState(mContext);
-// if (LOGV) Log.v(TAG, "Created " + ap);
- }
-
- // Give it the latest state
- ap.updateFromScanResult(scanResult);
-
- if (mCallback != null) {
- mCallback.onAccessPointSetChanged(ap, true);
- }
-
- newScanList.add(ap);
- }
- }
-
- // oldScanList contains the ones no longer seen
- List<AccessPointState> otherList = mApOtherList;
- for (int i = oldScanList.size() - 1; i >= 0; i--) {
- final AccessPointState ap = oldScanList.get(i);
-
- if (ap.configured) {
-
- // Keep it around, since it is configured
- ap.setSeen(false);
- otherList.add(ap);
-
- } else {
-
- // Remove it since it is not configured and not seen
- removeApFromUi(ap);
- }
- }
-
- mApScanList = newScanList;
- }
-
- onScanningEnded();
- }
-
- private void handleSupplicantConnectionChanged(boolean connected) {
- if (mCallback != null) {
- mCallback.onAccessPointsStateChanged(connected);
- }
-
- if (connected) {
- refreshAll(true);
- }
- }
-
- private void handleWifiStateChanged(int wifiState) {
-
- if (wifiState == WIFI_STATE_ENABLED) {
- loadConfiguredAccessPoints();
- attemptScan();
-
- } else if (wifiState == WIFI_STATE_DISABLED) {
- removeFutureScans();
- if (LOGV) Log.v(TAG, "Clearing AP lists because wifi is disabled");
- clearApLists();
- }
-
- if (mCallback != null) {
- mCallback.onAccessPointsStateChanged(wifiState == WIFI_STATE_ENABLED);
- }
- }
-
- private void handleSignalChanged(int rssi) {
-
- if (mCurrentPrimaryAp != null) {
- mCurrentPrimaryAp.setSignal(rssi);
- }
- }
-
- private void handleSupplicantStateChanged(SupplicantState state, boolean hasError, int error) {
- mCurrentSupplicantState = state;
-
- if (SupplicantState.FOUR_WAY_HANDSHAKE.equals(state)) {
- mLastAuthenticatingAp = getCurrentAp();
- }
-
- if (hasError) {
- handleSupplicantStateError(error);
- }
- }
-
- private void handleSupplicantStateError(int supplicantError) {
- if (supplicantError == WifiManager.ERROR_AUTHENTICATING) {
- if (mCallback != null) {
- if (mLastAuthenticatingAp != null) {
- mCallback.onRetryPassword(mLastAuthenticatingAp);
- }
- }
- }
- }
-
- private void handleNetworkIdsChanged() {
- synchronized (this) {
- final List<WifiConfiguration> configs = getConfiguredNetworks();
-
- for (int i = configs.size() - 1; i >= 0; i--) {
- final WifiConfiguration config = configs.get(i);
-
- AccessPointState ap;
- // Since network IDs have changed, we can't use it to find our previous AP state
- ap = findApLocked(AccessPointState.NETWORK_ID_ANY, config.BSSID, config.SSID,
- AccessPointState.getWifiConfigurationSecurity(config));
-
- if (ap == null) {
- continue;
- }
-
- ap.setNetworkId(config.networkId);
- }
- }
- }
-
- private class MyHandler extends Handler {
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MESSAGE_ATTEMPT_SCAN:
- attemptScan();
- break;
- }
- }
- }
-
-}