• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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