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