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