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