• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.googlecode.android_scripting.facade;
18 
19 import android.app.Service;
20 import android.content.BroadcastReceiver;
21 import android.content.Context;
22 import android.content.Intent;
23 import android.content.IntentFilter;
24 import android.net.ConnectivityManager;
25 import android.net.ConnectivityManager.PacketKeepalive;
26 import android.net.ConnectivityManager.PacketKeepaliveCallback;
27 import android.net.LinkProperties;
28 import android.net.Network;
29 import android.net.NetworkCapabilities;
30 import android.net.NetworkInfo;
31 import android.net.NetworkRequest;
32 import android.net.StringNetworkSpecifier;
33 import android.os.Bundle;
34 import android.provider.Settings;
35 
36 import com.googlecode.android_scripting.Log;
37 import com.googlecode.android_scripting.facade.wifi.WifiAwareManagerFacade;
38 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
39 import com.googlecode.android_scripting.rpc.Rpc;
40 import com.googlecode.android_scripting.rpc.RpcOptional;
41 import com.googlecode.android_scripting.rpc.RpcParameter;
42 
43 import org.json.JSONArray;
44 import org.json.JSONException;
45 import org.json.JSONObject;
46 
47 import java.net.Inet6Address;
48 import java.net.InetAddress;
49 import java.net.NetworkInterface;
50 import java.net.SocketException;
51 import java.net.UnknownHostException;
52 import java.util.Enumeration;
53 import java.util.HashMap;
54 
55 /**
56  * Access ConnectivityManager functions.
57  */
58 public class ConnectivityManagerFacade extends RpcReceiver {
59 
60     public static int AIRPLANE_MODE_OFF = 0;
61     public static int AIRPLANE_MODE_ON = 1;
62     public static int DATA_ROAMING_ON = 1;
63 
64     class ConnectivityReceiver extends BroadcastReceiver {
65 
66         @Override
onReceive(Context context, Intent intent)67         public void onReceive(Context context, Intent intent) {
68             String action = intent.getAction();
69 
70             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
71                 Log.e("ConnectivityReceiver received non-connectivity action!");
72                 return;
73             }
74 
75             Bundle b = intent.getExtras();
76 
77             if (b == null) {
78                 Log.e("ConnectivityReceiver failed to receive extras!");
79                 return;
80             }
81 
82             int netType =
83                     b.getInt(ConnectivityManager.EXTRA_NETWORK_TYPE,
84                             ConnectivityManager.TYPE_NONE);
85 
86             if (netType == ConnectivityManager.TYPE_NONE) {
87                 Log.i("ConnectivityReceiver received change to TYPE_NONE.");
88                 return;
89             }
90 
91             /*
92              * Technically there is a race condition here, but retrieving the NetworkInfo from the
93              * bundle is deprecated. See ConnectivityManager.EXTRA_NETWORK_INFO
94              */
95             for (NetworkInfo info : mManager.getAllNetworkInfo()) {
96                 if (info.getType() == netType) {
97                     mEventFacade.postEvent(ConnectivityConstants.EventConnectivityChanged, info);
98                 }
99             }
100         }
101     }
102 
103     class PacketKeepaliveReceiver extends PacketKeepaliveCallback {
104         public static final int EVENT_INVALID = -1;
105         public static final int EVENT_NONE = 0;
106         public static final int EVENT_STARTED = 1 << 0;
107         public static final int EVENT_STOPPED = 1 << 1;
108         public static final int EVENT_ERROR = 1 << 2;
109         public static final int EVENT_ALL = EVENT_STARTED |
110                 EVENT_STOPPED |
111                 EVENT_ERROR;
112         private int mEvents;
113         public String mId;
114         public PacketKeepalive mPacketKeepalive;
115 
PacketKeepaliveReceiver(int events)116         public PacketKeepaliveReceiver(int events) {
117             super();
118             mEvents = events;
119             mId = this.toString();
120         }
121 
startListeningForEvents(int events)122         public void startListeningForEvents(int events) {
123             mEvents |= events & EVENT_ALL;
124         }
125 
stopListeningForEvents(int events)126         public void stopListeningForEvents(int events) {
127             mEvents &= ~(events & EVENT_ALL);
128         }
129 
130         @Override
onStarted()131         public void onStarted() {
132             Log.d("PacketKeepaliveCallback on start!");
133             if ((mEvents & EVENT_STARTED) == EVENT_STARTED) {
134                 mEventFacade.postEvent(
135                     ConnectivityConstants.EventPacketKeepaliveCallback,
136                     new ConnectivityEvents.PacketKeepaliveEvent(
137                         mId,
138                         getPacketKeepaliveReceiverEventString(EVENT_STARTED)));
139             }
140         }
141 
142         @Override
onStopped()143         public void onStopped() {
144             Log.d("PacketKeepaliveCallback on stop!");
145             if ((mEvents & EVENT_STOPPED) == EVENT_STOPPED) {
146                 mEventFacade.postEvent(
147                         ConnectivityConstants.EventPacketKeepaliveCallback,
148                     new ConnectivityEvents.PacketKeepaliveEvent(
149                         mId,
150                         getPacketKeepaliveReceiverEventString(EVENT_STOPPED)));
151             }
152         }
153 
154         @Override
onError(int error)155         public void onError(int error) {
156             Log.d("PacketKeepaliveCallback on error! - code:" + error);
157             if ((mEvents & EVENT_ERROR) == EVENT_ERROR) {
158                 mEventFacade.postEvent(
159                         ConnectivityConstants.EventPacketKeepaliveCallback,
160                     new ConnectivityEvents.PacketKeepaliveEvent(
161                         mId,
162                         getPacketKeepaliveReceiverEventString(EVENT_ERROR)));
163             }
164         }
165     }
166 
167     class NetworkCallback extends ConnectivityManager.NetworkCallback {
168         public static final int EVENT_INVALID = -1;
169         public static final int EVENT_NONE = 0;
170         public static final int EVENT_PRECHECK = 1 << 0;
171         public static final int EVENT_AVAILABLE = 1 << 1;
172         public static final int EVENT_LOSING = 1 << 2;
173         public static final int EVENT_LOST = 1 << 3;
174         public static final int EVENT_UNAVAILABLE = 1 << 4;
175         public static final int EVENT_CAPABILITIES_CHANGED = 1 << 5;
176         public static final int EVENT_SUSPENDED = 1 << 6;
177         public static final int EVENT_RESUMED = 1 << 7;
178         public static final int EVENT_LINK_PROPERTIES_CHANGED = 1 << 8;
179         public static final int EVENT_ALL = EVENT_PRECHECK |
180                 EVENT_AVAILABLE |
181                 EVENT_LOSING |
182                 EVENT_LOST |
183                 EVENT_UNAVAILABLE |
184                 EVENT_CAPABILITIES_CHANGED |
185                 EVENT_SUSPENDED |
186                 EVENT_RESUMED |
187                 EVENT_LINK_PROPERTIES_CHANGED;
188 
189         private int mEvents;
190         public String mId;
191 
NetworkCallback(int events)192         public NetworkCallback(int events) {
193             super();
194             mEvents = events;
195             mId = this.toString();
196         }
197 
startListeningForEvents(int events)198         public void startListeningForEvents(int events) {
199             mEvents |= events & EVENT_ALL;
200         }
201 
stopListeningForEvents(int events)202         public void stopListeningForEvents(int events) {
203             mEvents &= ~(events & EVENT_ALL);
204         }
205 
206         @Override
onPreCheck(Network network)207         public void onPreCheck(Network network) {
208             Log.d("NetworkCallback onPreCheck");
209             if ((mEvents & EVENT_PRECHECK) == EVENT_PRECHECK) {
210                 mEventFacade.postEvent(
211                         ConnectivityConstants.EventNetworkCallback,
212                     new ConnectivityEvents.NetworkCallbackEventBase(
213                         mId,
214                         getNetworkCallbackEventString(EVENT_PRECHECK)));
215             }
216         }
217 
218         @Override
onAvailable(Network network)219         public void onAvailable(Network network) {
220             Log.d("NetworkCallback onAvailable");
221             if ((mEvents & EVENT_AVAILABLE) == EVENT_AVAILABLE) {
222                 mEventFacade.postEvent(
223                         ConnectivityConstants.EventNetworkCallback,
224                     new ConnectivityEvents.NetworkCallbackEventBase(
225                         mId,
226                         getNetworkCallbackEventString(EVENT_AVAILABLE)));
227             }
228         }
229 
230         @Override
onLosing(Network network, int maxMsToLive)231         public void onLosing(Network network, int maxMsToLive) {
232             Log.d("NetworkCallback onLosing");
233             if ((mEvents & EVENT_LOSING) == EVENT_LOSING) {
234                 mEventFacade.postEvent(
235                         ConnectivityConstants.EventNetworkCallback,
236                     new ConnectivityEvents.NetworkCallbackEventOnLosing(
237                         mId,
238                         getNetworkCallbackEventString(EVENT_LOSING),
239                         maxMsToLive));
240             }
241         }
242 
243         @Override
onLost(Network network)244         public void onLost(Network network) {
245             Log.d("NetworkCallback onLost");
246             if ((mEvents & EVENT_LOST) == EVENT_LOST) {
247                 mEventFacade.postEvent(
248                         ConnectivityConstants.EventNetworkCallback,
249                     new ConnectivityEvents.NetworkCallbackEventBase(
250                         mId,
251                         getNetworkCallbackEventString(EVENT_LOST)));
252             }
253         }
254 
255         @Override
onUnavailable()256         public void onUnavailable() {
257             Log.d("NetworkCallback onUnavailable");
258             if ((mEvents & EVENT_UNAVAILABLE) == EVENT_UNAVAILABLE) {
259                 mEventFacade.postEvent(
260                         ConnectivityConstants.EventNetworkCallback,
261                     new ConnectivityEvents.NetworkCallbackEventBase(
262                         mId,
263                         getNetworkCallbackEventString(EVENT_UNAVAILABLE)));
264             }
265         }
266 
267         @Override
onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)268         public void onCapabilitiesChanged(Network network,
269                 NetworkCapabilities networkCapabilities) {
270             Log.d("NetworkCallback onCapabilitiesChanged. RSSI:" +
271                     networkCapabilities.getSignalStrength());
272             if ((mEvents & EVENT_CAPABILITIES_CHANGED) == EVENT_CAPABILITIES_CHANGED) {
273                 mEventFacade.postEvent(
274                         ConnectivityConstants.EventNetworkCallback,
275                     new ConnectivityEvents.NetworkCallbackEventOnCapabilitiesChanged(
276                         mId,
277                         getNetworkCallbackEventString(EVENT_CAPABILITIES_CHANGED),
278                         networkCapabilities.getSignalStrength()));
279             }
280         }
281 
282         @Override
onNetworkSuspended(Network network)283         public void onNetworkSuspended(Network network) {
284             Log.d("NetworkCallback onNetworkSuspended");
285             if ((mEvents & EVENT_SUSPENDED) == EVENT_SUSPENDED) {
286                 mEventFacade.postEvent(
287                         ConnectivityConstants.EventNetworkCallback,
288                     new ConnectivityEvents.NetworkCallbackEventBase(
289                         mId,
290                         getNetworkCallbackEventString(EVENT_SUSPENDED)));
291             }
292         }
293 
294         @Override
onLinkPropertiesChanged(Network network, LinkProperties linkProperties)295         public void onLinkPropertiesChanged(Network network,
296                 LinkProperties linkProperties) {
297             Log.d("NetworkCallback onLinkPropertiesChanged");
298             if ((mEvents & EVENT_LINK_PROPERTIES_CHANGED) == EVENT_LINK_PROPERTIES_CHANGED) {
299                 mEventFacade.postEvent(
300                         ConnectivityConstants.EventNetworkCallback,
301                         new ConnectivityEvents.NetworkCallbackEventOnLinkPropertiesChanged(mId,
302                                 getNetworkCallbackEventString(EVENT_LINK_PROPERTIES_CHANGED),
303                                 linkProperties.getInterfaceName()));
304             }
305         }
306 
307         @Override
onNetworkResumed(Network network)308         public void onNetworkResumed(Network network) {
309             Log.d("NetworkCallback onNetworkResumed");
310             if ((mEvents & EVENT_RESUMED) == EVENT_RESUMED) {
311                 mEventFacade.postEvent(
312                         ConnectivityConstants.EventNetworkCallback,
313                     new ConnectivityEvents.NetworkCallbackEventBase(
314                         mId,
315                         getNetworkCallbackEventString(EVENT_RESUMED)));
316             }
317         }
318     }
319 
getNetworkCallbackEvent(String event)320     private static int getNetworkCallbackEvent(String event) {
321         switch (event) {
322             case ConnectivityConstants.NetworkCallbackPreCheck:
323                 return NetworkCallback.EVENT_PRECHECK;
324             case ConnectivityConstants.NetworkCallbackAvailable:
325                 return NetworkCallback.EVENT_AVAILABLE;
326             case ConnectivityConstants.NetworkCallbackLosing:
327                 return NetworkCallback.EVENT_LOSING;
328             case ConnectivityConstants.NetworkCallbackLost:
329                 return NetworkCallback.EVENT_LOST;
330             case ConnectivityConstants.NetworkCallbackUnavailable:
331                 return NetworkCallback.EVENT_UNAVAILABLE;
332             case ConnectivityConstants.NetworkCallbackCapabilitiesChanged:
333                 return NetworkCallback.EVENT_CAPABILITIES_CHANGED;
334             case ConnectivityConstants.NetworkCallbackSuspended:
335                 return NetworkCallback.EVENT_SUSPENDED;
336             case ConnectivityConstants.NetworkCallbackResumed:
337                 return NetworkCallback.EVENT_RESUMED;
338             case ConnectivityConstants.NetworkCallbackLinkPropertiesChanged:
339                 return NetworkCallback.EVENT_LINK_PROPERTIES_CHANGED;
340         }
341         return NetworkCallback.EVENT_INVALID;
342     }
343 
getNetworkCallbackEventString(int event)344     private static String getNetworkCallbackEventString(int event) {
345         switch (event) {
346             case NetworkCallback.EVENT_PRECHECK:
347                 return ConnectivityConstants.NetworkCallbackPreCheck;
348             case NetworkCallback.EVENT_AVAILABLE:
349                 return ConnectivityConstants.NetworkCallbackAvailable;
350             case NetworkCallback.EVENT_LOSING:
351                 return ConnectivityConstants.NetworkCallbackLosing;
352             case NetworkCallback.EVENT_LOST:
353                 return ConnectivityConstants.NetworkCallbackLost;
354             case NetworkCallback.EVENT_UNAVAILABLE:
355                 return ConnectivityConstants.NetworkCallbackUnavailable;
356             case NetworkCallback.EVENT_CAPABILITIES_CHANGED:
357                 return ConnectivityConstants.NetworkCallbackCapabilitiesChanged;
358             case NetworkCallback.EVENT_SUSPENDED:
359                 return ConnectivityConstants.NetworkCallbackSuspended;
360             case NetworkCallback.EVENT_RESUMED:
361                 return ConnectivityConstants.NetworkCallbackResumed;
362             case NetworkCallback.EVENT_LINK_PROPERTIES_CHANGED:
363                 return ConnectivityConstants.NetworkCallbackLinkPropertiesChanged;
364         }
365         return ConnectivityConstants.NetworkCallbackInvalid;
366     }
367 
getPacketKeepaliveReceiverEvent(String event)368     private static int getPacketKeepaliveReceiverEvent(String event) {
369         switch (event) {
370             case ConnectivityConstants.PacketKeepaliveCallbackStarted:
371                 return PacketKeepaliveReceiver.EVENT_STARTED;
372             case ConnectivityConstants.PacketKeepaliveCallbackStopped:
373                 return PacketKeepaliveReceiver.EVENT_STOPPED;
374             case ConnectivityConstants.PacketKeepaliveCallbackError:
375                 return PacketKeepaliveReceiver.EVENT_ERROR;
376         }
377         return PacketKeepaliveReceiver.EVENT_INVALID;
378     }
379 
getPacketKeepaliveReceiverEventString(int event)380     private static String getPacketKeepaliveReceiverEventString(int event) {
381         switch (event) {
382             case PacketKeepaliveReceiver.EVENT_STARTED:
383                 return ConnectivityConstants.PacketKeepaliveCallbackStarted;
384             case PacketKeepaliveReceiver.EVENT_STOPPED:
385                 return ConnectivityConstants.PacketKeepaliveCallbackStopped;
386             case PacketKeepaliveReceiver.EVENT_ERROR:
387                 return ConnectivityConstants.PacketKeepaliveCallbackError;
388         }
389         return ConnectivityConstants.PacketKeepaliveCallbackInvalid;
390     }
391 
392     /**
393      * Callbacks used in ConnectivityManager to confirm tethering has started/failed.
394      */
395     class OnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback {
396         @Override
onTetheringStarted()397         public void onTetheringStarted() {
398             mEventFacade.postEvent(ConnectivityConstants.TetheringStartedCallback, null);
399         }
400 
401         @Override
onTetheringFailed()402         public void onTetheringFailed() {
403             mEventFacade.postEvent(ConnectivityConstants.TetheringFailedCallback, null);
404         }
405     }
406 
407     private final ConnectivityManager mManager;
408     private final Service mService;
409     private final Context mContext;
410     private final ConnectivityReceiver mConnectivityReceiver;
411     private final EventFacade mEventFacade;
412     private PacketKeepalive mPacketKeepalive;
413     private NetworkCallback mNetworkCallback;
414     private static HashMap<String, PacketKeepaliveReceiver> mPacketKeepaliveReceiverMap =
415             new HashMap<String, PacketKeepaliveReceiver>();
416     private static HashMap<String, NetworkCallback> mNetworkCallbackMap =
417             new HashMap<String, NetworkCallback>();
418     private boolean mTrackingConnectivityStateChange;
419 
ConnectivityManagerFacade(FacadeManager manager)420     public ConnectivityManagerFacade(FacadeManager manager) {
421         super(manager);
422         mService = manager.getService();
423         mContext = mService.getBaseContext();
424         mManager = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE);
425         mEventFacade = manager.getReceiver(EventFacade.class);
426         mConnectivityReceiver = new ConnectivityReceiver();
427         mTrackingConnectivityStateChange = false;
428     }
429 
430     @Rpc(description = "Listen for connectivity changes")
connectivityStartTrackingConnectivityStateChange()431     public void connectivityStartTrackingConnectivityStateChange() {
432         if (!mTrackingConnectivityStateChange) {
433             mTrackingConnectivityStateChange = true;
434             mContext.registerReceiver(mConnectivityReceiver,
435                     new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
436         }
437     }
438 
439     @Rpc(description = "start natt keep alive")
connectivityStartNattKeepalive(Integer intervalSeconds, String srcAddrString, Integer srcPort, String dstAddrString)440     public String connectivityStartNattKeepalive(Integer intervalSeconds, String srcAddrString,
441             Integer srcPort, String dstAddrString) throws UnknownHostException {
442         try {
443             Network mNetwork = mManager.getActiveNetwork();
444             InetAddress srcAddr = InetAddress.getByName(srcAddrString);
445             InetAddress dstAddr = InetAddress.getByName(dstAddrString);
446             Log.d("startNattKeepalive srcAddr:" + srcAddr.getHostAddress());
447             Log.d("startNattKeepalive dstAddr:" + dstAddr.getHostAddress());
448             Log.d("startNattKeepalive srcPort:" + srcPort);
449             Log.d("startNattKeepalive intervalSeconds:" + intervalSeconds);
450             PacketKeepaliveReceiver mPacketKeepaliveReceiver = new PacketKeepaliveReceiver(
451                     PacketKeepaliveReceiver.EVENT_ALL);
452             mPacketKeepalive = mManager.startNattKeepalive(mNetwork, (int) intervalSeconds,
453                     mPacketKeepaliveReceiver, srcAddr, (int) srcPort, dstAddr);
454             if (mPacketKeepalive != null) {
455                 mPacketKeepaliveReceiver.mPacketKeepalive = mPacketKeepalive;
456                 String key = mPacketKeepaliveReceiver.mId;
457                 mPacketKeepaliveReceiverMap.put(key, mPacketKeepaliveReceiver);
458                 return key;
459             } else {
460                 Log.e("startNattKeepalive fail, startNattKeepalive return null");
461                 return null;
462             }
463         } catch (UnknownHostException e) {
464             Log.e("startNattKeepalive UnknownHostException");
465             return null;
466         }
467     }
468 
469     @Rpc(description = "stop natt keep alive")
connectivityStopNattKeepalive(String key)470     public Boolean connectivityStopNattKeepalive(String key) {
471         PacketKeepaliveReceiver mPacketKeepaliveReceiver =
472                 mPacketKeepaliveReceiverMap.get(key);
473         if (mPacketKeepaliveReceiver != null) {
474             mPacketKeepaliveReceiverMap.remove(key);
475             mPacketKeepaliveReceiver.mPacketKeepalive.stop();
476             return true;
477         } else {
478             return false;
479         }
480     }
481 
482     @Rpc(description = "start listening for NattKeepalive Event")
connectivityNattKeepaliveStartListeningForEvent(String key, String eventString)483     public Boolean connectivityNattKeepaliveStartListeningForEvent(String key, String eventString) {
484         PacketKeepaliveReceiver mPacketKeepaliveReceiver =
485                 mPacketKeepaliveReceiverMap.get(key);
486         if (mPacketKeepaliveReceiver != null) {
487             int event = getPacketKeepaliveReceiverEvent(eventString);
488             if (event == PacketKeepaliveReceiver.EVENT_INVALID) {
489                 return false;
490             }
491             mPacketKeepaliveReceiver.startListeningForEvents(event);
492             return true;
493         } else {
494             return false;
495         }
496     }
497 
498     @Rpc(description = "stop listening for NattKeepalive Event")
connectivityNattKeepaliveStopListeningForEvent(String key, String eventString)499     public Boolean connectivityNattKeepaliveStopListeningForEvent(String key, String eventString) {
500         PacketKeepaliveReceiver mPacketKeepaliveReceiver =
501                 mPacketKeepaliveReceiverMap.get(key);
502         if (mPacketKeepaliveReceiver != null) {
503             int event = getPacketKeepaliveReceiverEvent(eventString);
504             if (event == PacketKeepaliveReceiver.EVENT_INVALID) {
505                 return false;
506             }
507             mPacketKeepaliveReceiver.stopListeningForEvents(event);
508             return true;
509         } else {
510             return false;
511         }
512     }
513 
514     @Rpc(description = "start listening for NetworkCallback Event")
connectivityNetworkCallbackStartListeningForEvent(String key, String eventString)515     public Boolean connectivityNetworkCallbackStartListeningForEvent(String key, String eventString) {
516         NetworkCallback mNetworkCallback = mNetworkCallbackMap.get(key);
517         if (mNetworkCallback != null) {
518             int event = getNetworkCallbackEvent(eventString);
519             if (event == NetworkCallback.EVENT_INVALID) {
520                 return false;
521             }
522             mNetworkCallback.startListeningForEvents(event);
523             return true;
524         } else {
525             return false;
526         }
527     }
528 
529     @Rpc(description = "stop listening for NetworkCallback Event")
connectivityNetworkCallbackStopListeningForEvent(String key, String eventString)530     public Boolean connectivityNetworkCallbackStopListeningForEvent(String key, String eventString) {
531         NetworkCallback mNetworkCallback = mNetworkCallbackMap.get(key);
532         if (mNetworkCallback != null) {
533             int event = getNetworkCallbackEvent(eventString);
534             if (event == NetworkCallback.EVENT_INVALID) {
535                 return false;
536             }
537             mNetworkCallback.stopListeningForEvents(event);
538             return true;
539         } else {
540             return false;
541         }
542     }
543 
544     @Rpc(description = "Set Rssi Threshold Monitor")
connectivitySetRssiThresholdMonitor(Integer rssi)545     public String connectivitySetRssiThresholdMonitor(Integer rssi) {
546         Log.d("SL4A:setRssiThresholdMonitor rssi = " + rssi);
547         NetworkRequest.Builder builder = new NetworkRequest.Builder();
548         builder.setSignalStrength((int) rssi);
549         builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
550         NetworkRequest networkRequest = builder.build();
551         mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
552         mManager.registerNetworkCallback(networkRequest, mNetworkCallback);
553         String key = mNetworkCallback.mId;
554         mNetworkCallbackMap.put(key, mNetworkCallback);
555         return key;
556     }
557 
558     @Rpc(description = "Stop Rssi Threshold Monitor")
connectivityStopRssiThresholdMonitor(String key)559     public Boolean connectivityStopRssiThresholdMonitor(String key) {
560         Log.d("SL4A:stopRssiThresholdMonitor key = " + key);
561         return connectivityUnregisterNetworkCallback(key);
562     }
563 
buildNetworkRequestFromJson(JSONObject configJson)564     private NetworkRequest buildNetworkRequestFromJson(JSONObject configJson)
565             throws JSONException {
566         NetworkRequest.Builder builder = new NetworkRequest.Builder();
567 
568         if (configJson.has("ClearCapabilities")) {
569             /* the 'ClearCapabilities' property does not have a value (that we use). Its presence
570              is used to clear the capabilities of the constructed network request (which is
571              constructed with some default capabilities already present). */
572             Log.d("build ClearCapabilities");
573             builder.clearCapabilities();
574         }
575         if (configJson.has("TransportType")) {
576             Log.d("build TransportType" + configJson.getInt("TransportType"));
577             builder.addTransportType(configJson.getInt("TransportType"));
578         }
579         if (configJson.has("SignalStrength")) {
580             Log.d("build SignalStrength" + configJson.getInt("SignalStrength"));
581             builder.setSignalStrength(configJson.getInt("SignalStrength"));
582         }
583         if (configJson.has("Capability")) {
584             JSONArray capabilities = configJson.getJSONArray("Capability");
585             for (int i = 0; i < capabilities.length(); i++) {
586                 Log.d("build Capability" + capabilities.getInt(i));
587                 builder.addCapability(capabilities.getInt(i));
588             }
589         }
590         if (configJson.has("LinkUpstreamBandwidthKbps")) {
591             Log.d("build LinkUpstreamBandwidthKbps" + configJson.getInt(
592                     "LinkUpstreamBandwidthKbps"));
593             builder.setLinkUpstreamBandwidthKbps(configJson.getInt(
594                     "LinkUpstreamBandwidthKbps"));
595         }
596         if (configJson.has("LinkDownstreamBandwidthKbps")) {
597             Log.d("build LinkDownstreamBandwidthKbps" + configJson.getInt(
598                     "LinkDownstreamBandwidthKbps"));
599             builder.setLinkDownstreamBandwidthKbps(configJson.getInt(
600                     "LinkDownstreamBandwidthKbps"));
601         }
602         if (configJson.has("NetworkSpecifier")) {
603             Log.d("build NetworkSpecifier" + configJson.getString("NetworkSpecifier"));
604             builder.setNetworkSpecifier(configJson.getString(
605                     "NetworkSpecifier"));
606         }
607         NetworkRequest networkRequest = builder.build();
608         return networkRequest;
609     }
610 
611     @Rpc(description = "register a network callback")
connectivityRegisterNetworkCallback(@pcParametername = "configJson") JSONObject configJson)612     public String connectivityRegisterNetworkCallback(@RpcParameter(name = "configJson")
613     JSONObject configJson) throws JSONException {
614         NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
615         mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
616         mManager.registerNetworkCallback(networkRequest, mNetworkCallback);
617         String key = mNetworkCallback.mId;
618         mNetworkCallbackMap.put(key, mNetworkCallback);
619         return key;
620     }
621 
622     @Rpc(description = "unregister a network callback")
connectivityUnregisterNetworkCallback(@pcParametername = "key") String key)623     public Boolean connectivityUnregisterNetworkCallback(@RpcParameter(name = "key")
624     String key) {
625         mNetworkCallback = mNetworkCallbackMap.get(key);
626         if (mNetworkCallback != null) {
627             mNetworkCallbackMap.remove(key);
628             mManager.unregisterNetworkCallback(mNetworkCallback);
629             return true;
630         } else {
631             return false;
632         }
633     }
634 
635     @Rpc(description = "request a network")
connectivityRequestNetwork(@pcParametername = "configJson") JSONObject configJson)636     public String connectivityRequestNetwork(@RpcParameter(name = "configJson")
637     JSONObject configJson) throws JSONException {
638         NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
639         mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
640         mManager.requestNetwork(networkRequest, mNetworkCallback);
641         String key = mNetworkCallback.mId;
642         mNetworkCallbackMap.put(key, mNetworkCallback);
643         return key;
644     }
645 
646     @Rpc(description = "Request a Wi-Fi Aware network")
connectivityRequestWifiAwareNetwork(@pcParametername = "configJson") JSONObject configJson)647     public String connectivityRequestWifiAwareNetwork(@RpcParameter(name = "configJson")
648             JSONObject configJson) throws JSONException {
649         NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
650         if (networkRequest.networkCapabilities.getNetworkSpecifier() instanceof
651                 StringNetworkSpecifier) {
652             String ns =
653                     ((StringNetworkSpecifier) networkRequest.networkCapabilities
654                             .getNetworkSpecifier()).specifier;
655             JSONObject j = new JSONObject(ns);
656             networkRequest.networkCapabilities.setNetworkSpecifier(
657                     WifiAwareManagerFacade.getNetworkSpecifier(j));
658         }
659         mNetworkCallback = new NetworkCallback(NetworkCallback.EVENT_ALL);
660         mManager.requestNetwork(networkRequest, mNetworkCallback);
661         String key = mNetworkCallback.mId;
662         mNetworkCallbackMap.put(key, mNetworkCallback);
663         return key;
664     }
665 
666     @Rpc(description = "Stop listening for connectivity changes")
connectivityStopTrackingConnectivityStateChange()667     public void connectivityStopTrackingConnectivityStateChange() {
668         if (mTrackingConnectivityStateChange) {
669             mTrackingConnectivityStateChange = false;
670             mContext.unregisterReceiver(mConnectivityReceiver);
671         }
672     }
673 
674     @Rpc(description = "Get the extra information about the network state provided by lower network layers.")
connectivityNetworkGetActiveConnectionExtraInfo()675     public String connectivityNetworkGetActiveConnectionExtraInfo() {
676         NetworkInfo current = mManager.getActiveNetworkInfo();
677         if (current == null) {
678             Log.d("No network is active at the moment.");
679             return null;
680         }
681         return current.getExtraInfo();
682     }
683 
684     @Rpc(description = "Return the subtype name of the current network, null if not connected")
connectivityNetworkGetActiveConnectionSubtypeName()685     public String connectivityNetworkGetActiveConnectionSubtypeName() {
686         NetworkInfo current = mManager.getActiveNetworkInfo();
687         if (current == null) {
688             Log.d("No network is active at the moment.");
689             return null;
690         }
691         return current.getSubtypeName();
692     }
693 
694     @Rpc(description = "Return a human-readable name describe the type of the network, e.g. WIFI")
connectivityNetworkGetActiveConnectionTypeName()695     public String connectivityNetworkGetActiveConnectionTypeName() {
696         NetworkInfo current = mManager.getActiveNetworkInfo();
697         if (current == null) {
698             Log.d("No network is active at the moment.");
699             return null;
700         }
701         return current.getTypeName();
702     }
703 
704     @Rpc(description = "Get connection status information about all network types supported by the device.")
connectivityNetworkGetAllInfo()705     public NetworkInfo[] connectivityNetworkGetAllInfo() {
706         return mManager.getAllNetworkInfo();
707     }
708 
709     @Rpc(description = "Check whether the active network is connected to the Internet.")
connectivityNetworkIsConnected()710     public Boolean connectivityNetworkIsConnected() {
711         NetworkInfo current = mManager.getActiveNetworkInfo();
712         if (current == null) {
713             Log.d("No network is active at the moment.");
714             return false;
715         }
716         return current.isConnected();
717     }
718 
719     @Rpc(description = "Checks the airplane mode setting.",
720             returns = "True if airplane mode is enabled.")
connectivityCheckAirplaneMode()721     public Boolean connectivityCheckAirplaneMode() {
722         try {
723             return Settings.Global.getInt(mService.getContentResolver(),
724                     Settings.Global.AIRPLANE_MODE_ON) == AIRPLANE_MODE_ON;
725         } catch (Settings.SettingNotFoundException e) {
726             Log.e("Settings.Global.AIRPLANE_MODE_ON not found!");
727             return false;
728         }
729     }
730 
731     @Rpc(description = "Toggles airplane mode on and off.",
732             returns = "True if airplane mode is enabled.")
connectivityToggleAirplaneMode(@pcParametername = "enabled") @pcOptional Boolean enabled)733     public void connectivityToggleAirplaneMode(@RpcParameter(name = "enabled")
734     @RpcOptional
735     Boolean enabled) {
736         if (enabled == null) {
737             enabled = !connectivityCheckAirplaneMode();
738         }
739         mManager.setAirplaneMode(enabled);
740     }
741 
742     /**
743     * Check global data roaming setting.
744     * @return True if roaming is enabled; false otherwise.
745     */
746     @Rpc(description = "Checks data roaming mode setting.",
747             returns = "True if data roaming mode is enabled.")
connectivityCheckDataRoamingMode()748     public Boolean connectivityCheckDataRoamingMode() {
749         try {
750             return Settings.Global.getInt(mService.getContentResolver(),
751                     Settings.Global.DATA_ROAMING) == DATA_ROAMING_ON;
752         } catch (Settings.SettingNotFoundException e) {
753             Log.e("Settings.Global.DATA_ROAMING not found!");
754             return false;
755         }
756     }
757 
758     /**
759     * Enable or disable data roaming.
760     * @param roaming 1: Enable data roaming; 0: Disable data roaming.
761     * @return True for setting roaming mode successfully; false otherwise.
762     */
763     @Rpc(description = "Set Data Roaming Enabled or Disabled")
connectivitySetDataRoaming( @pcParametername = "roaming") Integer roaming)764     public boolean connectivitySetDataRoaming(
765             @RpcParameter(name = "roaming") Integer roaming) {
766         Log.d("connectivitySetDataRoaming by SubscriptionManager");
767         return Settings.Global.putInt(mService.getContentResolver(),
768                     Settings.Global.DATA_ROAMING, roaming);
769     }
770 
771     @Rpc(description = "Check if tethering supported or not.",
772             returns = "True if tethering is supported.")
connectivityIsTetheringSupported()773     public boolean connectivityIsTetheringSupported() {
774         return mManager.isTetheringSupported();
775     }
776 
777     @Rpc(description = "Call to start tethering with a provisioning check if needed")
connectivityStartTethering(@pcParametername = "type") Integer type, @RpcParameter(name = "showProvisioningUi") Boolean showProvisioningUi)778     public void connectivityStartTethering(@RpcParameter(name = "type") Integer type,
779             @RpcParameter(name = "showProvisioningUi") Boolean showProvisioningUi) {
780         Log.d("startTethering for type: " + type + " showProvUi: " + showProvisioningUi);
781         OnStartTetheringCallback tetherCallback = new OnStartTetheringCallback();
782         mManager.startTethering(type, showProvisioningUi, tetherCallback);
783     }
784 
785     @Rpc(description = "Call to stop tethering")
connectivityStopTethering(@pcParametername = "type") Integer type)786     public void connectivityStopTethering(@RpcParameter(name = "type") Integer type) {
787         Log.d("stopTethering for type: " + type);
788         mManager.stopTethering(type);
789     }
790 
791     @Rpc(description = "Returns the link local IPv6 address of the interface.")
connectivityGetLinkLocalIpv6Address(@pcParametername = "ifaceName") String ifaceName)792     public String connectivityGetLinkLocalIpv6Address(@RpcParameter(name = "ifaceName")
793             String ifaceName) {
794         NetworkInterface iface = null;
795         try {
796             iface = NetworkInterface.getByName(ifaceName);
797         } catch (SocketException e) {
798             return null;
799         }
800 
801         if (iface == null) {
802             return null;
803         }
804 
805         Inet6Address inet6Address = null;
806         Enumeration<InetAddress> inetAddresses = iface.getInetAddresses();
807         while (inetAddresses.hasMoreElements()) {
808             InetAddress addr = inetAddresses.nextElement();
809             if (addr instanceof Inet6Address) {
810                 if (((Inet6Address) addr).isLinkLocalAddress()) {
811                     inet6Address = (Inet6Address) addr;
812                     break;
813                 }
814             }
815         }
816 
817         if (inet6Address == null) {
818             return null;
819         }
820 
821         return inet6Address.getHostAddress();
822     }
823 
824     @Rpc(description = "Returns active link properties")
connectivityGetActiveLinkProperties()825     public LinkProperties connectivityGetActiveLinkProperties() {
826         return mManager.getActiveLinkProperties();
827     }
828 
829     @Override
shutdown()830     public void shutdown() {
831         connectivityStopTrackingConnectivityStateChange();
832     }
833 }
834