1 2package com.googlecode.android_scripting.facade.wifi; 3 4import android.app.Service; 5import android.content.BroadcastReceiver; 6import android.content.ContentResolver; 7import android.content.Context; 8import android.content.Intent; 9import android.content.IntentFilter; 10import android.net.ConnectivityManager; 11import android.net.DhcpInfo; 12import android.net.Network; 13import android.net.NetworkInfo; 14import android.net.NetworkInfo.DetailedState; 15import android.net.wifi.ScanResult; 16import android.net.wifi.WifiActivityEnergyInfo; 17import android.net.wifi.WifiConfiguration; 18import android.net.wifi.WifiConfiguration.AuthAlgorithm; 19import android.net.wifi.WifiConfiguration.KeyMgmt; 20import android.net.wifi.WifiEnterpriseConfig; 21import android.net.wifi.WifiInfo; 22import android.net.wifi.WifiManager; 23import android.net.wifi.WifiManager.WifiLock; 24import android.net.wifi.WpsInfo; 25import android.os.Bundle; 26import android.provider.Settings.Global; 27import android.provider.Settings.SettingNotFoundException; 28import android.util.Base64; 29 30import com.googlecode.android_scripting.Log; 31import com.googlecode.android_scripting.facade.EventFacade; 32import com.googlecode.android_scripting.facade.FacadeManager; 33import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 34import com.googlecode.android_scripting.rpc.Rpc; 35import com.googlecode.android_scripting.rpc.RpcOptional; 36import com.googlecode.android_scripting.rpc.RpcParameter; 37 38import org.json.JSONArray; 39import org.json.JSONException; 40import org.json.JSONObject; 41 42import java.io.ByteArrayInputStream; 43import java.io.ByteArrayOutputStream; 44import java.io.IOException; 45import java.io.InputStream; 46import java.io.ObjectOutput; 47import java.io.ObjectOutputStream; 48import java.net.ConnectException; 49import java.security.GeneralSecurityException; 50import java.security.KeyFactory; 51import java.security.NoSuchAlgorithmException; 52import java.security.PrivateKey; 53import java.security.PublicKey; 54import java.security.cert.CertificateException; 55import java.security.cert.CertificateFactory; 56import java.security.cert.X509Certificate; 57import java.security.spec.InvalidKeySpecException; 58import java.security.spec.PKCS8EncodedKeySpec; 59import java.security.spec.X509EncodedKeySpec; 60import java.util.ArrayList; 61import java.util.List; 62 63 64/** 65 * WifiManager functions. 66 */ 67// TODO: make methods handle various wifi states properly 68// e.g. wifi connection result will be null when flight mode is on 69public class WifiManagerFacade extends RpcReceiver { 70 private final static String mEventType = "WifiManager"; 71 private final Service mService; 72 private final WifiManager mWifi; 73 private final EventFacade mEventFacade; 74 75 private final IntentFilter mScanFilter; 76 private final IntentFilter mStateChangeFilter; 77 private final IntentFilter mTetherFilter; 78 private final WifiScanReceiver mScanResultsAvailableReceiver; 79 private final WifiStateChangeReceiver mStateChangeReceiver; 80 private boolean mTrackingWifiStateChange; 81 private boolean mTrackingTetherStateChange; 82 83 private final BroadcastReceiver mTetherStateReceiver = new BroadcastReceiver() { 84 @Override 85 public void onReceive(Context context, Intent intent) { 86 String action = intent.getAction(); 87 if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) { 88 Log.d("Wifi AP state changed."); 89 int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, 90 WifiManager.WIFI_AP_STATE_FAILED); 91 if (state == WifiManager.WIFI_AP_STATE_ENABLED) { 92 mEventFacade.postEvent("WifiManagerApEnabled", null); 93 } else if (state == WifiManager.WIFI_AP_STATE_DISABLED) { 94 mEventFacade.postEvent("WifiManagerApDisabled", null); 95 } 96 } else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) { 97 Log.d("Tether state changed."); 98 ArrayList<String> available = intent.getStringArrayListExtra( 99 ConnectivityManager.EXTRA_AVAILABLE_TETHER); 100 ArrayList<String> active = intent.getStringArrayListExtra( 101 ConnectivityManager.EXTRA_ACTIVE_TETHER); 102 ArrayList<String> errored = intent.getStringArrayListExtra( 103 ConnectivityManager.EXTRA_ERRORED_TETHER); 104 Bundle msg = new Bundle(); 105 msg.putStringArrayList("AVAILABLE_TETHER", available); 106 msg.putStringArrayList("ACTIVE_TETHER", active); 107 msg.putStringArrayList("ERRORED_TETHER", errored); 108 mEventFacade.postEvent("TetherStateChanged", msg); 109 } 110 } 111 }; 112 113 private WifiLock mLock = null; 114 private boolean mIsConnected = false; 115 116 public WifiManagerFacade(FacadeManager manager) { 117 super(manager); 118 mService = manager.getService(); 119 mWifi = (WifiManager) mService.getSystemService(Context.WIFI_SERVICE); 120 mEventFacade = manager.getReceiver(EventFacade.class); 121 122 mScanFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 123 mStateChangeFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION); 124 mStateChangeFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 125 mStateChangeFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); 126 mStateChangeFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1); 127 128 mTetherFilter = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); 129 mTetherFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 130 131 mScanResultsAvailableReceiver = new WifiScanReceiver(mEventFacade); 132 mStateChangeReceiver = new WifiStateChangeReceiver(); 133 mTrackingWifiStateChange = false; 134 mTrackingTetherStateChange = false; 135 } 136 137 private void makeLock(int wifiMode) { 138 if (mLock == null) { 139 mLock = mWifi.createWifiLock(wifiMode, "sl4a"); 140 mLock.acquire(); 141 } 142 } 143 144 /** 145 * Handle Broadcast receiver for Scan Result 146 * 147 * @parm eventFacade Object of EventFacade 148 */ 149 class WifiScanReceiver extends BroadcastReceiver { 150 private final EventFacade mEventFacade; 151 152 WifiScanReceiver(EventFacade eventFacade) { 153 mEventFacade = eventFacade; 154 } 155 156 @Override 157 public void onReceive(Context c, Intent intent) { 158 String action = intent.getAction(); 159 if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 160 Bundle mResults = new Bundle(); 161 Log.d("Wifi connection scan finished, results available."); 162 mResults.putLong("Timestamp", System.currentTimeMillis() / 1000); 163 mEventFacade.postEvent(mEventType + "ScanResultsAvailable", mResults); 164 mService.unregisterReceiver(mScanResultsAvailableReceiver); 165 } 166 } 167 } 168 169 class WifiActionListener implements WifiManager.ActionListener { 170 private final EventFacade mEventFacade; 171 private final String TAG; 172 173 public WifiActionListener(EventFacade eventFacade, String tag) { 174 mEventFacade = eventFacade; 175 this.TAG = tag; 176 } 177 178 @Override 179 public void onSuccess() { 180 Log.d("WifiActionListener onSuccess called for " + mEventType + TAG + "OnSuccess"); 181 mEventFacade.postEvent(mEventType + TAG + "OnSuccess", null); 182 } 183 184 @Override 185 public void onFailure(int reason) { 186 Log.d("WifiActionListener onFailure called for" + mEventType); 187 Bundle msg = new Bundle(); 188 msg.putInt("reason", reason); 189 mEventFacade.postEvent(mEventType + TAG + "OnFailure", msg); 190 } 191 } 192 193 public class WifiStateChangeReceiver extends BroadcastReceiver { 194 String mCachedWifiInfo = ""; 195 196 @Override 197 public void onReceive(Context context, Intent intent) { 198 String action = intent.getAction(); 199 if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 200 Log.d("Wifi network state changed."); 201 NetworkInfo nInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); 202 WifiInfo wInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); 203 Log.d("NetworkInfo " + nInfo); 204 Log.d("WifiInfo " + wInfo); 205 // If network info is of type wifi, send wifi events. 206 if (nInfo.getType() == ConnectivityManager.TYPE_WIFI) { 207 if (wInfo != null && nInfo.getDetailedState().equals(DetailedState.CONNECTED)) { 208 String bssid = wInfo.getBSSID(); 209 if (bssid != null && !mCachedWifiInfo.equals(wInfo.toString())) { 210 Log.d("WifiNetworkConnected"); 211 mEventFacade.postEvent("WifiNetworkConnected", wInfo); 212 } 213 mCachedWifiInfo = wInfo.toString(); 214 } else { 215 if (nInfo.getDetailedState().equals(DetailedState.DISCONNECTED)) { 216 if (!mCachedWifiInfo.equals("")) { 217 mCachedWifiInfo = ""; 218 mEventFacade.postEvent("WifiNetworkDisconnected", null); 219 } 220 } 221 } 222 } 223 } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { 224 Log.d("Supplicant connection state changed."); 225 mIsConnected = intent 226 .getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false); 227 Bundle msg = new Bundle(); 228 msg.putBoolean("Connected", mIsConnected); 229 mEventFacade.postEvent("SupplicantConnectionChanged", msg); 230 } 231 } 232 } 233 234 public class WifiWpsCallback extends WifiManager.WpsCallback { 235 private static final String tag = "WifiWps"; 236 237 @Override 238 public void onStarted(String pin) { 239 Bundle msg = new Bundle(); 240 msg.putString("pin", pin); 241 mEventFacade.postEvent(tag + "OnStarted", msg); 242 } 243 244 @Override 245 public void onSucceeded() { 246 Log.d("Wps op succeeded"); 247 mEventFacade.postEvent(tag + "OnSucceeded", null); 248 } 249 250 @Override 251 public void onFailed(int reason) { 252 Bundle msg = new Bundle(); 253 msg.putInt("reason", reason); 254 mEventFacade.postEvent(tag + "OnFailed", msg); 255 } 256 } 257 258 private void applyingkeyMgmt(WifiConfiguration config, ScanResult result) { 259 if (result.capabilities.contains("WEP")) { 260 config.allowedKeyManagement.set(KeyMgmt.NONE); 261 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); 262 config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); 263 } else if (result.capabilities.contains("PSK")) { 264 config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); 265 } else if (result.capabilities.contains("EAP")) { 266 // this is probably wrong, as we don't have a way to enter the enterprise config 267 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 268 config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); 269 } else { 270 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 271 } 272 } 273 274 private WifiConfiguration genWifiConfig(JSONObject j) throws JSONException { 275 if (j == null) { 276 return null; 277 } 278 WifiConfiguration config = new WifiConfiguration(); 279 if (j.has("SSID")) { 280 config.SSID = "\"" + j.getString("SSID") + "\""; 281 } else if (j.has("ssid")) { 282 config.SSID = "\"" + j.getString("ssid") + "\""; 283 } 284 if (j.has("password")) { 285 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 286 config.preSharedKey = "\"" + j.getString("password") + "\""; 287 } else { 288 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 289 } 290 if (j.has("BSSID")) { 291 config.BSSID = j.getString("BSSID"); 292 } 293 if (j.has("hiddenSSID")) { 294 config.hiddenSSID = j.getBoolean("hiddenSSID"); 295 } 296 if (j.has("priority")) { 297 config.priority = j.getInt("priority"); 298 } 299 if (j.has("apBand")) { 300 config.apBand = j.getInt("apBand"); 301 } 302 if (j.has("preSharedKey")) { 303 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); 304 config.preSharedKey = j.getString("preSharedKey"); 305 } 306 if (j.has("wepKeys")) { 307 // Looks like we only support static WEP. 308 config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); 309 config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); 310 config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); 311 JSONArray keys = j.getJSONArray("wepKeys"); 312 String[] wepKeys = new String[keys.length()]; 313 for (int i = 0; i < keys.length(); i++) { 314 wepKeys[i] = keys.getString(i); 315 } 316 config.wepKeys = wepKeys; 317 } 318 if (j.has("wepTxKeyIndex")) { 319 config.wepTxKeyIndex = j.getInt("wepTxKeyIndex"); 320 } 321 return config; 322 } 323 324 private WifiConfiguration genWifiEnterpriseConfig(JSONObject j) throws JSONException, 325 GeneralSecurityException { 326 if (j == null) { 327 return null; 328 } 329 WifiConfiguration config = new WifiConfiguration(); 330 config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); 331 config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); 332 if (j.has("SSID")) { 333 config.SSID = j.getString("SSID"); 334 } 335 if (j.has("FQDN")) { 336 config.FQDN = j.getString("FQDN"); 337 } 338 if (j.has("providerFriendlyName")) { 339 config.providerFriendlyName = j.getString("providerFriendlyName"); 340 } 341 if (j.has("roamingConsortiumIds")) { 342 JSONArray ids = j.getJSONArray("roamingConsortiumIds"); 343 long[] rIds = new long[ids.length()]; 344 for (int i = 0; i < ids.length(); i++) { 345 rIds[i] = ids.getLong(i); 346 } 347 config.roamingConsortiumIds = rIds; 348 } 349 WifiEnterpriseConfig eConfig = new WifiEnterpriseConfig(); 350 if (j.has(WifiEnterpriseConfig.EAP_KEY)) { 351 int eap = j.getInt(WifiEnterpriseConfig.EAP_KEY); 352 eConfig.setEapMethod(eap); 353 } 354 if (j.has(WifiEnterpriseConfig.PHASE2_KEY)) { 355 int p2Method = j.getInt(WifiEnterpriseConfig.PHASE2_KEY); 356 eConfig.setPhase2Method(p2Method); 357 } 358 if (j.has(WifiEnterpriseConfig.CA_CERT_KEY)) { 359 String certStr = j.getString(WifiEnterpriseConfig.CA_CERT_KEY); 360 Log.v("CA Cert String is " + certStr); 361 eConfig.setCaCertificate(strToX509Cert(certStr)); 362 } 363 if (j.has(WifiEnterpriseConfig.CLIENT_CERT_KEY) 364 && j.has(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)) { 365 String certStr = j.getString(WifiEnterpriseConfig.CLIENT_CERT_KEY); 366 String keyStr = j.getString(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY); 367 Log.v("Client Cert String is " + certStr); 368 Log.v("Client Key String is " + keyStr); 369 X509Certificate cert = strToX509Cert(certStr); 370 PrivateKey privKey = strToPrivateKey(keyStr); 371 Log.v("Cert is " + cert); 372 Log.v("Private Key is " + privKey); 373 eConfig.setClientKeyEntry(privKey, cert); 374 } 375 if (j.has(WifiEnterpriseConfig.IDENTITY_KEY)) { 376 String identity = j.getString(WifiEnterpriseConfig.IDENTITY_KEY); 377 Log.v("Setting identity to " + identity); 378 eConfig.setIdentity(identity); 379 } 380 if (j.has(WifiEnterpriseConfig.PASSWORD_KEY)) { 381 String pwd = j.getString(WifiEnterpriseConfig.PASSWORD_KEY); 382 Log.v("Setting password to " + pwd); 383 eConfig.setPassword(pwd); 384 } 385 if (j.has(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)) { 386 String altSub = j.getString(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY); 387 Log.v("Setting Alt Subject to " + altSub); 388 eConfig.setAltSubjectMatch(altSub); 389 } 390 if (j.has(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)) { 391 String domSuffix = j.getString(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY); 392 Log.v("Setting Domain Suffix Match to " + domSuffix); 393 eConfig.setDomainSuffixMatch(domSuffix); 394 } 395 if (j.has(WifiEnterpriseConfig.REALM_KEY)) { 396 String realm = j.getString(WifiEnterpriseConfig.REALM_KEY); 397 Log.v("Setting Domain Suffix Match to " + realm); 398 eConfig.setRealm(realm); 399 } 400 config.enterpriseConfig = eConfig; 401 return config; 402 } 403 404 private boolean matchScanResult(ScanResult result, String id) { 405 if (result.BSSID.equals(id) || result.SSID.equals(id)) { 406 return true; 407 } 408 return false; 409 } 410 411 private WpsInfo parseWpsInfo(String infoStr) throws JSONException { 412 if (infoStr == null) { 413 return null; 414 } 415 JSONObject j = new JSONObject(infoStr); 416 WpsInfo info = new WpsInfo(); 417 if (j.has("setup")) { 418 info.setup = j.getInt("setup"); 419 } 420 if (j.has("BSSID")) { 421 info.BSSID = j.getString("BSSID"); 422 } 423 if (j.has("pin")) { 424 info.pin = j.getString("pin"); 425 } 426 return info; 427 } 428 429 private byte[] base64StrToBytes(String input) { 430 return Base64.decode(input, Base64.DEFAULT); 431 } 432 433 private X509Certificate strToX509Cert(String certStr) throws CertificateException { 434 byte[] certBytes = base64StrToBytes(certStr); 435 InputStream certStream = new ByteArrayInputStream(certBytes); 436 CertificateFactory cf = CertificateFactory.getInstance("X509"); 437 return (X509Certificate) cf.generateCertificate(certStream); 438 } 439 440 private PrivateKey strToPrivateKey(String key) throws NoSuchAlgorithmException, 441 InvalidKeySpecException { 442 byte[] keyBytes = base64StrToBytes(key); 443 PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); 444 KeyFactory fact = KeyFactory.getInstance("RSA"); 445 PrivateKey priv = fact.generatePrivate(keySpec); 446 return priv; 447 } 448 449 private PublicKey strToPublicKey(String key) throws NoSuchAlgorithmException, 450 InvalidKeySpecException { 451 byte[] keyBytes = base64StrToBytes(key); 452 X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); 453 KeyFactory fact = KeyFactory.getInstance("RSA"); 454 PublicKey pub = fact.generatePublic(keySpec); 455 return pub; 456 } 457 458 private WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) { 459 if (result == null) 460 return null; 461 WifiConfiguration config = new WifiConfiguration(); 462 config.SSID = "\"" + result.SSID + "\""; 463 applyingkeyMgmt(config, result); 464 config.BSSID = result.BSSID; 465 return config; 466 } 467 468 @Rpc(description = "test.") 469 public String wifiTest( 470 @RpcParameter(name = "certString") String certString) throws CertificateException, IOException { 471 // TODO(angli): Make this work. Convert a X509Certificate back to a string. 472 X509Certificate caCert = strToX509Cert(certString); 473 caCert.getEncoded(); 474 ByteArrayOutputStream bos = new ByteArrayOutputStream(); 475 ObjectOutput out = new ObjectOutputStream(bos); 476 out.writeObject(caCert); 477 byte[] data = bos.toByteArray(); 478 bos.close(); 479 return Base64.encodeToString(data, Base64.DEFAULT); 480 } 481 482 @Rpc(description = "Add a network.") 483 public Integer wifiAddNetwork(@RpcParameter(name = "wifiConfig") JSONObject wifiConfig) 484 throws JSONException { 485 return mWifi.addNetwork(genWifiConfig(wifiConfig)); 486 } 487 488 @Rpc(description = "Builds a WifiConfiguration from Hotspot 2.0 MIME file.") 489 public WifiConfiguration wifiBuildConfig( 490 @RpcParameter(name = "uriString") String uriString, 491 @RpcParameter(name = "mimeType") String mimeType, 492 String dataString) 493 throws JSONException { 494 byte[] data = base64StrToBytes(dataString); 495 return mWifi.buildWifiConfig(uriString, mimeType, data); 496 } 497 498 @Rpc(description = "Cancel Wi-fi Protected Setup.") 499 public void wifiCancelWps() throws JSONException { 500 WifiWpsCallback listener = new WifiWpsCallback(); 501 mWifi.cancelWps(listener); 502 } 503 504 @Rpc(description = "Checks Wifi state.", returns = "True if Wifi is enabled.") 505 public Boolean wifiCheckState() { 506 return mWifi.getWifiState() == WifiManager.WIFI_STATE_ENABLED; 507 } 508 509 /** 510 * Connects to a WPA protected wifi network 511 * 512 * @param wifiSSID SSID of the wifi network 513 * @param wifiPassword password for the wifi network 514 * @return true on success 515 * @throws ConnectException 516 * @throws JSONException 517 */ 518 @Rpc(description = "Connects a wifi network by ssid", returns = "True if the operation succeeded.") 519 public Boolean wifiConnect(@RpcParameter(name = "config") JSONObject config) 520 throws ConnectException, JSONException { 521 WifiConfiguration wifiConfig = genWifiConfig(config); 522 int nId = mWifi.addNetwork(wifiConfig); 523 if (nId < 0) { 524 Log.e("Got negative network Id."); 525 return false; 526 } 527 if (!mWifi.enableNetwork(nId, true)) { 528 Log.e("Failed to enable wifi network."); 529 return false; 530 } 531 return mWifi.reconnect(); 532 } 533 534 @Rpc(description = "Disconnects from the currently active access point.", returns = "True if the operation succeeded.") 535 public Boolean wifiDisconnect() { 536 return mWifi.disconnect(); 537 } 538 539 @Rpc(description = "Enable/disable autojoin scan and switch network when connected.") 540 public Boolean wifiSetEnableAutoJoinWhenAssociated(@RpcParameter(name = "enable") Boolean enable) { 541 return mWifi.setEnableAutoJoinWhenAssociated(enable); 542 } 543 544 @Rpc(description = "Enable a configured network. Initiate a connection if disableOthers is true", returns = "True if the operation succeeded.") 545 public Boolean wifiEnableNetwork(@RpcParameter(name = "netId") Integer netId, 546 @RpcParameter(name = "disableOthers") Boolean disableOthers) { 547 return mWifi.enableNetwork(netId, disableOthers); 548 } 549 550 @Rpc(description = "Enable WiFi verbose logging.") 551 public void wifiEnableVerboseLogging(@RpcParameter(name = "level") Integer level) { 552 mWifi.enableVerboseLogging(level); 553 } 554 555 @Rpc(description = "Connect to a wifi network that uses Enterprise authentication methods.") 556 public Boolean wifiEnterpriseConnect(@RpcParameter(name = "config") JSONObject config) 557 throws JSONException, GeneralSecurityException { 558 // Create Certificate 559 WifiActionListener listener = new WifiActionListener(mEventFacade, "EnterpriseConnect"); 560 WifiConfiguration wifiConfig = genWifiEnterpriseConfig(config); 561 if (wifiConfig.isPasspoint()) { 562 Log.d("Got a passpoint config, add it and save config."); 563 if (mWifi.addNetwork(wifiConfig) == -1) { 564 Log.e("Failed to add a wifi network"); 565 return false; 566 } 567 return mWifi.saveConfiguration(); 568 } else { 569 Log.d("Got a non-passpoint enterprise config, connect directly."); 570 mWifi.connect(wifiConfig, listener); 571 return true; 572 } 573 } 574 575 @Rpc(description = "Resets all WifiManager settings.") 576 public void wifiFactoryReset() { 577 mWifi.factoryReset(); 578 } 579 580 /** 581 * Forget a wifi network with priority 582 * 583 * @param networkID Id of wifi network 584 */ 585 @Rpc(description = "Forget a wifi network with priority") 586 public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer newtorkId) { 587 WifiActionListener listener = new WifiActionListener(mEventFacade, "ForgetNetwork"); 588 mWifi.forget(newtorkId, listener); 589 } 590 591 @Rpc(description = "Gets the Wi-Fi AP Configuration.") 592 public WifiConfiguration wifiGetApConfiguration() { 593 return mWifi.getWifiApConfiguration(); 594 } 595 596 @Rpc(description = "Returns the file in which IP and proxy configuration data is stored.") 597 public String wifiGetConfigFile() { 598 return mWifi.getConfigFile(); 599 } 600 601 @Rpc(description = "Return a list of all the configured wifi networks.") 602 public List<WifiConfiguration> wifiGetConfiguredNetworks() { 603 return mWifi.getConfiguredNetworks(); 604 } 605 606 @Rpc(description = "Returns information about the currently active access point.") 607 public WifiInfo wifiGetConnectionInfo() { 608 return mWifi.getConnectionInfo(); 609 } 610 611 @Rpc(description = "Returns wifi activity and energy usage info.") 612 public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() { 613 return mWifi.getControllerActivityEnergyInfo(0); 614 } 615 616 @Rpc(description = "Get the country code used by WiFi.") 617 public String wifiGetCountryCode() { 618 return mWifi.getCountryCode(); 619 } 620 621 @Rpc(description = "Get the current network.") 622 public Network wifiGetCurrentNetwork() { 623 return mWifi.getCurrentNetwork(); 624 } 625 626 @Rpc(description = "Get the info from last successful DHCP request.") 627 public DhcpInfo wifiGetDhcpInfo() { 628 return mWifi.getDhcpInfo(); 629 } 630 631 @Rpc(description = "Get setting for Framework layer autojoin enable status.") 632 public Boolean wifiGetEnableAutoJoinWhenAssociated() { 633 return mWifi.getEnableAutoJoinWhenAssociated(); 634 } 635 636 @Rpc(description = "Get privileged configured networks.") 637 public List<WifiConfiguration> wifiGetPrivilegedConfiguredNetworks() { 638 return mWifi.getPrivilegedConfiguredNetworks(); 639 } 640 641 @Rpc(description = "Returns the list of access points found during the most recent Wifi scan.") 642 public List<ScanResult> wifiGetScanResults() { 643 return mWifi.getScanResults(); 644 } 645 646 @Rpc(description = "Get the current level of WiFi verbose logging.") 647 public Integer wifiGetVerboseLoggingLevel() { 648 return mWifi.getVerboseLoggingLevel(); 649 } 650 651 @Rpc(description = "true if this adapter supports 5 GHz band.") 652 public Boolean wifiIs5GHzBandSupported() { 653 return mWifi.is5GHzBandSupported(); 654 } 655 656 @Rpc(description = "true if this adapter supports multiple simultaneous connections.") 657 public Boolean wifiIsAdditionalStaSupported() { 658 return mWifi.isAdditionalStaSupported(); 659 } 660 661 @Rpc(description = "Return whether Wi-Fi AP is enabled or disabled.") 662 public Boolean wifiIsApEnabled() { 663 return mWifi.isWifiApEnabled(); 664 } 665 666 @Rpc(description = "Check if Device-to-AP RTT is supported.") 667 public Boolean wifiIsDeviceToApRttSupported() { 668 return mWifi.isDeviceToApRttSupported(); 669 } 670 671 @Rpc(description = "Check if Device-to-device RTT is supported.") 672 public Boolean wifiIsDeviceToDeviceRttSupported() { 673 return mWifi.isDeviceToDeviceRttSupported(); 674 } 675 676 @Rpc(description = "Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz).") 677 public Boolean wifiIsDualBandSupported() { 678 return mWifi.isDualBandSupported(); 679 } 680 681 @Rpc(description = "Check if this adapter supports advanced power/performance counters.") 682 public Boolean wifiIsEnhancedPowerReportingSupported() { 683 return mWifi.isEnhancedPowerReportingSupported(); 684 } 685 686 @Rpc(description = "Check if multicast is enabled.") 687 public Boolean wifiIsMulticastEnabled() { 688 return mWifi.isMulticastEnabled(); 689 } 690 691 @Rpc(description = "true if this adapter supports Neighbour Awareness Network APIs.") 692 public Boolean wifiIsNanSupported() { 693 return mWifi.isNanSupported(); 694 } 695 696 @Rpc(description = "true if this adapter supports Off Channel Tunnel Directed Link Setup.") 697 public Boolean wifiIsOffChannelTdlsSupported() { 698 return mWifi.isOffChannelTdlsSupported(); 699 } 700 701 @Rpc(description = "true if this adapter supports WifiP2pManager (Wi-Fi Direct).") 702 public Boolean wifiIsP2pSupported() { 703 return mWifi.isP2pSupported(); 704 } 705 706 @Rpc(description = "true if this adapter supports passpoint.") 707 public Boolean wifiIsPasspointSupported() { 708 return mWifi.isPasspointSupported(); 709 } 710 711 @Rpc(description = "true if this adapter supports portable Wi-Fi hotspot.") 712 public Boolean wifiIsPortableHotspotSupported() { 713 return mWifi.isPortableHotspotSupported(); 714 } 715 716 @Rpc(description = "true if this adapter supports offloaded connectivity scan.") 717 public Boolean wifiIsPreferredNetworkOffloadSupported() { 718 return mWifi.isPreferredNetworkOffloadSupported(); 719 } 720 721 @Rpc(description = "Check if wifi scanner is supported on this device.") 722 public Boolean wifiIsScannerSupported() { 723 return mWifi.isWifiScannerSupported(); 724 } 725 726 @Rpc(description = "Check if tdls is supported on this device.") 727 public Boolean wifiIsTdlsSupported() { 728 return mWifi.isTdlsSupported(); 729 } 730 731 @Rpc(description = "Acquires a full Wifi lock.") 732 public void wifiLockAcquireFull() { 733 makeLock(WifiManager.WIFI_MODE_FULL); 734 } 735 736 @Rpc(description = "Acquires a scan only Wifi lock.") 737 public void wifiLockAcquireScanOnly() { 738 makeLock(WifiManager.WIFI_MODE_SCAN_ONLY); 739 } 740 741 @Rpc(description = "Releases a previously acquired Wifi lock.") 742 public void wifiLockRelease() { 743 if (mLock != null) { 744 mLock.release(); 745 mLock = null; 746 } 747 } 748 749 /** 750 * Connects to a wifi network with priority 751 * 752 * @param wifiSSID SSID of the wifi network 753 * @param wifiPassword password for the wifi network 754 * @throws JSONException 755 */ 756 @Rpc(description = "Connects a wifi network as priority by pasing ssid") 757 public void wifiPriorityConnect(@RpcParameter(name = "config") JSONObject config) 758 throws JSONException { 759 WifiConfiguration wifiConfig = genWifiConfig(config); 760 WifiActionListener listener = new WifiActionListener(mEventFacade, "PriorityConnect"); 761 mWifi.connect(wifiConfig, listener); 762 } 763 764 @Rpc(description = "Reassociates with the currently active access point.", returns = "True if the operation succeeded.") 765 public Boolean wifiReassociate() { 766 return mWifi.reassociate(); 767 } 768 769 @Rpc(description = "Reconnects to the currently active access point.", returns = "True if the operation succeeded.") 770 public Boolean wifiReconnect() { 771 return mWifi.reconnect(); 772 } 773 774 @Rpc(description = "Remove a configured network.", returns = "True if the operation succeeded.") 775 public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) { 776 return mWifi.removeNetwork(netId); 777 } 778 779 private WifiConfiguration createSoftApWifiConfiguration(JSONObject configJson) 780 throws JSONException { 781 WifiConfiguration config = genWifiConfig(configJson); 782 // Need to strip of extra quotation marks for SSID and password. 783 String ssid = config.SSID; 784 if (ssid != null) { 785 config.SSID = ssid.substring(1, ssid.length() - 1); 786 } 787 String pwd = config.preSharedKey; 788 if (pwd != null) { 789 config.preSharedKey = pwd.substring(1, pwd.length() - 1); 790 } 791 return config; 792 } 793 794 @Rpc(description = "Set configuration for soft AP.") 795 public Boolean wifiSetWifiApConfiguration( 796 @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { 797 WifiConfiguration config = createSoftApWifiConfiguration(configJson); 798 return mWifi.setWifiApConfiguration(config); 799 } 800 801 @Rpc(description = "Start/stop wifi soft AP.") 802 public Boolean wifiSetApEnabled( 803 @RpcParameter(name = "enable") Boolean enable, 804 @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { 805 int wifiState = mWifi.getWifiState(); 806 if (enable) { 807 WifiConfiguration config = createSoftApWifiConfiguration(configJson); 808 return mWifi.setWifiApEnabled(config, enable); 809 } else { 810 return mWifi.setWifiApEnabled(null, false); 811 } 812 } 813 814 @Rpc(description = "Set the country code used by WiFi.") 815 public void wifiSetCountryCode( 816 @RpcParameter(name = "country") String country, 817 @RpcParameter(name = "persist") Boolean persist) { 818 mWifi.setCountryCode(country, persist); 819 } 820 821 @Rpc(description = "Enable/disable tdls with a mac address.") 822 public void wifiSetTdlsEnabledWithMacAddress( 823 @RpcParameter(name = "remoteMacAddress") String remoteMacAddress, 824 @RpcParameter(name = "enable") Boolean enable) { 825 mWifi.setTdlsEnabledWithMacAddress(remoteMacAddress, enable); 826 } 827 828 @Rpc(description = "Starts a scan for Wifi access points.", returns = "True if the scan was initiated successfully.") 829 public Boolean wifiStartScan() { 830 mService.registerReceiver(mScanResultsAvailableReceiver, mScanFilter); 831 return mWifi.startScan(); 832 } 833 834 @Rpc(description = "Start Wi-fi Protected Setup.") 835 public void wifiStartWps( 836 @RpcParameter(name = "config", description = "A json string with fields \"setup\", \"BSSID\", and \"pin\"") String config) 837 throws JSONException { 838 WpsInfo info = parseWpsInfo(config); 839 WifiWpsCallback listener = new WifiWpsCallback(); 840 Log.d("Starting wps with: " + info); 841 mWifi.startWps(info, listener); 842 } 843 844 @Rpc(description = "Start listening for wifi state change related broadcasts.") 845 public void wifiStartTrackingStateChange() { 846 mService.registerReceiver(mStateChangeReceiver, mStateChangeFilter); 847 mTrackingWifiStateChange = true; 848 } 849 850 @Rpc(description = "Stop listening for wifi state change related broadcasts.") 851 public void wifiStopTrackingStateChange() { 852 if (mTrackingWifiStateChange == true) { 853 mService.unregisterReceiver(mStateChangeReceiver); 854 mTrackingWifiStateChange = false; 855 } 856 } 857 858 @Rpc(description = "Start listening for tether state change related broadcasts.") 859 public void wifiStartTrackingTetherStateChange() { 860 mService.registerReceiver(mTetherStateReceiver, mTetherFilter); 861 mTrackingTetherStateChange = true; 862 } 863 864 @Rpc(description = "Stop listening for wifi state change related broadcasts.") 865 public void wifiStopTrackingTetherStateChange() { 866 if (mTrackingTetherStateChange == true) { 867 mService.unregisterReceiver(mTetherStateReceiver); 868 mTrackingTetherStateChange = false; 869 } 870 } 871 872 @Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.") 873 public Boolean wifiToggleState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) { 874 if (enabled == null) { 875 enabled = !wifiCheckState(); 876 } 877 mWifi.setWifiEnabled(enabled); 878 return enabled; 879 } 880 881 @Rpc(description = "Toggle Wifi scan always available on and off.", returns = "True if Wifi scan is always available.") 882 public Boolean wifiToggleScanAlwaysAvailable( 883 @RpcParameter(name = "enabled") @RpcOptional Boolean enabled) 884 throws SettingNotFoundException { 885 ContentResolver cr = mService.getContentResolver(); 886 int isSet = 0; 887 if (enabled == null) { 888 isSet = Global.getInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE); 889 isSet ^= 1; 890 } else if (enabled == true) { 891 isSet = 1; 892 } 893 Global.putInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE, isSet); 894 if (isSet == 1) { 895 return true; 896 } 897 return false; 898 } 899 900 @Rpc(description = "Enable/disable WifiConnectivityManager.") 901 public void wifiEnableWifiConnectivityManager( 902 @RpcParameter(name = "enable") Boolean enable) { 903 mWifi.enableWifiConnectivityManager(enable); 904 } 905 906 @Override 907 public void shutdown() { 908 wifiLockRelease(); 909 if (mTrackingWifiStateChange == true) { 910 wifiStopTrackingStateChange(); 911 } 912 if (mTrackingTetherStateChange == true) { 913 wifiStopTrackingTetherStateChange(); 914 } 915 } 916} 917