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
19ac57f3e1eb56998550534c1b32d99cb7b5cc2b7bRussell Brennerimport com.android.settings.R;
20ac57f3e1eb56998550534c1b32d99cb7b5cc2b7bRussell Brenner
2148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.content.Context;
2248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.NetworkInfo.DetailedState;
23d36699282cbd0a6897f425106081d3f2c0db55d4Daisuke Miyakawaimport android.net.wifi.ScanResult;
2448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiConfiguration;
2548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiConfiguration.KeyMgmt;
2648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiInfo;
2748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.net.wifi.WifiManager;
283d13110d40b972a44c80558e0179323f9b330b2fAmith Yamasaniimport android.os.Bundle;
2948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.preference.Preference;
308b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levyimport android.util.Log;
3148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.view.View;
3248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yehimport android.widget.ImageView;
3348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
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());
214ac57f3e1eb56998550534c1b32d99cb7b5cc2b7bRussell Brenner            signal.setImageDrawable(getContext().getTheme().obtainStyledAttributes(
215ac57f3e1eb56998550534c1b32d99cb7b5cc2b7bRussell Brenner                    new int[] {R.attr.wifi_signal}).getDrawable(0));
216e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            signal.setImageState((security != SECURITY_NONE) ?
21748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh                    STATE_SECURED : STATE_NONE, true);
21848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
21948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
22048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
22152727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff    @Override
22252727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff    public int compareTo(Preference preference) {
22352727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        if (!(preference instanceof AccessPoint)) {
22452727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff            return 1;
22552727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        }
22652727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        AccessPoint other = (AccessPoint) preference;
22752727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Active one goes first.
228ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mInfo != null && other.mInfo == null) return -1;
229ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mInfo == null && other.mInfo != null) return 1;
230ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
23152727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Reachable one goes before unreachable one.
232ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1;
233ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1;
234ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
23552727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Configured one goes before unconfigured one.
236ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (networkId != WifiConfiguration.INVALID_NETWORK_ID
237ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff                && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1;
238ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (networkId == WifiConfiguration.INVALID_NETWORK_ID
239ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff                && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1;
240ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
24152727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Sort by signal strength.
24252727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi);
24352727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        if (difference != 0) {
24452727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff            return difference;
24552727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        }
24652727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        // Sort by ssid.
24752727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff        return ssid.compareToIgnoreCase(other.ssid);
24852727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff    }
24952727dd1fbca7612c2179b50689cd77f8f939b1aIrfan Sheriff
250ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    @Override
251ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    public boolean equals(Object other) {
252ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (!(other instanceof AccessPoint)) return false;
253ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        return (this.compareTo((AccessPoint) other) == 0);
254ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    }
255ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
256ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    @Override
257ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    public int hashCode() {
258ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        int result = 0;
259ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        if (mInfo != null) result += 13 * mInfo.hashCode();
260ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        result += 19 * mRssi;
261ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        result += 23 * networkId;
262ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        result += 29 * ssid.hashCode();
263ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff        return result;
264ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff    }
265ebc57e3ae68524c5612be7d9a5564b87203c432aIrfan Sheriff
26648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    boolean update(ScanResult result) {
26748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (ssid.equals(result.SSID) && security == getSecurity(result)) {
26848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) {
269e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                int oldLevel = getLevel();
27048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh                mRssi = result.level;
271e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                if (getLevel() != oldLevel) {
272e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                    notifyChanged();
273e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                }
27448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            }
2758b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            // This flag only comes from scans, is not easily saved in config
276e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            if (security == SECURITY_PSK) {
2778b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                pskType = getPskType(result);
278e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            }
279e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy            refresh();
28048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return true;
28148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
28248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return false;
28348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
28448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
28548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    void update(WifiInfo info, DetailedState state) {
28648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        boolean reorder = false;
287e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        if (info != null && networkId != WifiConfiguration.INVALID_NETWORK_ID
288e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy                && networkId == info.getNetworkId()) {
28948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            reorder = (mInfo == null);
29048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mRssi = info.getRssi();
29148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mInfo = info;
29248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mState = state;
29348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            refresh();
29448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        } else if (mInfo != null) {
29548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            reorder = true;
29648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mInfo = null;
29748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            mState = null;
29848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            refresh();
29948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
30048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (reorder) {
30148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            notifyHierarchyChanged();
30248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
30348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
30448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
30548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    int getLevel() {
30648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        if (mRssi == Integer.MAX_VALUE) {
30748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            return -1;
30848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
30948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return WifiManager.calculateSignalLevel(mRssi, 4);
31048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
31148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
31248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    WifiConfiguration getConfig() {
31348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return mConfig;
31448090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
31548090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
31648090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    WifiInfo getInfo() {
31748090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return mInfo;
31848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
31948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
32048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    DetailedState getState() {
32148090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        return mState;
32248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
32348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
3248c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    static String removeDoubleQuotes(String string) {
3258c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        int length = string.length();
3268c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        if ((length > 1) && (string.charAt(0) == '"')
3278c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang                && (string.charAt(length - 1) == '"')) {
3288c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang            return string.substring(1, length - 1);
3298c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        }
3308c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        return string;
3318c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    }
3328c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang
3338c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    static String convertToQuotedString(String string) {
3348c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang        return "\"" + string + "\"";
3358c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang    }
3368c81257f70fabeaa505e292bd0c2226dd5eefc4cChung-yih Wang
337e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy    /** Updates the title and summary; may indirectly call notifyChanged()  */
33848090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    private void refresh() {
339e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        setTitle(ssid);
34048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
341e2c6e7520b5002573bf76bcdee909281514eabb0Isaac Levy        Context context = getContext();
3420085de7999bea8140c82c72efc0e56b9af0529a1Jaewan Kim        if (mConfig != null && mConfig.status == WifiConfiguration.Status.DISABLED) {
3438b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            switch (mConfig.disableReason) {
3448b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_AUTH_FAILURE:
3458b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    setSummary(context.getString(R.string.wifi_disabled_password_failure));
3468b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    break;
3478b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_DHCP_FAILURE:
3488b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_DNS_FAILURE:
3498b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    setSummary(context.getString(R.string.wifi_disabled_network_failure));
3508b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    break;
3518b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                case WifiConfiguration.DISABLED_UNKNOWN_REASON:
3528b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    setSummary(context.getString(R.string.wifi_disabled_generic));
3538b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            }
3540085de7999bea8140c82c72efc0e56b9af0529a1Jaewan Kim        } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range
3550085de7999bea8140c82c72efc0e56b9af0529a1Jaewan Kim            setSummary(context.getString(R.string.wifi_not_in_range));
3560085de7999bea8140c82c72efc0e56b9af0529a1Jaewan Kim        } else if (mState != null) { // This is the active connection
3570085de7999bea8140c82c72efc0e56b9af0529a1Jaewan Kim            setSummary(Summary.get(context, mState));
3588b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy        } else { // In range, not disabled.
3598b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            StringBuilder summary = new StringBuilder();
3608b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            if (mConfig != null) { // Is saved network
3618b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                summary.append(context.getString(R.string.wifi_remembered));
36248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            }
36348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh
3648b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            if (security != SECURITY_NONE) {
3658b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                String securityStrFormat;
3668b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                if (summary.length() == 0) {
3678b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    securityStrFormat = context.getString(R.string.wifi_secured_first_item);
368e45e13f47ad5e09aa8291d81a03a136618b383c0Irfan Sheriff                } else {
3698b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    securityStrFormat = context.getString(R.string.wifi_secured_second_item);
370e45e13f47ad5e09aa8291d81a03a136618b383c0Irfan Sheriff                }
3718b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                summary.append(String.format(securityStrFormat, getSecurityString(true)));
3728b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            }
3738b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy
3748b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            if (mConfig == null && wpsAvailable) { // Only list WPS available for unsaved networks
3758b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                if (summary.length() == 0) {
3768b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    summary.append(context.getString(R.string.wifi_wps_available_first_item));
377b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff                } else {
3788b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy                    summary.append(context.getString(R.string.wifi_wps_available_second_item));
379b3024fa6a0359f18b93fd8aaf197fce59f806edeIrfan Sheriff                }
38048090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh            }
3818b2bf2e53814a20f09f658554cde61657df8ac99Isaac Levy            setSummary(summary.toString());
38248090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh        }
38348090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh    }
38422d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy
38522d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy    /**
38622d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     * Generate and save a default wifiConfiguration with common values.
38722d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     * Can only be called for unsecured networks.
38822d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     * @hide
38922d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy     */
39022d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy    protected void generateOpenNetworkConfig() {
39122d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        if (security != SECURITY_NONE)
39222d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy            throw new IllegalStateException();
39322d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        if (mConfig != null)
39422d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy            return;
39522d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        mConfig = new WifiConfiguration();
39622d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        mConfig.SSID = AccessPoint.convertToQuotedString(ssid);
39722d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy        mConfig.allowedKeyManagement.set(KeyMgmt.NONE);
39822d441acdba0fb7b99f5958ddd0198f4c371b2a7Isaac Levy    }
39948090d4066fdf3084a4fb31277e785149c1bce37Chia-chi Yeh}
400