• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
WifiManagerFacade(FacadeManager manager)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 
makeLock(int wifiMode)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 
WifiScanReceiver(EventFacade eventFacade)150         WifiScanReceiver(EventFacade eventFacade) {
151             mEventFacade = eventFacade;
152         }
153 
154         @Override
onReceive(Context c, Intent intent)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 
WifiActionListener(EventFacade eventFacade, String tag)171         public WifiActionListener(EventFacade eventFacade, String tag) {
172             mEventFacade = eventFacade;
173             this.TAG = tag;
174         }
175 
176         @Override
onSuccess()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
onFailure(int reason)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
onReceive(Context context, Intent intent)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
onStarted(String pin)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
onSucceeded()243         public void onSucceeded() {
244             Log.d("Wps op succeeded");
245             mEventFacade.postEvent(tag + "OnSucceeded", null);
246         }
247 
248         @Override
onFailed(int reason)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 
applyingkeyMgmt(WifiConfiguration config, ScanResult result)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 
genWifiConfig(JSONObject j)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 
genWifiEnterpriseConfig(JSONObject j)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 
matchScanResult(ScanResult result, String id)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 
parseWpsInfo(String infoStr)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 
base64StrToBytes(String input)427     private byte[] base64StrToBytes(String input) {
428         return Base64.decode(input, Base64.DEFAULT);
429     }
430 
strToX509Cert(String certStr)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 
strToPrivateKey(String key)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 
strToPublicKey(String key)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 
wifiConfigurationFromScanResult(ScanResult result)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.")
wifiTest(String certString)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.")
wifiAddNetwork(@pcParametername = "wifiConfig") JSONObject wifiConfig)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.")
wifiBuildConfig( @pcParametername = "uriString") String uriString, @RpcParameter(name = "mimeType") String mimeType, String dataString)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.")
wifiCancelWps()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.")
wifiCheckState()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.")
wifiConnect(@pcParametername = "config") JSONObject config)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.")
wifiDisconnect()530     public Boolean wifiDisconnect() {
531         return mWifi.disconnect();
532     }
533 
534     @Rpc(description = "Enable/disable autojoin scan and switch network when connected.")
wifiSetEnableAutoJoinWhenAssociated(@pcParametername = "enable") Boolean enable)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.")
wifiEnableNetwork(@pcParametername = "netId") Integer netId, @RpcParameter(name = "disableOthers") Boolean disableOthers)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.")
wifiEnableVerboseLogging(@pcParametername = "level") Integer level)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.")
wifiEnterpriseConnect(@pcParametername = "config") JSONObject config)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.")
wifiFactoryReset()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")
wifiForgetNetwork(@pcParametername = "wifiSSID") Integer newtorkId)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.")
wifiGetApConfiguration()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.")
wifiGetConfigFile()588     public String wifiGetConfigFile() {
589         return mWifi.getConfigFile();
590     }
591 
592     @Rpc(description = "Return a list of all the configured wifi networks.")
wifiGetConfiguredNetworks()593     public List<WifiConfiguration> wifiGetConfiguredNetworks() {
594         return mWifi.getConfiguredNetworks();
595     }
596 
597     @Rpc(description = "Returns information about the currently active access point.")
wifiGetConnectionInfo()598     public WifiInfo wifiGetConnectionInfo() {
599         return mWifi.getConnectionInfo();
600     }
601 
602     @Rpc(description = "Returns wifi activity and energy usage info.")
wifiGetControllerActivityEnergyInfo()603     public WifiActivityEnergyInfo wifiGetControllerActivityEnergyInfo() {
604         return mWifi.getControllerActivityEnergyInfo(0);
605     }
606 
607     @Rpc(description = "Get the country code used by WiFi.")
wifiGetCountryCode()608     public String wifiGetCountryCode() {
609         return mWifi.getCountryCode();
610     }
611 
612     @Rpc(description = "Get the current network.")
wifiGetCurrentNetwork()613     public Network wifiGetCurrentNetwork() {
614         return mWifi.getCurrentNetwork();
615     }
616 
617     @Rpc(description = "Get the info from last successful DHCP request.")
wifiGetDhcpInfo()618     public DhcpInfo wifiGetDhcpInfo() {
619         return mWifi.getDhcpInfo();
620     }
621 
622     @Rpc(description = "Get setting for Framework layer autojoin enable status.")
wifiGetEnableAutoJoinWhenAssociated()623     public Boolean wifiGetEnableAutoJoinWhenAssociated() {
624         return mWifi.getEnableAutoJoinWhenAssociated();
625     }
626 
627     @Rpc(description = "Get privileged configured networks.")
wifiGetPrivilegedConfiguredNetworks()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.")
wifiGetScanResults()633     public List<ScanResult> wifiGetScanResults() {
634         return mWifi.getScanResults();
635     }
636 
637     @Rpc(description = "Get the current level of WiFi verbose logging.")
wifiGetVerboseLoggingLevel()638     public Integer wifiGetVerboseLoggingLevel() {
639         return mWifi.getVerboseLoggingLevel();
640     }
641 
642     @Rpc(description = "true if this adapter supports 5 GHz band.")
wifiIs5GHzBandSupported()643     public Boolean wifiIs5GHzBandSupported() {
644         return mWifi.is5GHzBandSupported();
645     }
646 
647     @Rpc(description = "true if this adapter supports multiple simultaneous connections.")
wifiIsAdditionalStaSupported()648     public Boolean wifiIsAdditionalStaSupported() {
649         return mWifi.isAdditionalStaSupported();
650     }
651 
652     @Rpc(description = "Return whether Wi-Fi AP is enabled or disabled.")
wifiIsApEnabled()653     public Boolean wifiIsApEnabled() {
654         return mWifi.isWifiApEnabled();
655     }
656 
657     @Rpc(description = "Check if Device-to-AP RTT is supported.")
wifiIsDeviceToApRttSupported()658     public Boolean wifiIsDeviceToApRttSupported() {
659         return mWifi.isDeviceToApRttSupported();
660     }
661 
662     @Rpc(description = "Check if Device-to-device RTT is supported.")
wifiIsDeviceToDeviceRttSupported()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).")
wifiIsDualBandSupported()668     public Boolean wifiIsDualBandSupported() {
669         return mWifi.isDualBandSupported();
670     }
671 
672     @Rpc(description = "Check if this adapter supports advanced power/performance counters.")
wifiIsEnhancedPowerReportingSupported()673     public Boolean wifiIsEnhancedPowerReportingSupported() {
674         return mWifi.isEnhancedPowerReportingSupported();
675     }
676 
677     @Rpc(description = "Check if multicast is enabled.")
wifiIsMulticastEnabled()678     public Boolean wifiIsMulticastEnabled() {
679         return mWifi.isMulticastEnabled();
680     }
681 
682     @Rpc(description = "true if this adapter supports Neighbour Awareness Network APIs.")
wifiIsNanSupported()683     public Boolean wifiIsNanSupported() {
684         return mWifi.isNanSupported();
685     }
686 
687     @Rpc(description = "true if this adapter supports Off Channel Tunnel Directed Link Setup.")
wifiIsOffChannelTdlsSupported()688     public Boolean wifiIsOffChannelTdlsSupported() {
689         return mWifi.isOffChannelTdlsSupported();
690     }
691 
692     @Rpc(description = "true if this adapter supports WifiP2pManager (Wi-Fi Direct).")
wifiIsP2pSupported()693     public Boolean wifiIsP2pSupported() {
694         return mWifi.isP2pSupported();
695     }
696 
697     @Rpc(description = "true if this adapter supports passpoint.")
wifiIsPasspointSupported()698     public Boolean wifiIsPasspointSupported() {
699         return mWifi.isPasspointSupported();
700     }
701 
702     @Rpc(description = "true if this adapter supports portable Wi-Fi hotspot.")
wifiIsPortableHotspotSupported()703     public Boolean wifiIsPortableHotspotSupported() {
704         return mWifi.isPortableHotspotSupported();
705     }
706 
707     @Rpc(description = "true if this adapter supports offloaded connectivity scan.")
wifiIsPreferredNetworkOffloadSupported()708     public Boolean wifiIsPreferredNetworkOffloadSupported() {
709         return mWifi.isPreferredNetworkOffloadSupported();
710     }
711 
712     @Rpc(description = "Check if wifi scanner is supported on this device.")
wifiIsScannerSupported()713     public Boolean wifiIsScannerSupported() {
714         return mWifi.isWifiScannerSupported();
715     }
716 
717     @Rpc(description = "Check if tdls is supported on this device.")
wifiIsTdlsSupported()718     public Boolean wifiIsTdlsSupported() {
719         return mWifi.isTdlsSupported();
720     }
721 
722     @Rpc(description = "Acquires a full Wifi lock.")
wifiLockAcquireFull()723     public void wifiLockAcquireFull() {
724         makeLock(WifiManager.WIFI_MODE_FULL);
725     }
726 
727     @Rpc(description = "Acquires a scan only Wifi lock.")
wifiLockAcquireScanOnly()728     public void wifiLockAcquireScanOnly() {
729         makeLock(WifiManager.WIFI_MODE_SCAN_ONLY);
730     }
731 
732     @Rpc(description = "Releases a previously acquired Wifi lock.")
wifiLockRelease()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")
wifiPriorityConnect(@pcParametername = "config") JSONObject config)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.")
wifiReassociate()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.")
wifiReconnect()761     public Boolean wifiReconnect() {
762         return mWifi.reconnect();
763     }
764 
765     @Rpc(description = "Remove a configured network.", returns = "True if the operation succeeded.")
wifiRemoveNetwork(@pcParametername = "netId") Integer netId)766     public Boolean wifiRemoveNetwork(@RpcParameter(name = "netId") Integer netId) {
767         return mWifi.removeNetwork(netId);
768     }
769 
770     @Rpc(description = "Start/stop wifi soft AP.")
wifiSetApEnabled( @pcParametername = "enable") Boolean enable, @RpcParameter(name = "configJson") JSONObject configJson)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.")
wifiSetCountryCode( @pcParametername = "country") String country, @RpcParameter(name = "persist") Boolean persist)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.")
wifiSetTdlsEnabledWithMacAddress( @pcParametername = "remoteMacAddress") String remoteMacAddress, @RpcParameter(name = "enable") Boolean enable)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.")
wifiStartScan()807     public Boolean wifiStartScan() {
808         mService.registerReceiver(mScanResultsAvailableReceiver, mScanFilter);
809         return mWifi.startScan();
810     }
811 
812     @Rpc(description = "Start Wi-fi Protected Setup.")
wifiStartWps( @pcParametername = "config", description = "A json string with fields \\"setup\\", \\"BSSID\\", and \\"pin\\"") String config)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.")
wifiStartTrackingStateChange()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.")
wifiStopTrackingStateChange()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.")
wifiToggleState(@pcParametername = "enabled") @pcOptional Boolean 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.")
wifiToggleScanAlwaysAvailable( @pcParametername = "enabled") @pcOptional Boolean enabled)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.")
wifiEnableWifiConnectivityManager( @pcParametername = "enable") Boolean enable)867     public void wifiEnableWifiConnectivityManager(
868             @RpcParameter(name = "enable") Boolean enable) {
869         mWifi.enableWifiConnectivityManager(enable);
870     }
871 
872     @Override
shutdown()873     public void shutdown() {
874         wifiLockRelease();
875         if (mTrackingWifiStateChange == true) {
876             wifiStopTrackingStateChange();
877         }
878     }
879 }
880