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