| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.googlecode.android_scripting.facade.wifi; |
| |
| import android.app.Service; |
| import android.content.BroadcastReceiver; |
| import android.content.ContentResolver; |
| import android.content.Context; |
| import android.content.Intent; |
| import android.content.IntentFilter; |
| import android.net.ConnectivityManager; |
| import android.net.DhcpInfo; |
| import android.net.Network; |
| import android.net.NetworkInfo; |
| import android.net.NetworkInfo.DetailedState; |
| import android.net.wifi.hotspot2.ConfigParser; |
| import android.net.wifi.hotspot2.PasspointConfiguration; |
| import android.net.wifi.ScanResult; |
| import android.net.wifi.WifiActivityEnergyInfo; |
| import android.net.wifi.WifiConfiguration; |
| import android.net.wifi.WifiConfiguration.AuthAlgorithm; |
| import android.net.wifi.WifiConfiguration.KeyMgmt; |
| import android.net.wifi.WifiEnterpriseConfig; |
| import android.net.wifi.WifiInfo; |
| import android.net.wifi.WifiManager; |
| import android.net.wifi.WifiManager.WifiLock; |
| import android.net.wifi.WpsInfo; |
| import android.os.Bundle; |
| import android.provider.Settings.Global; |
| import android.provider.Settings.SettingNotFoundException; |
| import android.util.Base64; |
| import java.util.Arrays; |
| |
| import com.googlecode.android_scripting.Log; |
| import com.googlecode.android_scripting.facade.EventFacade; |
| import com.googlecode.android_scripting.facade.FacadeManager; |
| import com.googlecode.android_scripting.jsonrpc.RpcReceiver; |
| import com.googlecode.android_scripting.rpc.Rpc; |
| import com.googlecode.android_scripting.rpc.RpcDeprecated; |
| import com.googlecode.android_scripting.rpc.RpcOptional; |
| import com.googlecode.android_scripting.rpc.RpcParameter; |
| |
| import org.json.JSONArray; |
| import org.json.JSONException; |
| import org.json.JSONObject; |
| |
| import java.io.ByteArrayInputStream; |
| import java.io.ByteArrayOutputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.ObjectOutput; |
| import java.io.ObjectOutputStream; |
| import java.security.GeneralSecurityException; |
| import java.security.KeyFactory; |
| import java.security.NoSuchAlgorithmException; |
| import java.security.PrivateKey; |
| import java.security.PublicKey; |
| import java.security.cert.CertificateException; |
| import java.security.cert.CertificateFactory; |
| import java.security.cert.X509Certificate; |
| import java.security.spec.InvalidKeySpecException; |
| import java.security.spec.PKCS8EncodedKeySpec; |
| import java.security.spec.X509EncodedKeySpec; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * WifiManager functions. |
| */ |
| // TODO: make methods handle various wifi states properly |
| // e.g. wifi connection result will be null when flight mode is on |
| public class WifiManagerFacade extends RpcReceiver { |
| private final static String mEventType = "WifiManager"; |
| // MIME type for passpoint config. |
| private final static String TYPE_WIFICONFIG = "application/x-wifi-config"; |
| private final Service mService; |
| private final WifiManager mWifi; |
| private final EventFacade mEventFacade; |
| |
| private final IntentFilter mScanFilter; |
| private final IntentFilter mStateChangeFilter; |
| private final IntentFilter mTetherFilter; |
| private final WifiScanReceiver mScanResultsAvailableReceiver; |
| private final WifiStateChangeReceiver mStateChangeReceiver; |
| private boolean mTrackingWifiStateChange; |
| private boolean mTrackingTetherStateChange; |
| |
| private final BroadcastReceiver mTetherStateReceiver = new BroadcastReceiver() { |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| if (WifiManager.WIFI_AP_STATE_CHANGED_ACTION.equals(action)) { |
| Log.d("Wifi AP state changed."); |
| int state = intent.getIntExtra(WifiManager.EXTRA_WIFI_AP_STATE, |
| WifiManager.WIFI_AP_STATE_FAILED); |
| if (state == WifiManager.WIFI_AP_STATE_ENABLED) { |
| mEventFacade.postEvent("WifiManagerApEnabled", null); |
| } else if (state == WifiManager.WIFI_AP_STATE_DISABLED) { |
| mEventFacade.postEvent("WifiManagerApDisabled", null); |
| } |
| } else if (ConnectivityManager.ACTION_TETHER_STATE_CHANGED.equals(action)) { |
| Log.d("Tether state changed."); |
| ArrayList<String> available = intent.getStringArrayListExtra( |
| ConnectivityManager.EXTRA_AVAILABLE_TETHER); |
| ArrayList<String> active = intent.getStringArrayListExtra( |
| ConnectivityManager.EXTRA_ACTIVE_TETHER); |
| ArrayList<String> errored = intent.getStringArrayListExtra( |
| ConnectivityManager.EXTRA_ERRORED_TETHER); |
| Bundle msg = new Bundle(); |
| msg.putStringArrayList("AVAILABLE_TETHER", available); |
| msg.putStringArrayList("ACTIVE_TETHER", active); |
| msg.putStringArrayList("ERRORED_TETHER", errored); |
| mEventFacade.postEvent("TetherStateChanged", msg); |
| } |
| } |
| }; |
| |
| private WifiLock mLock = null; |
| private boolean mIsConnected = false; |
| |
| public WifiManagerFacade(FacadeManager manager) { |
| super(manager); |
| mService = manager.getService(); |
| mWifi = (WifiManager) mService.getSystemService(Context.WIFI_SERVICE); |
| mEventFacade = manager.getReceiver(EventFacade.class); |
| |
| mScanFilter = new IntentFilter(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); |
| mStateChangeFilter = new IntentFilter(WifiManager.NETWORK_STATE_CHANGED_ACTION); |
| mStateChangeFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); |
| mStateChangeFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION); |
| mStateChangeFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY - 1); |
| |
| mTetherFilter = new IntentFilter(WifiManager.WIFI_AP_STATE_CHANGED_ACTION); |
| mTetherFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); |
| |
| mScanResultsAvailableReceiver = new WifiScanReceiver(mEventFacade); |
| mStateChangeReceiver = new WifiStateChangeReceiver(); |
| mTrackingWifiStateChange = false; |
| mTrackingTetherStateChange = false; |
| } |
| |
| private void makeLock(int wifiMode) { |
| if (mLock == null) { |
| mLock = mWifi.createWifiLock(wifiMode, "sl4a"); |
| mLock.acquire(); |
| } |
| } |
| |
| /** |
| * Handle Broadcast receiver for Scan Result |
| * |
| * @parm eventFacade Object of EventFacade |
| */ |
| class WifiScanReceiver extends BroadcastReceiver { |
| private final EventFacade mEventFacade; |
| |
| WifiScanReceiver(EventFacade eventFacade) { |
| mEventFacade = eventFacade; |
| } |
| |
| @Override |
| public void onReceive(Context c, Intent intent) { |
| String action = intent.getAction(); |
| if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { |
| Bundle mResults = new Bundle(); |
| Log.d("Wifi connection scan finished, results available."); |
| mResults.putLong("Timestamp", System.currentTimeMillis() / 1000); |
| mEventFacade.postEvent(mEventType + "ScanResultsAvailable", mResults); |
| mService.unregisterReceiver(mScanResultsAvailableReceiver); |
| } |
| } |
| } |
| |
| class WifiActionListener implements WifiManager.ActionListener { |
| private final EventFacade mEventFacade; |
| private final String TAG; |
| |
| public WifiActionListener(EventFacade eventFacade, String tag) { |
| mEventFacade = eventFacade; |
| this.TAG = tag; |
| } |
| |
| @Override |
| public void onSuccess() { |
| Log.d("WifiActionListener onSuccess called for " + mEventType + TAG + "OnSuccess"); |
| mEventFacade.postEvent(mEventType + TAG + "OnSuccess", null); |
| } |
| |
| @Override |
| public void onFailure(int reason) { |
| Log.d("WifiActionListener onFailure called for" + mEventType); |
| Bundle msg = new Bundle(); |
| msg.putInt("reason", reason); |
| mEventFacade.postEvent(mEventType + TAG + "OnFailure", msg); |
| } |
| } |
| |
| public class WifiStateChangeReceiver extends BroadcastReceiver { |
| String mCachedWifiInfo = ""; |
| |
| @Override |
| public void onReceive(Context context, Intent intent) { |
| String action = intent.getAction(); |
| if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { |
| Log.d("Wifi network state changed."); |
| NetworkInfo nInfo = intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO); |
| WifiInfo wInfo = intent.getParcelableExtra(WifiManager.EXTRA_WIFI_INFO); |
| Log.d("NetworkInfo " + nInfo); |
| Log.d("WifiInfo " + wInfo); |
| // If network info is of type wifi, send wifi events. |
| if (nInfo.getType() == ConnectivityManager.TYPE_WIFI) { |
| if (wInfo != null && nInfo.getDetailedState().equals(DetailedState.CONNECTED)) { |
| String bssid = wInfo.getBSSID(); |
| if (bssid != null && !mCachedWifiInfo.equals(wInfo.toString())) { |
| Log.d("WifiNetworkConnected"); |
| mEventFacade.postEvent("WifiNetworkConnected", wInfo); |
| } |
| mCachedWifiInfo = wInfo.toString(); |
| } else { |
| if (nInfo.getDetailedState().equals(DetailedState.DISCONNECTED)) { |
| if (!mCachedWifiInfo.equals("")) { |
| mCachedWifiInfo = ""; |
| mEventFacade.postEvent("WifiNetworkDisconnected", null); |
| } |
| } |
| } |
| } |
| } else if (action.equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { |
| Log.d("Supplicant connection state changed."); |
| mIsConnected = intent |
| .getBooleanExtra(WifiManager.EXTRA_SUPPLICANT_CONNECTED, false); |
| Bundle msg = new Bundle(); |
| msg.putBoolean("Connected", mIsConnected); |
| mEventFacade.postEvent("SupplicantConnectionChanged", msg); |
| } |
| } |
| } |
| |
| public class WifiWpsCallback extends WifiManager.WpsCallback { |
| private static final String tag = "WifiWps"; |
| |
| @Override |
| public void onStarted(String pin) { |
| Bundle msg = new Bundle(); |
| msg.putString("pin", pin); |
| mEventFacade.postEvent(tag + "OnStarted", msg); |
| } |
| |
| @Override |
| public void onSucceeded() { |
| Log.d("Wps op succeeded"); |
| mEventFacade.postEvent(tag + "OnSucceeded", null); |
| } |
| |
| @Override |
| public void onFailed(int reason) { |
| Bundle msg = new Bundle(); |
| msg.putInt("reason", reason); |
| mEventFacade.postEvent(tag + "OnFailed", msg); |
| } |
| } |
| |
| private void applyingkeyMgmt(WifiConfiguration config, ScanResult result) { |
| if (result.capabilities.contains("WEP")) { |
| config.allowedKeyManagement.set(KeyMgmt.NONE); |
| config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); |
| config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); |
| } else if (result.capabilities.contains("PSK")) { |
| config.allowedKeyManagement.set(KeyMgmt.WPA_PSK); |
| } else if (result.capabilities.contains("EAP")) { |
| // this is probably wrong, as we don't have a way to enter the enterprise config |
| config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); |
| config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); |
| } else { |
| config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); |
| } |
| } |
| |
| private WifiConfiguration genWifiConfig(JSONObject j) throws JSONException { |
| if (j == null) { |
| return null; |
| } |
| WifiConfiguration config = new WifiConfiguration(); |
| if (j.has("SSID")) { |
| config.SSID = "\"" + j.getString("SSID") + "\""; |
| } else if (j.has("ssid")) { |
| config.SSID = "\"" + j.getString("ssid") + "\""; |
| } |
| if (j.has("password")) { |
| config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); |
| config.preSharedKey = "\"" + j.getString("password") + "\""; |
| } else { |
| config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); |
| } |
| if (j.has("BSSID")) { |
| config.BSSID = j.getString("BSSID"); |
| } |
| if (j.has("hiddenSSID")) { |
| config.hiddenSSID = j.getBoolean("hiddenSSID"); |
| } |
| if (j.has("priority")) { |
| config.priority = j.getInt("priority"); |
| } |
| if (j.has("apBand")) { |
| config.apBand = j.getInt("apBand"); |
| } |
| if (j.has("preSharedKey")) { |
| config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK); |
| config.preSharedKey = j.getString("preSharedKey"); |
| } |
| if (j.has("wepKeys")) { |
| // Looks like we only support static WEP. |
| config.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE); |
| config.allowedAuthAlgorithms.set(AuthAlgorithm.OPEN); |
| config.allowedAuthAlgorithms.set(AuthAlgorithm.SHARED); |
| JSONArray keys = j.getJSONArray("wepKeys"); |
| String[] wepKeys = new String[keys.length()]; |
| for (int i = 0; i < keys.length(); i++) { |
| wepKeys[i] = keys.getString(i); |
| } |
| config.wepKeys = wepKeys; |
| } |
| if (j.has("wepTxKeyIndex")) { |
| config.wepTxKeyIndex = j.getInt("wepTxKeyIndex"); |
| } |
| return config; |
| } |
| |
| private WifiConfiguration genWifiEnterpriseConfig(JSONObject j) throws JSONException, |
| GeneralSecurityException { |
| if (j == null) { |
| return null; |
| } |
| WifiConfiguration config = new WifiConfiguration(); |
| config.allowedKeyManagement.set(KeyMgmt.WPA_EAP); |
| config.allowedKeyManagement.set(KeyMgmt.IEEE8021X); |
| if (j.has("SSID")) { |
| config.SSID = "\"" + j.getString("SSID") + "\""; |
| } else if (j.has("ssid")) { |
| config.SSID = "\"" + j.getString("ssid") + "\""; |
| } |
| if (j.has("FQDN")) { |
| config.FQDN = j.getString("FQDN"); |
| } |
| if (j.has("providerFriendlyName")) { |
| config.providerFriendlyName = j.getString("providerFriendlyName"); |
| } |
| if (j.has("roamingConsortiumIds")) { |
| JSONArray ids = j.getJSONArray("roamingConsortiumIds"); |
| long[] rIds = new long[ids.length()]; |
| for (int i = 0; i < ids.length(); i++) { |
| rIds[i] = ids.getLong(i); |
| } |
| config.roamingConsortiumIds = rIds; |
| } |
| WifiEnterpriseConfig eConfig = new WifiEnterpriseConfig(); |
| if (j.has(WifiEnterpriseConfig.EAP_KEY)) { |
| int eap = j.getInt(WifiEnterpriseConfig.EAP_KEY); |
| eConfig.setEapMethod(eap); |
| } |
| if (j.has(WifiEnterpriseConfig.PHASE2_KEY)) { |
| int p2Method = j.getInt(WifiEnterpriseConfig.PHASE2_KEY); |
| eConfig.setPhase2Method(p2Method); |
| } |
| if (j.has(WifiEnterpriseConfig.CA_CERT_KEY)) { |
| String certStr = j.getString(WifiEnterpriseConfig.CA_CERT_KEY); |
| Log.v("CA Cert String is " + certStr); |
| eConfig.setCaCertificate(strToX509Cert(certStr)); |
| } |
| if (j.has(WifiEnterpriseConfig.CLIENT_CERT_KEY) |
| && j.has(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY)) { |
| String certStr = j.getString(WifiEnterpriseConfig.CLIENT_CERT_KEY); |
| String keyStr = j.getString(WifiEnterpriseConfig.PRIVATE_KEY_ID_KEY); |
| Log.v("Client Cert String is " + certStr); |
| Log.v("Client Key String is " + keyStr); |
| X509Certificate cert = strToX509Cert(certStr); |
| PrivateKey privKey = strToPrivateKey(keyStr); |
| Log.v("Cert is " + cert); |
| Log.v("Private Key is " + privKey); |
| eConfig.setClientKeyEntry(privKey, cert); |
| } |
| if (j.has(WifiEnterpriseConfig.IDENTITY_KEY)) { |
| String identity = j.getString(WifiEnterpriseConfig.IDENTITY_KEY); |
| Log.v("Setting identity to " + identity); |
| eConfig.setIdentity(identity); |
| } |
| if (j.has(WifiEnterpriseConfig.PASSWORD_KEY)) { |
| String pwd = j.getString(WifiEnterpriseConfig.PASSWORD_KEY); |
| Log.v("Setting password to " + pwd); |
| eConfig.setPassword(pwd); |
| } |
| if (j.has(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY)) { |
| String altSub = j.getString(WifiEnterpriseConfig.ALTSUBJECT_MATCH_KEY); |
| Log.v("Setting Alt Subject to " + altSub); |
| eConfig.setAltSubjectMatch(altSub); |
| } |
| if (j.has(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY)) { |
| String domSuffix = j.getString(WifiEnterpriseConfig.DOM_SUFFIX_MATCH_KEY); |
| Log.v("Setting Domain Suffix Match to " + domSuffix); |
| eConfig.setDomainSuffixMatch(domSuffix); |
| } |
| if (j.has(WifiEnterpriseConfig.REALM_KEY)) { |
| String realm = j.getString(WifiEnterpriseConfig.REALM_KEY); |
| Log.v("Setting Domain Suffix Match to " + realm); |
| eConfig.setRealm(realm); |
| } |
| config.enterpriseConfig = eConfig; |
| return config; |
| } |
| |
| private boolean matchScanResult(ScanResult result, String id) { |
| if (result.BSSID.equals(id) || result.SSID.equals(id)) { |
| return true; |
| } |
| return false; |
| } |
| |
| private WpsInfo parseWpsInfo(String infoStr) throws JSONException { |
| if (infoStr == null) { |
| return null; |
| } |
| JSONObject j = new JSONObject(infoStr); |
| WpsInfo info = new WpsInfo(); |
| if (j.has("setup")) { |
| info.setup = j.getInt("setup"); |
| } |
| if (j.has("BSSID")) { |
| info.BSSID = j.getString("BSSID"); |
| } |
| if (j.has("pin")) { |
| info.pin = j.getString("pin"); |
| } |
| return info; |
| } |
| |
| private byte[] base64StrToBytes(String input) { |
| return Base64.decode(input, Base64.DEFAULT); |
| } |
| |
| private X509Certificate strToX509Cert(String certStr) throws CertificateException { |
| byte[] certBytes = base64StrToBytes(certStr); |
| InputStream certStream = new ByteArrayInputStream(certBytes); |
| CertificateFactory cf = CertificateFactory.getInstance("X509"); |
| return (X509Certificate) cf.generateCertificate(certStream); |
| } |
| |
| private PrivateKey strToPrivateKey(String key) throws NoSuchAlgorithmException, |
| InvalidKeySpecException { |
| byte[] keyBytes = base64StrToBytes(key); |
| PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); |
| KeyFactory fact = KeyFactory.getInstance("RSA"); |
| PrivateKey priv = fact.generatePrivate(keySpec); |
| return priv; |
| } |
| |
| private PublicKey strToPublicKey(String key) throws NoSuchAlgorithmException, |
| InvalidKeySpecException { |
| byte[] keyBytes = base64StrToBytes(key); |
| X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); |
| KeyFactory fact = KeyFactory.getInstance("RSA"); |
| PublicKey pub = fact.generatePublic(keySpec); |
| return pub; |
| } |
| |
| private WifiConfiguration wifiConfigurationFromScanResult(ScanResult result) { |
| if (result == null) |
| return null; |
| WifiConfiguration config = new WifiConfiguration(); |
| config.SSID = "\"" + result.SSID + "\""; |
| applyingkeyMgmt(config, result); |
| config.BSSID = result.BSSID; |
| return config; |
| } |
| |
| @Rpc(description = "test.") |
| public String wifiTest( |
| @RpcParameter(name = "certString") String certString) throws CertificateException, IOException { |
| // TODO(angli): Make this work. Convert a X509Certificate back to a string. |
| X509Certificate caCert = strToX509Cert(certString); |
| caCert.getEncoded(); |
| ByteArrayOutputStream bos = new ByteArrayOutputStream(); |
| ObjectOutput out = new ObjectOutputStream(bos); |
| out.writeObject(caCert); |
| byte[] data = bos.toByteArray(); |
| bos.close(); |
| return Base64.encodeToString(data, Base64.DEFAULT); |
| } |
| |
| @Rpc(description = "Add a network.") |
| public Integer wifiAddNetwork(@RpcParameter(name = "wifiConfig") JSONObject wifiConfig) |
| throws JSONException { |
| return mWifi.addNetwork(genWifiConfig(wifiConfig)); |
| } |
| |
| @Rpc(description = "Cancel Wi-fi Protected Setup.") |
| public void wifiCancelWps() throws JSONException { |
| WifiWpsCallback listener = new WifiWpsCallback(); |
| mWifi.cancelWps(listener); |
| } |
| |
| @Rpc(description = "Checks Wifi state.", returns = "True if Wifi is enabled.") |
| public Boolean wifiCheckState() { |
| return mWifi.getWifiState() == WifiManager.WIFI_STATE_ENABLED; |
| } |
| |
| @RpcDeprecated(value = "wifiConnectByConfig") |
| @Rpc(description = "Connects to the network with the given configuration") |
| public Boolean wifiConnect(@RpcParameter(name = "config") JSONObject config) |
| throws JSONException { |
| try { |
| wifiConnectByConfig(config); |
| } catch (GeneralSecurityException e) { |
| String msg = "Caught GeneralSecurityException with the provided" |
| + "configuration"; |
| throw new RuntimeException(msg); |
| } |
| return true; |
| } |
| |
| @RpcDeprecated(value = "wifiConnectByConfig") |
| @Rpc(description = "Connect to Enterprise network with given configuration") |
| public Boolean wifiEnterpriseConnect(@RpcParameter(name = "config") |
| JSONObject config) throws JSONException, GeneralSecurityException { |
| try { |
| wifiConnectByConfig(config); |
| } catch (GeneralSecurityException e) { |
| throw e; |
| } |
| return true; |
| } |
| |
| /** |
| * Connects to a wifi network using configuration. |
| * @param config JSONObject Dictionary of wifi connection parameters |
| * @throws JSONException |
| * @throws GeneralSecurityException |
| */ |
| @Rpc(description = "Connects to the network with the given configuration") |
| public void wifiConnectByConfig(@RpcParameter(name = "config") JSONObject config) |
| throws JSONException, GeneralSecurityException { |
| WifiConfiguration wifiConfig; |
| WifiActionListener listener; |
| // Check if this is 802.1x or 802.11x config. |
| if (config.has(WifiEnterpriseConfig.EAP_KEY)) { |
| wifiConfig = genWifiEnterpriseConfig(config); |
| } else { |
| wifiConfig = genWifiConfig(config); |
| } |
| listener = new WifiActionListener(mEventFacade, |
| WifiConstants.WIFI_CONNECT_BY_CONFIG_CALLBACK); |
| mWifi.connect(wifiConfig, listener); |
| } |
| |
| /** |
| * Generate a Passpoint configuration from JSON config. |
| * @param config JSON config containing base64 encoded Passpoint profile |
| */ |
| @Rpc(description = "Generate Passpoint configuration", returns = "PasspointConfiguration object") |
| public PasspointConfiguration genWifiPasspointConfig(@RpcParameter( |
| name = "config") JSONObject config) |
| throws JSONException,CertificateException, IOException { |
| String profileStr = ""; |
| if (config == null) { |
| return null; |
| } |
| if (config.has("profile")) { |
| profileStr = config.getString("profile"); |
| } |
| return ConfigParser.parsePasspointConfig(TYPE_WIFICONFIG, |
| profileStr.getBytes()); |
| } |
| |
| /** |
| * Add or update a Passpoint configuration. |
| * @param config base64 encoded message containing Passpoint profile |
| * @throws JSONException |
| */ |
| @Rpc(description = "Add or update a Passpoint configuration") |
| public boolean addUpdatePasspointConfig(@RpcParameter( |
| name = "config") JSONObject config) |
| throws JSONException,CertificateException, IOException { |
| PasspointConfiguration passpointConfig = genWifiPasspointConfig(config); |
| return mWifi.addOrUpdatePasspointConfiguration(passpointConfig); |
| } |
| |
| /** |
| * Remove a Passpoint configuration. |
| * @param fqdn The FQDN of the passpoint configuration to be removed |
| * @return true on success; false otherwise |
| */ |
| @Rpc(description = "Remove a Passpoint configuration", returns = "true if operation succeeds; false otherwise") |
| public boolean removePasspointConfig( |
| @RpcParameter(name = "fqdn") String fqdn) { |
| return mWifi.removePasspointConfiguration(fqdn); |
| } |
| |
| /** |
| * Get list of Passpoint configurations. |
| * @return A list of FQDNs of the Passpoint configurations |
| */ |
| @Rpc(description = "Return the list of installed Passpoint configurations", returns = "A list of Passpoint configurations") |
| public List<String> getPasspointConfigs() { |
| List<String> fqdnList = new ArrayList<String>(); |
| for(PasspointConfiguration passpoint : |
| mWifi.getPasspointConfigurations()) { |
| fqdnList.add(passpoint.getHomeSp().getFqdn()); |
| } |
| return fqdnList; |
| } |
| |
| /** |
| * Connects to a wifi network using networkId. |
| * @param networkId the network identity for the network in the supplicant |
| */ |
| @Rpc(description = "Connects to the network with the given networkId") |
| public void wifiConnectByNetworkId( |
| @RpcParameter(name = "networkId") Integer networkId) { |
| WifiActionListener listener; |
| listener = new WifiActionListener(mEventFacade, |
| WifiConstants.WIFI_CONNECT_BY_NETID_CALLBACK); |
| mWifi.connect(networkId, listener); |
| } |
| |
| @Rpc(description = "Disconnects from the currently active access point.", returns = "True if the operation succeeded.") |
| public Boolean wifiDisconnect() { |
| return mWifi.disconnect(); |
| } |
| |
| @Rpc(description = "Enable/disable autojoin scan and switch network when connected.") |
| public Boolean wifiSetEnableAutoJoinWhenAssociated(@RpcParameter(name = "enable") Boolean enable) { |
| return mWifi.setEnableAutoJoinWhenAssociated(enable); |
| } |
| |
| @Rpc(description = "Enable a configured network. Initiate a connection if disableOthers is true", returns = "True if the operation succeeded.") |
| public Boolean wifiEnableNetwork(@RpcParameter(name = "netId") Integer netId, |
| @RpcParameter(name = "disableOthers") Boolean disableOthers) { |
| return mWifi.enableNetwork(netId, disableOthers); |
| } |
| |
| @Rpc(description = "Enable WiFi verbose logging.") |
| public void wifiEnableVerboseLogging(@RpcParameter(name = "level") Integer level) { |
| mWifi.enableVerboseLogging(level); |
| } |
| |
| @Rpc(description = "Resets all WifiManager settings.") |
| public void wifiFactoryReset() { |
| mWifi.factoryReset(); |
| } |
| |
| /** |
| * Forget a wifi network by networkId. |
| * |
| * @param networkId Id of wifi network |
| */ |
| @Rpc(description = "Forget a wifi network by networkId") |
| public void wifiForgetNetwork(@RpcParameter(name = "wifiSSID") Integer networkId) { |
| WifiActionListener listener = new WifiActionListener(mEventFacade, |
| WifiConstants.WIFI_FORGET_NETWORK_CALLBACK); |
| mWifi.forget(networkId, listener); |
| } |
| |
| @Rpc(description = "Gets the Wi-Fi AP Configuration.") |
| public WifiConfiguration wifiGetApConfiguration() { |
| return mWifi.getWifiApConfiguration(); |
| } |
| |
| @Rpc(description = "Return a list of all the configured wifi networks.") |
| public List<WifiConfiguration> wifiGetConfiguredNetworks() { |
| return mWifi.getConfiguredNetworks(); |
| } |
| |
| @Rpc(description = "Returns information about the currently active access point.") |
| public WifiInfo wifiGetConnectionInfo() { |
| return mWifi.getConnectionInfo(); |
| } |
| |
| @Rpc(description = "Returns wifi activity and energy usage info.") |
| public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() { |
| return mWifi.getControllerActivityEnergyInfo(0); |
| } |
| |
| @Rpc(description = "Get the country code used by WiFi.") |
| public String wifiGetCountryCode() { |
| return mWifi.getCountryCode(); |
| } |
| |
| @Rpc(description = "Get the current network.") |
| public Network wifiGetCurrentNetwork() { |
| return mWifi.getCurrentNetwork(); |
| } |
| |
| @Rpc(description = "Get the info from last successful DHCP request.") |
| public DhcpInfo wifiGetDhcpInfo() { |
| return mWifi.getDhcpInfo(); |
| } |
| |
| @Rpc(description = "Get setting for Framework layer autojoin enable status.") |
| public Boolean wifiGetEnableAutoJoinWhenAssociated() { |
| return mWifi.getEnableAutoJoinWhenAssociated(); |
| } |
| |
| @Rpc(description = "Get privileged configured networks.") |
| public List<WifiConfiguration> wifiGetPrivilegedConfiguredNetworks() { |
| return mWifi.getPrivilegedConfiguredNetworks(); |
| } |
| |
| @Rpc(description = "Returns the list of access points found during the most recent Wifi scan.") |
| public List<ScanResult> wifiGetScanResults() { |
| return mWifi.getScanResults(); |
| } |
| |
| @Rpc(description = "Get the current level of WiFi verbose logging.") |
| public Integer wifiGetVerboseLoggingLevel() { |
| return mWifi.getVerboseLoggingLevel(); |
| } |
| |
| @Rpc(description = "true if this adapter supports 5 GHz band.") |
| public Boolean wifiIs5GHzBandSupported() { |
| return mWifi.is5GHzBandSupported(); |
| } |
| |
| @Rpc(description = "true if this adapter supports multiple simultaneous connections.") |
| public Boolean wifiIsAdditionalStaSupported() { |
| return mWifi.isAdditionalStaSupported(); |
| } |
| |
| @Rpc(description = "Return whether Wi-Fi AP is enabled or disabled.") |
| public Boolean wifiIsApEnabled() { |
| return mWifi.isWifiApEnabled(); |
| } |
| |
| @Rpc(description = "Check if Device-to-AP RTT is supported.") |
| public Boolean wifiIsDeviceToApRttSupported() { |
| return mWifi.isDeviceToApRttSupported(); |
| } |
| |
| @Rpc(description = "Check if Device-to-device RTT is supported.") |
| public Boolean wifiIsDeviceToDeviceRttSupported() { |
| return mWifi.isDeviceToDeviceRttSupported(); |
| } |
| |
| @Rpc(description = "Check if the chipset supports dual frequency band (2.4 GHz and 5 GHz).") |
| public Boolean wifiIsDualBandSupported() { |
| return mWifi.isDualBandSupported(); |
| } |
| |
| @Rpc(description = "Check if this adapter supports advanced power/performance counters.") |
| public Boolean wifiIsEnhancedPowerReportingSupported() { |
| return mWifi.isEnhancedPowerReportingSupported(); |
| } |
| |
| @Rpc(description = "Check if multicast is enabled.") |
| public Boolean wifiIsMulticastEnabled() { |
| return mWifi.isMulticastEnabled(); |
| } |
| |
| @Rpc(description = "true if this adapter supports Wi-Fi Aware APIs.") |
| public Boolean wifiIsAwareSupported() { |
| return mWifi.isWifiAwareSupported(); |
| } |
| |
| @Rpc(description = "true if this adapter supports Off Channel Tunnel Directed Link Setup.") |
| public Boolean wifiIsOffChannelTdlsSupported() { |
| return mWifi.isOffChannelTdlsSupported(); |
| } |
| |
| @Rpc(description = "true if this adapter supports WifiP2pManager (Wi-Fi Direct).") |
| public Boolean wifiIsP2pSupported() { |
| return mWifi.isP2pSupported(); |
| } |
| |
| @Rpc(description = "true if this adapter supports passpoint.") |
| public Boolean wifiIsPasspointSupported() { |
| return mWifi.isPasspointSupported(); |
| } |
| |
| @Rpc(description = "true if this adapter supports portable Wi-Fi hotspot.") |
| public Boolean wifiIsPortableHotspotSupported() { |
| return mWifi.isPortableHotspotSupported(); |
| } |
| |
| @Rpc(description = "true if this adapter supports offloaded connectivity scan.") |
| public Boolean wifiIsPreferredNetworkOffloadSupported() { |
| return mWifi.isPreferredNetworkOffloadSupported(); |
| } |
| |
| @Rpc(description = "Check if wifi scanner is supported on this device.") |
| public Boolean wifiIsScannerSupported() { |
| return mWifi.isWifiScannerSupported(); |
| } |
| |
| @Rpc(description = "Check if tdls is supported on this device.") |
| public Boolean wifiIsTdlsSupported() { |
| return mWifi.isTdlsSupported(); |
| } |
| |
| @Rpc(description = "Acquires a full Wifi lock.") |
| public void wifiLockAcquireFull() { |
| makeLock(WifiManager.WIFI_MODE_FULL); |
| } |
| |
| @Rpc(description = "Acquires a scan only Wifi lock.") |
| public void wifiLockAcquireScanOnly() { |
| makeLock(WifiManager.WIFI_MODE_SCAN_ONLY); |
| } |
| |
| @Rpc(description = "Releases a previously acquired Wifi lock.") |
| public void wifiLockRelease() { |
| if (mLock != null) { |
| mLock.release(); |
| mLock = null; |
| } |
| } |
| |
| @Rpc(description = "Reassociates with the currently active access point.", returns = "True if the operation succeeded.") |
| public Boolean wifiReassociate() { |
| return mWifi.reassociate(); |
| } |
| |
| @Rpc(description = "Reconnects to the currently active access point.", returns = "True if the operation succeeded.") |
| public Boolean wifiReconnect() { |
| return mWifi.reconnect(); |
| } |
| |
| @Rpc(description = "Remove a configured network.", returns = "True if the operation succeeded.") |
| public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) { |
| return mWifi.removeNetwork(netId); |
| } |
| |
| private WifiConfiguration createSoftApWifiConfiguration(JSONObject configJson) |
| throws JSONException { |
| WifiConfiguration config = genWifiConfig(configJson); |
| // Need to strip of extra quotation marks for SSID and password. |
| String ssid = config.SSID; |
| if (ssid != null) { |
| config.SSID = ssid.substring(1, ssid.length() - 1); |
| } |
| String pwd = config.preSharedKey; |
| if (pwd != null) { |
| config.preSharedKey = pwd.substring(1, pwd.length() - 1); |
| } |
| return config; |
| } |
| |
| @Rpc(description = "Set configuration for soft AP.") |
| public Boolean wifiSetWifiApConfiguration( |
| @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { |
| WifiConfiguration config = createSoftApWifiConfiguration(configJson); |
| return mWifi.setWifiApConfiguration(config); |
| } |
| |
| @Rpc(description = "Start/stop wifi soft AP.") |
| public Boolean wifiSetApEnabled( |
| @RpcParameter(name = "enable") Boolean enable, |
| @RpcParameter(name = "configJson") JSONObject configJson) throws JSONException { |
| int wifiState = mWifi.getWifiState(); |
| if (enable) { |
| WifiConfiguration config = createSoftApWifiConfiguration(configJson); |
| return mWifi.setWifiApEnabled(config, enable); |
| } else { |
| return mWifi.setWifiApEnabled(null, false); |
| } |
| } |
| |
| @Rpc(description = "Set the country code used by WiFi.") |
| public void wifiSetCountryCode( |
| @RpcParameter(name = "country") String country, |
| @RpcParameter(name = "persist") Boolean persist) { |
| mWifi.setCountryCode(country, persist); |
| } |
| |
| @Rpc(description = "Enable/disable tdls with a mac address.") |
| public void wifiSetTdlsEnabledWithMacAddress( |
| @RpcParameter(name = "remoteMacAddress") String remoteMacAddress, |
| @RpcParameter(name = "enable") Boolean enable) { |
| mWifi.setTdlsEnabledWithMacAddress(remoteMacAddress, enable); |
| } |
| |
| @Rpc(description = "Starts a scan for Wifi access points.", returns = "True if the scan was initiated successfully.") |
| public Boolean wifiStartScan() { |
| mService.registerReceiver(mScanResultsAvailableReceiver, mScanFilter); |
| return mWifi.startScan(); |
| } |
| |
| @Rpc(description = "Start Wi-fi Protected Setup.") |
| public void wifiStartWps( |
| @RpcParameter(name = "config", description = "A json string with fields \"setup\", \"BSSID\", and \"pin\"") String config) |
| throws JSONException { |
| WpsInfo info = parseWpsInfo(config); |
| WifiWpsCallback listener = new WifiWpsCallback(); |
| Log.d("Starting wps with: " + info); |
| mWifi.startWps(info, listener); |
| } |
| |
| @Rpc(description = "Start listening for wifi state change related broadcasts.") |
| public void wifiStartTrackingStateChange() { |
| mService.registerReceiver(mStateChangeReceiver, mStateChangeFilter); |
| mTrackingWifiStateChange = true; |
| } |
| |
| @Rpc(description = "Stop listening for wifi state change related broadcasts.") |
| public void wifiStopTrackingStateChange() { |
| if (mTrackingWifiStateChange == true) { |
| mService.unregisterReceiver(mStateChangeReceiver); |
| mTrackingWifiStateChange = false; |
| } |
| } |
| |
| @Rpc(description = "Start listening for tether state change related broadcasts.") |
| public void wifiStartTrackingTetherStateChange() { |
| mService.registerReceiver(mTetherStateReceiver, mTetherFilter); |
| mTrackingTetherStateChange = true; |
| } |
| |
| @Rpc(description = "Stop listening for wifi state change related broadcasts.") |
| public void wifiStopTrackingTetherStateChange() { |
| if (mTrackingTetherStateChange == true) { |
| mService.unregisterReceiver(mTetherStateReceiver); |
| mTrackingTetherStateChange = false; |
| } |
| } |
| |
| @Rpc(description = "Toggle Wifi on and off.", returns = "True if Wifi is enabled.") |
| public Boolean wifiToggleState(@RpcParameter(name = "enabled") @RpcOptional Boolean enabled) { |
| if (enabled == null) { |
| enabled = !wifiCheckState(); |
| } |
| mWifi.setWifiEnabled(enabled); |
| return enabled; |
| } |
| |
| @Rpc(description = "Toggle Wifi scan always available on and off.", returns = "True if Wifi scan is always available.") |
| public Boolean wifiToggleScanAlwaysAvailable( |
| @RpcParameter(name = "enabled") @RpcOptional Boolean enabled) |
| throws SettingNotFoundException { |
| ContentResolver cr = mService.getContentResolver(); |
| int isSet = 0; |
| if (enabled == null) { |
| isSet = Global.getInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE); |
| isSet ^= 1; |
| } else if (enabled == true) { |
| isSet = 1; |
| } |
| Global.putInt(cr, Global.WIFI_SCAN_ALWAYS_AVAILABLE, isSet); |
| if (isSet == 1) { |
| return true; |
| } |
| return false; |
| } |
| |
| @Rpc(description = "Enable/disable WifiConnectivityManager.") |
| public void wifiEnableWifiConnectivityManager( |
| @RpcParameter(name = "enable") Boolean enable) { |
| mWifi.enableWifiConnectivityManager(enable); |
| } |
| |
| @Override |
| public void shutdown() { |
| wifiLockRelease(); |
| if (mTrackingWifiStateChange == true) { |
| wifiStopTrackingStateChange(); |
| } |
| if (mTrackingTetherStateChange == true) { |
| wifiStopTrackingTetherStateChange(); |
| } |
| } |
| } |