• 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 static android.net.NetworkCapabilities.TRANSPORT_WIFI;
20 
21 import android.app.Service;
22 import android.app.usage.NetworkStats;
23 import android.app.usage.NetworkStats.Bucket;
24 import android.app.usage.NetworkStatsManager;
25 import android.content.BroadcastReceiver;
26 import android.content.Context;
27 import android.content.Intent;
28 import android.content.IntentFilter;
29 import android.net.ConnectivityManager;
30 import android.net.LinkProperties;
31 import android.net.Network;
32 import android.net.NetworkCapabilities;
33 import android.net.NetworkInfo;
34 import android.net.NetworkPolicy;
35 import android.net.NetworkPolicyManager;
36 import android.net.NetworkRequest;
37 import android.net.NetworkSpecifier;
38 import android.net.ProxyInfo;
39 import android.net.RouteInfo;
40 import android.net.Uri;
41 import android.net.wifi.WifiNetworkSpecifier;
42 import android.os.Bundle;
43 import android.os.RemoteException;
44 import android.provider.Settings;
45 
46 import com.android.modules.utils.build.SdkLevel;
47 
48 import com.google.common.io.ByteStreams;
49 import com.googlecode.android_scripting.FileUtils;
50 import com.googlecode.android_scripting.Log;
51 import com.googlecode.android_scripting.facade.wifi.WifiAwareManagerFacade;
52 import com.googlecode.android_scripting.facade.wifi.WifiManagerFacade;
53 import com.googlecode.android_scripting.jsonrpc.RpcReceiver;
54 import com.googlecode.android_scripting.rpc.Rpc;
55 import com.googlecode.android_scripting.rpc.RpcOptional;
56 import com.googlecode.android_scripting.rpc.RpcParameter;
57 
58 import org.json.JSONArray;
59 import org.json.JSONException;
60 import org.json.JSONObject;
61 
62 import java.io.BufferedInputStream;
63 import java.io.File;
64 import java.io.FileOutputStream;
65 import java.io.IOException;
66 import java.io.InputStream;
67 import java.io.OutputStream;
68 import java.net.Inet4Address;
69 import java.net.Inet6Address;
70 import java.net.InetAddress;
71 import java.net.NetworkInterface;
72 import java.net.SocketException;
73 import java.net.URL;
74 import java.net.URLConnection;
75 import java.security.GeneralSecurityException;
76 import java.util.ArrayList;
77 import java.util.Collections;
78 import java.util.Enumeration;
79 import java.util.HashMap;
80 import java.util.List;
81 
82 /**
83  * Access ConnectivityManager functions.
84  */
85 public class ConnectivityManagerFacade extends RpcReceiver {
86 
87     public static int AIRPLANE_MODE_OFF = 0;
88     public static int AIRPLANE_MODE_ON = 1;
89     public static int DATA_ROAMING_ON = 1;
90 
91     private static HashMap<Long, Network> sNetworkHashMap = new HashMap<Long, Network>();
92 
93     class ConnectivityReceiver extends BroadcastReceiver {
94 
95         @Override
onReceive(Context context, Intent intent)96         public void onReceive(Context context, Intent intent) {
97             String action = intent.getAction();
98 
99             if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
100                 Log.e("ConnectivityReceiver received non-connectivity action!");
101                 return;
102             }
103 
104             Bundle b = intent.getExtras();
105 
106             if (b == null) {
107                 Log.e("ConnectivityReceiver failed to receive extras!");
108                 return;
109             }
110 
111             int netType =
112                     b.getInt(ConnectivityManager.EXTRA_NETWORK_TYPE,
113                             ConnectivityManager.TYPE_NONE);
114 
115             if (netType == ConnectivityManager.TYPE_NONE) {
116                 Log.i("ConnectivityReceiver received change to TYPE_NONE.");
117                 return;
118             }
119 
120             /*
121              * Technically there is a race condition here, but retrieving the NetworkInfo from the
122              * bundle is deprecated. See ConnectivityManager.EXTRA_NETWORK_INFO
123              */
124             for (NetworkInfo info : mManager.getAllNetworkInfo()) {
125                 if (info.getType() == netType) {
126                     mEventFacade.postEvent(ConnectivityConstants.EventConnectivityChanged, info);
127                 }
128             }
129         }
130     }
131 
132     /**
133      * Used to dispatch to a different constructor depending on R or S, since
134      * {@link ConnectivityManager.NetworkCallback#NetworkCallback(int)} was added in S.
135      */
newNetworkCallback(int events)136     private NetworkCallback newNetworkCallback(int events) {
137         if (SdkLevel.isAtLeastS()) {
138             return new NetworkCallback(events);
139         } else {
140             return new NetworkCallback(events, false);
141         }
142     }
143 
144     private class NetworkCallback extends ConnectivityManager.NetworkCallback {
145         public static final int EVENT_INVALID = -1;
146         public static final int EVENT_NONE = 0;
147         public static final int EVENT_PRECHECK = 1 << 0;
148         public static final int EVENT_AVAILABLE = 1 << 1;
149         public static final int EVENT_LOSING = 1 << 2;
150         public static final int EVENT_LOST = 1 << 3;
151         public static final int EVENT_UNAVAILABLE = 1 << 4;
152         public static final int EVENT_CAPABILITIES_CHANGED = 1 << 5;
153         public static final int EVENT_SUSPENDED = 1 << 6;
154         public static final int EVENT_RESUMED = 1 << 7;
155         public static final int EVENT_LINK_PROPERTIES_CHANGED = 1 << 8;
156         public static final int EVENT_BLOCKED_STATUS_CHANGED = 1 << 9;
157         public static final int EVENT_ALL =
158                 EVENT_PRECHECK
159                         | EVENT_AVAILABLE
160                         | EVENT_LOSING
161                         | EVENT_LOST
162                         | EVENT_UNAVAILABLE
163                         | EVENT_CAPABILITIES_CHANGED
164                         | EVENT_SUSPENDED
165                         | EVENT_RESUMED
166                         | EVENT_LINK_PROPERTIES_CHANGED
167                         | EVENT_BLOCKED_STATUS_CHANGED;
168 
169         private int mEvents;
170         public String mId;
171         private long mCreateTimestamp;
172 
173         /** Called in >= Android S where super(int) does exist. */
NetworkCallback(int events)174         private NetworkCallback(int events) {
175             super(ConnectivityManager.NetworkCallback.FLAG_INCLUDE_LOCATION_INFO);
176             init(events);
177         }
178 
179         /**
180          * Called in <= Android R where super(int) doesn't exist.
181          * @param ignore placeholder argument to differentiate between R and S constructors' method
182          *              signatures.
183          */
NetworkCallback(int events, boolean ignore)184         private NetworkCallback(int events, boolean ignore) {
185             super();
186             init(events);
187         }
188 
init(int events)189         private void init(int events) {
190             mEvents = events;
191             mId = this.toString();
192             mCreateTimestamp = System.currentTimeMillis();
193         }
194 
startListeningForEvents(int events)195         public void startListeningForEvents(int events) {
196             mEvents |= events & EVENT_ALL;
197         }
198 
stopListeningForEvents(int events)199         public void stopListeningForEvents(int events) {
200             mEvents &= ~(events & EVENT_ALL);
201         }
202 
203         @Override
onPreCheck(Network network)204         public void onPreCheck(Network network) {
205             Log.d("NetworkCallback onPreCheck");
206             if ((mEvents & EVENT_PRECHECK) == EVENT_PRECHECK) {
207                 mEventFacade.postEvent(
208                         ConnectivityConstants.EventNetworkCallback,
209                     new ConnectivityEvents.NetworkCallbackEventBase(
210                         mId,
211                         getNetworkCallbackEventString(EVENT_PRECHECK), mCreateTimestamp));
212             }
213         }
214 
215         @Override
onAvailable(Network network)216         public void onAvailable(Network network) {
217             Log.d("NetworkCallback onAvailable");
218             if ((mEvents & EVENT_AVAILABLE) == EVENT_AVAILABLE) {
219                 mEventFacade.postEvent(
220                         ConnectivityConstants.EventNetworkCallback,
221                     new ConnectivityEvents.NetworkCallbackEventBase(
222                         mId,
223                         getNetworkCallbackEventString(EVENT_AVAILABLE), mCreateTimestamp));
224             }
225         }
226 
227         @Override
onLosing(Network network, int maxMsToLive)228         public void onLosing(Network network, int maxMsToLive) {
229             Log.d("NetworkCallback onLosing");
230             if ((mEvents & EVENT_LOSING) == EVENT_LOSING) {
231                 mEventFacade.postEvent(
232                         ConnectivityConstants.EventNetworkCallback,
233                     new ConnectivityEvents.NetworkCallbackEventOnLosing(
234                         mId,
235                         getNetworkCallbackEventString(EVENT_LOSING), mCreateTimestamp,
236                         maxMsToLive));
237             }
238         }
239 
240         @Override
onLost(Network network)241         public void onLost(Network network) {
242             Log.d("NetworkCallback onLost");
243             if ((mEvents & EVENT_LOST) == EVENT_LOST) {
244                 mEventFacade.postEvent(
245                         ConnectivityConstants.EventNetworkCallback,
246                     new ConnectivityEvents.NetworkCallbackEventBase(
247                         mId,
248                         getNetworkCallbackEventString(EVENT_LOST), mCreateTimestamp));
249             }
250         }
251 
252         @Override
onUnavailable()253         public void onUnavailable() {
254             Log.d("NetworkCallback onUnavailable");
255             if ((mEvents & EVENT_UNAVAILABLE) == EVENT_UNAVAILABLE) {
256                 mEventFacade.postEvent(
257                         ConnectivityConstants.EventNetworkCallback,
258                     new ConnectivityEvents.NetworkCallbackEventBase(
259                         mId,
260                         getNetworkCallbackEventString(EVENT_UNAVAILABLE), mCreateTimestamp));
261             }
262         }
263 
264         @Override
onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities)265         public void onCapabilitiesChanged(Network network,
266                 NetworkCapabilities networkCapabilities) {
267             Log.d("NetworkCallback onCapabilitiesChanged. RSSI:" +
268                     networkCapabilities.getSignalStrength());
269             if ((mEvents & EVENT_CAPABILITIES_CHANGED) == EVENT_CAPABILITIES_CHANGED) {
270                 mEventFacade.postEvent(
271                         ConnectivityConstants.EventNetworkCallback,
272                     new ConnectivityEvents.NetworkCallbackEventOnCapabilitiesChanged(
273                         mId,
274                         getNetworkCallbackEventString(EVENT_CAPABILITIES_CHANGED), mCreateTimestamp,
275                         networkCapabilities));
276             }
277         }
278 
279         @Override
onBlockedStatusChanged(Network network, boolean blocked)280         public void onBlockedStatusChanged(Network network, boolean blocked) {
281             Log.d("NetworkCallback onBlockedStatusChanged");
282             if ((mEvents & EVENT_BLOCKED_STATUS_CHANGED) == EVENT_BLOCKED_STATUS_CHANGED) {
283                 mEventFacade.postEvent(
284                         ConnectivityConstants.EventNetworkCallback,
285                         new ConnectivityEvents.NetworkCallbackEventBase(
286                             mId,
287                             getNetworkCallbackEventString(EVENT_BLOCKED_STATUS_CHANGED),
288                             mCreateTimestamp));
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             case ConnectivityConstants.NetworkCallbackBlockedStatusChanged:
352                 return NetworkCallback.EVENT_BLOCKED_STATUS_CHANGED;
353         }
354         return NetworkCallback.EVENT_INVALID;
355     }
356 
getNetworkCallbackEventString(int event)357     private static String getNetworkCallbackEventString(int event) {
358         switch (event) {
359             case NetworkCallback.EVENT_PRECHECK:
360                 return ConnectivityConstants.NetworkCallbackPreCheck;
361             case NetworkCallback.EVENT_AVAILABLE:
362                 return ConnectivityConstants.NetworkCallbackAvailable;
363             case NetworkCallback.EVENT_LOSING:
364                 return ConnectivityConstants.NetworkCallbackLosing;
365             case NetworkCallback.EVENT_LOST:
366                 return ConnectivityConstants.NetworkCallbackLost;
367             case NetworkCallback.EVENT_UNAVAILABLE:
368                 return ConnectivityConstants.NetworkCallbackUnavailable;
369             case NetworkCallback.EVENT_CAPABILITIES_CHANGED:
370                 return ConnectivityConstants.NetworkCallbackCapabilitiesChanged;
371             case NetworkCallback.EVENT_SUSPENDED:
372                 return ConnectivityConstants.NetworkCallbackSuspended;
373             case NetworkCallback.EVENT_RESUMED:
374                 return ConnectivityConstants.NetworkCallbackResumed;
375             case NetworkCallback.EVENT_LINK_PROPERTIES_CHANGED:
376                 return ConnectivityConstants.NetworkCallbackLinkPropertiesChanged;
377             case NetworkCallback.EVENT_BLOCKED_STATUS_CHANGED:
378                 return ConnectivityConstants.NetworkCallbackBlockedStatusChanged;
379         }
380         return ConnectivityConstants.NetworkCallbackInvalid;
381     }
382 
383     /**
384      * Callbacks used in ConnectivityManager to confirm tethering has started/failed.
385      */
386     class OnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback {
387         @Override
onTetheringStarted()388         public void onTetheringStarted() {
389             mEventFacade.postEvent(ConnectivityConstants.TetheringStartedCallback, null);
390         }
391 
392         @Override
onTetheringFailed()393         public void onTetheringFailed() {
394             mEventFacade.postEvent(ConnectivityConstants.TetheringFailedCallback, null);
395         }
396     }
397 
398     private final ConnectivityManager mManager;
399     private NetworkPolicyManager mNetPolicyManager;
400     private NetworkStatsManager mNetStatsManager;
401     private final Service mService;
402     private final Context mContext;
403     private final ConnectivityReceiver mConnectivityReceiver;
404     private final EventFacade mEventFacade;
405     private NetworkCallback mNetworkCallback;
406     private static HashMap<String, NetworkCallback> mNetworkCallbackMap =
407             new HashMap<String, NetworkCallback>();
408     private boolean mTrackingConnectivityStateChange;
409 
ConnectivityManagerFacade(FacadeManager manager)410     public ConnectivityManagerFacade(FacadeManager manager) {
411         super(manager);
412         mService = manager.getService();
413         mContext = mService.getBaseContext();
414         mManager = (ConnectivityManager) mService.getSystemService(Context.CONNECTIVITY_SERVICE);
415         mNetPolicyManager = NetworkPolicyManager.from(mContext);
416         mNetStatsManager = (NetworkStatsManager)
417               mService.getSystemService(Context.NETWORK_STATS_SERVICE);
418         mEventFacade = manager.getReceiver(EventFacade.class);
419         mConnectivityReceiver = new ConnectivityReceiver();
420         mTrackingConnectivityStateChange = false;
421     }
422 
423     @Rpc(description = "Listen for connectivity changes")
connectivityStartTrackingConnectivityStateChange()424     public void connectivityStartTrackingConnectivityStateChange() {
425         if (!mTrackingConnectivityStateChange) {
426             mTrackingConnectivityStateChange = true;
427             mContext.registerReceiver(mConnectivityReceiver,
428                     new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
429         }
430     }
431 
432     @Rpc(description = "start listening for NetworkCallback Event")
connectivityNetworkCallbackStartListeningForEvent(String key, String eventString)433     public Boolean connectivityNetworkCallbackStartListeningForEvent(String key, String eventString) {
434         NetworkCallback mNetworkCallback = mNetworkCallbackMap.get(key);
435         if (mNetworkCallback != null) {
436             int event = getNetworkCallbackEvent(eventString);
437             if (event == NetworkCallback.EVENT_INVALID) {
438                 return false;
439             }
440             mNetworkCallback.startListeningForEvents(event);
441             return true;
442         } else {
443             return false;
444         }
445     }
446 
447     @Rpc(description = "stop listening for NetworkCallback Event")
connectivityNetworkCallbackStopListeningForEvent(String key, String eventString)448     public Boolean connectivityNetworkCallbackStopListeningForEvent(String key, String eventString) {
449         NetworkCallback mNetworkCallback = mNetworkCallbackMap.get(key);
450         if (mNetworkCallback != null) {
451             int event = getNetworkCallbackEvent(eventString);
452             if (event == NetworkCallback.EVENT_INVALID) {
453                 return false;
454             }
455             mNetworkCallback.stopListeningForEvents(event);
456             return true;
457         } else {
458             return false;
459         }
460     }
461 
462     @Rpc(description = "Set Rssi Threshold Monitor")
connectivitySetRssiThresholdMonitor(Integer rssi)463     public String connectivitySetRssiThresholdMonitor(Integer rssi) {
464         Log.d("SL4A:setRssiThresholdMonitor rssi = " + rssi);
465         NetworkRequest.Builder builder = new NetworkRequest.Builder();
466         builder.setSignalStrength((int) rssi);
467         builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
468         NetworkRequest networkRequest = builder.build();
469         mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
470         mManager.registerNetworkCallback(networkRequest, mNetworkCallback);
471         String key = mNetworkCallback.mId;
472         mNetworkCallbackMap.put(key, mNetworkCallback);
473         return key;
474     }
475 
476     @Rpc(description = "Stop Rssi Threshold Monitor")
connectivityStopRssiThresholdMonitor(String key)477     public Boolean connectivityStopRssiThresholdMonitor(String key) {
478         Log.d("SL4A:stopRssiThresholdMonitor key = " + key);
479         return connectivityUnregisterNetworkCallback(key);
480     }
481 
buildNetworkRequestFromJson(JSONObject configJson)482     private NetworkRequest buildNetworkRequestFromJson(JSONObject configJson)
483             throws JSONException {
484         return makeNetworkRequestBuilderFromJson(configJson).build();
485     }
486 
buildWifiAwareNetworkRequestFromJson(JSONObject configJson)487     private NetworkRequest buildWifiAwareNetworkRequestFromJson(JSONObject configJson)
488             throws JSONException {
489         final NetworkRequest.Builder builder = makeNetworkRequestBuilderFromJson(configJson);
490         if (configJson.has("NetworkSpecifier")) {
491             final String strSpecifier = configJson.getString("NetworkSpecifier");
492             Log.d("build NetworkSpecifier" + strSpecifier);
493             final NetworkSpecifier specifier = WifiAwareManagerFacade.getNetworkSpecifier(
494                     new JSONObject(strSpecifier));
495             builder.setNetworkSpecifier(specifier);
496         }
497         return builder.build();
498     }
499 
makeNetworkRequestBuilderFromJson(JSONObject configJson)500     private NetworkRequest.Builder makeNetworkRequestBuilderFromJson(JSONObject configJson)
501             throws JSONException {
502         NetworkRequest.Builder builder = new NetworkRequest.Builder();
503 
504         if (configJson.has("ClearCapabilities")) {
505             /* the 'ClearCapabilities' property does not have a value (that we use). Its presence
506              is used to clear the capabilities of the constructed network request (which is
507              constructed with some default capabilities already present). */
508             Log.d("build ClearCapabilities");
509             builder.clearCapabilities();
510         }
511         if (configJson.has(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE)) {
512             Log.d("build TransportType"
513                     + configJson.getInt(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE));
514             builder.addTransportType(
515                     configJson.getInt(ConnectivityConstants.NET_CAPABILITIES_TRANSPORT_TYPE));
516         }
517         if (configJson.has("SignalStrength")) {
518             Log.d("build SignalStrength" + configJson.getInt("SignalStrength"));
519             builder.setSignalStrength(configJson.getInt("SignalStrength"));
520         }
521         if (configJson.has(ConnectivityConstants.NET_CAPABILITIES_CAPABILITIES)) {
522             JSONArray capabilities =
523                     configJson.getJSONArray(ConnectivityConstants.NET_CAPABILITIES_CAPABILITIES);
524             for (int i = 0; i < capabilities.length(); i++) {
525                 Log.d("build Capability" + capabilities.getInt(i));
526                 builder.addCapability(capabilities.getInt(i));
527             }
528         }
529         if (configJson.has("LinkUpstreamBandwidthKbps")) {
530             Log.d("build LinkUpstreamBandwidthKbps" + configJson.getInt(
531                     "LinkUpstreamBandwidthKbps"));
532             builder.setLinkUpstreamBandwidthKbps(configJson.getInt(
533                     "LinkUpstreamBandwidthKbps"));
534         }
535         if (configJson.has("LinkDownstreamBandwidthKbps")) {
536             Log.d("build LinkDownstreamBandwidthKbps" + configJson.getInt(
537                     "LinkDownstreamBandwidthKbps"));
538             builder.setLinkDownstreamBandwidthKbps(configJson.getInt(
539                     "LinkDownstreamBandwidthKbps"));
540         }
541         return builder;
542     }
543 
544     @Rpc(description = "register a network callback")
connectivityRegisterNetworkCallback(@pcParametername = "configJson") JSONObject configJson)545     public String connectivityRegisterNetworkCallback(@RpcParameter(name = "configJson")
546     JSONObject configJson) throws JSONException {
547         NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
548         mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
549         mManager.registerNetworkCallback(networkRequest, mNetworkCallback);
550         String key = mNetworkCallback.mId;
551         mNetworkCallbackMap.put(key, mNetworkCallback);
552         return key;
553     }
554 
555     @Rpc(description = "unregister a network callback")
connectivityUnregisterNetworkCallback(@pcParametername = "key") String key)556     public Boolean connectivityUnregisterNetworkCallback(@RpcParameter(name = "key")
557     String key) {
558         mNetworkCallback = mNetworkCallbackMap.get(key);
559         if (mNetworkCallback != null) {
560             mNetworkCallbackMap.remove(key);
561             mManager.unregisterNetworkCallback(mNetworkCallback);
562             return true;
563         } else {
564             return false;
565         }
566     }
567 
568     @Rpc(description = "register a default network callback")
connectivityRegisterDefaultNetworkCallback()569     public String connectivityRegisterDefaultNetworkCallback() {
570         mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
571         mManager.registerDefaultNetworkCallback(mNetworkCallback);
572         String key = mNetworkCallback.mId;
573         mNetworkCallbackMap.put(key, mNetworkCallback);
574         return key;
575     }
576 
577     @Rpc(description = "request a network")
connectivityRequestNetwork(@pcParametername = "configJson") JSONObject configJson)578     public String connectivityRequestNetwork(@RpcParameter(name = "configJson")
579     JSONObject configJson) throws JSONException {
580         NetworkRequest networkRequest = buildNetworkRequestFromJson(configJson);
581         mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
582         mManager.requestNetwork(networkRequest, mNetworkCallback);
583         String key = mNetworkCallback.mId;
584         mNetworkCallbackMap.put(key, mNetworkCallback);
585         return key;
586     }
587 
588     @Rpc(description = "Request a Wi-Fi Aware network")
connectivityRequestWifiAwareNetwork(@pcParametername = "configJson") JSONObject configJson)589     public String connectivityRequestWifiAwareNetwork(@RpcParameter(name = "configJson")
590             JSONObject configJson) throws JSONException {
591         NetworkRequest networkRequest = buildWifiAwareNetworkRequestFromJson(configJson);
592         mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
593         mManager.requestNetwork(networkRequest, mNetworkCallback);
594         String key = mNetworkCallback.mId;
595         mNetworkCallbackMap.put(key, mNetworkCallback);
596         return key;
597     }
598 
599     /**
600      * Initiates a network request {@link NetworkRequest} using {@link WifiNetworkSpecifier}.
601      *
602      * @param wNs JSONObject Dictionary of wifi network specifier parameters
603      * @param timeoutInMs Timeout for the request. 0 indicates no timeout.
604      * @throws JSONException
605      * @throws GeneralSecurityException
606      */
607     @Rpc(description = "Initiates a network request using the provided network specifier")
connectivityRequestWifiNetwork( @pcParametername = "wifiNetworkSpecifier") JSONObject wNs, @RpcParameter(name = "timeoutInMS") Integer timeoutInMs)608     public String connectivityRequestWifiNetwork(
609             @RpcParameter(name = "wifiNetworkSpecifier") JSONObject wNs,
610             @RpcParameter(name = "timeoutInMS") Integer timeoutInMs)
611             throws JSONException, GeneralSecurityException {
612         NetworkRequest networkRequest = new NetworkRequest.Builder()
613                 .addTransportType(TRANSPORT_WIFI)
614                 .setNetworkSpecifier(WifiManagerFacade.genWifiNetworkSpecifier(wNs))
615                 .build();
616         mNetworkCallback = newNetworkCallback(NetworkCallback.EVENT_ALL);
617         if (timeoutInMs != 0) {
618             mManager.requestNetwork(networkRequest, mNetworkCallback, timeoutInMs);
619         } else {
620             mManager.requestNetwork(networkRequest, mNetworkCallback);
621         }
622         String key = mNetworkCallback.mId;
623         mNetworkCallbackMap.put(key, mNetworkCallback);
624         return key;
625     }
626 
627     @Rpc(description = "Stop listening for connectivity changes")
connectivityStopTrackingConnectivityStateChange()628     public void connectivityStopTrackingConnectivityStateChange() {
629         if (mTrackingConnectivityStateChange) {
630             mTrackingConnectivityStateChange = false;
631             mContext.unregisterReceiver(mConnectivityReceiver);
632         }
633     }
634 
635     @Rpc(description = "Get the extra information about the network state provided by lower network layers.")
connectivityNetworkGetActiveConnectionExtraInfo()636     public String connectivityNetworkGetActiveConnectionExtraInfo() {
637         NetworkInfo current = mManager.getActiveNetworkInfo();
638         if (current == null) {
639             Log.d("No network is active at the moment.");
640             return null;
641         }
642         return current.getExtraInfo();
643     }
644 
645     @Rpc(description = "Return the subtype name of the current network, null if not connected")
connectivityNetworkGetActiveConnectionSubtypeName()646     public String connectivityNetworkGetActiveConnectionSubtypeName() {
647         NetworkInfo current = mManager.getActiveNetworkInfo();
648         if (current == null) {
649             Log.d("No network is active at the moment.");
650             return null;
651         }
652         return current.getSubtypeName();
653     }
654 
655     @Rpc(description = "Return a human-readable name describe the type of the network, e.g. WIFI")
connectivityNetworkGetActiveConnectionTypeName()656     public String connectivityNetworkGetActiveConnectionTypeName() {
657         NetworkInfo current = mManager.getActiveNetworkInfo();
658         if (current == null) {
659             Log.d("No network is active at the moment.");
660             return null;
661         }
662         return current.getTypeName();
663     }
664 
665     @Rpc(description = "Get connection status information about all network types supported by the device.")
connectivityNetworkGetAllInfo()666     public NetworkInfo[] connectivityNetworkGetAllInfo() {
667         return mManager.getAllNetworkInfo();
668     }
669 
670     @Rpc(description = "Get connection status information about all network types supported by the device.")
connectivityNetworkGetAllCapabilities()671     public NetworkCapabilities[] connectivityNetworkGetAllCapabilities() {
672         Network[] networks = mManager.getAllNetworks();
673         NetworkCapabilities[] networkCapabilties = new NetworkCapabilities[networks.length];
674         for (int i = 0; i < networks.length; i++) {
675             networkCapabilties[i] = mManager.getNetworkCapabilities(networks[i]);
676         }
677         return networkCapabilties;
678     }
679 
680     @Rpc(description = "Check whether the active network is connected to the Internet.")
connectivityNetworkIsConnected()681     public Boolean connectivityNetworkIsConnected() {
682         NetworkInfo current = mManager.getActiveNetworkInfo();
683         if (current == null) {
684             Log.d("No network is active at the moment.");
685             return false;
686         }
687         return current.isConnected();
688     }
689 
690     @Rpc(description = "Checks the airplane mode setting.",
691             returns = "True if airplane mode is enabled.")
connectivityCheckAirplaneMode()692     public Boolean connectivityCheckAirplaneMode() {
693         try {
694             return Settings.Global.getInt(mService.getContentResolver(),
695                     Settings.Global.AIRPLANE_MODE_ON) == AIRPLANE_MODE_ON;
696         } catch (Settings.SettingNotFoundException e) {
697             Log.e("Settings.Global.AIRPLANE_MODE_ON not found!");
698             return false;
699         }
700     }
701 
702     @Rpc(description = "Toggles airplane mode on and off.",
703             returns = "True if airplane mode is enabled.")
connectivityToggleAirplaneMode(@pcParametername = "enabled") @pcOptional Boolean enabled)704     public void connectivityToggleAirplaneMode(@RpcParameter(name = "enabled")
705     @RpcOptional
706     Boolean enabled) {
707         if (enabled == null) {
708             enabled = !connectivityCheckAirplaneMode();
709         }
710         mManager.setAirplaneMode(enabled);
711     }
712 
713     /**
714     * Check global data roaming setting.
715     * @return True if roaming is enabled; false otherwise.
716     */
717     @Rpc(description = "Checks data roaming mode setting.",
718             returns = "True if data roaming mode is enabled.")
connectivityCheckDataRoamingMode()719     public Boolean connectivityCheckDataRoamingMode() {
720         try {
721             return Settings.Global.getInt(mService.getContentResolver(),
722                     Settings.Global.DATA_ROAMING) == DATA_ROAMING_ON;
723         } catch (Settings.SettingNotFoundException e) {
724             Log.e("Settings.Global.DATA_ROAMING not found!");
725             return false;
726         }
727     }
728 
729     /**
730     * Enable or disable data roaming.
731     * @param roaming 1: Enable data roaming; 0: Disable data roaming.
732     * @return True for setting roaming mode successfully; false otherwise.
733     */
734     @Rpc(description = "Set Data Roaming Enabled or Disabled")
connectivitySetDataRoaming( @pcParametername = "roaming") Integer roaming)735     public boolean connectivitySetDataRoaming(
736             @RpcParameter(name = "roaming") Integer roaming) {
737         Log.d("connectivitySetDataRoaming by SubscriptionManager");
738         return Settings.Global.putInt(mService.getContentResolver(),
739                     Settings.Global.DATA_ROAMING, roaming);
740     }
741 
742     @Rpc(description = "Check if tethering supported or not.",
743             returns = "True if tethering is supported.")
connectivityIsTetheringSupported()744     public boolean connectivityIsTetheringSupported() {
745         return mManager.isTetheringSupported();
746     }
747 
748     @Rpc(description = "Call to start tethering with a provisioning check if needed")
connectivityStartTethering(@pcParametername = "type") Integer type, @RpcParameter(name = "showProvisioningUi") Boolean showProvisioningUi)749     public void connectivityStartTethering(@RpcParameter(name = "type") Integer type,
750             @RpcParameter(name = "showProvisioningUi") Boolean showProvisioningUi) {
751         Log.d("startTethering for type: " + type + " showProvUi: " + showProvisioningUi);
752         OnStartTetheringCallback tetherCallback = new OnStartTetheringCallback();
753         mManager.startTethering(type, showProvisioningUi, tetherCallback);
754     }
755 
756     @Rpc(description = "Call to stop tethering")
connectivityStopTethering(@pcParametername = "type") Integer type)757     public void connectivityStopTethering(@RpcParameter(name = "type") Integer type) {
758         Log.d("stopTethering for type: " + type);
759         mManager.stopTethering(type);
760     }
761 
getInetAddrsForInterface(String ifaceName)762     private Enumeration<InetAddress> getInetAddrsForInterface(String ifaceName) {
763         NetworkInterface iface = null;
764         try {
765             iface = NetworkInterface.getByName(ifaceName);
766         } catch (SocketException e) {
767             return null;
768         }
769 
770         if (iface == null)
771             return null;
772         return iface.getInetAddresses();
773     }
774 
775     @Rpc(description = "Returns the link local IPv6 address of the interface.")
connectivityGetLinkLocalIpv6Address(@pcParametername = "ifaceName") String ifaceName)776     public String connectivityGetLinkLocalIpv6Address(@RpcParameter(name = "ifaceName")
777             String ifaceName) {
778         Inet6Address inet6Address = null;
779         Enumeration<InetAddress> inetAddresses = getInetAddrsForInterface(ifaceName);
780         if (inetAddresses == null) {
781             return null;
782         }
783 
784         while (inetAddresses.hasMoreElements()) {
785             InetAddress addr = inetAddresses.nextElement();
786             if (addr instanceof Inet6Address) {
787                 if (((Inet6Address) addr).isLinkLocalAddress()) {
788                     inet6Address = (Inet6Address) addr;
789                     break;
790                 }
791             }
792         }
793 
794         if (inet6Address == null) {
795             return null;
796         }
797 
798         return inet6Address.getHostAddress();
799     }
800 
801     @Rpc(description = "Return IPv4 address of an interface")
connectivityGetIPv4Addresses( @pcParametername = "ifaceName") String ifaceName)802     public List<String> connectivityGetIPv4Addresses(
803             @RpcParameter(name = "ifaceName") String ifaceName) {
804         Enumeration<InetAddress> inetAddresses
805                 = getInetAddrsForInterface(ifaceName);
806         if (inetAddresses == null)
807             return null;
808 
809         List<String> inetAddrs = new ArrayList<String>();
810         while (inetAddresses.hasMoreElements()) {
811             InetAddress addr = inetAddresses.nextElement();
812             if (addr instanceof Inet4Address) {
813                 Inet4Address inet4Address =  (Inet4Address) addr;
814                 inetAddrs.add(inet4Address.getHostAddress());
815             }
816         }
817 
818         return inetAddrs;
819     }
820 
821     @Rpc(description = "Return IPv6 addrs of an interface except link local")
connectivityGetIPv6Addresses( @pcParametername = "ifaceName") String ifaceName)822     public List<String> connectivityGetIPv6Addresses(
823             @RpcParameter(name = "ifaceName") String ifaceName) {
824         Enumeration<InetAddress> inetAddresses
825                 = getInetAddrsForInterface(ifaceName);
826         if (inetAddresses == null)
827             return null;
828 
829         List<String> inetAddrs = new ArrayList<String>();
830         while (inetAddresses.hasMoreElements()) {
831             InetAddress addr = inetAddresses.nextElement();
832             if (addr instanceof Inet6Address) {
833                 if (((Inet6Address) addr).isLinkLocalAddress())
834                     continue;
835                 Inet6Address inet6Address =  (Inet6Address) addr;
836                 inetAddrs.add(inet6Address.getHostAddress());
837             }
838         }
839 
840         return inetAddrs;
841     }
842 
843     @Rpc(description = "Returns active link properties")
connectivityGetActiveLinkProperties()844     public LinkProperties connectivityGetActiveLinkProperties() {
845         return mManager.getActiveLinkProperties();
846     }
847 
848     /**
849      * Get the IPv4 default gateway for the active network.
850      */
851     @Rpc(description = "Return default gateway of the active network")
connectivityGetIPv4DefaultGateway()852     public String connectivityGetIPv4DefaultGateway() {
853         LinkProperties linkProp = mManager.getActiveLinkProperties();
854         List<RouteInfo> routeInfos = linkProp.getRoutes();
855         for (RouteInfo routeInfo: routeInfos) {
856             if (routeInfo.isIPv4Default()) {
857                 return routeInfo.getGateway().toString().split("/")[1];
858             }
859         }
860         return null;
861     }
862 
863     @Rpc(description = "Returns all IP addresses of the active link")
connectivityGetAllAddressesOfActiveLink()864     public List<InetAddress> connectivityGetAllAddressesOfActiveLink() {
865         LinkProperties linkProp = mManager.getActiveLinkProperties();
866         return linkProp.getAllAddresses();
867     }
868 
869     @Rpc(description = "Check if active link has default IPv6 route")
connectivityHasIPv6DefaultRoute()870     public boolean connectivityHasIPv6DefaultRoute() {
871         LinkProperties linkProp = mManager.getActiveLinkProperties();
872         return linkProp.hasIPv6DefaultRoute();
873     }
874 
875     @Rpc(description = "Factory reset of network policies")
connectivityFactoryResetNetworkPolicies(String subscriberId)876     public void connectivityFactoryResetNetworkPolicies(String subscriberId) {
877         mNetPolicyManager.factoryReset(subscriberId);
878     }
879 
880     /**
881      * Method to set data warning limit on the device.
882      */
883     @Rpc(description = "Set data warning limit for subscriber ID")
connectivitySetDataWarningLimit(String subscriberId, Long dataLimit)884     public void connectivitySetDataWarningLimit(String subscriberId, Long dataLimit) {
885         NetworkPolicy[] allPolicies = mNetPolicyManager.getNetworkPolicies();
886         for (int i = 0; i < allPolicies.length; i++) {
887             String subId = allPolicies[i].template.getSubscriberId();
888             if (subId != null && subId.equals(subscriberId)) {
889                 allPolicies[i].warningBytes = dataLimit.longValue();
890                 break;
891             }
892         }
893         mNetPolicyManager.setNetworkPolicies(allPolicies);
894     }
895 
896     /**
897      * Method to set data usage limit on the device.
898      */
899     @Rpc(description = "Set data usage limit for subscriber ID")
connectivitySetDataUsageLimit(String subscriberId, Long dataLimit)900     public void connectivitySetDataUsageLimit(String subscriberId, Long 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 = dataLimit.longValue();
906                 break;
907             }
908         }
909         mNetPolicyManager.setNetworkPolicies(allPolicies);
910     }
911 
912     /**
913      * Method to get data usage limit on the device.
914      */
915     @Rpc(description = "Get data usage limit for subscriber ID")
connectivityGetDataUsageLimit(String subscriberId)916     public long connectivityGetDataUsageLimit(String subscriberId) {
917         NetworkPolicy[] allPolicies = mNetPolicyManager.getNetworkPolicies();
918         for (int i = 0; i < allPolicies.length; i++) {
919             String subId = allPolicies[i].template.getSubscriberId();
920             if (subId != null && subId.equals(subscriberId)) return allPolicies[i].limitBytes;
921         }
922         return -1;
923     }
924 
925     /**
926      * Method to get data warning limit on the device
927      */
928     @Rpc(description = "Get data warning limit for subscriber ID")
connectivityGetDataWarningLimit(String subscriberId)929     public long connectivityGetDataWarningLimit(String subscriberId) {
930         NetworkPolicy[] allPolicies = mNetPolicyManager.getNetworkPolicies();
931         for (int i = 0; i < allPolicies.length; i++) {
932             String subId = allPolicies[i].template.getSubscriberId();
933             if (subId != null && subId.equals(subscriberId)) return allPolicies[i].warningBytes;
934         }
935         return -1;
936     }
937 
938     @Rpc(description = "Get network stats for device")
connectivityQuerySummaryForDevice(Integer connType, String subscriberId, Long startTime, Long endTime)939     public long connectivityQuerySummaryForDevice(Integer connType,
940             String subscriberId, Long startTime, Long endTime)
941             throws SecurityException, RemoteException {
942         Bucket bucket = mNetStatsManager.querySummaryForDevice(
943               connType, subscriberId, startTime, endTime);
944         return bucket.getTxBytes() + bucket.getRxBytes();
945     }
946 
947     @Rpc(description = "Get network stats for device - Rx bytes")
connectivityQuerySummaryForDeviceRxBytes(Integer connType, String subscriberId, Long startTime, Long endTime)948     public long connectivityQuerySummaryForDeviceRxBytes(Integer connType,
949             String subscriberId, Long startTime, Long endTime)
950             throws SecurityException, RemoteException {
951         Bucket bucket = mNetStatsManager.querySummaryForDevice(
952               connType, subscriberId, startTime, endTime);
953         return bucket.getRxBytes();
954     }
955 
956     @Rpc(description = "Get network stats for UID")
connectivityQueryDetailsForUid(Integer connType, String subscriberId, Long startTime, Long endTime, Integer uid)957     public long connectivityQueryDetailsForUid(Integer connType,
958             String subscriberId, Long startTime, Long endTime, Integer uid)
959             throws SecurityException, RemoteException {
960         long totalData = 0;
961         NetworkStats netStats = mNetStatsManager.queryDetailsForUid(
962                 connType, subscriberId, startTime, endTime, uid);
963         Bucket bucket = new Bucket();
964         while(netStats.hasNextBucket() && netStats.getNextBucket(bucket)) {
965             totalData += bucket.getTxBytes() + bucket.getRxBytes();
966         }
967         netStats.close();
968         return totalData;
969     }
970 
971     @Rpc(description = "Get network stats for UID - Rx bytes")
connectivityQueryDetailsForUidRxBytes(Integer connType, String subscriberId, Long startTime, Long endTime, Integer uid)972     public long connectivityQueryDetailsForUidRxBytes(Integer connType,
973             String subscriberId, Long startTime, Long endTime, Integer uid)
974             throws SecurityException, RemoteException {
975         long rxBytes = 0;
976         NetworkStats netStats = mNetStatsManager.queryDetailsForUid(
977                 connType, subscriberId, startTime, endTime, uid);
978         Bucket bucket = new Bucket();
979         while(netStats.hasNextBucket() && netStats.getNextBucket(bucket)) {
980             rxBytes += bucket.getRxBytes();
981         }
982         netStats.close();
983         return rxBytes;
984     }
985 
986     @Rpc(description = "Returns all interfaces on the android deivce")
connectivityGetNetworkInterfaces()987     public List<NetworkInterface> connectivityGetNetworkInterfaces() {
988         List<NetworkInterface> interfaces = null;
989         try {
990             interfaces = Collections.list(
991                   NetworkInterface.getNetworkInterfaces());
992         } catch (SocketException e) {
993             return null;
994         };
995 
996         return interfaces;
997     }
998 
999     /**
1000     * Get multipath preference for a given network.
1001     * @param networkId : network id of wifi or cell network
1002     * @return Integer value of multipath preference
1003     */
1004     @Rpc(description = "Return Multipath preference for a given network")
connectivityGetMultipathPreferenceForNetwork(Long networkId)1005     public Integer connectivityGetMultipathPreferenceForNetwork(Long networkId) {
1006         Network network = sNetworkHashMap.get(networkId.longValue());
1007         return mManager.getMultipathPreference(network);
1008     }
1009 
1010     /**
1011     * Return HashMap key for Network object.
1012     * @return long value of Network object key
1013     */
1014     @Rpc(description = "Return key to active network stored in a hash map")
connectivityGetActiveNetwork()1015     public long connectivityGetActiveNetwork() {
1016         Network network = mManager.getActiveNetwork();
1017         long id = network.getNetworkHandle();
1018         sNetworkHashMap.put(id, network);
1019         return id;
1020     }
1021 
1022     /**
1023     * Get mutlipath preference for active network.
1024     * @return Integer value of multipath preference
1025     */
1026     @Rpc(description = "Return Multipath preference for active network")
connectivityGetMultipathPreference()1027     public Integer connectivityGetMultipathPreference() {
1028         Network network = mManager.getActiveNetwork();
1029         return mManager.getMultipathPreference(network);
1030     }
1031 
1032     /**
1033     * Download file of a given url using Network#openConnection call.
1034     * @param networkId : network id of wifi or cell network
1035     * @param urlString : url in String format
1036     */
1037     @Rpc(description = "Download file on a given network with Network#openConnection")
connectivityNetworkOpenConnection(Long networkId, String urlString)1038     public void connectivityNetworkOpenConnection(Long networkId, String urlString) {
1039         Network network = sNetworkHashMap.get(networkId.longValue());
1040         try {
1041             URL url = new URL(urlString);
1042             URLConnection urlConnection = network.openConnection(url);
1043             File outFile = FileUtils.getExternalDownload();
1044             int lastIdx = urlString.lastIndexOf('/');
1045             String filename = urlString.substring(lastIdx + 1);
1046             Log.d("Using name from url: " + filename);
1047             outFile = new File(outFile, filename);
1048             InputStream in = new BufferedInputStream(urlConnection.getInputStream());
1049             OutputStream output = new FileOutputStream(outFile);
1050             ByteStreams.copy(in, output);
1051         } catch (IOException e) {
1052             Log.e("Failed to download file: " + e.toString());
1053         }
1054     }
1055 
1056     /**
1057      * Sets the global proxy using the given information.
1058      *
1059      * @param hostname hostname of the proxy
1060      * @param port     port set on the proxy server
1061      * @param exclList List of hostnames excluded
1062      */
1063     @Rpc(description = "Set global proxy")
connectivitySetGlobalProxy(String hostname, Integer port, String exclList)1064     public void connectivitySetGlobalProxy(String hostname, Integer port, String exclList) {
1065         ProxyInfo proxyInfo = new ProxyInfo(hostname, port.intValue(), exclList);
1066         mManager.setGlobalProxy(proxyInfo);
1067     }
1068 
1069     /**
1070      * Sets the global proxy using a PAC URI.
1071      *
1072      * @param pac PAC URI in string
1073      */
1074     @Rpc(description = "Set global proxy with proxy autoconfig")
connectivitySetGlobalPacProxy(String pac)1075     public void connectivitySetGlobalPacProxy(String pac) {
1076         Uri uri = Uri.parse(pac);
1077         ProxyInfo proxyInfo = new ProxyInfo(uri);
1078         mManager.setGlobalProxy(proxyInfo);
1079     }
1080 
1081     /**
1082      * Gets the global proxy settings.
1083      *
1084      * @return ProxyInfo object in dictionary
1085      */
1086     @Rpc(description = "Get global proxy")
connectivityGetGlobalProxy()1087     public ProxyInfo connectivityGetGlobalProxy() {
1088         ProxyInfo proxyInfo = mManager.getGlobalProxy();
1089         if (proxyInfo == null) return null;
1090         return proxyInfo;
1091     }
1092 
1093     /**
1094      * Resets the global proxy settings.
1095      */
1096     @Rpc(description = "Reset global proxy")
connectivityResetGlobalProxy()1097     public void connectivityResetGlobalProxy() {
1098         mManager.setGlobalProxy(null);
1099     }
1100 
1101     /**
1102      * Check if active network is metered.
1103      */
1104     @Rpc(description = "Is active network metered")
connectivityIsActiveNetworkMetered()1105     public boolean connectivityIsActiveNetworkMetered() {
1106         return mManager.isActiveNetworkMetered();
1107     }
1108 
1109     /**
1110      * Check if device connected to WiFi network
1111      */
1112     @Rpc(description = "Is active network WiFi")
connectivityIsActiveNetworkWiFi()1113     public boolean connectivityIsActiveNetworkWiFi() {
1114         NetworkInfo mWifi = mManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
1115         return mWifi.isConnected();
1116     }
1117 
1118     @Override
shutdown()1119     public void shutdown() {
1120         connectivityStopTrackingConnectivityStateChange();
1121         for (NetworkCallback networkCallback : mNetworkCallbackMap.values()) {
1122             mManager.unregisterNetworkCallback(networkCallback);
1123         }
1124     }
1125 }
1126