/* * Copyright (C) 2010 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 com.android.settings.R; import android.content.Context; import android.net.NetworkInfo.DetailedState; import android.net.wifi.ScanResult; import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiConfiguration.KeyMgmt; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.preference.Preference; import android.view.View; import android.widget.ImageView; import java.util.Comparator; class AccessPoint extends Preference { private static final String KEY_DETAILEDSTATE = "key_detailedstate"; private static final String KEY_WIFIINFO = "key_wifiinfo"; private static final String KEY_SCANRESULT = "key_scanresult"; private static final String KEY_CONFIG = "key_config"; private static final int[] STATE_SECURED = {R.attr.state_encrypted}; private static final int[] STATE_NONE = {}; static final int SECURITY_NONE = 0; static final int SECURITY_WEP = 1; static final int SECURITY_PSK = 2; static final int SECURITY_EAP = 3; String ssid; String bssid; int security; int networkId; boolean wpsAvailable = false; private WifiConfiguration mConfig; /*package*/ScanResult mScanResult; private int mRssi; private WifiInfo mInfo; private DetailedState mState; private ImageView mSignal; static int getSecurity(WifiConfiguration config) { if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { return SECURITY_PSK; } if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) || config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { return SECURITY_EAP; } return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE; } private static int getSecurity(ScanResult result) { if (result.capabilities.contains("WEP")) { return SECURITY_WEP; } else if (result.capabilities.contains("PSK")) { return SECURITY_PSK; } else if (result.capabilities.contains("EAP")) { return SECURITY_EAP; } return SECURITY_NONE; } AccessPoint(Context context, WifiConfiguration config) { super(context); setWidgetLayoutResource(R.layout.preference_widget_wifi_signal); loadConfig(config); } AccessPoint(Context context, ScanResult result) { super(context); setWidgetLayoutResource(R.layout.preference_widget_wifi_signal); loadResult(result); } AccessPoint(Context context, Bundle savedState) { super(context); setWidgetLayoutResource(R.layout.preference_widget_wifi_signal); mConfig = savedState.getParcelable(KEY_CONFIG); if (mConfig != null) { loadConfig(mConfig); } mScanResult = (ScanResult) savedState.getParcelable(KEY_SCANRESULT); if (mScanResult != null) { loadResult(mScanResult); } mInfo = (WifiInfo) savedState.getParcelable(KEY_WIFIINFO); if (savedState.containsKey(KEY_DETAILEDSTATE)) { mState = DetailedState.valueOf(savedState.getString(KEY_DETAILEDSTATE)); } update(mInfo, mState); } public void saveWifiState(Bundle savedState) { savedState.putParcelable(KEY_CONFIG, mConfig); savedState.putParcelable(KEY_SCANRESULT, mScanResult); savedState.putParcelable(KEY_WIFIINFO, mInfo); if (mState != null) { savedState.putString(KEY_DETAILEDSTATE, mState.toString()); } } private void loadConfig(WifiConfiguration config) { ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID)); bssid = config.BSSID; security = getSecurity(config); networkId = config.networkId; mRssi = Integer.MAX_VALUE; mConfig = config; } private void loadResult(ScanResult result) { ssid = result.SSID; bssid = result.BSSID; security = getSecurity(result); wpsAvailable = security != SECURITY_EAP && result.capabilities.contains("WPS"); networkId = -1; mRssi = result.level; mScanResult = result; } @Override protected void onBindView(View view) { setTitle(ssid); mSignal = (ImageView) view.findViewById(R.id.signal); if (mRssi == Integer.MAX_VALUE) { mSignal.setImageDrawable(null); } else { mSignal.setImageResource(R.drawable.wifi_signal); mSignal.setImageState((security != SECURITY_NONE) ? STATE_SECURED : STATE_NONE, true); } refresh(); super.onBindView(view); } @Override public int compareTo(Preference preference) { if (!(preference instanceof AccessPoint)) { return 1; } AccessPoint other = (AccessPoint) preference; // Active one goes first. if (mInfo != other.mInfo) { return (mInfo != null) ? -1 : 1; } // Reachable one goes before unreachable one. if ((mRssi ^ other.mRssi) < 0) { return (mRssi != Integer.MAX_VALUE) ? -1 : 1; } // Configured one goes before unconfigured one. if ((networkId ^ other.networkId) < 0) { return (networkId != -1) ? -1 : 1; } // Sort by signal strength. int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi); if (difference != 0) { return difference; } // Sort by ssid. return ssid.compareToIgnoreCase(other.ssid); } boolean update(ScanResult result) { // We do not call refresh() since this is called before onBindView(). if (ssid.equals(result.SSID) && security == getSecurity(result)) { if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) { mRssi = result.level; } return true; } return false; } void update(WifiInfo info, DetailedState state) { boolean reorder = false; if (info != null && networkId != -1 && networkId == info.getNetworkId()) { reorder = (mInfo == null); mRssi = info.getRssi(); mInfo = info; mState = state; refresh(); } else if (mInfo != null) { reorder = true; mInfo = null; mState = null; refresh(); } if (reorder) { notifyHierarchyChanged(); } } int getLevel() { if (mRssi == Integer.MAX_VALUE) { return -1; } return WifiManager.calculateSignalLevel(mRssi, 4); } WifiConfiguration getConfig() { return mConfig; } WifiInfo getInfo() { return mInfo; } DetailedState getState() { return mState; } static String removeDoubleQuotes(String string) { int length = string.length(); if ((length > 1) && (string.charAt(0) == '"') && (string.charAt(length - 1) == '"')) { return string.substring(1, length - 1); } return string; } static String convertToQuotedString(String string) { return "\"" + string + "\""; } private void refresh() { if (mSignal == null) { return; } Context context = getContext(); mSignal.setImageLevel(getLevel()); if (mState != null) { setSummary(Summary.get(context, mState)); } else { String status = null; if (mRssi == Integer.MAX_VALUE) { status = context.getString(R.string.wifi_not_in_range); } else if (mConfig != null) { status = context.getString((mConfig.status == WifiConfiguration.Status.DISABLED) ? R.string.wifi_disabled : R.string.wifi_remembered); } if (security == SECURITY_NONE) { if (wpsAvailable && mConfig == null) { setSummary(context.getString(R.string.wifi_open_with_wps)); } else { setSummary(status); } } else { String format; if (wpsAvailable && mConfig == null) { format = context.getString(R.string.wifi_secured_with_wps); } else { format = context.getString((status == null) ? R.string.wifi_secured : R.string.wifi_secured_with_status); } String[] type = context.getResources().getStringArray(R.array.wifi_security); setSummary(String.format(format, type[security], status)); } } } }