1 2 package com.googlecode.android_scripting.facade.wifi; 3 4 import android.app.Service; 5 import android.content.BroadcastReceiver; 6 import android.content.ContentResolver; 7 import android.content.Context; 8 import android.content.Intent; 9 import android.content.IntentFilter; 10 import android.net.ConnectivityManager; 11 import android.net.DhcpInfo; 12 import android.net.Network; 13 import android.net.NetworkInfo; 14 import android.net.NetworkInfo.DetailedState; 15 import android.net.wifi.ScanResult; 16 import android.net.wifi.WifiActivityEnergyInfo; 17 import android.net.wifi.WifiConfiguration; 18 import android.net.wifi.WifiConfiguration.AuthAlgorithm; 19 import android.net.wifi.WifiConfiguration.KeyMgmt; 20 import android.net.wifi.WifiEnterpriseConfig; 21 import android.net.wifi.WifiInfo; 22 import android.net.wifi.WifiManager; 23 import android.net.wifi.WifiManager.WifiLock; 24 import android.net.wifi.WpsInfo; 25 import android.os.Bundle; 26 import android.provider.Settings.Global; 27 import android.provider.Settings.SettingNotFoundException; 28 import android.util.Base64; 29 30 import com.googlecode.android_scripting.Log; 31 import com.googlecode.android_scripting.facade.EventFacade; 32 import com.googlecode.android_scripting.facade.FacadeManager; 33 import com.googlecode.android_scripting.jsonrpc.RpcReceiver; 34 import com.googlecode.android_scripting.rpc.Rpc; 35 import com.googlecode.android_scripting.rpc.RpcOptional; 36 import com.googlecode.android_scripting.rpc.RpcParameter; 37 38 import org.json.JSONArray; 39 import org.json.JSONException; 40 import org.json.JSONObject; 41 42 import java.io.ByteArrayInputStream; 43 import java.io.ByteArrayOutputStream; 44 import java.io.IOException; 45 import java.io.InputStream; 46 import java.io.ObjectOutput; 47 import java.io.ObjectOutputStream; 48 import java.net.ConnectException; 49 import java.security.GeneralSecurityException; 50 import java.security.KeyFactory; 51 import java.security.NoSuchAlgorithmException; 52 import java.security.PrivateKey; 53 import java.security.PublicKey; 54 import java.security.cert.CertificateException; 55 import java.security.cert.CertificateFactory; 56 import java.security.cert.X509Certificate; 57 import java.security.spec.InvalidKeySpecException; 58 import java.security.spec.PKCS8EncodedKeySpec; 59 import java.security.spec.X509EncodedKeySpec; 60 import java.util.ArrayList; 61 import 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 69 public 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 mWifi.enableNetwork(nId, true); 528 return mWifi.reconnect(); 529 } 530 531 @Rpc(description = "Disconnects from the currently active access point.", returns = "True if the operation succeeded.") 532 public Boolean wifiDisconnect() { 533 return mWifi.disconnect(); 534 } 535 536 @Rpc(description = "Enable/disable autojoin scan and switch network when connected.") 537 public Boolean wifiSetEnableAutoJoinWhenAssociated(@RpcParameter(name = "enable") Boolean enable) { 538 return mWifi.setEnableAutoJoinWhenAssociated(enable); 539 } 540 541 @Rpc(description = "Enable a configured network. Initiate a connection if disableOthers is true", returns = "True if the operation succeeded.") 542 public Boolean wifiEnableNetwork(@RpcParameter(name = "netId") Integer netId, 543 @RpcParameter(name = "disableOthers") Boolean disableOthers) { 544 return mWifi.enableNetwork(netId, disableOthers); 545 } 546 547 @Rpc(description = "Enable WiFi verbose logging.") 548 public void wifiEnableVerboseLogging(@RpcParameter(name = "level") Integer level) { 549 mWifi.enableVerboseLogging(level); 550 } 551 552 @Rpc(description = "Connect to a wifi network that uses Enterprise authentication methods.") 553 public void wifiEnterpriseConnect(@RpcParameter(name = "config") JSONObject config) 554 throws JSONException, GeneralSecurityException { 555 // Create Certificate 556 WifiActionListener listener = new WifiActionListener(mEventFacade, "EnterpriseConnect"); 557 WifiConfiguration wifiConfig = genWifiEnterpriseConfig(config); 558 if (wifiConfig.isPasspoint()) { 559 Log.d("Got a passpoint config, add it and save config."); 560 mWifi.addNetwork(wifiConfig); 561 mWifi.saveConfiguration(); 562 } else { 563 Log.d("Got a non-passpoint enterprise config, connect directly."); 564 mWifi.connect(wifiConfig, listener); 565 } 566 } 567 568 @Rpc(description = "Resets all WifiManager settings.") 569 public void wifiFactoryReset() { 570 mWifi.factoryReset(); 571 } 572 573 /** 574 * Forget a wifi network with priority 575 * 576 * @param networkID Id of wifi network 577 */ 578 @Rpc(description = "Forget a wifi network with priority") 579 public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer newtorkId) { 580 WifiActionListener listener = new WifiActionListener(mEventFacade, "ForgetNetwork"); 581 mWifi.forget(newtorkId, listener); 582 } 583 584 @Rpc(description = "Gets the Wi-Fi AP Configuration.") 585 public WifiConfiguration wifiGetApConfiguration() { 586 return mWifi.getWifiApConfiguration(); 587 } 588 589 @Rpc(description = "Returns the file in which IP and proxy configuration data is stored.") 590 public String wifiGetConfigFile() { 591 return mWifi.getConfigFile(); 592 } 593 594 @Rpc(description = "Return a list of all the configured wifi networks.") 595 public List<WifiConfiguration> wifiGetConfiguredNetworks() { 596 return mWifi.getConfiguredNetworks(); 597 } 598 599 @Rpc(description = "Returns information about the currently active access point.") 600 public WifiInfo wifiGetConnectionInfo() { 601 return mWifi.getConnectionInfo(); 602 } 603 604 @Rpc(description = "Returns wifi activity and energy usage info.") 605 public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() { 606 return mWifi.getControllerActivityEnergyInfo(0); 607 } 608 609 @Rpc(description = "Get the country code used by WiFi.") 610 public String wifiGetCountryCode() { 611 return mWifi.getCountryCode(); 612 } 613 614 @Rpc(description = "Get the current network.") 615 public Network wifiGetCurrentNetwork() { 616 return mWifi.getCurrentNetwork(); 617 } 618 619 @Rpc(description = "Get the info from last successful DHCP request.") 620 public DhcpInfo wifiGetDhcpInfo() { 621 return mWifi.getDhcpInfo(); 622 } 623 624 @Rpc(description = "Get setting for Framework layer autojoin enable status.") 625 public Boolean wifiGetEnableAutoJoinWhenAssociated() { 626 return mWifi.getEnableAutoJoinWhenAssociated(); 627 } 628 629 @Rpc(description = "Get privileged configured networks.") 630 public List<WifiConfiguration> wifiGetPrivilegedConfiguredNetworks() { 631 return mWifi.getPrivilegedConfiguredNetworks(); 632 } 633 634 @Rpc(description = "Returns the list of access points found during the most recent Wifi scan.") 635 public List<ScanResult> wifiGetScanResults() { 636 return mWifi.getScanResults(); 637 } 638 639 @Rpc(description = "Get the current level of WiFi verbose logging.") 640 public Integer wifiGetVerboseLoggingLevel() { 641 return mWifi.getVerboseLoggingLevel(); 642 } 643 644 @Rpc(description = "true if this adapter supports 5 GHz band.") 645 public Boolean wifiIs5GHzBandSupported() { 646 return mWifi.is5GHzBandSupported(); 647 } 648 649 @Rpc(description = "true if this adapter supports multiple simultaneous connections.") 650 public Boolean wifiIsAdditionalStaSupported() { 651 return mWifi.isAdditionalStaSupported(); 652 } 653 654 @Rpc(description = "Return whether Wi-Fi AP is enabled or disabled.") 655 public Boolean wifiIsApEnabled() { 656 return mWifi.isWifiApEnabled(); 657 } 658 659 @Rpc(description = "Check if Device-to-AP RTT is supported.") 660 public Boolean wifiIsDeviceToApRttSupported() { 661 return mWifi.isDeviceToApRttSupported(); 662 } 663 664 @Rpc(description = "Check if Device-to-device RTT is supported.") 665 public Boolean wifiIsDeviceToDeviceRttSupported() { 666 return mWifi.isDeviceToDeviceRttSupported(); 667 } 668 669 @Rpc(description = "Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz).") 670 public Boolean wifiIsDualBandSupported() { 671 return mWifi.isDualBandSupported(); 672 } 673 674 @Rpc(description = "Check if this adapter supports advanced power/performance counters.") 675 public Boolean wifiIsEnhancedPowerReportingSupported() { 676 return mWifi.isEnhancedPowerReportingSupported(); 677 } 678 679 @Rpc(description = "Check if multicast is enabled.") 680 public Boolean wifiIsMulticastEnabled() { 681 return mWifi.isMulticastEnabled(); 682 } 683 684 @Rpc(description = "true if this adapter supports Neighbour Awareness Network APIs.") 685 public Boolean wifiIsNanSupported() { 686 return mWifi.isNanSupported(); 687 } 688 689 @Rpc(description = "true if this adapter supports Off Channel Tunnel Directed Link Setup.") 690 public Boolean wifiIsOffChannelTdlsSupported() { 691 return mWifi.isOffChannelTdlsSupported(); 692 } 693 694 @Rpc(description = "true if this adapter supports WifiP2pManager (Wi-Fi Direct).") 695 public Boolean wifiIsP2pSupported() { 696 return mWifi.isP2pSupported(); 697 } 698 699 @Rpc(description = "true if this adapter supports passpoint.") 700 public Boolean wifiIsPasspointSupported() { 701 return mWifi.isPasspointSupported(); 702 } 703 704 @Rpc(description = "true if this adapter supports portable Wi-Fi hotspot.") 705 public Boolean wifiIsPortableHotspotSupported() { 706 return mWifi.isPortableHotspotSupported(); 707 } 708 709 @Rpc(description = "true if this adapter supports offloaded connectivity scan.") 710 public Boolean wifiIsPreferredNetworkOffloadSupported() { 711 return mWifi.isPreferredNetworkOffloadSupported(); 712 } 713 714 @Rpc(description = "Check if wifi scanner is supported on this device.") 715 public Boolean wifiIsScannerSupported() { 716 return mWifi.isWifiScannerSupported(); 717 } 718 719 @Rpc(description = "Check if tdls is supported on this device.") 720 public Boolean wifiIsTdlsSupported() { 721 return mWifi.isTdlsSupported(); 722 } 723 724 @Rpc(description = "Acquires a full Wifi lock.") 725 public void wifiLockAcquireFull() { 726 makeLock(WifiManager.WIFI_MODE_FULL); 727 } 728 729 @Rpc(description = "Acquires a scan only Wifi lock.") 730 public void wifiLockAcquireScanOnly() { 731 makeLock(WifiManager.WIFI_MODE_SCAN_ONLY); 732 } 733 734 @Rpc(description = "Releases a previously acquired Wifi lock.") 735 public void wifiLockRelease() { 736 if (mLock != null) { 737 mLock.release(); 738 mLock = null; 739 } 740 } 741 742 /** 743 * Connects to a wifi network with priority 744 * 745 * @param wifiSSID SSID of the wifi network 746 * @param wifiPassword password for the wifi network 747 * @throws JSONException 748 */ 749 @Rpc(description = "Connects a wifi network as priority by pasing ssid") 750 public void wifiPriorityConnect(@RpcParameter(name = "config") JSONObject config) 751 throws JSONException { 752 WifiConfiguration wifiConfig = genWifiConfig(config); 753 WifiActionListener listener = new WifiActionListener(mEventFacade, "PriorityConnect"); 754 mWifi.connect(wifiConfig, listener); 755 } 756 757 @Rpc(description = "Reassociates with the currently active access point.", returns = "True if the operation succeeded.") 758 public Boolean wifiReassociate() { 759 return mWifi.reassociate(); 760 } 761 762 @Rpc(description = "Reconnects to the currently active access point.", returns = "True if the operation succeeded.") 763 public Boolean wifiReconnect() { 764 return mWifi.reconnect(); 765 } 766 767 @Rpc(description = "Remove a configured network.", returns = "True if the operation succeeded.") 768 public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) { 769 return mWifi.removeNetwork(netId); 770 } 771 772 private WifiConfiguration createSoftApWifiConfiguration(JSONObject configJson) 773 throws JSONException { 774 WifiConfiguration config = genWifiConfig(configJson); 775 // Need to strip of extra quotation marks for SSID and password. 776 String ssid = config.SSID; 777 if (ssid != null) { 778 config.SSID = ssid.substring(1, ssid.length() - 1); 779 } 780 String pwd = config.preSharedKey; 781 if (pwd != null) { 782 config.preSharedKey = pwd.substring(1, pwd.length() - 1); 783 } 784 return config; 785 } 786 787 @Rpc(description = "Set configuration for soft AP.") 788 public Boolean wifiSetWifiApConfiguration( 789 @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { 790 WifiConfiguration config = createSoftApWifiConfiguration(configJson); 791 return mWifi.setWifiApConfiguration(config); 792 } 793 794 @Rpc(description = "Start/stop wifi soft AP.") 795 public Boolean wifiSetApEnabled( 796 @RpcParameter(name = "enable") Boolean enable, 797 @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { 798 int wifiState = mWifi.getWifiState(); 799 if (enable) { 800 WifiConfiguration config = createSoftApWifiConfiguration(configJson); 801 return mWifi.setWifiApEnabled(config, enable); 802 } else { 803 return mWifi.setWifiApEnabled(null, false); 804 } 805 } 806 807 @Rpc(description = "Set the country code used by WiFi.") 808 public void wifiSetCountryCode( 809 @RpcParameter(name = "country") String country, 810 @RpcParameter(name = "persist") Boolean persist) { 811 mWifi.setCountryCode(country, persist); 812 } 813 814 @Rpc(description = "Enable/disable tdls with a mac address.") 815 public void wifiSetTdlsEnabledWithMacAddress( 816 @RpcParameter(name = "remoteMacAddress") String remoteMacAddress, 817 @RpcParameter(name = "enable") Boolean enable) { 818 mWifi.setTdlsEnabledWithMacAddress(remoteMacAddress, enable); 819 } 820 821 @Rpc(description = "Starts a scan for Wifi access points.", returns = "True if the scan was initiated successfully.") 822 public Boolean wifiStartScan() { 823 mService.registerReceiver(mScanResultsAvailableReceiver, mScanFilter); 824 return mWifi.startScan(); 825 } 826 827 @Rpc(description = "Start Wi-fi Protected Setup.") 828 public void wifiStartWps( 829 @RpcParameter(name = "config", description = "A json string with fields \"setup\", \"BSSID\", and \"pin\"") String config) 830 throws JSONException { 831 WpsInfo info = parseWpsInfo(config); 832 WifiWpsCallback listener = new WifiWpsCallback(); 833 Log.d("Starting wps with: " + info); 834 mWifi.startWps(info, listener); 835 } 836 837 @Rpc(description = "Start listening for wifi state change related broadcasts.") 838 public void wifiStartTrackingStateChange() { 839 mService.registerReceiver(mStateChangeReceiver, mStateChangeFilter); 840 mTrackingWifiStateChange = true; 841 } 842 843 @Rpc(description = "Stop listening for wifi state change related broadcasts.") 844 public void wifiStopTrackingStateChange() { 845 if (mTrackingWifiStateChange == true) { 846 mService.unregisterReceiver(mStateChangeReceiver); 847 mTrackingWifiStateChange = false; 848 } 849 } 850 851 @Rpc(description = "Start listening for tether state change related broadcasts.") 852 public void wifiStartTrackingTetherStateChange() { 853 mService.registerReceiver(mTetherStateReceiver, mTetherFilter); 854 mTrackingTetherStateChange = true; 855 } 856 857 @Rpc(description = "Stop listening for wifi state change related broadcasts.") 858 public void wifiStopTrackingTetherStateChange() { 859 if (mTrackingTetherStateChange == true) { 860 mService.unregisterReceiver(mTetherStateReceiver); 861 mTrackingTetherStateChange = false; 862 } 863 } 864 865 @Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.") 866 public Boolean wifiToggleState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) { 867 if (enabled == null) { 868 enabled = !wifiCheckState(); 869 } 870 mWifi.setWifiEnabled(enabled); 871 return enabled; 872 } 873 874 @Rpc(description = "Toggle Wifi scan always available on and off.", returns = "True if Wifi scan is always available.") 875 public Boolean wifiToggleScanAlwaysAvailable( 876 @RpcParameter(name = "enabled") @RpcOptional Boolean enabled) 877 throws SettingNotFoundException { 878 ContentResolver cr = mService.getContentResolver(); 879 int isSet = 0; 880 if (enabled == null) { 881 isSet = Global.getInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE); 882 isSet ^= 1; 883 } else if (enabled == true) { 884 isSet = 1; 885 } 886 Global.putInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE, isSet); 887 if (isSet == 1) { 888 return true; 889 } 890 return false; 891 } 892 893 @Rpc(description = "Enable/disable WifiConnectivityManager.") 894 public void wifiEnableWifiConnectivityManager( 895 @RpcParameter(name = "enable") Boolean enable) { 896 mWifi.enableWifiConnectivityManager(enable); 897 } 898 899 @Override 900 public void shutdown() { 901 wifiLockRelease(); 902 if (mTrackingWifiStateChange == true) { 903 wifiStopTrackingStateChange(); 904 } 905 if (mTrackingTetherStateChange == true) { 906 wifiStopTrackingTetherStateChange(); 907 } 908 } 909 } 910