148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh/*
248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * Copyright (C) 2010 The Android Open Source Project
348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh *
448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * you may not use this file except in compliance with the License.
648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * You may obtain a copy of the License at
748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh *
848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh *
1048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * See the License for the specific language governing permissions and
1448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh * limitations under the License.
1548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh */
1648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
1748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehpackage com.android.settings.wifi;
1848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
1948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.content.Context;
2048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.NetworkInfo.DetailedState;
21d36699282cbd0a6897f425106081d3f2c0db55d4Daisuke Miyakawaimport android.net.wifi.ScanResult;
2248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiConfiguration;
2348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiConfiguration.KeyMgmt;
2448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiInfo;
2548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiManager;
263d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasaniimport android.os.Bundle;
2748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.preference.Preference;
288b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levyimport android.util.Log;
2948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.view.View;
3048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.widget.ImageView;
3148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
328b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levyimport com.android.settings.R;
33d36699282cbd0a6897f425106081d3f2c0db55d4Daisuke Miyakawa
3448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehclass AccessPoint extends Preference {
358b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    static final String TAG = "Settings.AccessPoint";
363d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
373d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    private static final String KEY_DETAILEDSTATE = "key_detailedstate";
383d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    private static final String KEY_WIFIINFO = "key_wifiinfo";
393d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    private static final String KEY_SCANRESULT = "key_scanresult";
403d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    private static final String KEY_CONFIG = "key_config";
413d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
428b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    private static final int[] STATE_SECURED = {
438b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        R.attr.state_encrypted
448b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    };
4548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private static final int[] STATE_NONE = {};
4648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
478b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    /** These values are matched in string arrays -- changes must be kept in sync */
4848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    static final int SECURITY_NONE = 0;
4948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    static final int SECURITY_WEP = 1;
5048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    static final int SECURITY_PSK = 2;
5148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    static final int SECURITY_EAP = 3;
5248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
538b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    enum PskType {
548b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        UNKNOWN,
558b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        WPA,
568b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        WPA2,
578b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        WPA_WPA2
588b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    }
598b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy
603d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    String ssid;
613d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    String bssid;
623d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    int security;
633d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    int networkId;
64b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff    boolean wpsAvailable = false;
6548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
668b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    PskType pskType = PskType.UNKNOWN;
678b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy
6848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private WifiConfiguration mConfig;
698b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    /* package */ScanResult mScanResult;
703d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
7148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private int mRssi;
7248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private WifiInfo mInfo;
7348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private DetailedState mState;
7448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
7565cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff    static int getSecurity(WifiConfiguration config) {
7648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
7748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return SECURITY_PSK;
7848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
7948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
8048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh                config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
8148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return SECURITY_EAP;
8248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
8348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
8448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
8548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
8648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private static int getSecurity(ScanResult result) {
8748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (result.capabilities.contains("WEP")) {
8848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return SECURITY_WEP;
8948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        } else if (result.capabilities.contains("PSK")) {
9048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return SECURITY_PSK;
9148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        } else if (result.capabilities.contains("EAP")) {
9248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return SECURITY_EAP;
9348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
9448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return SECURITY_NONE;
9548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
9648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
978b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    public String getSecurityString(boolean concise) {
988b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        Context context = getContext();
998b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        switch(security) {
1008b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            case SECURITY_EAP:
1018b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                return concise ? context.getString(R.string.wifi_security_short_eap) :
1028b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    context.getString(R.string.wifi_security_eap);
1038b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            case SECURITY_PSK:
1048b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                switch (pskType) {
1058b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    case WPA:
1068b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                        return concise ? context.getString(R.string.wifi_security_short_wpa) :
1078b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                            context.getString(R.string.wifi_security_wpa);
1088b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    case WPA2:
1098b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                        return concise ? context.getString(R.string.wifi_security_short_wpa2) :
1108b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                            context.getString(R.string.wifi_security_wpa2);
1118b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    case WPA_WPA2:
1128b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                        return concise ? context.getString(R.string.wifi_security_short_wpa_wpa2) :
1138b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                            context.getString(R.string.wifi_security_wpa_wpa2);
1148b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    case UNKNOWN:
1158b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    default:
1168b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                        return concise ? context.getString(R.string.wifi_security_short_psk_generic)
1178b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                                : context.getString(R.string.wifi_security_psk_generic);
1188b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                }
1198b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            case SECURITY_WEP:
1208b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                return concise ? context.getString(R.string.wifi_security_short_wep) :
1218b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    context.getString(R.string.wifi_security_wep);
1228b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            case SECURITY_NONE:
1238b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            default:
1248b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                return concise ? "" : context.getString(R.string.wifi_security_none);
1258b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        }
1268b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    }
1278b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy
1288b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    private static PskType getPskType(ScanResult result) {
1298b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        boolean wpa = result.capabilities.contains("WPA-PSK");
1308b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        boolean wpa2 = result.capabilities.contains("WPA2-PSK");
1318b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        if (wpa2 && wpa) {
1328b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            return PskType.WPA_WPA2;
1338b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else if (wpa2) {
1348b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            return PskType.WPA2;
1358b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else if (wpa) {
1368b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            return PskType.WPA;
1378b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else {
1388b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            Log.w(TAG, "Received abnormal flag string: " + result.capabilities);
1398b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            return PskType.UNKNOWN;
1408b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        }
1418b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy    }
1428b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy
14348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    AccessPoint(Context context, WifiConfiguration config) {
14448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        super(context);
14548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
1463d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        loadConfig(config);
147e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        refresh();
1483d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    }
1493d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
1503d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    AccessPoint(Context context, ScanResult result) {
1513d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        super(context);
1523d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
1533d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        loadResult(result);
154e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        refresh();
1553d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    }
1563d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
1573d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    AccessPoint(Context context, Bundle savedState) {
1583d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        super(context);
1593d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
1603d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
1613d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        mConfig = savedState.getParcelable(KEY_CONFIG);
1623d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        if (mConfig != null) {
1633d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani            loadConfig(mConfig);
1643d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        }
1653d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        mScanResult = (ScanResult) savedState.getParcelable(KEY_SCANRESULT);
1663d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        if (mScanResult != null) {
1673d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani            loadResult(mScanResult);
1683d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        }
1693d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        mInfo = (WifiInfo) savedState.getParcelable(KEY_WIFIINFO);
1703d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        if (savedState.containsKey(KEY_DETAILEDSTATE)) {
1713d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani            mState = DetailedState.valueOf(savedState.getString(KEY_DETAILEDSTATE));
1723d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        }
1733d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        update(mInfo, mState);
1743d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    }
1753d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
1763d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    public void saveWifiState(Bundle savedState) {
1773d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        savedState.putParcelable(KEY_CONFIG, mConfig);
1783d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        savedState.putParcelable(KEY_SCANRESULT, mScanResult);
1793d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        savedState.putParcelable(KEY_WIFIINFO, mInfo);
1803d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        if (mState != null) {
1813d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani            savedState.putString(KEY_DETAILEDSTATE, mState.toString());
1823d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        }
1833d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    }
1843d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani
1853d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    private void loadConfig(WifiConfiguration config) {
1868c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
187b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff        bssid = config.BSSID;
18848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        security = getSecurity(config);
18948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        networkId = config.networkId;
19048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        mRssi = Integer.MAX_VALUE;
1913d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        mConfig = config;
19248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
19348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
1943d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani    private void loadResult(ScanResult result) {
19548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        ssid = result.SSID;
196b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff        bssid = result.BSSID;
19748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        security = getSecurity(result);
1983d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        wpsAvailable = security != SECURITY_EAP && result.capabilities.contains("WPS");
1998b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        if (security == SECURITY_PSK)
2008b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            pskType = getPskType(result);
20148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        networkId = -1;
20248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        mRssi = result.level;
2033d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasani        mScanResult = result;
20448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
20548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
20648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    @Override
20748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    protected void onBindView(View view) {
208e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        super.onBindView(view);
209e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        ImageView signal = (ImageView) view.findViewById(R.id.signal);
21048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (mRssi == Integer.MAX_VALUE) {
211e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            signal.setImageDrawable(null);
21248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        } else {
213e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            signal.setImageLevel(getLevel());
214e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            signal.setImageResource(R.drawable.wifi_signal);
215e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            signal.setImageState((security != SECURITY_NONE) ?
21648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh                    STATE_SECURED : STATE_NONE, true);
21748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
21848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
21948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
22052727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff    @Override
22152727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff    public int compareTo(Preference preference) {
22252727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        if (!(preference instanceof AccessPoint)) {
22352727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff            return 1;
22452727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        }
22552727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        AccessPoint other = (AccessPoint) preference;
22652727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Active one goes first.
227ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mInfo != null && other.mInfo == null) return -1;
228ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mInfo == null && other.mInfo != null) return 1;
229ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
23052727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Reachable one goes before unreachable one.
231ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
232ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
233ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
23452727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Configured one goes before unconfigured one.
235ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (networkId != WifiConfiguration.INVALID_NETWORK_ID
236ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff                && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
237ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (networkId == WifiConfiguration.INVALID_NETWORK_ID
238ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff                && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
239ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
24052727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Sort by signal strength.
24152727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi);
24252727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        if (difference != 0) {
24352727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff            return difference;
24452727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        }
24552727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Sort by ssid.
24652727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        return ssid.compareToIgnoreCase(other.ssid);
24752727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff    }
24852727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff
249ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    @Override
250ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    public boolean equals(Object other) {
251ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (!(other instanceof AccessPoint)) return false;
252ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        return (this.compareTo((AccessPoint) other) == 0);
253ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    }
254ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
255ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    @Override
256ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    public int hashCode() {
257ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        int result = 0;
258ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mInfo != null) result += 13 * mInfo.hashCode();
259ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        result += 19 * mRssi;
260ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        result += 23 * networkId;
261ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        result += 29 * ssid.hashCode();
262ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        return result;
263ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    }
264ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
26548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    boolean update(ScanResult result) {
26648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (ssid.equals(result.SSID) && security == getSecurity(result)) {
26748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) {
268e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                int oldLevel = getLevel();
26948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh                mRssi = result.level;
270e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                if (getLevel() != oldLevel) {
271e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                    notifyChanged();
272e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                }
27348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            }
2748b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            // This flag only comes from scans, is not easily saved in config
275e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            if (security == SECURITY_PSK) {
2768b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                pskType = getPskType(result);
277e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            }
278e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            refresh();
27948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return true;
28048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
28148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return false;
28248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
28348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
28448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    void update(WifiInfo info, DetailedState state) {
28548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        boolean reorder = false;
286e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        if (info != null && networkId != WifiConfiguration.INVALID_NETWORK_ID
287e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                && networkId == info.getNetworkId()) {
28848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            reorder = (mInfo == null);
28948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mRssi = info.getRssi();
29048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mInfo = info;
29148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mState = state;
29248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            refresh();
29348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        } else if (mInfo != null) {
29448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            reorder = true;
29548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mInfo = null;
29648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mState = null;
29748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            refresh();
29848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
29948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (reorder) {
30048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            notifyHierarchyChanged();
30148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
30248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
30348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
30448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    int getLevel() {
30548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (mRssi == Integer.MAX_VALUE) {
30648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return -1;
30748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
30848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return WifiManager.calculateSignalLevel(mRssi, 4);
30948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
31048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
31148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    WifiConfiguration getConfig() {
31248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return mConfig;
31348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
31448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
31548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    WifiInfo getInfo() {
31648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return mInfo;
31748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
31848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
31948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    DetailedState getState() {
32048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return mState;
32148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
32248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
3238c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    static String removeDoubleQuotes(String string) {
3248c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        int length = string.length();
3258c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        if ((length > 1) && (string.charAt(0) == '"')
3268c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang                && (string.charAt(length - 1) == '"')) {
3278c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang            return string.substring(1, length - 1);
3288c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        }
3298c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        return string;
3308c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    }
3318c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang
3328c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    static String convertToQuotedString(String string) {
3338c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        return "\"" + string + "\"";
3348c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    }
3358c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang
336e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy    /** Updates the title and summary; may indirectly call notifyChanged()  */
33748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private void refresh() {
338e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        setTitle(ssid);
33948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
340e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        Context context = getContext();
3418b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        if (mState != null) { // This is the active connection
34248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            setSummary(Summary.get(context, mState));
3438b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
3448b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            setSummary(context.getString(R.string.wifi_not_in_range));
3458b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else if (mConfig != null && mConfig.status == WifiConfiguration.Status.DISABLED) {
3468b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            switch (mConfig.disableReason) {
3478b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_AUTH_FAILURE:
3488b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    setSummary(context.getString(R.string.wifi_disabled_password_failure));
3498b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    break;
3508b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_DHCP_FAILURE:
3518b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_DNS_FAILURE:
3528b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    setSummary(context.getString(R.string.wifi_disabled_network_failure));
3538b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    break;
3548b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_UNKNOWN_REASON:
3558b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    setSummary(context.getString(R.string.wifi_disabled_generic));
3568b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            }
3578b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else { // In range, not disabled.
3588b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            StringBuilder summary = new StringBuilder();
3598b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            if (mConfig != null) { // Is saved network
3608b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                summary.append(context.getString(R.string.wifi_remembered));
36148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            }
36248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
3638b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            if (security != SECURITY_NONE) {
3648b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                String securityStrFormat;
3658b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                if (summary.length() == 0) {
3668b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    securityStrFormat = context.getString(R.string.wifi_secured_first_item);
367e45e13f47ad5e09aa8291d81a03a136618b383c0Irfan Sheriff                } else {
3688b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    securityStrFormat = context.getString(R.string.wifi_secured_second_item);
369e45e13f47ad5e09aa8291d81a03a136618b383c0Irfan Sheriff                }
3708b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                summary.append(String.format(securityStrFormat, getSecurityString(true)));
3718b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            }
3728b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy
3738b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            if (mConfig == null && wpsAvailable) { // Only list WPS available for unsaved networks
3748b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                if (summary.length() == 0) {
3758b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    summary.append(context.getString(R.string.wifi_wps_available_first_item));
376b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff                } else {
3778b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    summary.append(context.getString(R.string.wifi_wps_available_second_item));
378b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff                }
37948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            }
3808b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            setSummary(summary.toString());
38148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
38248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
38322d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy
38422d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy    /**
38522d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     * Generate and save a default wifiConfiguration with common values.
38622d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     * Can only be called for unsecured networks.
38722d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     * @hide
38822d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     */
38922d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy    protected void generateOpenNetworkConfig() {
39022d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        if (security != SECURITY_NONE)
39122d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy            throw new IllegalStateException();
39222d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        if (mConfig != null)
39322d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy            return;
39422d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        mConfig = new WifiConfiguration();
39522d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
39622d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
39722d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy    }
39848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh}
399