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 17 package android.net.wifi; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.net.DhcpInfoInternal; 22 import android.net.LinkAddress; 23 import android.net.LinkProperties; 24 import android.net.NetworkUtils; 25 import android.net.ProxyProperties; 26 import android.net.RouteInfo; 27 import android.net.wifi.WifiConfiguration.IpAssignment; 28 import android.net.wifi.WifiConfiguration.KeyMgmt; 29 import android.net.wifi.WifiConfiguration.ProxySettings; 30 import android.net.wifi.WifiConfiguration.Status; 31 import android.net.wifi.NetworkUpdateResult; 32 import static android.net.wifi.WifiConfiguration.INVALID_NETWORK_ID; 33 import android.os.Environment; 34 import android.text.TextUtils; 35 import android.util.Log; 36 37 import java.io.BufferedInputStream; 38 import java.io.BufferedOutputStream; 39 import java.io.DataInputStream; 40 import java.io.DataOutputStream; 41 import java.io.EOFException; 42 import java.io.FileInputStream; 43 import java.io.FileOutputStream; 44 import java.io.IOException; 45 import java.net.InetAddress; 46 import java.net.UnknownHostException; 47 import java.util.ArrayList; 48 import java.util.BitSet; 49 import java.util.Collection; 50 import java.util.HashMap; 51 import java.util.Iterator; 52 import java.util.List; 53 54 /** 55 * This class provides the API to manage configured 56 * wifi networks. The API is not thread safe is being 57 * used only from WifiStateMachine. 58 * 59 * It deals with the following 60 * - Add/update/remove a WifiConfiguration 61 * The configuration contains two types of information. 62 * = IP and proxy configuration that is handled by WifiConfigStore and 63 * is saved to disk on any change. 64 * 65 * The format of configuration file is as follows: 66 * <version> 67 * <netA_key1><netA_value1><netA_key2><netA_value2>...<EOS> 68 * <netB_key1><netB_value1><netB_key2><netB_value2>...<EOS> 69 * .. 70 * 71 * (key, value) pairs for a given network are grouped together and can 72 * be in any order. A EOS at the end of a set of (key, value) pairs 73 * indicates that the next set of (key, value) pairs are for a new 74 * network. A network is identified by a unique ID_KEY. If there is no 75 * ID_KEY in the (key, value) pairs, the data is discarded. 76 * 77 * An invalid version on read would result in discarding the contents of 78 * the file. On the next write, the latest version is written to file. 79 * 80 * Any failures during read or write to the configuration file are ignored 81 * without reporting to the user since the likelihood of these errors are 82 * low and the impact on connectivity is low. 83 * 84 * = SSID & security details that is pushed to the supplicant. 85 * supplicant saves these details to the disk on calling 86 * saveConfigCommand(). 87 * 88 * We have two kinds of APIs exposed: 89 * > public API calls that provide fine grained control 90 * - enableNetwork, disableNetwork, addOrUpdateNetwork(), 91 * removeNetwork(). For these calls, the config is not persisted 92 * to the disk. (TODO: deprecate these calls in WifiManager) 93 * > The new API calls - selectNetwork(), saveNetwork() & forgetNetwork(). 94 * These calls persist the supplicant config to disk. 95 * 96 * - Maintain a list of configured networks for quick access 97 * 98 */ 99 class WifiConfigStore { 100 101 private static Context sContext; 102 private static final String TAG = "WifiConfigStore"; 103 private static final boolean DBG = false; 104 105 /* configured networks with network id as the key */ 106 private static HashMap<Integer, WifiConfiguration> sConfiguredNetworks = 107 new HashMap<Integer, WifiConfiguration>(); 108 109 /* A network id is a unique identifier for a network configured in the 110 * supplicant. Network ids are generated when the supplicant reads 111 * the configuration file at start and can thus change for networks. 112 * We store the IP configuration for networks along with a unique id 113 * that is generated from SSID and security type of the network. A mapping 114 * from the generated unique id to network id of the network is needed to 115 * map supplicant config to IP configuration. */ 116 private static HashMap<Integer, Integer> sNetworkIds = 117 new HashMap<Integer, Integer>(); 118 119 /* Tracks the highest priority of configured networks */ 120 private static int sLastPriority = -1; 121 122 private static final String ipConfigFile = Environment.getDataDirectory() + 123 "/misc/wifi/ipconfig.txt"; 124 125 private static final int IPCONFIG_FILE_VERSION = 2; 126 127 /* IP and proxy configuration keys */ 128 private static final String ID_KEY = "id"; 129 private static final String IP_ASSIGNMENT_KEY = "ipAssignment"; 130 private static final String LINK_ADDRESS_KEY = "linkAddress"; 131 private static final String GATEWAY_KEY = "gateway"; 132 private static final String DNS_KEY = "dns"; 133 private static final String PROXY_SETTINGS_KEY = "proxySettings"; 134 private static final String PROXY_HOST_KEY = "proxyHost"; 135 private static final String PROXY_PORT_KEY = "proxyPort"; 136 private static final String EXCLUSION_LIST_KEY = "exclusionList"; 137 private static final String EOS = "eos"; 138 139 /** 140 * Initialize context, fetch the list of configured networks 141 * and enable all stored networks in supplicant. 142 */ 143 static void initialize(Context context) { 144 if (DBG) log("Loading config and enabling all networks"); 145 sContext = context; 146 loadConfiguredNetworks(); 147 enableAllNetworks(); 148 } 149 150 /** 151 * Fetch the list of currently configured networks 152 * @return List of networks 153 */ 154 static List<WifiConfiguration> getConfiguredNetworks() { 155 List<WifiConfiguration> networks = new ArrayList<WifiConfiguration>(); 156 synchronized (sConfiguredNetworks) { 157 for(WifiConfiguration config : sConfiguredNetworks.values()) { 158 networks.add(new WifiConfiguration(config)); 159 } 160 } 161 return networks; 162 } 163 164 /** 165 * enable all networks and save config. This will be a no-op if the list 166 * of configured networks indicates all networks as being enabled 167 */ 168 static void enableAllNetworks() { 169 boolean networkEnabledStateChanged = false; 170 synchronized (sConfiguredNetworks) { 171 for(WifiConfiguration config : sConfiguredNetworks.values()) { 172 if(config != null && config.status == Status.DISABLED) { 173 if(WifiNative.enableNetworkCommand(config.networkId, false)) { 174 networkEnabledStateChanged = true; 175 config.status = Status.ENABLED; 176 } else { 177 loge("Enable network failed on " + config.networkId); 178 } 179 } 180 } 181 } 182 183 if (networkEnabledStateChanged) { 184 WifiNative.saveConfigCommand(); 185 sendConfiguredNetworksChangedBroadcast(); 186 } 187 } 188 189 /** 190 * Selects the specified network config for connection. This involves 191 * addition/update of the specified config, updating the priority of 192 * all the networks and enabling the given network while disabling others. 193 * 194 * Selecting a network will leave the other networks disabled and 195 * a call to enableAllNetworks() needs to be issued upon a connection 196 * or a failure event from supplicant 197 * 198 * @param config The configuration details in WifiConfiguration 199 * @return the networkId now associated with the specified configuration 200 */ 201 static int selectNetwork(WifiConfiguration config) { 202 if (config != null) { 203 NetworkUpdateResult result = addOrUpdateNetworkNative(config); 204 int netId = result.getNetworkId(); 205 if (netId != INVALID_NETWORK_ID) { 206 selectNetwork(netId); 207 } else { 208 loge("Failed to update network " + config); 209 } 210 return netId; 211 } 212 return INVALID_NETWORK_ID; 213 } 214 215 /** 216 * Selects the specified network for connection. This involves 217 * updating the priority of all the networks and enabling the given 218 * network while disabling others. 219 * 220 * Selecting a network will leave the other networks disabled and 221 * a call to enableAllNetworks() needs to be issued upon a connection 222 * or a failure event from supplicant 223 * 224 * @param netId network to select for connection 225 */ 226 static void selectNetwork(int netId) { 227 // Reset the priority of each network at start or if it goes too high. 228 if (sLastPriority == -1 || sLastPriority > 1000000) { 229 synchronized (sConfiguredNetworks) { 230 for(WifiConfiguration config : sConfiguredNetworks.values()) { 231 if (config.networkId != INVALID_NETWORK_ID) { 232 config.priority = 0; 233 addOrUpdateNetworkNative(config); 234 } 235 } 236 } 237 sLastPriority = 0; 238 } 239 240 // Set to the highest priority and save the configuration. 241 WifiConfiguration config = new WifiConfiguration(); 242 config.networkId = netId; 243 config.priority = ++sLastPriority; 244 245 addOrUpdateNetworkNative(config); 246 WifiNative.saveConfigCommand(); 247 248 /* Enable the given network while disabling all other networks */ 249 enableNetworkWithoutBroadcast(netId, true); 250 251 /* Avoid saving the config & sending a broadcast to prevent settings 252 * from displaying a disabled list of networks */ 253 } 254 255 /** 256 * Add/update the specified configuration and save config 257 * 258 * @param config WifiConfiguration to be saved 259 */ 260 static NetworkUpdateResult saveNetwork(WifiConfiguration config) { 261 boolean newNetwork = (config.networkId == INVALID_NETWORK_ID); 262 NetworkUpdateResult result = addOrUpdateNetworkNative(config); 263 int netId = result.getNetworkId(); 264 /* enable a new network */ 265 if (newNetwork && netId != INVALID_NETWORK_ID) { 266 WifiNative.enableNetworkCommand(netId, false); 267 synchronized (sConfiguredNetworks) { 268 sConfiguredNetworks.get(netId).status = Status.ENABLED; 269 } 270 } 271 WifiNative.saveConfigCommand(); 272 sendConfiguredNetworksChangedBroadcast(); 273 return result; 274 } 275 276 /** 277 * Forget the specified network and save config 278 * 279 * @param netId network to forget 280 */ 281 static void forgetNetwork(int netId) { 282 if (WifiNative.removeNetworkCommand(netId)) { 283 WifiNative.saveConfigCommand(); 284 synchronized (sConfiguredNetworks) { 285 WifiConfiguration config = sConfiguredNetworks.get(netId); 286 if (config != null) { 287 sConfiguredNetworks.remove(netId); 288 sNetworkIds.remove(configKey(config)); 289 } 290 } 291 writeIpAndProxyConfigurations(); 292 sendConfiguredNetworksChangedBroadcast(); 293 } else { 294 loge("Failed to remove network " + netId); 295 } 296 } 297 298 /** 299 * Add/update a network. Note that there is no saveConfig operation. 300 * This function is retained for compatibility with the public 301 * API. The more powerful saveNetwork() is used by the 302 * state machine 303 * 304 * @param config wifi configuration to add/update 305 */ 306 static int addOrUpdateNetwork(WifiConfiguration config) { 307 NetworkUpdateResult result = addOrUpdateNetworkNative(config); 308 sendConfiguredNetworksChangedBroadcast(); 309 return result.getNetworkId(); 310 } 311 312 /** 313 * Remove a network. Note that there is no saveConfig operation. 314 * This function is retained for compatibility with the public 315 * API. The more powerful forgetNetwork() is used by the 316 * state machine for network removal 317 * 318 * @param netId network to be removed 319 */ 320 static boolean removeNetwork(int netId) { 321 boolean ret = WifiNative.removeNetworkCommand(netId); 322 synchronized (sConfiguredNetworks) { 323 if (ret) { 324 WifiConfiguration config = sConfiguredNetworks.get(netId); 325 if (config != null) { 326 sConfiguredNetworks.remove(netId); 327 sNetworkIds.remove(configKey(config)); 328 } 329 } 330 } 331 sendConfiguredNetworksChangedBroadcast(); 332 return ret; 333 } 334 335 /** 336 * Enable a network. Note that there is no saveConfig operation. 337 * This function is retained for compatibility with the public 338 * API. The more powerful selectNetwork()/saveNetwork() is used by the 339 * state machine for connecting to a network 340 * 341 * @param netId network to be removed 342 */ 343 static boolean enableNetwork(int netId, boolean disableOthers) { 344 boolean ret = enableNetworkWithoutBroadcast(netId, disableOthers); 345 sendConfiguredNetworksChangedBroadcast(); 346 return ret; 347 } 348 349 static boolean enableNetworkWithoutBroadcast(int netId, boolean disableOthers) { 350 boolean ret = WifiNative.enableNetworkCommand(netId, disableOthers); 351 352 synchronized (sConfiguredNetworks) { 353 WifiConfiguration config = sConfiguredNetworks.get(netId); 354 if (config != null) config.status = Status.ENABLED; 355 } 356 357 if (disableOthers) { 358 markAllNetworksDisabledExcept(netId); 359 } 360 return ret; 361 } 362 363 /** 364 * Disable a network. Note that there is no saveConfig operation. 365 * @param netId network to be disabled 366 */ 367 static boolean disableNetwork(int netId) { 368 return disableNetwork(netId, WifiConfiguration.DISABLED_UNKNOWN_REASON); 369 } 370 371 /** 372 * Disable a network. Note that there is no saveConfig operation. 373 * @param netId network to be disabled 374 * @param reason reason code network was disabled 375 */ 376 static boolean disableNetwork(int netId, int reason) { 377 boolean ret = WifiNative.disableNetworkCommand(netId); 378 synchronized (sConfiguredNetworks) { 379 WifiConfiguration config = sConfiguredNetworks.get(netId); 380 /* Only change the reason if the network was not previously disabled */ 381 if (config != null && config.status != Status.DISABLED) { 382 config.status = Status.DISABLED; 383 config.disableReason = reason; 384 } 385 } 386 sendConfiguredNetworksChangedBroadcast(); 387 return ret; 388 } 389 390 /** 391 * Save the configured networks in supplicant to disk 392 */ 393 static boolean saveConfig() { 394 return WifiNative.saveConfigCommand(); 395 } 396 397 /** 398 * Start WPS pin method configuration with pin obtained 399 * from the access point 400 */ 401 static WpsResult startWpsWithPinFromAccessPoint(WpsInfo config) { 402 WpsResult result = new WpsResult(); 403 if (WifiNative.startWpsWithPinFromAccessPointCommand(config.BSSID, config.pin)) { 404 /* WPS leaves all networks disabled */ 405 markAllNetworksDisabled(); 406 result.status = WpsResult.Status.SUCCESS; 407 } else { 408 loge("Failed to start WPS pin method configuration"); 409 result.status = WpsResult.Status.FAILURE; 410 } 411 return result; 412 } 413 414 /** 415 * Start WPS pin method configuration with pin obtained 416 * from the device 417 * @return WpsResult indicating status and pin 418 */ 419 static WpsResult startWpsWithPinFromDevice(WpsInfo config) { 420 WpsResult result = new WpsResult(); 421 result.pin = WifiNative.startWpsWithPinFromDeviceCommand(config.BSSID); 422 /* WPS leaves all networks disabled */ 423 if (!TextUtils.isEmpty(result.pin)) { 424 markAllNetworksDisabled(); 425 result.status = WpsResult.Status.SUCCESS; 426 } else { 427 loge("Failed to start WPS pin method configuration"); 428 result.status = WpsResult.Status.FAILURE; 429 } 430 return result; 431 } 432 433 /** 434 * Start WPS push button configuration 435 */ 436 static WpsResult startWpsPbc(WpsInfo config) { 437 WpsResult result = new WpsResult(); 438 if (WifiNative.startWpsPbcCommand(config.BSSID)) { 439 /* WPS leaves all networks disabled */ 440 markAllNetworksDisabled(); 441 result.status = WpsResult.Status.SUCCESS; 442 } else { 443 loge("Failed to start WPS push button configuration"); 444 result.status = WpsResult.Status.FAILURE; 445 } 446 return result; 447 } 448 449 /** 450 * Fetch the link properties for a given network id 451 */ 452 static LinkProperties getLinkProperties(int netId) { 453 synchronized (sConfiguredNetworks) { 454 WifiConfiguration config = sConfiguredNetworks.get(netId); 455 if (config != null) return new LinkProperties(config.linkProperties); 456 } 457 return null; 458 } 459 460 /** 461 * get IP configuration for a given network id 462 * TODO: We cannot handle IPv6 addresses for configuration 463 * right now until NetworkUtils is fixed. When we do 464 * that, we should remove handling DhcpInfo and move 465 * to using LinkProperties 466 */ 467 static DhcpInfoInternal getIpConfiguration(int netId) { 468 DhcpInfoInternal dhcpInfoInternal = new DhcpInfoInternal(); 469 LinkProperties linkProperties = getLinkProperties(netId); 470 471 if (linkProperties != null) { 472 Iterator<LinkAddress> iter = linkProperties.getLinkAddresses().iterator(); 473 if (iter.hasNext()) { 474 LinkAddress linkAddress = iter.next(); 475 dhcpInfoInternal.ipAddress = linkAddress.getAddress().getHostAddress(); 476 for (RouteInfo route : linkProperties.getRoutes()) { 477 dhcpInfoInternal.addRoute(route); 478 } 479 dhcpInfoInternal.prefixLength = linkAddress.getNetworkPrefixLength(); 480 Iterator<InetAddress> dnsIterator = linkProperties.getDnses().iterator(); 481 dhcpInfoInternal.dns1 = dnsIterator.next().getHostAddress(); 482 if (dnsIterator.hasNext()) { 483 dhcpInfoInternal.dns2 = dnsIterator.next().getHostAddress(); 484 } 485 } 486 } 487 return dhcpInfoInternal; 488 } 489 490 /** 491 * set IP configuration for a given network id 492 */ 493 static void setIpConfiguration(int netId, DhcpInfoInternal dhcpInfo) { 494 LinkProperties linkProperties = dhcpInfo.makeLinkProperties(); 495 496 synchronized (sConfiguredNetworks) { 497 WifiConfiguration config = sConfiguredNetworks.get(netId); 498 if (config != null) { 499 // add old proxy details 500 if(config.linkProperties != null) { 501 linkProperties.setHttpProxy(config.linkProperties.getHttpProxy()); 502 } 503 config.linkProperties = linkProperties; 504 } 505 } 506 } 507 508 /** 509 * clear IP configuration for a given network id 510 */ 511 static void clearIpConfiguration(int netId) { 512 synchronized (sConfiguredNetworks) { 513 WifiConfiguration config = sConfiguredNetworks.get(netId); 514 if (config != null && config.linkProperties != null) { 515 // Clear everything except proxy 516 ProxyProperties proxy = config.linkProperties.getHttpProxy(); 517 config.linkProperties.clear(); 518 config.linkProperties.setHttpProxy(proxy); 519 } 520 } 521 } 522 523 524 /** 525 * Fetch the proxy properties for a given network id 526 */ 527 static ProxyProperties getProxyProperties(int netId) { 528 LinkProperties linkProperties = getLinkProperties(netId); 529 if (linkProperties != null) { 530 return new ProxyProperties(linkProperties.getHttpProxy()); 531 } 532 return null; 533 } 534 535 /** 536 * Return if the specified network is using static IP 537 */ 538 static boolean isUsingStaticIp(int netId) { 539 synchronized (sConfiguredNetworks) { 540 WifiConfiguration config = sConfiguredNetworks.get(netId); 541 if (config != null && config.ipAssignment == IpAssignment.STATIC) { 542 return true; 543 } 544 } 545 return false; 546 } 547 548 private static void sendConfiguredNetworksChangedBroadcast() { 549 Intent intent = new Intent(WifiManager.CONFIGURED_NETWORKS_CHANGED_ACTION); 550 intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT); 551 sContext.sendBroadcast(intent); 552 } 553 554 static void loadConfiguredNetworks() { 555 String listStr = WifiNative.listNetworksCommand(); 556 sLastPriority = 0; 557 558 synchronized (sConfiguredNetworks) { 559 sConfiguredNetworks.clear(); 560 sNetworkIds.clear(); 561 562 if (listStr == null) 563 return; 564 565 String[] lines = listStr.split("\n"); 566 // Skip the first line, which is a header 567 for (int i = 1; i < lines.length; i++) { 568 String[] result = lines[i].split("\t"); 569 // network-id | ssid | bssid | flags 570 WifiConfiguration config = new WifiConfiguration(); 571 try { 572 config.networkId = Integer.parseInt(result[0]); 573 } catch(NumberFormatException e) { 574 continue; 575 } 576 if (result.length > 3) { 577 if (result[3].indexOf("[CURRENT]") != -1) 578 config.status = WifiConfiguration.Status.CURRENT; 579 else if (result[3].indexOf("[DISABLED]") != -1) 580 config.status = WifiConfiguration.Status.DISABLED; 581 else 582 config.status = WifiConfiguration.Status.ENABLED; 583 } else { 584 config.status = WifiConfiguration.Status.ENABLED; 585 } 586 readNetworkVariables(config); 587 if (config.priority > sLastPriority) { 588 sLastPriority = config.priority; 589 } 590 sConfiguredNetworks.put(config.networkId, config); 591 sNetworkIds.put(configKey(config), config.networkId); 592 } 593 } 594 readIpAndProxyConfigurations(); 595 sendConfiguredNetworksChangedBroadcast(); 596 } 597 598 static void updateIpAndProxyFromWpsConfig(int netId, WpsInfo wpsConfig) { 599 synchronized (sConfiguredNetworks) { 600 WifiConfiguration config = sConfiguredNetworks.get(netId); 601 if (config != null) { 602 config.ipAssignment = wpsConfig.ipAssignment; 603 config.proxySettings = wpsConfig.proxySettings; 604 config.linkProperties = wpsConfig.linkProperties; 605 writeIpAndProxyConfigurations(); 606 } 607 } 608 } 609 610 /* Mark all networks except specified netId as disabled */ 611 private static void markAllNetworksDisabledExcept(int netId) { 612 synchronized (sConfiguredNetworks) { 613 for(WifiConfiguration config : sConfiguredNetworks.values()) { 614 if(config != null && config.networkId != netId) { 615 if (config.status != Status.DISABLED) { 616 config.status = Status.DISABLED; 617 config.disableReason = WifiConfiguration.DISABLED_UNKNOWN_REASON; 618 } 619 } 620 } 621 } 622 } 623 624 private static void markAllNetworksDisabled() { 625 markAllNetworksDisabledExcept(INVALID_NETWORK_ID); 626 } 627 628 private static void writeIpAndProxyConfigurations() { 629 630 DataOutputStream out = null; 631 try { 632 out = new DataOutputStream(new BufferedOutputStream( 633 new FileOutputStream(ipConfigFile))); 634 635 out.writeInt(IPCONFIG_FILE_VERSION); 636 637 synchronized (sConfiguredNetworks) { 638 for(WifiConfiguration config : sConfiguredNetworks.values()) { 639 boolean writeToFile = false; 640 641 try { 642 LinkProperties linkProperties = config.linkProperties; 643 switch (config.ipAssignment) { 644 case STATIC: 645 out.writeUTF(IP_ASSIGNMENT_KEY); 646 out.writeUTF(config.ipAssignment.toString()); 647 for (LinkAddress linkAddr : linkProperties.getLinkAddresses()) { 648 out.writeUTF(LINK_ADDRESS_KEY); 649 out.writeUTF(linkAddr.getAddress().getHostAddress()); 650 out.writeInt(linkAddr.getNetworkPrefixLength()); 651 } 652 for (RouteInfo route : linkProperties.getRoutes()) { 653 out.writeUTF(GATEWAY_KEY); 654 LinkAddress dest = route.getDestination(); 655 if (dest != null) { 656 out.writeInt(1); 657 out.writeUTF(dest.getAddress().getHostAddress()); 658 out.writeInt(dest.getNetworkPrefixLength()); 659 } else { 660 out.writeInt(0); 661 } 662 if (route.getGateway() != null) { 663 out.writeInt(1); 664 out.writeUTF(route.getGateway().getHostAddress()); 665 } else { 666 out.writeInt(0); 667 } 668 } 669 for (InetAddress inetAddr : linkProperties.getDnses()) { 670 out.writeUTF(DNS_KEY); 671 out.writeUTF(inetAddr.getHostAddress()); 672 } 673 writeToFile = true; 674 break; 675 case DHCP: 676 out.writeUTF(IP_ASSIGNMENT_KEY); 677 out.writeUTF(config.ipAssignment.toString()); 678 writeToFile = true; 679 break; 680 case UNASSIGNED: 681 /* Ignore */ 682 break; 683 default: 684 loge("Ignore invalid ip assignment while writing"); 685 break; 686 } 687 688 switch (config.proxySettings) { 689 case STATIC: 690 ProxyProperties proxyProperties = linkProperties.getHttpProxy(); 691 String exclusionList = proxyProperties.getExclusionList(); 692 out.writeUTF(PROXY_SETTINGS_KEY); 693 out.writeUTF(config.proxySettings.toString()); 694 out.writeUTF(PROXY_HOST_KEY); 695 out.writeUTF(proxyProperties.getHost()); 696 out.writeUTF(PROXY_PORT_KEY); 697 out.writeInt(proxyProperties.getPort()); 698 out.writeUTF(EXCLUSION_LIST_KEY); 699 out.writeUTF(exclusionList); 700 writeToFile = true; 701 break; 702 case NONE: 703 out.writeUTF(PROXY_SETTINGS_KEY); 704 out.writeUTF(config.proxySettings.toString()); 705 writeToFile = true; 706 break; 707 case UNASSIGNED: 708 /* Ignore */ 709 break; 710 default: 711 loge("Ignore invalid proxy settings while writing"); 712 break; 713 } 714 if (writeToFile) { 715 out.writeUTF(ID_KEY); 716 out.writeInt(configKey(config)); 717 } 718 } catch (NullPointerException e) { 719 loge("Failure in writing " + config.linkProperties + e); 720 } 721 out.writeUTF(EOS); 722 } 723 } 724 725 } catch (IOException e) { 726 loge("Error writing data file"); 727 } finally { 728 if (out != null) { 729 try { 730 out.close(); 731 } catch (Exception e) {} 732 } 733 } 734 } 735 736 private static void readIpAndProxyConfigurations() { 737 738 DataInputStream in = null; 739 try { 740 in = new DataInputStream(new BufferedInputStream(new FileInputStream( 741 ipConfigFile))); 742 743 int version = in.readInt(); 744 if (version != 2 && version != 1) { 745 loge("Bad version on IP configuration file, ignore read"); 746 return; 747 } 748 749 while (true) { 750 int id = -1; 751 IpAssignment ipAssignment = IpAssignment.UNASSIGNED; 752 ProxySettings proxySettings = ProxySettings.UNASSIGNED; 753 LinkProperties linkProperties = new LinkProperties(); 754 String proxyHost = null; 755 int proxyPort = -1; 756 String exclusionList = null; 757 String key; 758 759 do { 760 key = in.readUTF(); 761 try { 762 if (key.equals(ID_KEY)) { 763 id = in.readInt(); 764 } else if (key.equals(IP_ASSIGNMENT_KEY)) { 765 ipAssignment = IpAssignment.valueOf(in.readUTF()); 766 } else if (key.equals(LINK_ADDRESS_KEY)) { 767 LinkAddress linkAddr = new LinkAddress( 768 NetworkUtils.numericToInetAddress(in.readUTF()), in.readInt()); 769 linkProperties.addLinkAddress(linkAddr); 770 } else if (key.equals(GATEWAY_KEY)) { 771 LinkAddress dest = null; 772 InetAddress gateway = null; 773 if (version == 1) { 774 // only supported default gateways - leave the dest/prefix empty 775 gateway = NetworkUtils.numericToInetAddress(in.readUTF()); 776 } else { 777 if (in.readInt() == 1) { 778 dest = new LinkAddress( 779 NetworkUtils.numericToInetAddress(in.readUTF()), 780 in.readInt()); 781 } 782 if (in.readInt() == 1) { 783 gateway = NetworkUtils.numericToInetAddress(in.readUTF()); 784 } 785 } 786 linkProperties.addRoute(new RouteInfo(dest, gateway)); 787 } else if (key.equals(DNS_KEY)) { 788 linkProperties.addDns( 789 NetworkUtils.numericToInetAddress(in.readUTF())); 790 } else if (key.equals(PROXY_SETTINGS_KEY)) { 791 proxySettings = ProxySettings.valueOf(in.readUTF()); 792 } else if (key.equals(PROXY_HOST_KEY)) { 793 proxyHost = in.readUTF(); 794 } else if (key.equals(PROXY_PORT_KEY)) { 795 proxyPort = in.readInt(); 796 } else if (key.equals(EXCLUSION_LIST_KEY)) { 797 exclusionList = in.readUTF(); 798 } else if (key.equals(EOS)) { 799 break; 800 } else { 801 loge("Ignore unknown key " + key + "while reading"); 802 } 803 } catch (IllegalArgumentException e) { 804 loge("Ignore invalid address while reading" + e); 805 } 806 } while (true); 807 808 if (id != -1) { 809 synchronized (sConfiguredNetworks) { 810 WifiConfiguration config = sConfiguredNetworks.get( 811 sNetworkIds.get(id)); 812 813 if (config == null) { 814 loge("configuration found for missing network, ignored"); 815 } else { 816 config.linkProperties = linkProperties; 817 switch (ipAssignment) { 818 case STATIC: 819 case DHCP: 820 config.ipAssignment = ipAssignment; 821 break; 822 case UNASSIGNED: 823 //Ignore 824 break; 825 default: 826 loge("Ignore invalid ip assignment while reading"); 827 break; 828 } 829 830 switch (proxySettings) { 831 case STATIC: 832 config.proxySettings = proxySettings; 833 ProxyProperties proxyProperties = 834 new ProxyProperties(proxyHost, proxyPort, exclusionList); 835 linkProperties.setHttpProxy(proxyProperties); 836 break; 837 case NONE: 838 config.proxySettings = proxySettings; 839 break; 840 case UNASSIGNED: 841 //Ignore 842 break; 843 default: 844 loge("Ignore invalid proxy settings while reading"); 845 break; 846 } 847 } 848 } 849 } else { 850 loge("Missing id while parsing configuration"); 851 } 852 } 853 } catch (EOFException ignore) { 854 } catch (IOException e) { 855 loge("Error parsing configuration" + e); 856 } finally { 857 if (in != null) { 858 try { 859 in.close(); 860 } catch (Exception e) {} 861 } 862 } 863 } 864 865 private static NetworkUpdateResult addOrUpdateNetworkNative(WifiConfiguration config) { 866 /* 867 * If the supplied networkId is INVALID_NETWORK_ID, we create a new empty 868 * network configuration. Otherwise, the networkId should 869 * refer to an existing configuration. 870 */ 871 int netId = config.networkId; 872 boolean newNetwork = false; 873 // networkId of INVALID_NETWORK_ID means we want to create a new network 874 if (netId == INVALID_NETWORK_ID) { 875 Integer savedNetId = sNetworkIds.get(configKey(config)); 876 if (savedNetId != null) { 877 netId = savedNetId; 878 } else { 879 newNetwork = true; 880 netId = WifiNative.addNetworkCommand(); 881 if (netId < 0) { 882 loge("Failed to add a network!"); 883 return new NetworkUpdateResult(INVALID_NETWORK_ID); 884 } 885 } 886 } 887 888 boolean updateFailed = true; 889 890 setVariables: { 891 892 if (config.SSID != null && 893 !WifiNative.setNetworkVariableCommand( 894 netId, 895 WifiConfiguration.ssidVarName, 896 config.SSID)) { 897 loge("failed to set SSID: "+config.SSID); 898 break setVariables; 899 } 900 901 if (config.BSSID != null && 902 !WifiNative.setNetworkVariableCommand( 903 netId, 904 WifiConfiguration.bssidVarName, 905 config.BSSID)) { 906 loge("failed to set BSSID: "+config.BSSID); 907 break setVariables; 908 } 909 910 String allowedKeyManagementString = 911 makeString(config.allowedKeyManagement, WifiConfiguration.KeyMgmt.strings); 912 if (config.allowedKeyManagement.cardinality() != 0 && 913 !WifiNative.setNetworkVariableCommand( 914 netId, 915 WifiConfiguration.KeyMgmt.varName, 916 allowedKeyManagementString)) { 917 loge("failed to set key_mgmt: "+ 918 allowedKeyManagementString); 919 break setVariables; 920 } 921 922 String allowedProtocolsString = 923 makeString(config.allowedProtocols, WifiConfiguration.Protocol.strings); 924 if (config.allowedProtocols.cardinality() != 0 && 925 !WifiNative.setNetworkVariableCommand( 926 netId, 927 WifiConfiguration.Protocol.varName, 928 allowedProtocolsString)) { 929 loge("failed to set proto: "+ 930 allowedProtocolsString); 931 break setVariables; 932 } 933 934 String allowedAuthAlgorithmsString = 935 makeString(config.allowedAuthAlgorithms, WifiConfiguration.AuthAlgorithm.strings); 936 if (config.allowedAuthAlgorithms.cardinality() != 0 && 937 !WifiNative.setNetworkVariableCommand( 938 netId, 939 WifiConfiguration.AuthAlgorithm.varName, 940 allowedAuthAlgorithmsString)) { 941 loge("failed to set auth_alg: "+ 942 allowedAuthAlgorithmsString); 943 break setVariables; 944 } 945 946 String allowedPairwiseCiphersString = 947 makeString(config.allowedPairwiseCiphers, 948 WifiConfiguration.PairwiseCipher.strings); 949 if (config.allowedPairwiseCiphers.cardinality() != 0 && 950 !WifiNative.setNetworkVariableCommand( 951 netId, 952 WifiConfiguration.PairwiseCipher.varName, 953 allowedPairwiseCiphersString)) { 954 loge("failed to set pairwise: "+ 955 allowedPairwiseCiphersString); 956 break setVariables; 957 } 958 959 String allowedGroupCiphersString = 960 makeString(config.allowedGroupCiphers, WifiConfiguration.GroupCipher.strings); 961 if (config.allowedGroupCiphers.cardinality() != 0 && 962 !WifiNative.setNetworkVariableCommand( 963 netId, 964 WifiConfiguration.GroupCipher.varName, 965 allowedGroupCiphersString)) { 966 loge("failed to set group: "+ 967 allowedGroupCiphersString); 968 break setVariables; 969 } 970 971 // Prevent client screw-up by passing in a WifiConfiguration we gave it 972 // by preventing "*" as a key. 973 if (config.preSharedKey != null && !config.preSharedKey.equals("*") && 974 !WifiNative.setNetworkVariableCommand( 975 netId, 976 WifiConfiguration.pskVarName, 977 config.preSharedKey)) { 978 loge("failed to set psk"); 979 break setVariables; 980 } 981 982 boolean hasSetKey = false; 983 if (config.wepKeys != null) { 984 for (int i = 0; i < config.wepKeys.length; i++) { 985 // Prevent client screw-up by passing in a WifiConfiguration we gave it 986 // by preventing "*" as a key. 987 if (config.wepKeys[i] != null && !config.wepKeys[i].equals("*")) { 988 if (!WifiNative.setNetworkVariableCommand( 989 netId, 990 WifiConfiguration.wepKeyVarNames[i], 991 config.wepKeys[i])) { 992 loge("failed to set wep_key" + i + ": " + config.wepKeys[i]); 993 break setVariables; 994 } 995 hasSetKey = true; 996 } 997 } 998 } 999 1000 if (hasSetKey) { 1001 if (!WifiNative.setNetworkVariableCommand( 1002 netId, 1003 WifiConfiguration.wepTxKeyIdxVarName, 1004 Integer.toString(config.wepTxKeyIndex))) { 1005 loge("failed to set wep_tx_keyidx: " + config.wepTxKeyIndex); 1006 break setVariables; 1007 } 1008 } 1009 1010 if (!WifiNative.setNetworkVariableCommand( 1011 netId, 1012 WifiConfiguration.priorityVarName, 1013 Integer.toString(config.priority))) { 1014 loge(config.SSID + ": failed to set priority: " 1015 +config.priority); 1016 break setVariables; 1017 } 1018 1019 if (config.hiddenSSID && !WifiNative.setNetworkVariableCommand( 1020 netId, 1021 WifiConfiguration.hiddenSSIDVarName, 1022 Integer.toString(config.hiddenSSID ? 1 : 0))) { 1023 loge(config.SSID + ": failed to set hiddenSSID: "+ 1024 config.hiddenSSID); 1025 break setVariables; 1026 } 1027 1028 for (WifiConfiguration.EnterpriseField field 1029 : config.enterpriseFields) { 1030 String varName = field.varName(); 1031 String value = field.value(); 1032 if (value != null) { 1033 if (field != config.eap) { 1034 value = (value.length() == 0) ? "NULL" : convertToQuotedString(value); 1035 } 1036 if (!WifiNative.setNetworkVariableCommand( 1037 netId, 1038 varName, 1039 value)) { 1040 loge(config.SSID + ": failed to set " + varName + 1041 ": " + value); 1042 break setVariables; 1043 } 1044 } 1045 } 1046 updateFailed = false; 1047 } 1048 1049 if (updateFailed) { 1050 if (newNetwork) { 1051 WifiNative.removeNetworkCommand(netId); 1052 loge("Failed to set a network variable, removed network: " + netId); 1053 } 1054 return new NetworkUpdateResult(INVALID_NETWORK_ID); 1055 } 1056 1057 /* An update of the network variables requires reading them 1058 * back from the supplicant to update sConfiguredNetworks. 1059 * This is because some of the variables (SSID, wep keys & 1060 * passphrases) reflect different values when read back than 1061 * when written. For example, wep key is stored as * irrespective 1062 * of the value sent to the supplicant 1063 */ 1064 WifiConfiguration sConfig; 1065 synchronized (sConfiguredNetworks) { 1066 sConfig = sConfiguredNetworks.get(netId); 1067 } 1068 if (sConfig == null) { 1069 sConfig = new WifiConfiguration(); 1070 sConfig.networkId = netId; 1071 } 1072 1073 readNetworkVariables(sConfig); 1074 1075 synchronized (sConfiguredNetworks) { 1076 sConfiguredNetworks.put(netId, sConfig); 1077 sNetworkIds.put(configKey(sConfig), netId); 1078 } 1079 1080 NetworkUpdateResult result = writeIpAndProxyConfigurationsOnChange(sConfig, config); 1081 result.setNetworkId(netId); 1082 return result; 1083 } 1084 1085 /* Compare current and new configuration and write to file on change */ 1086 private static NetworkUpdateResult writeIpAndProxyConfigurationsOnChange( 1087 WifiConfiguration currentConfig, 1088 WifiConfiguration newConfig) { 1089 boolean ipChanged = false; 1090 boolean proxyChanged = false; 1091 LinkProperties linkProperties = new LinkProperties(); 1092 1093 switch (newConfig.ipAssignment) { 1094 case STATIC: 1095 Collection<LinkAddress> currentLinkAddresses = currentConfig.linkProperties 1096 .getLinkAddresses(); 1097 Collection<LinkAddress> newLinkAddresses = newConfig.linkProperties 1098 .getLinkAddresses(); 1099 Collection<InetAddress> currentDnses = currentConfig.linkProperties.getDnses(); 1100 Collection<InetAddress> newDnses = newConfig.linkProperties.getDnses(); 1101 Collection<RouteInfo> currentRoutes = currentConfig.linkProperties.getRoutes(); 1102 Collection<RouteInfo> newRoutes = newConfig.linkProperties.getRoutes(); 1103 1104 boolean linkAddressesDiffer = 1105 (currentLinkAddresses.size() != newLinkAddresses.size()) || 1106 !currentLinkAddresses.containsAll(newLinkAddresses); 1107 boolean dnsesDiffer = (currentDnses.size() != newDnses.size()) || 1108 !currentDnses.containsAll(newDnses); 1109 boolean routesDiffer = (currentRoutes.size() != newRoutes.size()) || 1110 !currentRoutes.containsAll(newRoutes); 1111 1112 if ((currentConfig.ipAssignment != newConfig.ipAssignment) || 1113 linkAddressesDiffer || 1114 dnsesDiffer || 1115 routesDiffer) { 1116 ipChanged = true; 1117 } 1118 break; 1119 case DHCP: 1120 if (currentConfig.ipAssignment != newConfig.ipAssignment) { 1121 ipChanged = true; 1122 } 1123 break; 1124 case UNASSIGNED: 1125 /* Ignore */ 1126 break; 1127 default: 1128 loge("Ignore invalid ip assignment during write"); 1129 break; 1130 } 1131 1132 switch (newConfig.proxySettings) { 1133 case STATIC: 1134 ProxyProperties newHttpProxy = newConfig.linkProperties.getHttpProxy(); 1135 ProxyProperties currentHttpProxy = currentConfig.linkProperties.getHttpProxy(); 1136 1137 if (newHttpProxy != null) { 1138 proxyChanged = !newHttpProxy.equals(currentHttpProxy); 1139 } else { 1140 proxyChanged = (currentHttpProxy != null); 1141 } 1142 break; 1143 case NONE: 1144 if (currentConfig.proxySettings != newConfig.proxySettings) { 1145 proxyChanged = true; 1146 } 1147 break; 1148 case UNASSIGNED: 1149 /* Ignore */ 1150 break; 1151 default: 1152 loge("Ignore invalid proxy configuration during write"); 1153 break; 1154 } 1155 1156 if (!ipChanged) { 1157 addIpSettingsFromConfig(linkProperties, currentConfig); 1158 } else { 1159 currentConfig.ipAssignment = newConfig.ipAssignment; 1160 addIpSettingsFromConfig(linkProperties, newConfig); 1161 log("IP config changed SSID = " + currentConfig.SSID + " linkProperties: " + 1162 linkProperties.toString()); 1163 } 1164 1165 1166 if (!proxyChanged) { 1167 linkProperties.setHttpProxy(currentConfig.linkProperties.getHttpProxy()); 1168 } else { 1169 currentConfig.proxySettings = newConfig.proxySettings; 1170 linkProperties.setHttpProxy(newConfig.linkProperties.getHttpProxy()); 1171 log("proxy changed SSID = " + currentConfig.SSID); 1172 if (linkProperties.getHttpProxy() != null) { 1173 log(" proxyProperties: " + linkProperties.getHttpProxy().toString()); 1174 } 1175 } 1176 1177 if (ipChanged || proxyChanged) { 1178 currentConfig.linkProperties = linkProperties; 1179 writeIpAndProxyConfigurations(); 1180 sendConfiguredNetworksChangedBroadcast(); 1181 } 1182 return new NetworkUpdateResult(ipChanged, proxyChanged); 1183 } 1184 1185 private static void addIpSettingsFromConfig(LinkProperties linkProperties, 1186 WifiConfiguration config) { 1187 for (LinkAddress linkAddr : config.linkProperties.getLinkAddresses()) { 1188 linkProperties.addLinkAddress(linkAddr); 1189 } 1190 for (RouteInfo route : config.linkProperties.getRoutes()) { 1191 linkProperties.addRoute(route); 1192 } 1193 for (InetAddress dns : config.linkProperties.getDnses()) { 1194 linkProperties.addDns(dns); 1195 } 1196 } 1197 1198 /** 1199 * Read the variables from the supplicant daemon that are needed to 1200 * fill in the WifiConfiguration object. 1201 * 1202 * @param config the {@link WifiConfiguration} object to be filled in. 1203 */ 1204 private static void readNetworkVariables(WifiConfiguration config) { 1205 1206 int netId = config.networkId; 1207 if (netId < 0) 1208 return; 1209 1210 /* 1211 * TODO: maybe should have a native method that takes an array of 1212 * variable names and returns an array of values. But we'd still 1213 * be doing a round trip to the supplicant daemon for each variable. 1214 */ 1215 String value; 1216 1217 value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.ssidVarName); 1218 if (!TextUtils.isEmpty(value)) { 1219 config.SSID = value; 1220 } else { 1221 config.SSID = null; 1222 } 1223 1224 value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.bssidVarName); 1225 if (!TextUtils.isEmpty(value)) { 1226 config.BSSID = value; 1227 } else { 1228 config.BSSID = null; 1229 } 1230 1231 value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.priorityVarName); 1232 config.priority = -1; 1233 if (!TextUtils.isEmpty(value)) { 1234 try { 1235 config.priority = Integer.parseInt(value); 1236 } catch (NumberFormatException ignore) { 1237 } 1238 } 1239 1240 value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.hiddenSSIDVarName); 1241 config.hiddenSSID = false; 1242 if (!TextUtils.isEmpty(value)) { 1243 try { 1244 config.hiddenSSID = Integer.parseInt(value) != 0; 1245 } catch (NumberFormatException ignore) { 1246 } 1247 } 1248 1249 value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.wepTxKeyIdxVarName); 1250 config.wepTxKeyIndex = -1; 1251 if (!TextUtils.isEmpty(value)) { 1252 try { 1253 config.wepTxKeyIndex = Integer.parseInt(value); 1254 } catch (NumberFormatException ignore) { 1255 } 1256 } 1257 1258 for (int i = 0; i < 4; i++) { 1259 value = WifiNative.getNetworkVariableCommand(netId, 1260 WifiConfiguration.wepKeyVarNames[i]); 1261 if (!TextUtils.isEmpty(value)) { 1262 config.wepKeys[i] = value; 1263 } else { 1264 config.wepKeys[i] = null; 1265 } 1266 } 1267 1268 value = WifiNative.getNetworkVariableCommand(netId, WifiConfiguration.pskVarName); 1269 if (!TextUtils.isEmpty(value)) { 1270 config.preSharedKey = value; 1271 } else { 1272 config.preSharedKey = null; 1273 } 1274 1275 value = WifiNative.getNetworkVariableCommand(config.networkId, 1276 WifiConfiguration.Protocol.varName); 1277 if (!TextUtils.isEmpty(value)) { 1278 String vals[] = value.split(" "); 1279 for (String val : vals) { 1280 int index = 1281 lookupString(val, WifiConfiguration.Protocol.strings); 1282 if (0 <= index) { 1283 config.allowedProtocols.set(index); 1284 } 1285 } 1286 } 1287 1288 value = WifiNative.getNetworkVariableCommand(config.networkId, 1289 WifiConfiguration.KeyMgmt.varName); 1290 if (!TextUtils.isEmpty(value)) { 1291 String vals[] = value.split(" "); 1292 for (String val : vals) { 1293 int index = 1294 lookupString(val, WifiConfiguration.KeyMgmt.strings); 1295 if (0 <= index) { 1296 config.allowedKeyManagement.set(index); 1297 } 1298 } 1299 } 1300 1301 value = WifiNative.getNetworkVariableCommand(config.networkId, 1302 WifiConfiguration.AuthAlgorithm.varName); 1303 if (!TextUtils.isEmpty(value)) { 1304 String vals[] = value.split(" "); 1305 for (String val : vals) { 1306 int index = 1307 lookupString(val, WifiConfiguration.AuthAlgorithm.strings); 1308 if (0 <= index) { 1309 config.allowedAuthAlgorithms.set(index); 1310 } 1311 } 1312 } 1313 1314 value = WifiNative.getNetworkVariableCommand(config.networkId, 1315 WifiConfiguration.PairwiseCipher.varName); 1316 if (!TextUtils.isEmpty(value)) { 1317 String vals[] = value.split(" "); 1318 for (String val : vals) { 1319 int index = 1320 lookupString(val, WifiConfiguration.PairwiseCipher.strings); 1321 if (0 <= index) { 1322 config.allowedPairwiseCiphers.set(index); 1323 } 1324 } 1325 } 1326 1327 value = WifiNative.getNetworkVariableCommand(config.networkId, 1328 WifiConfiguration.GroupCipher.varName); 1329 if (!TextUtils.isEmpty(value)) { 1330 String vals[] = value.split(" "); 1331 for (String val : vals) { 1332 int index = 1333 lookupString(val, WifiConfiguration.GroupCipher.strings); 1334 if (0 <= index) { 1335 config.allowedGroupCiphers.set(index); 1336 } 1337 } 1338 } 1339 1340 for (WifiConfiguration.EnterpriseField field : 1341 config.enterpriseFields) { 1342 value = WifiNative.getNetworkVariableCommand(netId, 1343 field.varName()); 1344 if (!TextUtils.isEmpty(value)) { 1345 if (field != config.eap) value = removeDoubleQuotes(value); 1346 field.setValue(value); 1347 } 1348 } 1349 } 1350 1351 private static String removeDoubleQuotes(String string) { 1352 if (string.length() <= 2) return ""; 1353 return string.substring(1, string.length() - 1); 1354 } 1355 1356 private static String convertToQuotedString(String string) { 1357 return "\"" + string + "\""; 1358 } 1359 1360 private static String makeString(BitSet set, String[] strings) { 1361 StringBuffer buf = new StringBuffer(); 1362 int nextSetBit = -1; 1363 1364 /* Make sure all set bits are in [0, strings.length) to avoid 1365 * going out of bounds on strings. (Shouldn't happen, but...) */ 1366 set = set.get(0, strings.length); 1367 1368 while ((nextSetBit = set.nextSetBit(nextSetBit + 1)) != -1) { 1369 buf.append(strings[nextSetBit].replace('_', '-')).append(' '); 1370 } 1371 1372 // remove trailing space 1373 if (set.cardinality() > 0) { 1374 buf.setLength(buf.length() - 1); 1375 } 1376 1377 return buf.toString(); 1378 } 1379 1380 private static int lookupString(String string, String[] strings) { 1381 int size = strings.length; 1382 1383 string = string.replace('-', '_'); 1384 1385 for (int i = 0; i < size; i++) 1386 if (string.equals(strings[i])) 1387 return i; 1388 1389 // if we ever get here, we should probably add the 1390 // value to WifiConfiguration to reflect that it's 1391 // supported by the WPA supplicant 1392 loge("Failed to look-up a string: " + string); 1393 1394 return -1; 1395 } 1396 1397 /* Returns a unique for a given configuration */ 1398 private static int configKey(WifiConfiguration config) { 1399 String key; 1400 1401 if (config.allowedKeyManagement.get(KeyMgmt.WPA_PSK)) { 1402 key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_PSK]; 1403 } else if (config.allowedKeyManagement.get(KeyMgmt.WPA_EAP) || 1404 config.allowedKeyManagement.get(KeyMgmt.IEEE8021X)) { 1405 key = config.SSID + KeyMgmt.strings[KeyMgmt.WPA_EAP]; 1406 } else if (config.wepKeys[0] != null) { 1407 key = config.SSID + "WEP"; 1408 } else { 1409 key = config.SSID + KeyMgmt.strings[KeyMgmt.NONE]; 1410 } 1411 1412 return key.hashCode(); 1413 } 1414 1415 static String dump() { 1416 StringBuffer sb = new StringBuffer(); 1417 String LS = System.getProperty("line.separator"); 1418 sb.append("sLastPriority ").append(sLastPriority).append(LS); 1419 sb.append("Configured networks ").append(LS); 1420 for (WifiConfiguration conf : getConfiguredNetworks()) { 1421 sb.append(conf).append(LS); 1422 } 1423 return sb.toString(); 1424 } 1425 1426 public static String getConfigFile() { 1427 return ipConfigFile; 1428 } 1429 1430 private static void loge(String s) { 1431 Log.e(TAG, s); 1432 } 1433 1434 private static void log(String s) { 1435 Log.d(TAG, s); 1436 } 1437 } 1438