AccessPoint.java revision b3024fa6a0359f18b93fd8aaf197fce59f806ede
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.android.settings.wifi;
18
19import com.android.settings.R;
20
21import android.content.Context;
22import android.net.NetworkInfo.DetailedState;
23import android.net.wifi.ScanResult;
24import android.net.wifi.WifiConfiguration;
25import android.net.wifi.WifiConfiguration.KeyMgmt;
26import android.net.wifi.WifiInfo;
27import android.net.wifi.WifiManager;
28import android.preference.Preference;
29import android.view.View;
30import android.widget.ImageView;
31
32import java.util.Comparator;
33
34class AccessPoint extends Preference {
35    private static final int[] STATE_SECURED = {R.attr.state_encrypted};
36    private static final int[] STATE_NONE = {};
37
38    public static final class Comparater
39            implements Comparator<AccessPoint> {
40        @Override
41        public int compare(AccessPoint accessPoint1, AccessPoint accessPoint2) {
42            // Active one goes first.
43            if (accessPoint1.mInfo != accessPoint2.mInfo) {
44                return (accessPoint1.mInfo != null) ? -1 : 1;
45            }
46
47            // Reachable one goes before unreachable one.
48            if ((accessPoint1.mRssi ^ accessPoint2.mRssi) < 0) {
49                return (accessPoint1.mRssi != Integer.MAX_VALUE) ? -1 : 1;
50            }
51            // Configured one goes before unconfigured one.
52            if ((accessPoint1.networkId ^ accessPoint2.networkId) < 0) {
53                return (accessPoint1.networkId != -1) ? -1 : 1;
54            }
55            // Sort by signal strength.
56            int difference = WifiManager.compareSignalLevel(
57                    accessPoint2.mRssi, accessPoint1.mRssi);
58            if (difference != 0) {
59                return difference;
60            }
61            // Sort by ssid.
62            return accessPoint1.ssid.compareToIgnoreCase(accessPoint2.ssid);
63        }
64    }
65
66    static final int SECURITY_NONE = 0;
67    static final int SECURITY_WEP = 1;
68    static final int SECURITY_PSK = 2;
69    static final int SECURITY_EAP = 3;
70
71    final String ssid;
72    final String bssid;
73    final int security;
74    final int networkId;
75    boolean wpsAvailable = false;
76
77    private WifiConfiguration mConfig;
78    private int mRssi;
79    private WifiInfo mInfo;
80    private DetailedState mState;
81    private ImageView mSignal;
82
83    static int getSecurity(WifiConfiguration config) {
84        if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) {
85            return SECURITY_PSK;
86        }
87        if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) ||
88                config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) {
89            return SECURITY_EAP;
90        }
91        return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE;
92    }
93
94    private static int getSecurity(ScanResult result) {
95        if (result.capabilities.contains("WEP")) {
96            return SECURITY_WEP;
97        } else if (result.capabilities.contains("PSK")) {
98            return SECURITY_PSK;
99        } else if (result.capabilities.contains("EAP")) {
100            return SECURITY_EAP;
101        }
102        return SECURITY_NONE;
103    }
104
105    AccessPoint(Context context, WifiConfiguration config) {
106        super(context);
107        setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
108        ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID));
109        bssid = config.BSSID;
110        security = getSecurity(config);
111        networkId = config.networkId;
112        mConfig = config;
113        mRssi = Integer.MAX_VALUE;
114    }
115
116    AccessPoint(Context context, ScanResult result) {
117        super(context);
118        setWidgetLayoutResource(R.layout.preference_widget_wifi_signal);
119        ssid = result.SSID;
120        bssid = result.BSSID;
121        security = getSecurity(result);
122        wpsAvailable = security != SECURITY_NONE && security != SECURITY_EAP &&
123                result.capabilities.contains("WPS");
124        networkId = -1;
125        mRssi = result.level;
126    }
127
128    @Override
129    protected void onBindView(View view) {
130        setTitle(ssid);
131        mSignal = (ImageView) view.findViewById(R.id.signal);
132        if (mRssi == Integer.MAX_VALUE) {
133            mSignal.setImageDrawable(null);
134        } else {
135            mSignal.setImageResource(R.drawable.wifi_signal);
136            mSignal.setImageState((security != SECURITY_NONE) ?
137                    STATE_SECURED : STATE_NONE, true);
138        }
139        refresh();
140        super.onBindView(view);
141    }
142
143
144    boolean update(ScanResult result) {
145        // We do not call refresh() since this is called before onBindView().
146        if (ssid.equals(result.SSID) && security == getSecurity(result)) {
147            if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) {
148                mRssi = result.level;
149            }
150            return true;
151        }
152        return false;
153    }
154
155    void update(WifiInfo info, DetailedState state) {
156        boolean reorder = false;
157        if (info != null && networkId != -1 && networkId == info.getNetworkId()) {
158            reorder = (mInfo == null);
159            mRssi = info.getRssi();
160            mInfo = info;
161            mState = state;
162            refresh();
163        } else if (mInfo != null) {
164            reorder = true;
165            mInfo = null;
166            mState = null;
167            refresh();
168        }
169        if (reorder) {
170            notifyHierarchyChanged();
171        }
172    }
173
174    int getLevel() {
175        if (mRssi == Integer.MAX_VALUE) {
176            return -1;
177        }
178        return WifiManager.calculateSignalLevel(mRssi, 4);
179    }
180
181    WifiConfiguration getConfig() {
182        return mConfig;
183    }
184
185    WifiInfo getInfo() {
186        return mInfo;
187    }
188
189    DetailedState getState() {
190        return mState;
191    }
192
193    static String removeDoubleQuotes(String string) {
194        int length = string.length();
195        if ((length > 1) && (string.charAt(0) == '"')
196                && (string.charAt(length - 1) == '"')) {
197            return string.substring(1, length - 1);
198        }
199        return string;
200    }
201
202    static String convertToQuotedString(String string) {
203        return "\"" + string + "\"";
204    }
205
206    private void refresh() {
207        if (mSignal == null) {
208            return;
209        }
210        Context context = getContext();
211        mSignal.setImageLevel(getLevel());
212
213        if (mState != null) {
214            setSummary(Summary.get(context, mState));
215        } else {
216            String status = null;
217            if (mRssi == Integer.MAX_VALUE) {
218                status = context.getString(R.string.wifi_not_in_range);
219            } else if (mConfig != null) {
220                status = context.getString((mConfig.status == WifiConfiguration.Status.DISABLED) ?
221                        R.string.wifi_disabled : R.string.wifi_remembered);
222            }
223
224            if (security == SECURITY_NONE) {
225                setSummary(status);
226            } else {
227                String format;
228                if (wpsAvailable && mConfig == null) {
229                    format = context.getString(R.string.wifi_secured_with_wps);
230                } else {
231                    format = context.getString((status == null) ?
232                            R.string.wifi_secured : R.string.wifi_secured_with_status);
233                }
234                String[] type = context.getResources().getStringArray(R.array.wifi_security);
235                setSummary(String.format(format, type[security], status));
236            }
237        }
238    }
239}
240