1 /* 2 * Copyright (C) 2014 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 android.net; 18 19 import android.annotation.IntDef; 20 import android.annotation.IntRange; 21 import android.annotation.NonNull; 22 import android.annotation.Nullable; 23 import android.annotation.SuppressLint; 24 import android.annotation.SystemApi; 25 import android.annotation.TestApi; 26 import android.compat.annotation.UnsupportedAppUsage; 27 import android.content.Context; 28 import android.os.Build; 29 import android.os.Bundle; 30 import android.os.ConditionVariable; 31 import android.os.Handler; 32 import android.os.Looper; 33 import android.os.Message; 34 import android.os.RemoteException; 35 import android.telephony.data.EpsBearerQosSessionAttributes; 36 import android.telephony.data.NrQosSessionAttributes; 37 import android.util.Log; 38 39 import com.android.internal.annotations.VisibleForTesting; 40 41 import java.lang.annotation.Retention; 42 import java.lang.annotation.RetentionPolicy; 43 import java.time.Duration; 44 import java.util.ArrayList; 45 import java.util.List; 46 import java.util.Objects; 47 import java.util.concurrent.atomic.AtomicBoolean; 48 49 /** 50 * A utility class for handling for communicating between bearer-specific 51 * code and ConnectivityService. 52 * 53 * An agent manages the life cycle of a network. A network starts its 54 * life cycle when {@link register} is called on NetworkAgent. The network 55 * is then connecting. When full L3 connectivity has been established, 56 * the agent should call {@link markConnected} to inform the system that 57 * this network is ready to use. When the network disconnects its life 58 * ends and the agent should call {@link unregister}, at which point the 59 * system will clean up and free resources. 60 * Any reconnection becomes a new logical network, so after a network 61 * is disconnected the agent cannot be used any more. Network providers 62 * should create a new NetworkAgent instance to handle new connections. 63 * 64 * A bearer may have more than one NetworkAgent if it can simultaneously 65 * support separate networks (IMS / Internet / MMS Apns on cellular, or 66 * perhaps connections with different SSID or P2P for Wi-Fi). 67 * 68 * This class supports methods to start and stop sending keepalive packets. 69 * Keepalive packets are typically sent at periodic intervals over a network 70 * with NAT when there is no other traffic to avoid the network forcefully 71 * closing the connection. NetworkAgents that manage technologies that 72 * have hardware support for keepalive should implement the related 73 * methods to save battery life. NetworkAgent that cannot get support 74 * without waking up the CPU should not, as this would be prohibitive in 75 * terms of battery - these agents should simply not override the related 76 * methods, which results in the implementation returning 77 * {@link SocketKeepalive.ERROR_UNSUPPORTED} as appropriate. 78 * 79 * Keepalive packets need to be sent at relatively frequent intervals 80 * (a few seconds to a few minutes). As the contents of keepalive packets 81 * depend on the current network status, hardware needs to be configured 82 * to send them and has a limited amount of memory to do so. The HAL 83 * formalizes this as slots that an implementation can configure to send 84 * the correct packets. Devices typically have a small number of slots 85 * per radio technology, and the specific number of slots for each 86 * technology is specified in configuration files. 87 * {@see SocketKeepalive} for details. 88 * 89 * @hide 90 */ 91 @SystemApi 92 public abstract class NetworkAgent { 93 /** 94 * The {@link Network} corresponding to this object. 95 */ 96 @Nullable 97 private volatile Network mNetwork; 98 99 @Nullable 100 private volatile INetworkAgentRegistry mRegistry; 101 102 private interface RegistryAction { execute(@onNull INetworkAgentRegistry registry)103 void execute(@NonNull INetworkAgentRegistry registry) throws RemoteException; 104 } 105 106 private final Handler mHandler; 107 private final String LOG_TAG; 108 private static final boolean DBG = true; 109 private static final boolean VDBG = false; 110 /** @hide */ 111 @TestApi 112 public static final int MIN_LINGER_TIMER_MS = 2000; 113 private final ArrayList<RegistryAction> mPreConnectedQueue = new ArrayList<>(); 114 private volatile long mLastBwRefreshTime = 0; 115 private static final long BW_REFRESH_MIN_WIN_MS = 500; 116 private boolean mBandwidthUpdateScheduled = false; 117 private AtomicBoolean mBandwidthUpdatePending = new AtomicBoolean(false); 118 @NonNull 119 private NetworkInfo mNetworkInfo; 120 @NonNull 121 private final Object mRegisterLock = new Object(); 122 123 /** 124 * The ID of the {@link NetworkProvider} that created this object, or 125 * {@link NetworkProvider#ID_NONE} if unknown. 126 * @hide 127 */ 128 public final int providerId; 129 130 // ConnectivityService parses message constants from itself and NetworkAgent with MessageUtils 131 // for debugging purposes, and crashes if some messages have the same values. 132 // TODO: have ConnectivityService store message names in different maps and remove this base 133 private static final int BASE = 200; 134 135 /** 136 * Sent by ConnectivityService to the NetworkAgent to inform it of 137 * suspected connectivity problems on its network. The NetworkAgent 138 * should take steps to verify and correct connectivity. 139 * @hide 140 */ 141 public static final int CMD_SUSPECT_BAD = BASE; 142 143 /** 144 * Sent by the NetworkAgent (note the EVENT vs CMD prefix) to 145 * ConnectivityService to pass the current NetworkInfo (connection state). 146 * Sent when the NetworkInfo changes, mainly due to change of state. 147 * obj = NetworkInfo 148 * @hide 149 */ 150 public static final int EVENT_NETWORK_INFO_CHANGED = BASE + 1; 151 152 /** 153 * Sent by the NetworkAgent to ConnectivityService to pass the current 154 * NetworkCapabilties. 155 * obj = NetworkCapabilities 156 * @hide 157 */ 158 public static final int EVENT_NETWORK_CAPABILITIES_CHANGED = BASE + 2; 159 160 /** 161 * Sent by the NetworkAgent to ConnectivityService to pass the current 162 * NetworkProperties. 163 * obj = NetworkProperties 164 * @hide 165 */ 166 public static final int EVENT_NETWORK_PROPERTIES_CHANGED = BASE + 3; 167 168 /** 169 * Centralize the place where base network score, and network score scaling, will be 170 * stored, so as we can consistently compare apple and oranges, or wifi, ethernet and LTE 171 * @hide 172 */ 173 public static final int WIFI_BASE_SCORE = 60; 174 175 /** 176 * Sent by the NetworkAgent to ConnectivityService to pass the current 177 * network score. 178 * arg1 = network score int 179 * @hide 180 */ 181 public static final int EVENT_NETWORK_SCORE_CHANGED = BASE + 4; 182 183 /** 184 * Sent by the NetworkAgent to ConnectivityService to pass the current 185 * list of underlying networks. 186 * obj = array of Network objects 187 * @hide 188 */ 189 public static final int EVENT_UNDERLYING_NETWORKS_CHANGED = BASE + 5; 190 191 /** 192 * Sent by the NetworkAgent to ConnectivityService to pass the current value of the teardown 193 * delay. 194 * arg1 = teardown delay in milliseconds 195 * @hide 196 */ 197 public static final int EVENT_TEARDOWN_DELAY_CHANGED = BASE + 6; 198 199 /** 200 * The maximum value for the teardown delay, in milliseconds. 201 * @hide 202 */ 203 public static final int MAX_TEARDOWN_DELAY_MS = 5000; 204 205 /** 206 * Sent by ConnectivityService to the NetworkAgent to inform the agent of the 207 * networks status - whether we could use the network or could not, due to 208 * either a bad network configuration (no internet link) or captive portal. 209 * 210 * arg1 = either {@code VALID_NETWORK} or {@code INVALID_NETWORK} 211 * obj = Bundle containing map from {@code REDIRECT_URL_KEY} to {@code String} 212 * representing URL that Internet probe was redirect to, if it was redirected, 213 * or mapping to {@code null} otherwise. 214 * @hide 215 */ 216 public static final int CMD_REPORT_NETWORK_STATUS = BASE + 7; 217 218 /** 219 * Network validation suceeded. 220 * Corresponds to {@link NetworkCapabilities.NET_CAPABILITY_VALIDATED}. 221 */ 222 public static final int VALIDATION_STATUS_VALID = 1; 223 224 /** 225 * Network validation was attempted and failed. This may be received more than once as 226 * subsequent validation attempts are made. 227 */ 228 public static final int VALIDATION_STATUS_NOT_VALID = 2; 229 230 /** @hide */ 231 @Retention(RetentionPolicy.SOURCE) 232 @IntDef(prefix = { "VALIDATION_STATUS_" }, value = { 233 VALIDATION_STATUS_VALID, 234 VALIDATION_STATUS_NOT_VALID 235 }) 236 public @interface ValidationStatus {} 237 238 // TODO: remove. 239 /** @hide */ 240 public static final int VALID_NETWORK = 1; 241 /** @hide */ 242 public static final int INVALID_NETWORK = 2; 243 244 /** 245 * The key for the redirect URL in the Bundle argument of {@code CMD_REPORT_NETWORK_STATUS}. 246 * @hide 247 */ 248 public static final String REDIRECT_URL_KEY = "redirect URL"; 249 250 /** 251 * Sent by the NetworkAgent to ConnectivityService to indicate this network was 252 * explicitly selected. This should be sent before the NetworkInfo is marked 253 * CONNECTED so it can be given special treatment at that time. 254 * 255 * obj = boolean indicating whether to use this network even if unvalidated 256 * @hide 257 */ 258 public static final int EVENT_SET_EXPLICITLY_SELECTED = BASE + 8; 259 260 /** 261 * Sent by ConnectivityService to the NetworkAgent to inform the agent of 262 * whether the network should in the future be used even if not validated. 263 * This decision is made by the user, but it is the network transport's 264 * responsibility to remember it. 265 * 266 * arg1 = 1 if true, 0 if false 267 * @hide 268 */ 269 public static final int CMD_SAVE_ACCEPT_UNVALIDATED = BASE + 9; 270 271 /** 272 * Sent by ConnectivityService to the NetworkAgent to inform the agent to pull 273 * the underlying network connection for updated bandwidth information. 274 * @hide 275 */ 276 public static final int CMD_REQUEST_BANDWIDTH_UPDATE = BASE + 10; 277 278 /** 279 * Sent by ConnectivityService to the NetworkAgent to request that the specified packet be sent 280 * periodically on the given interval. 281 * 282 * arg1 = the hardware slot number of the keepalive to start 283 * arg2 = interval in seconds 284 * obj = KeepalivePacketData object describing the data to be sent 285 * 286 * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. 287 * @hide 288 */ 289 public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11; 290 291 /** 292 * Requests that the specified keepalive packet be stopped. 293 * 294 * arg1 = hardware slot number of the keepalive to stop. 295 * 296 * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics. 297 * @hide 298 */ 299 public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12; 300 301 /** 302 * Sent by the NetworkAgent to ConnectivityService to provide status on a socket keepalive 303 * request. This may either be the reply to a CMD_START_SOCKET_KEEPALIVE, or an asynchronous 304 * error notification. 305 * 306 * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive}, 307 * so that the app's {@link SocketKeepalive.Callback} methods can be called. 308 * 309 * arg1 = hardware slot number of the keepalive 310 * arg2 = error code 311 * @hide 312 */ 313 public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13; 314 315 /** 316 * Sent by ConnectivityService to inform this network transport of signal strength thresholds 317 * that when crossed should trigger a system wakeup and a NetworkCapabilities update. 318 * 319 * obj = int[] describing signal strength thresholds. 320 * @hide 321 */ 322 public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14; 323 324 /** 325 * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid 326 * automatically reconnecting to this network (e.g. via autojoin). Happens 327 * when user selects "No" option on the "Stay connected?" dialog box. 328 * @hide 329 */ 330 public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15; 331 332 /** 333 * Sent by the KeepaliveTracker to NetworkAgent to add a packet filter. 334 * 335 * For TCP keepalive offloads, keepalive packets are sent by the firmware. However, because the 336 * remote site will send ACK packets in response to the keepalive packets, the firmware also 337 * needs to be configured to properly filter the ACKs to prevent the system from waking up. 338 * This does not happen with UDP, so this message is TCP-specific. 339 * arg1 = hardware slot number of the keepalive to filter for. 340 * obj = the keepalive packet to send repeatedly. 341 * @hide 342 */ 343 public static final int CMD_ADD_KEEPALIVE_PACKET_FILTER = BASE + 16; 344 345 /** 346 * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See 347 * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}. 348 * arg1 = hardware slot number of the keepalive packet filter to remove. 349 * @hide 350 */ 351 public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17; 352 353 /** 354 * Sent by ConnectivityService to the NetworkAgent to complete the bidirectional connection. 355 * obj = INetworkAgentRegistry 356 */ 357 private static final int EVENT_AGENT_CONNECTED = BASE + 18; 358 359 /** 360 * Sent by ConnectivityService to the NetworkAgent to inform the agent that it was disconnected. 361 */ 362 private static final int EVENT_AGENT_DISCONNECTED = BASE + 19; 363 364 /** 365 * Sent by QosCallbackTracker to {@link NetworkAgent} to register a new filter with 366 * callback. 367 * 368 * arg1 = QoS agent callback ID 369 * obj = {@link QosFilter} 370 * @hide 371 */ 372 public static final int CMD_REGISTER_QOS_CALLBACK = BASE + 20; 373 374 /** 375 * Sent by QosCallbackTracker to {@link NetworkAgent} to unregister a callback. 376 * 377 * arg1 = QoS agent callback ID 378 * @hide 379 */ 380 public static final int CMD_UNREGISTER_QOS_CALLBACK = BASE + 21; 381 382 /** 383 * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent that its native 384 * network was created and the Network object is now valid. 385 * 386 * @hide 387 */ 388 public static final int CMD_NETWORK_CREATED = BASE + 22; 389 390 /** 391 * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent that its native 392 * network was destroyed. 393 * 394 * @hide 395 */ 396 public static final int CMD_NETWORK_DESTROYED = BASE + 23; 397 398 /** 399 * Sent by the NetworkAgent to ConnectivityService to set the linger duration for this network 400 * agent. 401 * arg1 = the linger duration, represents by {@link Duration}. 402 * 403 * @hide 404 */ 405 public static final int EVENT_LINGER_DURATION_CHANGED = BASE + 24; 406 getLegacyNetworkInfo(final NetworkAgentConfig config)407 private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) { 408 final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType, 409 config.legacyTypeName, config.legacySubTypeName); 410 ni.setIsAvailable(true); 411 ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */, 412 config.getLegacyExtraInfo()); 413 return ni; 414 } 415 416 // Temporary backward compatibility constructor NetworkAgent(@onNull Context context, @NonNull Looper looper, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider)417 public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, 418 @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score, 419 @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) { 420 this(context, looper, logTag, nc, lp, 421 new NetworkScore.Builder().setLegacyInt(score).build(), config, provider); 422 } 423 424 /** 425 * Create a new network agent. 426 * @param context a {@link Context} to get system services from. 427 * @param looper the {@link Looper} on which to invoke the callbacks. 428 * @param logTag the tag for logs 429 * @param nc the initial {@link NetworkCapabilities} of this network. Update with 430 * sendNetworkCapabilities. 431 * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties. 432 * @param score the initial score of this network. Update with sendNetworkScore. 433 * @param config an immutable {@link NetworkAgentConfig} for this agent. 434 * @param provider the {@link NetworkProvider} managing this agent. 435 */ NetworkAgent(@onNull Context context, @NonNull Looper looper, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider)436 public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag, 437 @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, 438 @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, 439 @Nullable NetworkProvider provider) { 440 this(looper, context, logTag, nc, lp, score, config, 441 provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(), 442 getLegacyNetworkInfo(config)); 443 } 444 445 private static class InitialConfiguration { 446 public final Context context; 447 public final NetworkCapabilities capabilities; 448 public final LinkProperties properties; 449 public final NetworkScore score; 450 public final NetworkAgentConfig config; 451 public final NetworkInfo info; InitialConfiguration(@onNull Context context, @NonNull NetworkCapabilities capabilities, @NonNull LinkProperties properties, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info)452 InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities, 453 @NonNull LinkProperties properties, @NonNull NetworkScore score, 454 @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) { 455 this.context = context; 456 this.capabilities = capabilities; 457 this.properties = properties; 458 this.score = score; 459 this.config = config; 460 this.info = info; 461 } 462 } 463 private volatile InitialConfiguration mInitialConfiguration; 464 NetworkAgent(@onNull Looper looper, @NonNull Context context, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni)465 private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag, 466 @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, 467 @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, 468 @NonNull NetworkInfo ni) { 469 mHandler = new NetworkAgentHandler(looper); 470 LOG_TAG = logTag; 471 mNetworkInfo = new NetworkInfo(ni); 472 this.providerId = providerId; 473 if (ni == null || nc == null || lp == null) { 474 throw new IllegalArgumentException(); 475 } 476 477 mInitialConfiguration = new InitialConfiguration(context, 478 new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE), 479 new LinkProperties(lp), score, config, ni); 480 } 481 482 private class NetworkAgentHandler extends Handler { NetworkAgentHandler(Looper looper)483 NetworkAgentHandler(Looper looper) { 484 super(looper); 485 } 486 487 @Override handleMessage(Message msg)488 public void handleMessage(Message msg) { 489 switch (msg.what) { 490 case EVENT_AGENT_CONNECTED: { 491 if (mRegistry != null) { 492 log("Received new connection while already connected!"); 493 } else { 494 if (VDBG) log("NetworkAgent fully connected"); 495 synchronized (mPreConnectedQueue) { 496 final INetworkAgentRegistry registry = (INetworkAgentRegistry) msg.obj; 497 mRegistry = registry; 498 for (RegistryAction a : mPreConnectedQueue) { 499 try { 500 a.execute(registry); 501 } catch (RemoteException e) { 502 Log.wtf(LOG_TAG, "Communication error with registry", e); 503 // Fall through 504 } 505 } 506 mPreConnectedQueue.clear(); 507 } 508 } 509 break; 510 } 511 case EVENT_AGENT_DISCONNECTED: { 512 if (DBG) log("NetworkAgent channel lost"); 513 // let the client know CS is done with us. 514 onNetworkUnwanted(); 515 synchronized (mPreConnectedQueue) { 516 mRegistry = null; 517 } 518 break; 519 } 520 case CMD_SUSPECT_BAD: { 521 log("Unhandled Message " + msg); 522 break; 523 } 524 case CMD_REQUEST_BANDWIDTH_UPDATE: { 525 long currentTimeMs = System.currentTimeMillis(); 526 if (VDBG) { 527 log("CMD_REQUEST_BANDWIDTH_UPDATE request received."); 528 } 529 if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) { 530 mBandwidthUpdateScheduled = false; 531 if (!mBandwidthUpdatePending.getAndSet(true)) { 532 onBandwidthUpdateRequested(); 533 } 534 } else { 535 // deliver the request at a later time rather than discard it completely. 536 if (!mBandwidthUpdateScheduled) { 537 long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS 538 - currentTimeMs + 1; 539 mBandwidthUpdateScheduled = sendEmptyMessageDelayed( 540 CMD_REQUEST_BANDWIDTH_UPDATE, waitTime); 541 } 542 } 543 break; 544 } 545 case CMD_REPORT_NETWORK_STATUS: { 546 String redirectUrl = ((Bundle) msg.obj).getString(REDIRECT_URL_KEY); 547 if (VDBG) { 548 log("CMD_REPORT_NETWORK_STATUS(" 549 + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ") 550 + redirectUrl); 551 } 552 Uri uri = null; 553 try { 554 if (null != redirectUrl) { 555 uri = Uri.parse(redirectUrl); 556 } 557 } catch (Exception e) { 558 Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e); 559 } 560 onValidationStatus(msg.arg1 /* status */, uri); 561 break; 562 } 563 case CMD_SAVE_ACCEPT_UNVALIDATED: { 564 onSaveAcceptUnvalidated(msg.arg1 != 0); 565 break; 566 } 567 case CMD_START_SOCKET_KEEPALIVE: { 568 onStartSocketKeepalive(msg.arg1 /* slot */, 569 Duration.ofSeconds(msg.arg2) /* interval */, 570 (KeepalivePacketData) msg.obj /* packet */); 571 break; 572 } 573 case CMD_STOP_SOCKET_KEEPALIVE: { 574 onStopSocketKeepalive(msg.arg1 /* slot */); 575 break; 576 } 577 578 case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: { 579 onSignalStrengthThresholdsUpdated((int[]) msg.obj); 580 break; 581 } 582 case CMD_PREVENT_AUTOMATIC_RECONNECT: { 583 onAutomaticReconnectDisabled(); 584 break; 585 } 586 case CMD_ADD_KEEPALIVE_PACKET_FILTER: { 587 onAddKeepalivePacketFilter(msg.arg1 /* slot */, 588 (KeepalivePacketData) msg.obj /* packet */); 589 break; 590 } 591 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: { 592 onRemoveKeepalivePacketFilter(msg.arg1 /* slot */); 593 break; 594 } 595 case CMD_REGISTER_QOS_CALLBACK: { 596 onQosCallbackRegistered( 597 msg.arg1 /* QoS callback id */, 598 (QosFilter) msg.obj /* QoS filter */); 599 break; 600 } 601 case CMD_UNREGISTER_QOS_CALLBACK: { 602 onQosCallbackUnregistered( 603 msg.arg1 /* QoS callback id */); 604 break; 605 } 606 case CMD_NETWORK_CREATED: { 607 onNetworkCreated(); 608 break; 609 } 610 case CMD_NETWORK_DESTROYED: { 611 onNetworkDestroyed(); 612 break; 613 } 614 } 615 } 616 } 617 618 /** 619 * Register this network agent with ConnectivityService. 620 * 621 * This method can only be called once per network agent. 622 * 623 * @return the Network associated with this network agent (which can also be obtained later 624 * by calling getNetwork() on this agent). 625 * @throws IllegalStateException thrown by the system server if this network agent is 626 * already registered. 627 */ 628 @NonNull register()629 public Network register() { 630 if (VDBG) log("Registering NetworkAgent"); 631 synchronized (mRegisterLock) { 632 if (mNetwork != null) { 633 throw new IllegalStateException("Agent already registered"); 634 } 635 final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context 636 .getSystemService(Context.CONNECTIVITY_SERVICE); 637 mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler), 638 new NetworkInfo(mInitialConfiguration.info), 639 mInitialConfiguration.properties, mInitialConfiguration.capabilities, 640 mInitialConfiguration.score, mInitialConfiguration.config, providerId); 641 mInitialConfiguration = null; // All this memory can now be GC'd 642 } 643 return mNetwork; 644 } 645 646 private static class NetworkAgentBinder extends INetworkAgent.Stub { 647 private static final String LOG_TAG = NetworkAgentBinder.class.getSimpleName(); 648 649 private final Handler mHandler; 650 NetworkAgentBinder(Handler handler)651 private NetworkAgentBinder(Handler handler) { 652 mHandler = handler; 653 } 654 655 @Override onRegistered(@onNull INetworkAgentRegistry registry)656 public void onRegistered(@NonNull INetworkAgentRegistry registry) { 657 mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED, registry)); 658 } 659 660 @Override onDisconnected()661 public void onDisconnected() { 662 mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED)); 663 } 664 665 @Override onBandwidthUpdateRequested()666 public void onBandwidthUpdateRequested() { 667 mHandler.sendMessage(mHandler.obtainMessage(CMD_REQUEST_BANDWIDTH_UPDATE)); 668 } 669 670 @Override onValidationStatusChanged( int validationStatus, @Nullable String captivePortalUrl)671 public void onValidationStatusChanged( 672 int validationStatus, @Nullable String captivePortalUrl) { 673 // TODO: consider using a parcelable as argument when the interface is structured 674 Bundle redirectUrlBundle = new Bundle(); 675 redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, captivePortalUrl); 676 mHandler.sendMessage(mHandler.obtainMessage(CMD_REPORT_NETWORK_STATUS, 677 validationStatus, 0, redirectUrlBundle)); 678 } 679 680 @Override onSaveAcceptUnvalidated(boolean acceptUnvalidated)681 public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) { 682 mHandler.sendMessage(mHandler.obtainMessage(CMD_SAVE_ACCEPT_UNVALIDATED, 683 acceptUnvalidated ? 1 : 0, 0)); 684 } 685 686 @Override onStartNattSocketKeepalive(int slot, int intervalDurationMs, @NonNull NattKeepalivePacketData packetData)687 public void onStartNattSocketKeepalive(int slot, int intervalDurationMs, 688 @NonNull NattKeepalivePacketData packetData) { 689 mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, 690 slot, intervalDurationMs, packetData)); 691 } 692 693 @Override onStartTcpSocketKeepalive(int slot, int intervalDurationMs, @NonNull TcpKeepalivePacketData packetData)694 public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs, 695 @NonNull TcpKeepalivePacketData packetData) { 696 mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, 697 slot, intervalDurationMs, packetData)); 698 } 699 700 @Override onStopSocketKeepalive(int slot)701 public void onStopSocketKeepalive(int slot) { 702 mHandler.sendMessage(mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0)); 703 } 704 705 @Override onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)706 public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { 707 mHandler.sendMessage(mHandler.obtainMessage( 708 CMD_SET_SIGNAL_STRENGTH_THRESHOLDS, thresholds)); 709 } 710 711 @Override onPreventAutomaticReconnect()712 public void onPreventAutomaticReconnect() { 713 mHandler.sendMessage(mHandler.obtainMessage(CMD_PREVENT_AUTOMATIC_RECONNECT)); 714 } 715 716 @Override onAddNattKeepalivePacketFilter(int slot, @NonNull NattKeepalivePacketData packetData)717 public void onAddNattKeepalivePacketFilter(int slot, 718 @NonNull NattKeepalivePacketData packetData) { 719 mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, 720 slot, 0, packetData)); 721 } 722 723 @Override onAddTcpKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketData packetData)724 public void onAddTcpKeepalivePacketFilter(int slot, 725 @NonNull TcpKeepalivePacketData packetData) { 726 mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, 727 slot, 0, packetData)); 728 } 729 730 @Override onRemoveKeepalivePacketFilter(int slot)731 public void onRemoveKeepalivePacketFilter(int slot) { 732 mHandler.sendMessage(mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, 733 slot, 0)); 734 } 735 736 @Override onQosFilterCallbackRegistered(final int qosCallbackId, final QosFilterParcelable qosFilterParcelable)737 public void onQosFilterCallbackRegistered(final int qosCallbackId, 738 final QosFilterParcelable qosFilterParcelable) { 739 if (qosFilterParcelable.getQosFilter() != null) { 740 mHandler.sendMessage( 741 mHandler.obtainMessage(CMD_REGISTER_QOS_CALLBACK, qosCallbackId, 0, 742 qosFilterParcelable.getQosFilter())); 743 return; 744 } 745 746 Log.wtf(LOG_TAG, "onQosFilterCallbackRegistered: qos filter is null."); 747 } 748 749 @Override onQosCallbackUnregistered(final int qosCallbackId)750 public void onQosCallbackUnregistered(final int qosCallbackId) { 751 mHandler.sendMessage(mHandler.obtainMessage( 752 CMD_UNREGISTER_QOS_CALLBACK, qosCallbackId, 0, null)); 753 } 754 755 @Override onNetworkCreated()756 public void onNetworkCreated() { 757 mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_CREATED)); 758 } 759 760 @Override onNetworkDestroyed()761 public void onNetworkDestroyed() { 762 mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DESTROYED)); 763 } 764 } 765 766 /** 767 * Register this network agent with a testing harness. 768 * 769 * The returned Messenger sends messages to the Handler. This allows a test to send 770 * this object {@code CMD_*} messages as if they came from ConnectivityService, which 771 * is useful for testing the behavior. 772 * 773 * @hide 774 */ registerForTest(final Network network)775 public INetworkAgent registerForTest(final Network network) { 776 log("Registering NetworkAgent for test"); 777 synchronized (mRegisterLock) { 778 mNetwork = network; 779 mInitialConfiguration = null; 780 } 781 return new NetworkAgentBinder(mHandler); 782 } 783 784 /** 785 * Waits for the handler to be idle. 786 * This is useful for testing, and has smaller scope than an accessor to mHandler. 787 * TODO : move the implementation in common library with the tests 788 * @hide 789 */ 790 @VisibleForTesting waitForIdle(final long timeoutMs)791 public boolean waitForIdle(final long timeoutMs) { 792 final ConditionVariable cv = new ConditionVariable(false); 793 mHandler.post(cv::open); 794 return cv.block(timeoutMs); 795 } 796 797 /** 798 * @return The Network associated with this agent, or null if it's not registered yet. 799 */ 800 @Nullable getNetwork()801 public Network getNetwork() { 802 return mNetwork; 803 } 804 queueOrSendMessage(@onNull RegistryAction action)805 private void queueOrSendMessage(@NonNull RegistryAction action) { 806 synchronized (mPreConnectedQueue) { 807 if (mRegistry != null) { 808 try { 809 action.execute(mRegistry); 810 } catch (RemoteException e) { 811 Log.wtf(LOG_TAG, "Error executing registry action", e); 812 // Fall through: the channel is asynchronous and does not report errors back 813 } 814 } else { 815 mPreConnectedQueue.add(action); 816 } 817 } 818 } 819 820 /** 821 * Must be called by the agent when the network's {@link LinkProperties} change. 822 * @param linkProperties the new LinkProperties. 823 */ sendLinkProperties(@onNull LinkProperties linkProperties)824 public final void sendLinkProperties(@NonNull LinkProperties linkProperties) { 825 Objects.requireNonNull(linkProperties); 826 final LinkProperties lp = new LinkProperties(linkProperties); 827 queueOrSendMessage(reg -> reg.sendLinkProperties(lp)); 828 } 829 830 /** 831 * Must be called by the agent when the network's underlying networks change. 832 * 833 * <p>{@code networks} is one of the following: 834 * <ul> 835 * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in 836 * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular) 837 * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear 838 * first in the array.</li> 839 * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no 840 * underlying network connection, and thus, app traffic will not be sent or received.</li> 841 * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's 842 * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket} 843 * APIs mentioned above to send traffic over specific channels.</li> 844 * </ul> 845 * 846 * @param underlyingNetworks the new list of underlying networks. 847 * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])} 848 */ setUnderlyingNetworks( @uppressLint"NullableCollection") @ullable List<Network> underlyingNetworks)849 public final void setUnderlyingNetworks( 850 @SuppressLint("NullableCollection") @Nullable List<Network> underlyingNetworks) { 851 final ArrayList<Network> underlyingArray = (underlyingNetworks != null) 852 ? new ArrayList<>(underlyingNetworks) : null; 853 queueOrSendMessage(reg -> reg.sendUnderlyingNetworks(underlyingArray)); 854 } 855 856 /** 857 * Inform ConnectivityService that this agent has now connected. 858 * Call {@link #unregister} to disconnect. 859 */ markConnected()860 public void markConnected() { 861 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */, 862 mNetworkInfo.getExtraInfo()); 863 queueOrSendNetworkInfo(mNetworkInfo); 864 } 865 866 /** 867 * Unregister this network agent. 868 * 869 * This signals the network has disconnected and ends its lifecycle. After this is called, 870 * the network is torn down and this agent can no longer be used. 871 */ unregister()872 public void unregister() { 873 // When unregistering an agent nobody should use the extrainfo (or reason) any more. 874 mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */, 875 null /* extraInfo */); 876 queueOrSendNetworkInfo(mNetworkInfo); 877 } 878 879 /** 880 * Sets the value of the teardown delay. 881 * 882 * The teardown delay is the time between when the network disconnects and when the native 883 * network corresponding to this {@code NetworkAgent} is destroyed. By default, the native 884 * network is destroyed immediately. If {@code teardownDelayMs} is non-zero, then when this 885 * network disconnects, the system will instead immediately mark the network as restricted 886 * and unavailable to unprivileged apps, but will defer destroying the native network until the 887 * teardown delay timer expires. 888 * 889 * The interfaces in use by this network will remain in use until the native network is 890 * destroyed and cannot be reused until {@link #onNetworkDestroyed()} is called. 891 * 892 * This method may be called at any time while the network is connected. It has no effect if 893 * the network is already disconnected and the teardown delay timer is running. 894 * 895 * @param teardownDelayMillis the teardown delay to set, or 0 to disable teardown delay. 896 */ setTeardownDelayMillis( @ntRangefrom = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMillis)897 public void setTeardownDelayMillis( 898 @IntRange(from = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMillis) { 899 queueOrSendMessage(reg -> reg.sendTeardownDelayMs(teardownDelayMillis)); 900 } 901 902 /** 903 * Change the legacy subtype of this network agent. 904 * 905 * This is only for backward compatibility and should not be used by non-legacy network agents, 906 * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use 907 * this and others will be thrown an exception if they try. 908 * 909 * @deprecated this is for backward compatibility only. 910 * @param legacySubtype the legacy subtype. 911 * @hide 912 */ 913 @Deprecated 914 @SystemApi setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName)915 public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) { 916 mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName); 917 queueOrSendNetworkInfo(mNetworkInfo); 918 } 919 920 /** 921 * Set the ExtraInfo of this network agent. 922 * 923 * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the 924 * broadcasts about the corresponding Network. 925 * This is only for backward compatibility and should not be used by non-legacy network agents, 926 * who will be thrown an exception if they try. The extra info should only be : 927 * <ul> 928 * <li>For cellular agents, the APN name.</li> 929 * <li>For ethernet agents, the interface name.</li> 930 * </ul> 931 * 932 * @deprecated this is for backward compatibility only. 933 * @param extraInfo the ExtraInfo. 934 * @hide 935 */ 936 @Deprecated setLegacyExtraInfo(@ullable final String extraInfo)937 public void setLegacyExtraInfo(@Nullable final String extraInfo) { 938 mNetworkInfo.setExtraInfo(extraInfo); 939 queueOrSendNetworkInfo(mNetworkInfo); 940 } 941 942 /** 943 * Must be called by the agent when it has a new NetworkInfo object. 944 * @hide TODO: expose something better. 945 */ 946 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023) sendNetworkInfo(NetworkInfo networkInfo)947 public final void sendNetworkInfo(NetworkInfo networkInfo) { 948 queueOrSendNetworkInfo(new NetworkInfo(networkInfo)); 949 } 950 queueOrSendNetworkInfo(NetworkInfo networkInfo)951 private void queueOrSendNetworkInfo(NetworkInfo networkInfo) { 952 queueOrSendMessage(reg -> reg.sendNetworkInfo(networkInfo)); 953 } 954 955 /** 956 * Must be called by the agent when the network's {@link NetworkCapabilities} change. 957 * @param networkCapabilities the new NetworkCapabilities. 958 */ sendNetworkCapabilities(@onNull NetworkCapabilities networkCapabilities)959 public final void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) { 960 Objects.requireNonNull(networkCapabilities); 961 mBandwidthUpdatePending.set(false); 962 mLastBwRefreshTime = System.currentTimeMillis(); 963 final NetworkCapabilities nc = 964 new NetworkCapabilities(networkCapabilities, NetworkCapabilities.REDACT_NONE); 965 queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); 966 } 967 968 /** 969 * Must be called by the agent to update the score of this network. 970 * 971 * @param score the new score. 972 */ sendNetworkScore(@onNull NetworkScore score)973 public final void sendNetworkScore(@NonNull NetworkScore score) { 974 Objects.requireNonNull(score); 975 queueOrSendMessage(reg -> reg.sendScore(score)); 976 } 977 978 /** 979 * Must be called by the agent to update the score of this network. 980 * 981 * @param score the new score, between 0 and 99. 982 * deprecated use sendNetworkScore(NetworkScore) TODO : remove in S. 983 */ sendNetworkScore(@ntRangefrom = 0, to = 99) int score)984 public final void sendNetworkScore(@IntRange(from = 0, to = 99) int score) { 985 sendNetworkScore(new NetworkScore.Builder().setLegacyInt(score).build()); 986 } 987 988 /** 989 * Must be called by the agent to indicate this network was manually selected by the user. 990 * This should be called before the NetworkInfo is marked CONNECTED so that this 991 * Network can be given special treatment at that time. If {@code acceptUnvalidated} is 992 * {@code true}, then the system will switch to this network. If it is {@code false} and the 993 * network cannot be validated, the system will ask the user whether to switch to this network. 994 * If the user confirms and selects "don't ask again", then the system will call 995 * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever 996 * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement 997 * {@link #saveAcceptUnvalidated} to respect the user's choice. 998 * @hide should move to NetworkAgentConfig. 999 */ explicitlySelected(boolean acceptUnvalidated)1000 public void explicitlySelected(boolean acceptUnvalidated) { 1001 explicitlySelected(true /* explicitlySelected */, acceptUnvalidated); 1002 } 1003 1004 /** 1005 * Must be called by the agent to indicate whether the network was manually selected by the 1006 * user. This should be called before the network becomes connected, so it can be given 1007 * special treatment when it does. 1008 * 1009 * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true}, 1010 * then the system will switch to this network. If {@code explicitlySelected} is {@code true} 1011 * and {@code acceptUnvalidated} is {@code false}, and the network cannot be validated, the 1012 * system will ask the user whether to switch to this network. If the user confirms and selects 1013 * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the 1014 * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected} 1015 * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also 1016 * implement {@link #saveAcceptUnvalidated} to respect the user's choice. 1017 * 1018 * If {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is 1019 * {@code true}, the system will interpret this as the user having accepted partial connectivity 1020 * on this network. Thus, the system will switch to the network and consider it validated even 1021 * if it only provides partial connectivity, but the network is not otherwise treated specially. 1022 * @hide should move to NetworkAgentConfig. 1023 */ explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated)1024 public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) { 1025 queueOrSendMessage(reg -> reg.sendExplicitlySelected( 1026 explicitlySelected, acceptUnvalidated)); 1027 } 1028 1029 /** 1030 * Called when ConnectivityService has indicated they no longer want this network. 1031 * The parent factory should (previously) have received indication of the change 1032 * as well, either canceling NetworkRequests or altering their score such that this 1033 * network won't be immediately requested again. 1034 */ onNetworkUnwanted()1035 public void onNetworkUnwanted() { 1036 unwanted(); 1037 } 1038 /** @hide TODO delete once subclasses have moved to onNetworkUnwanted. */ unwanted()1039 protected void unwanted() { 1040 } 1041 1042 /** 1043 * Called when ConnectivityService request a bandwidth update. The parent factory 1044 * shall try to overwrite this method and produce a bandwidth update if capable. 1045 * @hide 1046 */ 1047 @SystemApi onBandwidthUpdateRequested()1048 public void onBandwidthUpdateRequested() { 1049 pollLceData(); 1050 } 1051 /** @hide TODO delete once subclasses have moved to onBandwidthUpdateRequested. */ pollLceData()1052 protected void pollLceData() { 1053 } 1054 1055 /** 1056 * Called when the system determines the usefulness of this network. 1057 * 1058 * The system attempts to validate Internet connectivity on networks that provide the 1059 * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} capability. 1060 * 1061 * Currently there are two possible values: 1062 * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated, 1063 * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated. 1064 * 1065 * This is guaranteed to be called again when the network status changes, but the system 1066 * may also call this multiple times even if the status does not change. 1067 * 1068 * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}. 1069 * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal), 1070 * this is the destination the probes are being redirected to, otherwise {@code null}. 1071 */ onValidationStatus(@alidationStatus int status, @Nullable Uri redirectUri)1072 public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) { 1073 networkStatus(status, null == redirectUri ? "" : redirectUri.toString()); 1074 } 1075 /** @hide TODO delete once subclasses have moved to onValidationStatus */ networkStatus(int status, String redirectUrl)1076 protected void networkStatus(int status, String redirectUrl) { 1077 } 1078 1079 1080 /** 1081 * Called when the user asks to remember the choice to use this network even if unvalidated. 1082 * The transport is responsible for remembering the choice, and the next time the user connects 1083 * to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}. 1084 * This method will only be called if {@link #explicitlySelected} was called with 1085 * {@code acceptUnvalidated} set to {@code false}. 1086 * @param accept whether the user wants to use the network even if unvalidated. 1087 */ onSaveAcceptUnvalidated(boolean accept)1088 public void onSaveAcceptUnvalidated(boolean accept) { 1089 saveAcceptUnvalidated(accept); 1090 } 1091 /** @hide TODO delete once subclasses have moved to onSaveAcceptUnvalidated */ saveAcceptUnvalidated(boolean accept)1092 protected void saveAcceptUnvalidated(boolean accept) { 1093 } 1094 1095 /** 1096 * Called when ConnectivityService has successfully created this NetworkAgent's native network. 1097 */ onNetworkCreated()1098 public void onNetworkCreated() {} 1099 1100 1101 /** 1102 * Called when ConnectivityService has successfully destroy this NetworkAgent's native network. 1103 */ onNetworkDestroyed()1104 public void onNetworkDestroyed() {} 1105 1106 /** 1107 * Requests that the network hardware send the specified packet at the specified interval. 1108 * 1109 * @param slot the hardware slot on which to start the keepalive. 1110 * @param interval the interval between packets, between 10 and 3600. Note that this API 1111 * does not support sub-second precision and will round off the request. 1112 * @param packet the packet to send. 1113 */ 1114 // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should 1115 // not be exposed as constants because they may change in the future (API guideline 4.8) 1116 // and should have getters if exposed at all. Getters can't be used in the annotation, 1117 // so the values unfortunately need to be copied. onStartSocketKeepalive(int slot, @NonNull Duration interval, @NonNull KeepalivePacketData packet)1118 public void onStartSocketKeepalive(int slot, @NonNull Duration interval, 1119 @NonNull KeepalivePacketData packet) { 1120 final long intervalSeconds = interval.getSeconds(); 1121 if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC 1122 || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) { 1123 throw new IllegalArgumentException("Interval needs to be comprised between " 1124 + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC 1125 + " but was " + intervalSeconds); 1126 } 1127 final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot, 1128 (int) intervalSeconds, packet); 1129 startSocketKeepalive(msg); 1130 msg.recycle(); 1131 } 1132 /** @hide TODO delete once subclasses have moved to onStartSocketKeepalive */ startSocketKeepalive(Message msg)1133 protected void startSocketKeepalive(Message msg) { 1134 onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); 1135 } 1136 1137 /** 1138 * Requests that the network hardware stop a previously-started keepalive. 1139 * 1140 * @param slot the hardware slot on which to stop the keepalive. 1141 */ onStopSocketKeepalive(int slot)1142 public void onStopSocketKeepalive(int slot) { 1143 Message msg = mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0, null); 1144 stopSocketKeepalive(msg); 1145 msg.recycle(); 1146 } 1147 /** @hide TODO delete once subclasses have moved to onStopSocketKeepalive */ stopSocketKeepalive(Message msg)1148 protected void stopSocketKeepalive(Message msg) { 1149 onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED); 1150 } 1151 1152 /** 1153 * Must be called by the agent when a socket keepalive event occurs. 1154 * 1155 * @param slot the hardware slot on which the event occurred. 1156 * @param event the event that occurred, as one of the SocketKeepalive.ERROR_* 1157 * or SocketKeepalive.SUCCESS constants. 1158 */ sendSocketKeepaliveEvent(int slot, @SocketKeepalive.KeepaliveEvent int event)1159 public final void sendSocketKeepaliveEvent(int slot, 1160 @SocketKeepalive.KeepaliveEvent int event) { 1161 queueOrSendMessage(reg -> reg.sendSocketKeepaliveEvent(slot, event)); 1162 } 1163 /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */ onSocketKeepaliveEvent(int slot, int reason)1164 public void onSocketKeepaliveEvent(int slot, int reason) { 1165 sendSocketKeepaliveEvent(slot, reason); 1166 } 1167 1168 /** 1169 * Called by ConnectivityService to add specific packet filter to network hardware to block 1170 * replies (e.g., TCP ACKs) matching the sent keepalive packets. Implementations that support 1171 * this feature must override this method. 1172 * 1173 * @param slot the hardware slot on which the keepalive should be sent. 1174 * @param packet the packet that is being sent. 1175 */ onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet)1176 public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) { 1177 Message msg = mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0, packet); 1178 addKeepalivePacketFilter(msg); 1179 msg.recycle(); 1180 } 1181 /** @hide TODO delete once subclasses have moved to onAddKeepalivePacketFilter */ addKeepalivePacketFilter(Message msg)1182 protected void addKeepalivePacketFilter(Message msg) { 1183 } 1184 1185 /** 1186 * Called by ConnectivityService to remove a packet filter installed with 1187 * {@link #addKeepalivePacketFilter(Message)}. Implementations that support this feature 1188 * must override this method. 1189 * 1190 * @param slot the hardware slot on which the keepalive is being sent. 1191 */ onRemoveKeepalivePacketFilter(int slot)1192 public void onRemoveKeepalivePacketFilter(int slot) { 1193 Message msg = mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, slot, 0, null); 1194 removeKeepalivePacketFilter(msg); 1195 msg.recycle(); 1196 } 1197 /** @hide TODO delete once subclasses have moved to onRemoveKeepalivePacketFilter */ removeKeepalivePacketFilter(Message msg)1198 protected void removeKeepalivePacketFilter(Message msg) { 1199 } 1200 1201 /** 1202 * Called by ConnectivityService to inform this network agent of signal strength thresholds 1203 * that when crossed should trigger a system wakeup and a NetworkCapabilities update. 1204 * 1205 * When the system updates the list of thresholds that should wake up the CPU for a 1206 * given agent it will call this method on the agent. The agent that implement this 1207 * should implement it in hardware so as to ensure the CPU will be woken up on breach. 1208 * Agents are expected to react to a breach by sending an updated NetworkCapabilities 1209 * object with the appropriate signal strength to sendNetworkCapabilities. 1210 * 1211 * The specific units are bearer-dependent. See details on the units and requests in 1212 * {@link NetworkCapabilities.Builder#setSignalStrength}. 1213 * 1214 * @param thresholds the array of thresholds that should trigger wakeups. 1215 */ onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)1216 public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) { 1217 setSignalStrengthThresholds(thresholds); 1218 } 1219 /** @hide TODO delete once subclasses have moved to onSetSignalStrengthThresholds */ setSignalStrengthThresholds(int[] thresholds)1220 protected void setSignalStrengthThresholds(int[] thresholds) { 1221 } 1222 1223 /** 1224 * Called when the user asks to not stay connected to this network because it was found to not 1225 * provide Internet access. Usually followed by call to {@code unwanted}. The transport is 1226 * responsible for making sure the device does not automatically reconnect to the same network 1227 * after the {@code unwanted} call. 1228 */ onAutomaticReconnectDisabled()1229 public void onAutomaticReconnectDisabled() { 1230 preventAutomaticReconnect(); 1231 } 1232 /** @hide TODO delete once subclasses have moved to onAutomaticReconnectDisabled */ preventAutomaticReconnect()1233 protected void preventAutomaticReconnect() { 1234 } 1235 1236 /** 1237 * Called when a qos callback is registered with a filter. 1238 * @param qosCallbackId the id for the callback registered 1239 * @param filter the filter being registered 1240 */ onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter)1241 public void onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter) { 1242 } 1243 1244 /** 1245 * Called when a qos callback is registered with a filter. 1246 * <p/> 1247 * Any QoS events that are sent with the same callback id after this method is called 1248 * are a no-op. 1249 * 1250 * @param qosCallbackId the id for the callback being unregistered 1251 */ onQosCallbackUnregistered(final int qosCallbackId)1252 public void onQosCallbackUnregistered(final int qosCallbackId) { 1253 } 1254 1255 1256 /** 1257 * Sends the attributes of Qos Session back to the Application 1258 * 1259 * @param qosCallbackId the callback id that the session belongs to 1260 * @param sessionId the unique session id across all Qos Sessions 1261 * @param attributes the attributes of the Qos Session 1262 */ sendQosSessionAvailable(final int qosCallbackId, final int sessionId, @NonNull final QosSessionAttributes attributes)1263 public final void sendQosSessionAvailable(final int qosCallbackId, final int sessionId, 1264 @NonNull final QosSessionAttributes attributes) { 1265 Objects.requireNonNull(attributes, "The attributes must be non-null"); 1266 if (attributes instanceof EpsBearerQosSessionAttributes) { 1267 queueOrSendMessage(ra -> ra.sendEpsQosSessionAvailable(qosCallbackId, 1268 new QosSession(sessionId, QosSession.TYPE_EPS_BEARER), 1269 (EpsBearerQosSessionAttributes)attributes)); 1270 } else if (attributes instanceof NrQosSessionAttributes) { 1271 queueOrSendMessage(ra -> ra.sendNrQosSessionAvailable(qosCallbackId, 1272 new QosSession(sessionId, QosSession.TYPE_NR_BEARER), 1273 (NrQosSessionAttributes)attributes)); 1274 } 1275 } 1276 1277 /** 1278 * Sends event that the Qos Session was lost. 1279 * 1280 * @param qosCallbackId the callback id that the session belongs to 1281 * @param sessionId the unique session id across all Qos Sessions 1282 * @param qosSessionType the session type {@code QosSesson#QosSessionType} 1283 */ sendQosSessionLost(final int qosCallbackId, final int sessionId, final int qosSessionType)1284 public final void sendQosSessionLost(final int qosCallbackId, 1285 final int sessionId, final int qosSessionType) { 1286 queueOrSendMessage(ra -> ra.sendQosSessionLost(qosCallbackId, 1287 new QosSession(sessionId, qosSessionType))); 1288 } 1289 1290 /** 1291 * Sends the exception type back to the application. 1292 * 1293 * The NetworkAgent should not send anymore messages with this id. 1294 * 1295 * @param qosCallbackId the callback id this exception belongs to 1296 * @param exceptionType the type of exception 1297 */ sendQosCallbackError(final int qosCallbackId, @QosCallbackException.ExceptionType final int exceptionType)1298 public final void sendQosCallbackError(final int qosCallbackId, 1299 @QosCallbackException.ExceptionType final int exceptionType) { 1300 queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType)); 1301 } 1302 1303 /** 1304 * Set the linger duration for this network agent. 1305 * @param duration the delay between the moment the network becomes unneeded and the 1306 * moment the network is disconnected or moved into the background. 1307 * Note that If this duration has greater than millisecond precision, then 1308 * the internal implementation will drop any excess precision. 1309 */ setLingerDuration(@onNull final Duration duration)1310 public void setLingerDuration(@NonNull final Duration duration) { 1311 Objects.requireNonNull(duration); 1312 final long durationMs = duration.toMillis(); 1313 if (durationMs < MIN_LINGER_TIMER_MS || durationMs > Integer.MAX_VALUE) { 1314 throw new IllegalArgumentException("Duration must be within [" 1315 + MIN_LINGER_TIMER_MS + "," + Integer.MAX_VALUE + "]ms"); 1316 } 1317 queueOrSendMessage(ra -> ra.sendLingerDuration((int) durationMs)); 1318 } 1319 1320 /** @hide */ log(final String s)1321 protected void log(final String s) { 1322 Log.d(LOG_TAG, "NetworkAgent: " + s); 1323 } 1324 } 1325