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