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