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