AccessPoint.java revision fc40600e30e281712f6c2fc899fc3894b8ad0050
1/* 2 * Copyright (C) 2015 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.settingslib.wifi; 18 19import android.content.Context; 20import android.net.NetworkInfo; 21import android.net.NetworkInfo.DetailedState; 22import android.net.NetworkInfo.State; 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.os.Bundle; 29import android.text.TextUtils; 30import android.util.Log; 31import android.util.LruCache; 32 33import com.android.settingslib.R; 34 35import java.util.Map; 36 37 38public class AccessPoint implements Comparable<AccessPoint> { 39 static final String TAG = "SettingsLib.AccessPoint"; 40 41 /** 42 * Lower bound on the 2.4 GHz (802.11b/g/n) WLAN channels 43 */ 44 public static final int LOWER_FREQ_24GHZ = 2400; 45 46 /** 47 * Upper bound on the 2.4 GHz (802.11b/g/n) WLAN channels 48 */ 49 public static final int HIGHER_FREQ_24GHZ = 2500; 50 51 /** 52 * Lower bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels 53 */ 54 public static final int LOWER_FREQ_5GHZ = 4900; 55 56 /** 57 * Upper bound on the 5.0 GHz (802.11a/h/j/n/ac) WLAN channels 58 */ 59 public static final int HIGHER_FREQ_5GHZ = 5900; 60 61 62 /** 63 * Experimental: we should be able to show the user the list of BSSIDs and bands 64 * for that SSID. 65 * For now this data is used only with Verbose Logging so as to show the band and number 66 * of BSSIDs on which that network is seen. 67 */ 68 public LruCache<String, ScanResult> mScanResultCache; 69 private static final String KEY_NETWORKINFO = "key_networkinfo"; 70 private static final String KEY_WIFIINFO = "key_wifiinfo"; 71 private static final String KEY_SCANRESULT = "key_scanresult"; 72 private static final String KEY_CONFIG = "key_config"; 73 74 /** 75 * These values are matched in string arrays -- changes must be kept in sync 76 */ 77 public static final int SECURITY_NONE = 0; 78 public static final int SECURITY_WEP = 1; 79 public static final int SECURITY_PSK = 2; 80 public static final int SECURITY_EAP = 3; 81 82 private static final int PSK_UNKNOWN = 0; 83 private static final int PSK_WPA = 1; 84 private static final int PSK_WPA2 = 2; 85 private static final int PSK_WPA_WPA2 = 3; 86 87 private static final int VISIBILITY_OUTDATED_AGE_IN_MILLI = 20000; 88 private final Context mContext; 89 90 private String ssid; 91 private int security; 92 private int networkId = WifiConfiguration.INVALID_NETWORK_ID; 93 94 private int pskType = PSK_UNKNOWN; 95 96 private WifiConfiguration mConfig; 97 private ScanResult mScanResult; 98 99 private int mRssi = Integer.MAX_VALUE; 100 private long mSeen = 0; 101 102 private WifiInfo mInfo; 103 private NetworkInfo mNetworkInfo; 104 private AccessPointListener mAccessPointListener; 105 106 private Object mTag; 107 108 public AccessPoint(Context context, Bundle savedState) { 109 mContext = context; 110 mConfig = savedState.getParcelable(KEY_CONFIG); 111 if (mConfig != null) { 112 loadConfig(mConfig); 113 } 114 mScanResult = (ScanResult) savedState.getParcelable(KEY_SCANRESULT); 115 if (mScanResult != null) { 116 loadResult(mScanResult); 117 } 118 mInfo = (WifiInfo) savedState.getParcelable(KEY_WIFIINFO); 119 if (savedState.containsKey(KEY_NETWORKINFO)) { 120 mNetworkInfo = savedState.getParcelable(KEY_NETWORKINFO); 121 } 122 update(mInfo, mNetworkInfo); 123 } 124 125 AccessPoint(Context context, ScanResult result) { 126 mContext = context; 127 loadResult(result); 128 } 129 130 AccessPoint(Context context, WifiConfiguration config) { 131 mContext = context; 132 loadConfig(config); 133 } 134 135 @Override 136 public int compareTo(AccessPoint other) { 137 // Active one goes first. 138 if (isActive() && !other.isActive()) return -1; 139 if (!isActive() && other.isActive()) return 1; 140 141 // Reachable one goes before unreachable one. 142 if (mRssi != Integer.MAX_VALUE && other.mRssi == Integer.MAX_VALUE) return -1; 143 if (mRssi == Integer.MAX_VALUE && other.mRssi != Integer.MAX_VALUE) return 1; 144 145 // Configured one goes before unconfigured one. 146 if (networkId != WifiConfiguration.INVALID_NETWORK_ID 147 && other.networkId == WifiConfiguration.INVALID_NETWORK_ID) return -1; 148 if (networkId == WifiConfiguration.INVALID_NETWORK_ID 149 && other.networkId != WifiConfiguration.INVALID_NETWORK_ID) return 1; 150 151 // Sort by signal strength. 152 int difference = WifiManager.compareSignalLevel(other.mRssi, mRssi); 153 if (difference != 0) { 154 return difference; 155 } 156 // Sort by ssid. 157 return ssid.compareToIgnoreCase(other.ssid); 158 } 159 160 @Override 161 public boolean equals(Object other) { 162 if (!(other instanceof AccessPoint)) return false; 163 return (this.compareTo((AccessPoint) other) == 0); 164 } 165 166 @Override 167 public int hashCode() { 168 int result = 0; 169 if (mInfo != null) result += 13 * mInfo.hashCode(); 170 result += 19 * mRssi; 171 result += 23 * networkId; 172 result += 29 * ssid.hashCode(); 173 return result; 174 } 175 176 @Override 177 public String toString() { 178 StringBuilder builder = new StringBuilder().append("AccessPoint(") 179 .append(ssid); 180 if (isSaved()) { 181 builder.append(',').append("saved"); 182 } 183 if (isActive()) { 184 builder.append(',').append("active"); 185 } 186 if (isEphemeral()) { 187 builder.append(',').append("ephemeral"); 188 } 189 if (isConnectable()) { 190 builder.append(',').append("connectable"); 191 } 192 if (security != SECURITY_NONE) { 193 builder.append(',').append(securityToString(security, pskType)); 194 } 195 return builder.append(')').toString(); 196 } 197 198 public boolean matches(ScanResult result) { 199 return ssid.equals(result.SSID) && security == getSecurity(result); 200 } 201 202 public boolean matches(WifiConfiguration config) { 203 return ssid.equals(removeDoubleQuotes(config.SSID)) && security == getSecurity(config); 204 } 205 206 public WifiConfiguration getConfig() { 207 return mConfig; 208 } 209 210 public void clearConfig() { 211 mConfig = null; 212 networkId = WifiConfiguration.INVALID_NETWORK_ID; 213 } 214 215 public WifiInfo getInfo() { 216 return mInfo; 217 } 218 219 public int getLevel() { 220 if (mRssi == Integer.MAX_VALUE) { 221 return -1; 222 } 223 return WifiManager.calculateSignalLevel(mRssi, 4); 224 } 225 226 public NetworkInfo getNetworkInfo() { 227 return mNetworkInfo; 228 } 229 230 public int getSecurity() { 231 return security; 232 } 233 234 public String getSecurityString(boolean concise) { 235 Context context = mContext; 236 switch(security) { 237 case SECURITY_EAP: 238 return concise ? context.getString(R.string.wifi_security_short_eap) : 239 context.getString(R.string.wifi_security_eap); 240 case SECURITY_PSK: 241 switch (pskType) { 242 case PSK_WPA: 243 return concise ? context.getString(R.string.wifi_security_short_wpa) : 244 context.getString(R.string.wifi_security_wpa); 245 case PSK_WPA2: 246 return concise ? context.getString(R.string.wifi_security_short_wpa2) : 247 context.getString(R.string.wifi_security_wpa2); 248 case PSK_WPA_WPA2: 249 return concise ? context.getString(R.string.wifi_security_short_wpa_wpa2) : 250 context.getString(R.string.wifi_security_wpa_wpa2); 251 case PSK_UNKNOWN: 252 default: 253 return concise ? context.getString(R.string.wifi_security_short_psk_generic) 254 : context.getString(R.string.wifi_security_psk_generic); 255 } 256 case SECURITY_WEP: 257 return concise ? context.getString(R.string.wifi_security_short_wep) : 258 context.getString(R.string.wifi_security_wep); 259 case SECURITY_NONE: 260 default: 261 return concise ? "" : context.getString(R.string.wifi_security_none); 262 } 263 } 264 265 public String getSsid() { 266 return ssid; 267 } 268 269 public DetailedState getDetailedState() { 270 return mNetworkInfo != null ? mNetworkInfo.getDetailedState() : null; 271 } 272 273 public String getSummary() { 274 // Update to new summary 275 StringBuilder summary = new StringBuilder(); 276 277 if (isActive()) { // This is the active connection 278 String passpointProvider = (mConfig != null && mConfig.isPasspoint()) ? 279 mConfig.providerFriendlyName : null; 280 summary.append(getSummary(mContext, getDetailedState(), 281 networkId == WifiConfiguration.INVALID_NETWORK_ID, passpointProvider)); 282 } else if (mConfig != null 283 && mConfig.hasNoInternetAccess()) { 284 summary.append(mContext.getString(R.string.wifi_no_internet)); 285 } else if (mConfig != null && ((mConfig.status == WifiConfiguration.Status.DISABLED && 286 mConfig.disableReason != WifiConfiguration.DISABLED_UNKNOWN_REASON) 287 || mConfig.autoJoinStatus 288 >= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE)) { 289 if (mConfig.autoJoinStatus 290 >= WifiConfiguration.AUTO_JOIN_DISABLED_ON_AUTH_FAILURE) { 291 if (mConfig.disableReason == WifiConfiguration.DISABLED_DHCP_FAILURE) { 292 summary.append(mContext.getString(R.string.wifi_disabled_network_failure)); 293 } else if (mConfig.disableReason == WifiConfiguration.DISABLED_AUTH_FAILURE) { 294 summary.append(mContext.getString(R.string.wifi_disabled_password_failure)); 295 } else { 296 summary.append(mContext.getString(R.string.wifi_disabled_wifi_failure)); 297 } 298 } else { 299 switch (mConfig.disableReason) { 300 case WifiConfiguration.DISABLED_AUTH_FAILURE: 301 summary.append(mContext.getString(R.string.wifi_disabled_password_failure)); 302 break; 303 case WifiConfiguration.DISABLED_DHCP_FAILURE: 304 case WifiConfiguration.DISABLED_DNS_FAILURE: 305 summary.append(mContext.getString(R.string.wifi_disabled_network_failure)); 306 break; 307 case WifiConfiguration.DISABLED_UNKNOWN_REASON: 308 case WifiConfiguration.DISABLED_ASSOCIATION_REJECT: 309 summary.append(mContext.getString(R.string.wifi_disabled_generic)); 310 break; 311 } 312 } 313 } else if (mRssi == Integer.MAX_VALUE) { // Wifi out of range 314 summary.append(mContext.getString(R.string.wifi_not_in_range)); 315 } else { // In range, not disabled. 316 if (mConfig != null) { // Is saved network 317 summary.append(mContext.getString(R.string.wifi_remembered)); 318 } 319 } 320 321 if (WifiTracker.sVerboseLogging > 0) { 322 // Add RSSI/band information for this config, what was seen up to 6 seconds ago 323 // verbose WiFi Logging is only turned on thru developers settings 324 if (mInfo != null && mNetworkInfo != null) { // This is the active connection 325 summary.append(" f=" + Integer.toString(mInfo.getFrequency())); 326 } 327 summary.append(" " + getVisibilityStatus()); 328 if (mConfig != null && mConfig.autoJoinStatus > 0) { 329 summary.append(" (" + mConfig.autoJoinStatus); 330 if (mConfig.blackListTimestamp > 0) { 331 long now = System.currentTimeMillis(); 332 long diff = (now - mConfig.blackListTimestamp)/1000; 333 long sec = diff%60; //seconds 334 long min = (diff/60)%60; //minutes 335 long hour = (min/60)%60; //hours 336 summary.append(", "); 337 if (hour > 0) summary.append(Long.toString(hour) + "h "); 338 summary.append( Long.toString(min) + "m "); 339 summary.append( Long.toString(sec) + "s "); 340 } 341 summary.append(")"); 342 } 343 if (mConfig != null && mConfig.numIpConfigFailures > 0) { 344 summary.append(" ipf=").append(mConfig.numIpConfigFailures); 345 } 346 if (mConfig != null && mConfig.numConnectionFailures > 0) { 347 summary.append(" cf=").append(mConfig.numConnectionFailures); 348 } 349 if (mConfig != null && mConfig.numAuthFailures > 0) { 350 summary.append(" authf=").append(mConfig.numAuthFailures); 351 } 352 if (mConfig != null && mConfig.numNoInternetAccessReports > 0) { 353 summary.append(" noInt=").append(mConfig.numNoInternetAccessReports); 354 } 355 } 356 return summary.toString(); 357 } 358 359 /** 360 * Returns the visibility status of the WifiConfiguration. 361 * 362 * @return autojoin debugging information 363 * TODO: use a string formatter 364 * ["rssi 5Ghz", "num results on 5GHz" / "rssi 5Ghz", "num results on 5GHz"] 365 * For instance [-40,5/-30,2] 366 */ 367 private String getVisibilityStatus() { 368 StringBuilder visibility = new StringBuilder(); 369 StringBuilder scans24GHz = null; 370 StringBuilder scans5GHz = null; 371 String bssid = null; 372 373 long now = System.currentTimeMillis(); 374 375 if (mInfo != null) { 376 bssid = mInfo.getBSSID(); 377 if (bssid != null) { 378 visibility.append(" ").append(bssid); 379 } 380 visibility.append(" rssi=").append(mInfo.getRssi()); 381 visibility.append(" "); 382 visibility.append(" score=").append(mInfo.score); 383 visibility.append(String.format(" tx=%.1f,", mInfo.txSuccessRate)); 384 visibility.append(String.format("%.1f,", mInfo.txRetriesRate)); 385 visibility.append(String.format("%.1f ", mInfo.txBadRate)); 386 visibility.append(String.format("rx=%.1f", mInfo.rxSuccessRate)); 387 } 388 389 if (mScanResultCache != null) { 390 int rssi5 = WifiConfiguration.INVALID_RSSI; 391 int rssi24 = WifiConfiguration.INVALID_RSSI; 392 int num5 = 0; 393 int num24 = 0; 394 int numBlackListed = 0; 395 int n24 = 0; // Number scan results we included in the string 396 int n5 = 0; // Number scan results we included in the string 397 Map<String, ScanResult> list = mScanResultCache.snapshot(); 398 // TODO: sort list by RSSI or age 399 for (ScanResult result : list.values()) { 400 if (result.seen == 0) 401 continue; 402 403 if (result.autoJoinStatus != ScanResult.ENABLED) numBlackListed++; 404 405 if (result.frequency >= LOWER_FREQ_5GHZ 406 && result.frequency <= HIGHER_FREQ_5GHZ) { 407 // Strictly speaking: [4915, 5825] 408 // number of known BSSID on 5GHz band 409 num5 = num5 + 1; 410 } else if (result.frequency >= LOWER_FREQ_24GHZ 411 && result.frequency <= HIGHER_FREQ_24GHZ) { 412 // Strictly speaking: [2412, 2482] 413 // number of known BSSID on 2.4Ghz band 414 num24 = num24 + 1; 415 } 416 417 // Ignore results seen, older than 20 seconds 418 if (now - result.seen > VISIBILITY_OUTDATED_AGE_IN_MILLI) continue; 419 420 if (result.frequency >= LOWER_FREQ_5GHZ 421 && result.frequency <= HIGHER_FREQ_5GHZ) { 422 if (result.level > rssi5) { 423 rssi5 = result.level; 424 } 425 if (n5 < 4) { 426 if (scans5GHz == null) scans5GHz = new StringBuilder(); 427 scans5GHz.append(" \n{").append(result.BSSID); 428 if (bssid != null && result.BSSID.equals(bssid)) scans5GHz.append("*"); 429 scans5GHz.append("=").append(result.frequency); 430 scans5GHz.append(",").append(result.level); 431 if (result.autoJoinStatus != 0) { 432 scans5GHz.append(",st=").append(result.autoJoinStatus); 433 } 434 if (result.numIpConfigFailures != 0) { 435 scans5GHz.append(",ipf=").append(result.numIpConfigFailures); 436 } 437 scans5GHz.append("}"); 438 n5++; 439 } 440 } else if (result.frequency >= LOWER_FREQ_24GHZ 441 && result.frequency <= HIGHER_FREQ_24GHZ) { 442 if (result.level > rssi24) { 443 rssi24 = result.level; 444 } 445 if (n24 < 4) { 446 if (scans24GHz == null) scans24GHz = new StringBuilder(); 447 scans24GHz.append(" \n{").append(result.BSSID); 448 if (bssid != null && result.BSSID.equals(bssid)) scans24GHz.append("*"); 449 scans24GHz.append("=").append(result.frequency); 450 scans24GHz.append(",").append(result.level); 451 if (result.autoJoinStatus != 0) { 452 scans24GHz.append(",st=").append(result.autoJoinStatus); 453 } 454 if (result.numIpConfigFailures != 0) { 455 scans24GHz.append(",ipf=").append(result.numIpConfigFailures); 456 } 457 scans24GHz.append("}"); 458 n24++; 459 } 460 } 461 } 462 visibility.append(" ["); 463 if (num24 > 0) { 464 visibility.append("(").append(num24).append(")"); 465 if (n24 <= 4) { 466 if (scans24GHz != null) { 467 visibility.append(scans24GHz.toString()); 468 } 469 } else { 470 visibility.append("max=").append(rssi24); 471 if (scans24GHz != null) { 472 visibility.append(",").append(scans24GHz.toString()); 473 } 474 } 475 } 476 visibility.append(";"); 477 if (num5 > 0) { 478 visibility.append("(").append(num5).append(")"); 479 if (n5 <= 4) { 480 if (scans5GHz != null) { 481 visibility.append(scans5GHz.toString()); 482 } 483 } else { 484 visibility.append("max=").append(rssi5); 485 if (scans5GHz != null) { 486 visibility.append(",").append(scans5GHz.toString()); 487 } 488 } 489 } 490 if (numBlackListed > 0) 491 visibility.append("!").append(numBlackListed); 492 visibility.append("]"); 493 } else { 494 if (mRssi != Integer.MAX_VALUE) { 495 visibility.append(" rssi="); 496 visibility.append(mRssi); 497 if (mScanResult != null) { 498 visibility.append(", f="); 499 visibility.append(mScanResult.frequency); 500 } 501 } 502 } 503 504 return visibility.toString(); 505 } 506 507 /** 508 * Return whether this is the active connection. 509 * For ephemeral connections (networkId is invalid), this returns false if the network is 510 * disconnected. 511 */ 512 public boolean isActive() { 513 return mNetworkInfo != null && 514 (networkId != WifiConfiguration.INVALID_NETWORK_ID || 515 mNetworkInfo.getState() != State.DISCONNECTED); 516 } 517 518 public boolean isConnectable() { 519 return getLevel() != -1 && getDetailedState() == null; 520 } 521 522 public boolean isEphemeral() { 523 return !isSaved() && mNetworkInfo != null && mNetworkInfo.getState() != State.DISCONNECTED; 524 } 525 526 /** Return whether the given {@link WifiInfo} is for this access point. */ 527 private boolean isInfoForThisAccessPoint(WifiInfo info) { 528 if (networkId != WifiConfiguration.INVALID_NETWORK_ID) { 529 return networkId == info.getNetworkId(); 530 } else { 531 // Might be an ephemeral connection with no WifiConfiguration. Try matching on SSID. 532 // (Note that we only do this if the WifiConfiguration explicitly equals INVALID). 533 // TODO: Handle hex string SSIDs. 534 return ssid.equals(removeDoubleQuotes(info.getSSID())); 535 } 536 } 537 538 public boolean isSaved() { 539 return networkId != WifiConfiguration.INVALID_NETWORK_ID; 540 } 541 542 public Object getTag() { 543 return mTag; 544 } 545 546 public void setTag(Object tag) { 547 mTag = tag; 548 } 549 550 /** 551 * Generate and save a default wifiConfiguration with common values. 552 * Can only be called for unsecured networks. 553 */ 554 public void generateOpenNetworkConfig() { 555 if (security != SECURITY_NONE) 556 throw new IllegalStateException(); 557 if (mConfig != null) 558 return; 559 mConfig = new WifiConfiguration(); 560 mConfig.SSID = AccessPoint.convertToQuotedString(ssid); 561 mConfig.allowedKeyManagement.set(KeyMgmt.NONE); 562 } 563 564 void loadConfig(WifiConfiguration config) { 565 if (config.isPasspoint()) 566 ssid = config.providerFriendlyName; 567 else 568 ssid = (config.SSID == null ? "" : removeDoubleQuotes(config.SSID)); 569 570 security = getSecurity(config); 571 networkId = config.networkId; 572 mConfig = config; 573 } 574 575 private void loadResult(ScanResult result) { 576 ssid = result.SSID; 577 security = getSecurity(result); 578 if (security == SECURITY_PSK) 579 pskType = getPskType(result); 580 mRssi = result.level; 581 mScanResult = result; 582 if (result.seen > mSeen) { 583 mSeen = result.seen; 584 } 585 } 586 587 public void saveWifiState(Bundle savedState) { 588 savedState.putParcelable(KEY_CONFIG, mConfig); 589 savedState.putParcelable(KEY_SCANRESULT, mScanResult); 590 savedState.putParcelable(KEY_WIFIINFO, mInfo); 591 if (mNetworkInfo != null) { 592 savedState.putParcelable(KEY_NETWORKINFO, mNetworkInfo); 593 } 594 } 595 596 public void setListener(AccessPointListener listener) { 597 mAccessPointListener = listener; 598 } 599 600 boolean update(ScanResult result) { 601 if (result.seen > mSeen) { 602 mSeen = result.seen; 603 } 604 if (WifiTracker.sVerboseLogging > 0) { 605 if (mScanResultCache == null) { 606 mScanResultCache = new LruCache<String, ScanResult>(32); 607 } 608 mScanResultCache.put(result.BSSID, result); 609 } 610 611 if (ssid.equals(result.SSID) && security == getSecurity(result)) { 612 if (WifiManager.compareSignalLevel(result.level, mRssi) > 0) { 613 int oldLevel = getLevel(); 614 mRssi = result.level; 615 if (getLevel() != oldLevel && mAccessPointListener != null) { 616 mAccessPointListener.onLevelChanged(this); 617 } 618 } 619 // This flag only comes from scans, is not easily saved in config 620 if (security == SECURITY_PSK) { 621 pskType = getPskType(result); 622 } 623 mScanResult = result; 624 if (mAccessPointListener != null) { 625 mAccessPointListener.onAccessPointChanged(this); 626 } 627 return true; 628 } 629 return false; 630 } 631 632 boolean update(WifiInfo info, NetworkInfo networkInfo) { 633 boolean reorder = false; 634 if (info != null && isInfoForThisAccessPoint(info)) { 635 reorder = (mInfo == null); 636 mRssi = info.getRssi(); 637 mInfo = info; 638 mNetworkInfo = networkInfo; 639 if (mAccessPointListener != null) { 640 mAccessPointListener.onAccessPointChanged(this); 641 } 642 } else if (mInfo != null) { 643 reorder = true; 644 mInfo = null; 645 mNetworkInfo = null; 646 if (mAccessPointListener != null) { 647 mAccessPointListener.onAccessPointChanged(this); 648 } 649 } 650 return reorder; 651 } 652 653 void update(WifiConfiguration config) { 654 mConfig = config; 655 } 656 657 public static String getSummary(Context context, String ssid, DetailedState state, 658 boolean isEphemeral, String passpointProvider) { 659 if (state == DetailedState.CONNECTED && isEphemeral && ssid == null) { 660 if (TextUtils.isEmpty(passpointProvider) == false) { 661 // Special case for connected + ephemeral networks. 662 String format = context.getString(R.string.connected_via_passpoint); 663 return String.format(format, passpointProvider); 664 } else if (isEphemeral && ssid == null) { 665 // Special case for connected + ephemeral networks. 666 return context.getString(R.string.connected_via_wfa); 667 } 668 } 669 670 String[] formats = context.getResources().getStringArray((ssid == null) 671 ? R.array.wifi_status : R.array.wifi_status_with_ssid); 672 int index = state.ordinal(); 673 674 if (index >= formats.length || formats[index].length() == 0) { 675 return null; 676 } 677 return String.format(formats[index], ssid); 678 } 679 680 public static String getSummary(Context context, DetailedState state, boolean isEphemeral) { 681 return getSummary(context, null, state, isEphemeral, null); 682 } 683 684 public static String getSummary(Context context, DetailedState state, boolean isEphemeral, 685 String passpointProvider) { 686 return getSummary(context, null, state, isEphemeral, passpointProvider); 687 } 688 689 public static String convertToQuotedString(String string) { 690 return "\"" + string + "\""; 691 } 692 693 private static int getPskType(ScanResult result) { 694 boolean wpa = result.capabilities.contains("WPA-PSK"); 695 boolean wpa2 = result.capabilities.contains("WPA2-PSK"); 696 if (wpa2 && wpa) { 697 return PSK_WPA_WPA2; 698 } else if (wpa2) { 699 return PSK_WPA2; 700 } else if (wpa) { 701 return PSK_WPA; 702 } else { 703 Log.w(TAG, "Received abnormal flag string: " + result.capabilities); 704 return PSK_UNKNOWN; 705 } 706 } 707 708 private static int getSecurity(ScanResult result) { 709 if (result.capabilities.contains("WEP")) { 710 return SECURITY_WEP; 711 } else if (result.capabilities.contains("PSK")) { 712 return SECURITY_PSK; 713 } else if (result.capabilities.contains("EAP")) { 714 return SECURITY_EAP; 715 } 716 return SECURITY_NONE; 717 } 718 719 static int getSecurity(WifiConfiguration config) { 720 if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 721 return SECURITY_PSK; 722 } 723 if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 724 config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 725 return SECURITY_EAP; 726 } 727 return (config.wepKeys[0] != null) ? SECURITY_WEP : SECURITY_NONE; 728 } 729 730 public static String securityToString(int security, int pskType) { 731 if (security == SECURITY_WEP) { 732 return "WEP"; 733 } else if (security == SECURITY_PSK) { 734 if (pskType == PSK_WPA) { 735 return "WPA"; 736 } else if (pskType == PSK_WPA2) { 737 return "WPA2"; 738 } else if (pskType == PSK_WPA_WPA2) { 739 return "WPA_WPA2"; 740 } 741 return "PSK"; 742 } else if (security == SECURITY_EAP) { 743 return "EAP"; 744 } 745 return "NONE"; 746 } 747 748 static String removeDoubleQuotes(String string) { 749 int length = string.length(); 750 if ((length > 1) && (string.charAt(0) == '"') 751 && (string.charAt(length - 1) == '"')) { 752 return string.substring(1, length - 1); 753 } 754 return string; 755 } 756 757 public interface AccessPointListener { 758 void onAccessPointChanged(AccessPoint accessPoint); 759 void onLevelChanged(AccessPoint accessPoint); 760 } 761} 762