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 {@link 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      * NetworkCapabilities.
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      * @hide
287      */
288     public static final int CMD_START_SOCKET_KEEPALIVE = BASE + 11;
289 
290     /**
291      * Requests that the specified keepalive packet be stopped.
292      *
293      * arg1 = unused
294      * arg2 = error code (SUCCESS)
295      * obj = callback to identify the keepalive
296      *
297      * Also used internally by ConnectivityService / KeepaliveTracker, with different semantics.
298      * @hide
299      */
300     public static final int CMD_STOP_SOCKET_KEEPALIVE = BASE + 12;
301 
302     /**
303      * Sent by the NetworkAgent to ConnectivityService to provide status on a socket keepalive
304      * request. This may either be the reply to a CMD_START_SOCKET_KEEPALIVE, or an asynchronous
305      * error notification.
306      *
307      * This is also sent by KeepaliveTracker to the app's {@link SocketKeepalive},
308      * so that the app's {@link SocketKeepalive.Callback} methods can be called.
309      *
310      * arg1 = hardware slot number of the keepalive
311      * arg2 = error code
312      * @hide
313      */
314     public static final int EVENT_SOCKET_KEEPALIVE = BASE + 13;
315 
316     /**
317      * Sent by ConnectivityService to inform this network transport of signal strength thresholds
318      * that when crossed should trigger a system wakeup and a NetworkCapabilities update.
319      *
320      *   obj = int[] describing signal strength thresholds.
321      * @hide
322      */
323     public static final int CMD_SET_SIGNAL_STRENGTH_THRESHOLDS = BASE + 14;
324 
325     /**
326      * Sent by ConnectivityService to the NeworkAgent to inform the agent to avoid
327      * automatically reconnecting to this network (e.g. via autojoin).  Happens
328      * when user selects "No" option on the "Stay connected?" dialog box.
329      * @hide
330      */
331     public static final int CMD_PREVENT_AUTOMATIC_RECONNECT = BASE + 15;
332 
333     /**
334      * Sent by the KeepaliveTracker to NetworkAgent to add a packet filter.
335      *
336      * For TCP keepalive offloads, keepalive packets are sent by the firmware. However, because the
337      * remote site will send ACK packets in response to the keepalive packets, the firmware also
338      * needs to be configured to properly filter the ACKs to prevent the system from waking up.
339      * This does not happen with UDP, so this message is TCP-specific.
340      * arg1 = hardware slot number of the keepalive to filter for.
341      * obj = the keepalive packet to send repeatedly.
342      * @hide
343      */
344     public static final int CMD_ADD_KEEPALIVE_PACKET_FILTER = BASE + 16;
345 
346     /**
347      * Sent by the KeepaliveTracker to NetworkAgent to remove a packet filter. See
348      * {@link #CMD_ADD_KEEPALIVE_PACKET_FILTER}.
349      * arg1 = hardware slot number of the keepalive packet filter to remove.
350      * @hide
351      */
352     public static final int CMD_REMOVE_KEEPALIVE_PACKET_FILTER = BASE + 17;
353 
354     /**
355      * Sent by ConnectivityService to the NetworkAgent to complete the bidirectional connection.
356      * obj = INetworkAgentRegistry
357      */
358     private static final int EVENT_AGENT_CONNECTED = BASE + 18;
359 
360     /**
361      * Sent by ConnectivityService to the NetworkAgent to inform the agent that it was disconnected.
362      */
363     private static final int EVENT_AGENT_DISCONNECTED = BASE + 19;
364 
365     /**
366      * Sent by QosCallbackTracker to {@link NetworkAgent} to register a new filter with
367      * callback.
368      *
369      * arg1 = QoS agent callback ID
370      * obj = {@link QosFilter}
371      * @hide
372      */
373     public static final int CMD_REGISTER_QOS_CALLBACK = BASE + 20;
374 
375     /**
376      * Sent by QosCallbackTracker to {@link NetworkAgent} to unregister a callback.
377      *
378      * arg1 = QoS agent callback ID
379      * @hide
380      */
381     public static final int CMD_UNREGISTER_QOS_CALLBACK = BASE + 21;
382 
383     /**
384      * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent that its native
385      * network was created and the Network object is now valid.
386      *
387      * @hide
388      */
389     public static final int CMD_NETWORK_CREATED = BASE + 22;
390 
391     /**
392      * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent that its native
393      * network was destroyed.
394      *
395      * @hide
396      */
397     public static final int CMD_NETWORK_DESTROYED = BASE + 23;
398 
399     /**
400      * Sent by the NetworkAgent to ConnectivityService to set the linger duration for this network
401      * agent.
402      * arg1 = the linger duration, represents by {@link Duration}.
403      *
404      * @hide
405      */
406     public static final int EVENT_LINGER_DURATION_CHANGED = BASE + 24;
407 
408     /**
409      * Sent by the NetworkAgent to ConnectivityService to set add a DSCP policy.
410      *
411      * @hide
412      */
413     public static final int EVENT_ADD_DSCP_POLICY = BASE + 25;
414 
415     /**
416      * Sent by the NetworkAgent to ConnectivityService to set remove a DSCP policy.
417      *
418      * @hide
419      */
420     public static final int EVENT_REMOVE_DSCP_POLICY = BASE + 26;
421 
422     /**
423      * Sent by the NetworkAgent to ConnectivityService to remove all DSCP policies.
424      *
425      * @hide
426      */
427     public static final int EVENT_REMOVE_ALL_DSCP_POLICIES = BASE + 27;
428 
429     /**
430      * Sent by ConnectivityService to {@link NetworkAgent} to inform the agent of an updated
431      * status for a DSCP policy.
432      *
433      * @hide
434      */
435     public static final int CMD_DSCP_POLICY_STATUS = BASE + 28;
436 
437     /**
438      * Sent by the NetworkAgent to ConnectivityService to notify that this network is expected to be
439      * replaced within the specified time by a similar network.
440      * arg1 = timeout in milliseconds
441      * @hide
442      */
443     public static final int EVENT_UNREGISTER_AFTER_REPLACEMENT = BASE + 29;
444 
445     /**
446      * Sent by the NetworkAgent to ConnectivityService to pass the new value of the local
447      * network agent config.
448      * obj = {@code Pair<NetworkAgentInfo, LocalNetworkConfig>}
449      * @hide
450      */
451     public static final int EVENT_LOCAL_NETWORK_CONFIG_CHANGED = BASE + 30;
452 
453     /**
454      * DSCP policy was successfully added.
455      */
456     public static final int DSCP_POLICY_STATUS_SUCCESS = 0;
457 
458     /**
459      * DSCP policy was rejected for any reason besides invalid classifier or insufficient resources.
460      */
461     public static final int DSCP_POLICY_STATUS_REQUEST_DECLINED = 1;
462 
463     /**
464      * Requested DSCP policy contained a classifier which is not supported.
465      */
466     public static final int DSCP_POLICY_STATUS_REQUESTED_CLASSIFIER_NOT_SUPPORTED = 2;
467 
468     /**
469      * Requested DSCP policy was not added due to insufficient processing resources.
470      */
471     // TODO: should this error case be supported?
472     public static final int DSCP_POLICY_STATUS_INSUFFICIENT_PROCESSING_RESOURCES = 3;
473 
474     /**
475      * DSCP policy was deleted.
476      */
477     public static final int DSCP_POLICY_STATUS_DELETED = 4;
478 
479     /**
480      * DSCP policy was not found during deletion.
481      */
482     public static final int DSCP_POLICY_STATUS_POLICY_NOT_FOUND = 5;
483 
484     /** @hide */
485     @IntDef(prefix = "DSCP_POLICY_STATUS_", value = {
486         DSCP_POLICY_STATUS_SUCCESS,
487         DSCP_POLICY_STATUS_REQUEST_DECLINED,
488         DSCP_POLICY_STATUS_REQUESTED_CLASSIFIER_NOT_SUPPORTED,
489         DSCP_POLICY_STATUS_INSUFFICIENT_PROCESSING_RESOURCES,
490         DSCP_POLICY_STATUS_DELETED
491     })
492     @Retention(RetentionPolicy.SOURCE)
493     public @interface DscpPolicyStatus {}
494 
getLegacyNetworkInfo(final NetworkAgentConfig config)495     private static NetworkInfo getLegacyNetworkInfo(final NetworkAgentConfig config) {
496         final NetworkInfo ni = new NetworkInfo(config.legacyType, config.legacySubType,
497                 config.legacyTypeName, config.legacySubTypeName);
498         ni.setIsAvailable(true);
499         ni.setDetailedState(NetworkInfo.DetailedState.CONNECTING, null /* reason */,
500                 config.getLegacyExtraInfo());
501         return ni;
502     }
503 
504     // 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)505     public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
506             @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, int score,
507             @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
508         this(context, looper, logTag, nc, lp,
509                 new NetworkScore.Builder().setLegacyInt(score).build(), config, provider);
510     }
511 
512     /**
513      * Create a new network agent.
514      * @param context a {@link Context} to get system services from.
515      * @param looper the {@link Looper} on which to invoke the callbacks.
516      * @param logTag the tag for logs
517      * @param nc the initial {@link NetworkCapabilities} of this network. Update with
518      *           sendNetworkCapabilities.
519      * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties.
520      * @param score the initial score of this network. Update with sendNetworkScore.
521      * @param config an immutable {@link NetworkAgentConfig} for this agent.
522      * @param provider the {@link NetworkProvider} managing this agent.
523      */
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)524     public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
525             @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
526             @NonNull NetworkScore score, @NonNull NetworkAgentConfig config,
527             @Nullable NetworkProvider provider) {
528         this(context, looper, logTag, nc, lp, null /* localNetworkConfig */, score, config,
529                 provider);
530     }
531 
532     /**
533      * Create a new network agent.
534      * @param context a {@link Context} to get system services from.
535      * @param looper the {@link Looper} on which to invoke the callbacks.
536      * @param logTag the tag for logs
537      * @param nc the initial {@link NetworkCapabilities} of this network. Update with
538      *           sendNetworkCapabilities.
539      * @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties.
540      * @param localNetworkConfig the initial {@link LocalNetworkConfig} of this
541      *                                  network. Update with sendLocalNetworkConfig. Must be
542      *                                  non-null iff the nc have NET_CAPABILITY_LOCAL_NETWORK.
543      * @param score the initial score of this network. Update with sendNetworkScore.
544      * @param config an immutable {@link NetworkAgentConfig} for this agent.
545      * @param provider the {@link NetworkProvider} managing this agent.
546      * @hide
547      */
548     // TODO : expose
NetworkAgent(@onNull Context context, @NonNull Looper looper, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider)549     public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
550             @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
551             @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
552             @NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
553         this(looper, context, logTag, nc, lp, localNetworkConfig, score, config,
554                 provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
555                 getLegacyNetworkInfo(config));
556     }
557 
558     private static class InitialConfiguration {
559         @NonNull public final Context context;
560         @NonNull public final NetworkCapabilities capabilities;
561         @NonNull public final LinkProperties properties;
562         @NonNull public final NetworkScore score;
563         @NonNull public final NetworkAgentConfig config;
564         @NonNull public final NetworkInfo info;
565         @Nullable public final LocalNetworkConfig localNetworkConfig;
InitialConfiguration(@onNull Context context, @NonNull NetworkCapabilities capabilities, @NonNull LinkProperties properties, @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info)566         InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities,
567                 @NonNull LinkProperties properties,
568                 @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
569                 @NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) {
570             this.context = context;
571             this.capabilities = capabilities;
572             this.properties = properties;
573             this.score = score;
574             this.config = config;
575             this.info = info;
576             this.localNetworkConfig = localNetworkConfig;
577         }
578     }
579     private volatile InitialConfiguration mInitialConfiguration;
580 
NetworkAgent(@onNull Looper looper, @NonNull Context context, @NonNull String logTag, @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp, @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni)581     private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
582             @NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
583             @Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
584             @NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) {
585         mHandler = new NetworkAgentHandler(looper);
586         LOG_TAG = logTag;
587         mNetworkInfo = new NetworkInfo(ni);
588         this.providerId = providerId;
589         if (ni == null || nc == null || lp == null) {
590             throw new IllegalArgumentException();
591         }
592 
593         mInitialConfiguration = new InitialConfiguration(context,
594                 new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE),
595                 new LinkProperties(lp), localNetworkConfig, score, config, ni);
596     }
597 
598     private class NetworkAgentHandler extends Handler {
NetworkAgentHandler(Looper looper)599         NetworkAgentHandler(Looper looper) {
600             super(looper);
601         }
602 
603         @Override
handleMessage(Message msg)604         public void handleMessage(Message msg) {
605             switch (msg.what) {
606                 case EVENT_AGENT_CONNECTED: {
607                     if (mRegistry != null) {
608                         log("Received new connection while already connected!");
609                     } else {
610                         if (VDBG) log("NetworkAgent fully connected");
611                         synchronized (mPreConnectedQueue) {
612                             final INetworkAgentRegistry registry = (INetworkAgentRegistry) msg.obj;
613                             mRegistry = registry;
614                             for (RegistryAction a : mPreConnectedQueue) {
615                                 try {
616                                     a.execute(registry);
617                                 } catch (RemoteException e) {
618                                     Log.wtf(LOG_TAG, "Communication error with registry", e);
619                                     // Fall through
620                                 }
621                             }
622                             mPreConnectedQueue.clear();
623                         }
624                     }
625                     break;
626                 }
627                 case EVENT_AGENT_DISCONNECTED: {
628                     if (DBG) log("NetworkAgent channel lost");
629                     // let the client know CS is done with us.
630                     onNetworkUnwanted();
631                     synchronized (mPreConnectedQueue) {
632                         mRegistry = null;
633                     }
634                     break;
635                 }
636                 case CMD_SUSPECT_BAD: {
637                     log("Unhandled Message " + msg);
638                     break;
639                 }
640                 case CMD_REQUEST_BANDWIDTH_UPDATE: {
641                     long currentTimeMs = System.currentTimeMillis();
642                     if (VDBG) {
643                         log("CMD_REQUEST_BANDWIDTH_UPDATE request received.");
644                     }
645                     if (currentTimeMs >= (mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS)) {
646                         mBandwidthUpdateScheduled = false;
647                         if (!mBandwidthUpdatePending.getAndSet(true)) {
648                             onBandwidthUpdateRequested();
649                         }
650                     } else {
651                         // deliver the request at a later time rather than discard it completely.
652                         if (!mBandwidthUpdateScheduled) {
653                             long waitTime = mLastBwRefreshTime + BW_REFRESH_MIN_WIN_MS
654                                     - currentTimeMs + 1;
655                             mBandwidthUpdateScheduled = sendEmptyMessageDelayed(
656                                     CMD_REQUEST_BANDWIDTH_UPDATE, waitTime);
657                         }
658                     }
659                     break;
660                 }
661                 case CMD_REPORT_NETWORK_STATUS: {
662                     String redirectUrl = ((Bundle) msg.obj).getString(REDIRECT_URL_KEY);
663                     if (VDBG) {
664                         log("CMD_REPORT_NETWORK_STATUS("
665                                 + (msg.arg1 == VALID_NETWORK ? "VALID, " : "INVALID, ")
666                                 + redirectUrl);
667                     }
668                     Uri uri = null;
669                     try {
670                         if (null != redirectUrl) {
671                             uri = Uri.parse(redirectUrl);
672                         }
673                     } catch (Exception e) {
674                         Log.wtf(LOG_TAG, "Surprising URI : " + redirectUrl, e);
675                     }
676                     onValidationStatus(msg.arg1 /* status */, uri);
677                     break;
678                 }
679                 case CMD_SAVE_ACCEPT_UNVALIDATED: {
680                     onSaveAcceptUnvalidated(msg.arg1 != 0);
681                     break;
682                 }
683                 case CMD_START_SOCKET_KEEPALIVE: {
684                     onStartSocketKeepalive(msg.arg1 /* slot */,
685                             Duration.ofSeconds(msg.arg2) /* interval */,
686                             (KeepalivePacketData) msg.obj /* packet */);
687                     break;
688                 }
689                 case CMD_STOP_SOCKET_KEEPALIVE: {
690                     onStopSocketKeepalive(msg.arg1 /* slot */);
691                     break;
692                 }
693 
694                 case CMD_SET_SIGNAL_STRENGTH_THRESHOLDS: {
695                     onSignalStrengthThresholdsUpdated((int[]) msg.obj);
696                     break;
697                 }
698                 case CMD_PREVENT_AUTOMATIC_RECONNECT: {
699                     onAutomaticReconnectDisabled();
700                     break;
701                 }
702                 case CMD_ADD_KEEPALIVE_PACKET_FILTER: {
703                     onAddKeepalivePacketFilter(msg.arg1 /* slot */,
704                             (KeepalivePacketData) msg.obj /* packet */);
705                     break;
706                 }
707                 case CMD_REMOVE_KEEPALIVE_PACKET_FILTER: {
708                     onRemoveKeepalivePacketFilter(msg.arg1 /* slot */);
709                     break;
710                 }
711                 case CMD_REGISTER_QOS_CALLBACK: {
712                     onQosCallbackRegistered(
713                             msg.arg1 /* QoS callback id */,
714                             (QosFilter) msg.obj /* QoS filter */);
715                     break;
716                 }
717                 case CMD_UNREGISTER_QOS_CALLBACK: {
718                     onQosCallbackUnregistered(
719                             msg.arg1 /* QoS callback id */);
720                     break;
721                 }
722                 case CMD_NETWORK_CREATED: {
723                     onNetworkCreated();
724                     break;
725                 }
726                 case CMD_NETWORK_DESTROYED: {
727                     onNetworkDestroyed();
728                     break;
729                 }
730                 case CMD_DSCP_POLICY_STATUS: {
731                     onDscpPolicyStatusUpdated(
732                             msg.arg1 /* Policy ID */,
733                             msg.arg2 /* DSCP Policy Status */);
734                     break;
735                 }
736             }
737         }
738     }
739 
740     /**
741      * Register this network agent with ConnectivityService.
742      *
743      * This method can only be called once per network agent.
744      *
745      * @return the Network associated with this network agent (which can also be obtained later
746      *         by calling getNetwork() on this agent).
747      * @throws IllegalStateException thrown by the system server if this network agent is
748      *         already registered.
749      */
750     @NonNull
register()751     public Network register() {
752         if (VDBG) log("Registering NetworkAgent");
753         synchronized (mRegisterLock) {
754             if (mNetwork != null) {
755                 throw new IllegalStateException("Agent already registered");
756             }
757             final ConnectivityManager cm = (ConnectivityManager) mInitialConfiguration.context
758                     .getSystemService(Context.CONNECTIVITY_SERVICE);
759             if (mInitialConfiguration.localNetworkConfig == null) {
760                 // Call registerNetworkAgent without localNetworkConfig argument to pass
761                 // android.net.cts.NetworkAgentTest#testAgentStartsInConnecting in old cts
762                 mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
763                         new NetworkInfo(mInitialConfiguration.info),
764                         mInitialConfiguration.properties, mInitialConfiguration.capabilities,
765                         mInitialConfiguration.score, mInitialConfiguration.config, providerId);
766             } else {
767                 mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
768                         new NetworkInfo(mInitialConfiguration.info),
769                         mInitialConfiguration.properties, mInitialConfiguration.capabilities,
770                         mInitialConfiguration.localNetworkConfig, mInitialConfiguration.score,
771                         mInitialConfiguration.config, providerId);
772             }
773             mInitialConfiguration = null; // All this memory can now be GC'd
774         }
775         return mNetwork;
776     }
777 
778     private static class NetworkAgentBinder extends INetworkAgent.Stub {
779         private static final String LOG_TAG = NetworkAgentBinder.class.getSimpleName();
780 
781         private final Handler mHandler;
782 
NetworkAgentBinder(Handler handler)783         private NetworkAgentBinder(Handler handler) {
784             mHandler = handler;
785         }
786 
787         @Override
onRegistered(@onNull INetworkAgentRegistry registry)788         public void onRegistered(@NonNull INetworkAgentRegistry registry) {
789             mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_CONNECTED, registry));
790         }
791 
792         @Override
onDisconnected()793         public void onDisconnected() {
794             mHandler.sendMessage(mHandler.obtainMessage(EVENT_AGENT_DISCONNECTED));
795         }
796 
797         @Override
onBandwidthUpdateRequested()798         public void onBandwidthUpdateRequested() {
799             mHandler.sendMessage(mHandler.obtainMessage(CMD_REQUEST_BANDWIDTH_UPDATE));
800         }
801 
802         @Override
onValidationStatusChanged( int validationStatus, @Nullable String captivePortalUrl)803         public void onValidationStatusChanged(
804                 int validationStatus, @Nullable String captivePortalUrl) {
805             // TODO: consider using a parcelable as argument when the interface is structured
806             Bundle redirectUrlBundle = new Bundle();
807             redirectUrlBundle.putString(NetworkAgent.REDIRECT_URL_KEY, captivePortalUrl);
808             mHandler.sendMessage(mHandler.obtainMessage(CMD_REPORT_NETWORK_STATUS,
809                     validationStatus, 0, redirectUrlBundle));
810         }
811 
812         @Override
onSaveAcceptUnvalidated(boolean acceptUnvalidated)813         public void onSaveAcceptUnvalidated(boolean acceptUnvalidated) {
814             mHandler.sendMessage(mHandler.obtainMessage(CMD_SAVE_ACCEPT_UNVALIDATED,
815                     acceptUnvalidated ? 1 : 0, 0));
816         }
817 
818         @Override
onStartNattSocketKeepalive(int slot, int intervalDurationMs, @NonNull NattKeepalivePacketData packetData)819         public void onStartNattSocketKeepalive(int slot, int intervalDurationMs,
820                 @NonNull NattKeepalivePacketData packetData) {
821             mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE,
822                     slot, intervalDurationMs, packetData));
823         }
824 
825         @Override
onStartTcpSocketKeepalive(int slot, int intervalDurationMs, @NonNull TcpKeepalivePacketData packetData)826         public void onStartTcpSocketKeepalive(int slot, int intervalDurationMs,
827                 @NonNull TcpKeepalivePacketData packetData) {
828             mHandler.sendMessage(mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE,
829                     slot, intervalDurationMs, packetData));
830         }
831 
832         @Override
onStopSocketKeepalive(int slot)833         public void onStopSocketKeepalive(int slot) {
834             mHandler.sendMessage(mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0));
835         }
836 
837         @Override
onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)838         public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
839             mHandler.sendMessage(mHandler.obtainMessage(
840                     CMD_SET_SIGNAL_STRENGTH_THRESHOLDS, thresholds));
841         }
842 
843         @Override
onPreventAutomaticReconnect()844         public void onPreventAutomaticReconnect() {
845             mHandler.sendMessage(mHandler.obtainMessage(CMD_PREVENT_AUTOMATIC_RECONNECT));
846         }
847 
848         @Override
onAddNattKeepalivePacketFilter(int slot, @NonNull NattKeepalivePacketData packetData)849         public void onAddNattKeepalivePacketFilter(int slot,
850                 @NonNull NattKeepalivePacketData packetData) {
851             mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER,
852                     slot, 0, packetData));
853         }
854 
855         @Override
onAddTcpKeepalivePacketFilter(int slot, @NonNull TcpKeepalivePacketData packetData)856         public void onAddTcpKeepalivePacketFilter(int slot,
857                 @NonNull TcpKeepalivePacketData packetData) {
858             mHandler.sendMessage(mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER,
859                     slot, 0, packetData));
860         }
861 
862         @Override
onRemoveKeepalivePacketFilter(int slot)863         public void onRemoveKeepalivePacketFilter(int slot) {
864             mHandler.sendMessage(mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER,
865                     slot, 0));
866         }
867 
868         @Override
onQosFilterCallbackRegistered(final int qosCallbackId, final QosFilterParcelable qosFilterParcelable)869         public void onQosFilterCallbackRegistered(final int qosCallbackId,
870                 final QosFilterParcelable qosFilterParcelable) {
871             if (qosFilterParcelable.getQosFilter() != null) {
872                 mHandler.sendMessage(
873                         mHandler.obtainMessage(CMD_REGISTER_QOS_CALLBACK, qosCallbackId, 0,
874                                 qosFilterParcelable.getQosFilter()));
875                 return;
876             }
877 
878             Log.wtf(LOG_TAG, "onQosFilterCallbackRegistered: qos filter is null.");
879         }
880 
881         @Override
onQosCallbackUnregistered(final int qosCallbackId)882         public void onQosCallbackUnregistered(final int qosCallbackId) {
883             mHandler.sendMessage(mHandler.obtainMessage(
884                     CMD_UNREGISTER_QOS_CALLBACK, qosCallbackId, 0, null));
885         }
886 
887         @Override
onNetworkCreated()888         public void onNetworkCreated() {
889             mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_CREATED));
890         }
891 
892         @Override
onNetworkDestroyed()893         public void onNetworkDestroyed() {
894             mHandler.sendMessage(mHandler.obtainMessage(CMD_NETWORK_DESTROYED));
895         }
896 
897         @Override
onDscpPolicyStatusUpdated(final int policyId, @DscpPolicyStatus final int status)898         public void onDscpPolicyStatusUpdated(final int policyId,
899                 @DscpPolicyStatus final int status) {
900             mHandler.sendMessage(mHandler.obtainMessage(
901                     CMD_DSCP_POLICY_STATUS, policyId, status));
902         }
903     }
904 
905     /**
906      * Register this network agent with a testing harness.
907      *
908      * The returned Messenger sends messages to the Handler. This allows a test to send
909      * this object {@code CMD_*} messages as if they came from ConnectivityService, which
910      * is useful for testing the behavior.
911      *
912      * @hide
913      */
registerForTest(final Network network)914     public INetworkAgent registerForTest(final Network network) {
915         log("Registering NetworkAgent for test");
916         synchronized (mRegisterLock) {
917             mNetwork = network;
918             mInitialConfiguration = null;
919         }
920         return new NetworkAgentBinder(mHandler);
921     }
922 
923     /**
924      * Waits for the handler to be idle.
925      * This is useful for testing, and has smaller scope than an accessor to mHandler.
926      * TODO : move the implementation in common library with the tests
927      * @hide
928      */
929     @VisibleForTesting
waitForIdle(final long timeoutMs)930     public boolean waitForIdle(final long timeoutMs) {
931         final ConditionVariable cv = new ConditionVariable(false);
932         mHandler.post(cv::open);
933         return cv.block(timeoutMs);
934     }
935 
936     /**
937      * @return The Network associated with this agent, or null if it's not registered yet.
938      */
939     @Nullable
getNetwork()940     public Network getNetwork() {
941         return mNetwork;
942     }
943 
queueOrSendMessage(@onNull RegistryAction action)944     private void queueOrSendMessage(@NonNull RegistryAction action) {
945         synchronized (mPreConnectedQueue) {
946             if (mRegistry != null) {
947                 try {
948                     action.execute(mRegistry);
949                 } catch (RemoteException e) {
950                     Log.wtf(LOG_TAG, "Error executing registry action", e);
951                     // Fall through: the channel is asynchronous and does not report errors back
952                 }
953             } else {
954                 mPreConnectedQueue.add(action);
955             }
956         }
957     }
958 
959     /**
960      * Must be called by the agent when the network's {@link LinkProperties} change.
961      * @param linkProperties the new LinkProperties.
962      */
sendLinkProperties(@onNull LinkProperties linkProperties)963     public void sendLinkProperties(@NonNull LinkProperties linkProperties) {
964         Objects.requireNonNull(linkProperties);
965         final LinkProperties lp = new LinkProperties(linkProperties);
966         queueOrSendMessage(reg -> reg.sendLinkProperties(lp));
967     }
968 
969     /**
970      * Must be called by the agent when the network's underlying networks change.
971      *
972      * <p>{@code networks} is one of the following:
973      * <ul>
974      * <li><strong>a non-empty array</strong>: an array of one or more {@link Network}s, in
975      * decreasing preference order. For example, if this VPN uses both wifi and mobile (cellular)
976      * networks to carry app traffic, but prefers or uses wifi more than mobile, wifi should appear
977      * first in the array.</li>
978      * <li><strong>an empty array</strong>: a zero-element array, meaning that the VPN has no
979      * underlying network connection, and thus, app traffic will not be sent or received.</li>
980      * <li><strong>null</strong>: (default) signifies that the VPN uses whatever is the system's
981      * default network. I.e., it doesn't use the {@code bindSocket} or {@code bindDatagramSocket}
982      * APIs mentioned above to send traffic over specific channels.</li>
983      * </ul>
984      *
985      * @param underlyingNetworks the new list of underlying networks.
986      * @see {@link VpnService.Builder#setUnderlyingNetworks(Network[])}
987      */
setUnderlyingNetworks( @uppressLint"NullableCollection") @ullable List<Network> underlyingNetworks)988     public void setUnderlyingNetworks(
989             @SuppressLint("NullableCollection") @Nullable List<Network> underlyingNetworks) {
990         final ArrayList<Network> underlyingArray = (underlyingNetworks != null)
991                 ? new ArrayList<>(underlyingNetworks) : null;
992         queueOrSendMessage(reg -> reg.sendUnderlyingNetworks(underlyingArray));
993     }
994 
995     /**
996      * Inform ConnectivityService that this agent has now connected.
997      * Call {@link #unregister} to disconnect.
998      */
markConnected()999     public void markConnected() {
1000         mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTED, null /* reason */,
1001                 mNetworkInfo.getExtraInfo());
1002         queueOrSendNetworkInfo(mNetworkInfo);
1003     }
1004 
1005     /**
1006      * Unregister this network agent.
1007      *
1008      * This signals the network has disconnected and ends its lifecycle. After this is called,
1009      * the network is torn down and this agent can no longer be used.
1010      */
unregister()1011     public void unregister() {
1012         // When unregistering an agent nobody should use the extrainfo (or reason) any more.
1013         mNetworkInfo.setDetailedState(NetworkInfo.DetailedState.DISCONNECTED, null /* reason */,
1014                 null /* extraInfo */);
1015         queueOrSendNetworkInfo(mNetworkInfo);
1016     }
1017 
1018     /**
1019      * Sets the value of the teardown delay.
1020      *
1021      * The teardown delay is the time between when the network disconnects and when the native
1022      * network corresponding to this {@code NetworkAgent} is destroyed. By default, the native
1023      * network is destroyed immediately. If {@code teardownDelayMs} is non-zero, then when this
1024      * network disconnects, the system will instead immediately mark the network as restricted
1025      * and unavailable to unprivileged apps, but will defer destroying the native network until the
1026      * teardown delay timer expires.
1027      *
1028      * The interfaces in use by this network will remain in use until the native network is
1029      * destroyed and cannot be reused until {@link #onNetworkDestroyed()} is called.
1030      *
1031      * This method may be called at any time while the network is connected. It has no effect if
1032      * the network is already disconnected and the teardown delay timer is running.
1033      *
1034      * @param teardownDelayMillis the teardown delay to set, or 0 to disable teardown delay.
1035      */
setTeardownDelayMillis( @ntRangefrom = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMillis)1036     public void setTeardownDelayMillis(
1037             @IntRange(from = 0, to = MAX_TEARDOWN_DELAY_MS) int teardownDelayMillis) {
1038         queueOrSendMessage(reg -> reg.sendTeardownDelayMs(teardownDelayMillis));
1039     }
1040 
1041     /**
1042      * Indicates that this agent will likely soon be replaced by another agent for a very similar
1043      * network (e.g., same Wi-Fi SSID).
1044      *
1045      * If the network is not currently satisfying any {@link NetworkRequest}s, it will be torn down.
1046      * If it is satisfying requests, then the native network corresponding to the agent will be
1047      * destroyed immediately, but the agent will remain registered and will continue to satisfy
1048      * requests until {@link #unregister} is called, the network is replaced by an equivalent or
1049      * better network, or the specified timeout expires. During this time:
1050      *
1051      * <ul>
1052      * <li>The agent may not send any further updates, for example by calling methods
1053      *    such as {@link #sendNetworkCapabilities}, {@link #sendLinkProperties},
1054      *    {@link #sendNetworkScore(NetworkScore)} and so on. Any such updates will be ignored.
1055      * <li>The network will remain connected and continue to satisfy any requests that it would
1056      *    otherwise satisfy (including, possibly, the default request).
1057      * <li>The validation state of the network will not change, and calls to
1058      *    {@link ConnectivityManager#reportNetworkConnectivity(Network, boolean)} will be ignored.
1059      * </ul>
1060      *
1061      * Once this method is called, it is not possible to restore the agent to a functioning state.
1062      * If a replacement network becomes available, then a new agent must be registered. When that
1063      * replacement network is fully capable of replacing this network (including, possibly, being
1064      * validated), this agent will no longer be needed and will be torn down. Otherwise, this agent
1065      * can be disconnected by calling {@link #unregister}. If {@link #unregister} is not called,
1066      * this agent will automatically be unregistered when the specified timeout expires. Any
1067      * teardown delay previously set using{@link #setTeardownDelayMillis} is ignored.
1068      *
1069      * <p>This method has no effect if {@link #markConnected} has not yet been called.
1070      * <p>This method may only be called once.
1071      *
1072      * @param timeoutMillis the timeout after which this network will be unregistered even if
1073      *                      {@link #unregister} was not called.
1074      */
unregisterAfterReplacement( @ntRangefrom = 0, to = MAX_TEARDOWN_DELAY_MS) int timeoutMillis)1075     public void unregisterAfterReplacement(
1076             @IntRange(from = 0, to = MAX_TEARDOWN_DELAY_MS) int timeoutMillis) {
1077         queueOrSendMessage(reg -> reg.sendUnregisterAfterReplacement(timeoutMillis));
1078     }
1079 
1080     /**
1081      * Change the legacy subtype of this network agent.
1082      *
1083      * This is only for backward compatibility and should not be used by non-legacy network agents,
1084      * or agents that did not use to set a subtype. As such, only TYPE_MOBILE type agents can use
1085      * this and others will be thrown an exception if they try.
1086      *
1087      * @deprecated this is for backward compatibility only.
1088      * @param legacySubtype the legacy subtype.
1089      * @hide
1090      */
1091     @Deprecated
1092     @SystemApi
setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName)1093     public void setLegacySubtype(final int legacySubtype, @NonNull final String legacySubtypeName) {
1094         mNetworkInfo.setSubtype(legacySubtype, legacySubtypeName);
1095         queueOrSendNetworkInfo(mNetworkInfo);
1096     }
1097 
1098     /**
1099      * Set the ExtraInfo of this network agent.
1100      *
1101      * This sets the ExtraInfo field inside the NetworkInfo returned by legacy public API and the
1102      * broadcasts about the corresponding Network.
1103      * This is only for backward compatibility and should not be used by non-legacy network agents,
1104      * who will be thrown an exception if they try. The extra info should only be :
1105      * <ul>
1106      *   <li>For cellular agents, the APN name.</li>
1107      *   <li>For ethernet agents, the interface name.</li>
1108      * </ul>
1109      *
1110      * @deprecated this is for backward compatibility only.
1111      * @param extraInfo the ExtraInfo.
1112      * @hide
1113      */
1114     @Deprecated
setLegacyExtraInfo(@ullable final String extraInfo)1115     public void setLegacyExtraInfo(@Nullable final String extraInfo) {
1116         mNetworkInfo.setExtraInfo(extraInfo);
1117         queueOrSendNetworkInfo(mNetworkInfo);
1118     }
1119 
1120     /**
1121      * Must be called by the agent when it has a new NetworkInfo object.
1122      * @hide TODO: expose something better.
1123      */
1124     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
sendNetworkInfo(NetworkInfo networkInfo)1125     public final void sendNetworkInfo(NetworkInfo networkInfo) {
1126         queueOrSendNetworkInfo(networkInfo);
1127     }
1128 
queueOrSendNetworkInfo(NetworkInfo networkInfo)1129     private void queueOrSendNetworkInfo(NetworkInfo networkInfo) {
1130         final NetworkInfo ni = new NetworkInfo(networkInfo);
1131         queueOrSendMessage(reg -> reg.sendNetworkInfo(ni));
1132     }
1133 
1134     /**
1135      * Must be called by the agent when the network's {@link NetworkCapabilities} change.
1136      * @param networkCapabilities the new NetworkCapabilities.
1137      */
sendNetworkCapabilities(@onNull NetworkCapabilities networkCapabilities)1138     public void sendNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
1139         Objects.requireNonNull(networkCapabilities);
1140         mBandwidthUpdatePending.set(false);
1141         mLastBwRefreshTime = System.currentTimeMillis();
1142         final NetworkCapabilities nc =
1143                 new NetworkCapabilities(networkCapabilities, NetworkCapabilities.REDACT_NONE);
1144         queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc));
1145     }
1146 
1147     /**
1148      * Must be called by the agent when the network's {@link LocalNetworkConfig} changes.
1149      * @param config the new LocalNetworkConfig
1150      * @hide
1151      */
sendLocalNetworkConfig(@onNull LocalNetworkConfig config)1152     public void sendLocalNetworkConfig(@NonNull LocalNetworkConfig config) {
1153         Objects.requireNonNull(config);
1154         // If the agent doesn't have NET_CAPABILITY_LOCAL_NETWORK, this will be ignored by
1155         // ConnectivityService with a Log.wtf.
1156         queueOrSendMessage(reg -> reg.sendLocalNetworkConfig(config));
1157     }
1158 
1159     /**
1160      * Must be called by the agent to update the score of this network.
1161      *
1162      * @param score the new score.
1163      */
sendNetworkScore(@onNull NetworkScore score)1164     public void sendNetworkScore(@NonNull NetworkScore score) {
1165         Objects.requireNonNull(score);
1166         queueOrSendMessage(reg -> reg.sendScore(score));
1167     }
1168 
1169     /**
1170      * Must be called by the agent to update the score of this network.
1171      *
1172      * @param score the new score, between 0 and 99.
1173      * deprecated use sendNetworkScore(NetworkScore) TODO : remove in S.
1174      */
sendNetworkScore(@ntRangefrom = 0, to = 99) int score)1175     public void sendNetworkScore(@IntRange(from = 0, to = 99) int score) {
1176         sendNetworkScore(new NetworkScore.Builder().setLegacyInt(score).build());
1177     }
1178 
1179     /**
1180      * Must be called by the agent to indicate this network was manually selected by the user.
1181      * This should be called before the NetworkInfo is marked CONNECTED so that this
1182      * Network can be given special treatment at that time. If {@code acceptUnvalidated} is
1183      * {@code true}, then the system will switch to this network. If it is {@code false} and the
1184      * network cannot be validated, the system will ask the user whether to switch to this network.
1185      * If the user confirms and selects "don't ask again", then the system will call
1186      * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever
1187      * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement
1188      * {@link #saveAcceptUnvalidated} to respect the user's choice.
1189      * @hide should move to NetworkAgentConfig.
1190      */
explicitlySelected(boolean acceptUnvalidated)1191     public void explicitlySelected(boolean acceptUnvalidated) {
1192         explicitlySelected(true /* explicitlySelected */, acceptUnvalidated);
1193     }
1194 
1195     /**
1196      * Must be called by the agent to indicate whether the network was manually selected by the
1197      * user. This should be called before the network becomes connected, so it can be given
1198      * special treatment when it does.
1199      *
1200      * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true},
1201      * then the system will switch to this network. If {@code explicitlySelected} is {@code true}
1202      * and {@code acceptUnvalidated} is {@code false}, and the  network cannot be validated, the
1203      * system will ask the user whether to switch to this network.  If the user confirms and selects
1204      * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the
1205      * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected}
1206      * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also
1207      * implement {@link #saveAcceptUnvalidated} to respect the user's choice.
1208      *
1209      * If  {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is
1210      * {@code true}, the system will interpret this as the user having accepted partial connectivity
1211      * on this network. Thus, the system will switch to the network and consider it validated even
1212      * if it only provides partial connectivity, but the network is not otherwise treated specially.
1213      * @hide should move to NetworkAgentConfig.
1214      */
explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated)1215     public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
1216         queueOrSendMessage(reg -> reg.sendExplicitlySelected(
1217                 explicitlySelected, acceptUnvalidated));
1218     }
1219 
1220     /**
1221      * Called when ConnectivityService has indicated they no longer want this network.
1222      * The parent factory should (previously) have received indication of the change
1223      * as well, either canceling NetworkRequests or altering their score such that this
1224      * network won't be immediately requested again.
1225      */
onNetworkUnwanted()1226     public void onNetworkUnwanted() {
1227         unwanted();
1228     }
1229     /** @hide TODO delete once subclasses have moved to onNetworkUnwanted. */
unwanted()1230     protected void unwanted() {
1231     }
1232 
1233     /**
1234      * Called when ConnectivityService request a bandwidth update. The parent factory
1235      * shall try to overwrite this method and produce a bandwidth update if capable.
1236      * @hide
1237      */
1238     @SystemApi
onBandwidthUpdateRequested()1239     public void onBandwidthUpdateRequested() {
1240         pollLceData();
1241     }
1242     /** @hide TODO delete once subclasses have moved to onBandwidthUpdateRequested. */
pollLceData()1243     protected void pollLceData() {
1244     }
1245 
1246     /**
1247      * Called when the system determines the usefulness of this network.
1248      *
1249      * The system attempts to validate Internet connectivity on networks that provide the
1250      * {@link NetworkCapabilities#NET_CAPABILITY_INTERNET} capability.
1251      *
1252      * Currently there are two possible values:
1253      * {@code VALIDATION_STATUS_VALID} if Internet connectivity was validated,
1254      * {@code VALIDATION_STATUS_NOT_VALID} if Internet connectivity was not validated.
1255      *
1256      * This is guaranteed to be called again when the network status changes, but the system
1257      * may also call this multiple times even if the status does not change.
1258      *
1259      * @param status one of {@code VALIDATION_STATUS_VALID} or {@code VALIDATION_STATUS_NOT_VALID}.
1260      * @param redirectUri If Internet connectivity is being redirected (e.g., on a captive portal),
1261      *        this is the destination the probes are being redirected to, otherwise {@code null}.
1262      */
onValidationStatus(@alidationStatus int status, @Nullable Uri redirectUri)1263     public void onValidationStatus(@ValidationStatus int status, @Nullable Uri redirectUri) {
1264         networkStatus(status, null == redirectUri ? "" : redirectUri.toString());
1265     }
1266     /** @hide TODO delete once subclasses have moved to onValidationStatus */
networkStatus(int status, String redirectUrl)1267     protected void networkStatus(int status, String redirectUrl) {
1268     }
1269 
1270 
1271     /**
1272      * Called when the user asks to remember the choice to use this network even if unvalidated.
1273      * The transport is responsible for remembering the choice, and the next time the user connects
1274      * to the network, should explicitlySelected with {@code acceptUnvalidated} set to {@code true}.
1275      * This method will only be called if {@link #explicitlySelected} was called with
1276      * {@code acceptUnvalidated} set to {@code false}.
1277      * @param accept whether the user wants to use the network even if unvalidated.
1278      */
onSaveAcceptUnvalidated(boolean accept)1279     public void onSaveAcceptUnvalidated(boolean accept) {
1280         saveAcceptUnvalidated(accept);
1281     }
1282     /** @hide TODO delete once subclasses have moved to onSaveAcceptUnvalidated */
saveAcceptUnvalidated(boolean accept)1283     protected void saveAcceptUnvalidated(boolean accept) {
1284     }
1285 
1286     /**
1287      * Called when ConnectivityService has successfully created this NetworkAgent's native network.
1288      */
onNetworkCreated()1289     public void onNetworkCreated() {}
1290 
1291 
1292     /**
1293      * Called when ConnectivityService has successfully destroy this NetworkAgent's native network.
1294      */
onNetworkDestroyed()1295     public void onNetworkDestroyed() {}
1296 
1297     /**
1298      * Called when when the DSCP Policy status has changed.
1299      */
onDscpPolicyStatusUpdated(int policyId, @DscpPolicyStatus int status)1300     public void onDscpPolicyStatusUpdated(int policyId, @DscpPolicyStatus int status) {}
1301 
1302     /**
1303      * Requests that the network hardware send the specified packet at the specified interval.
1304      *
1305      * @param slot the hardware slot on which to start the keepalive.
1306      * @param interval the interval between packets, between 10 and 3600. Note that this API
1307      *                 does not support sub-second precision and will round off the request.
1308      * @param packet the packet to send.
1309      */
1310     // seconds is from SocketKeepalive.MIN_INTERVAL_SEC to MAX_INTERVAL_SEC, but these should
1311     // not be exposed as constants because they may change in the future (API guideline 4.8)
1312     // and should have getters if exposed at all. Getters can't be used in the annotation,
1313     // so the values unfortunately need to be copied.
onStartSocketKeepalive(int slot, @NonNull Duration interval, @NonNull KeepalivePacketData packet)1314     public void onStartSocketKeepalive(int slot, @NonNull Duration interval,
1315             @NonNull KeepalivePacketData packet) {
1316         final long intervalSeconds = interval.getSeconds();
1317         if (intervalSeconds < SocketKeepalive.MIN_INTERVAL_SEC
1318                 || intervalSeconds > SocketKeepalive.MAX_INTERVAL_SEC) {
1319             throw new IllegalArgumentException("Interval needs to be comprised between "
1320                     + SocketKeepalive.MIN_INTERVAL_SEC + " and " + SocketKeepalive.MAX_INTERVAL_SEC
1321                     + " but was " + intervalSeconds);
1322         }
1323         final Message msg = mHandler.obtainMessage(CMD_START_SOCKET_KEEPALIVE, slot,
1324                 (int) intervalSeconds, packet);
1325         startSocketKeepalive(msg);
1326         msg.recycle();
1327     }
1328     /** @hide TODO delete once subclasses have moved to onStartSocketKeepalive */
startSocketKeepalive(Message msg)1329     protected void startSocketKeepalive(Message msg) {
1330         onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED);
1331     }
1332 
1333     /**
1334      * Requests that the network hardware stop a previously-started keepalive.
1335      *
1336      * @param slot the hardware slot on which to stop the keepalive.
1337      */
onStopSocketKeepalive(int slot)1338     public void onStopSocketKeepalive(int slot) {
1339         Message msg = mHandler.obtainMessage(CMD_STOP_SOCKET_KEEPALIVE, slot, 0, null);
1340         stopSocketKeepalive(msg);
1341         msg.recycle();
1342     }
1343     /** @hide TODO delete once subclasses have moved to onStopSocketKeepalive */
stopSocketKeepalive(Message msg)1344     protected void stopSocketKeepalive(Message msg) {
1345         onSocketKeepaliveEvent(msg.arg1, SocketKeepalive.ERROR_UNSUPPORTED);
1346     }
1347 
1348     /**
1349      * Must be called by the agent when a socket keepalive event occurs.
1350      *
1351      * @param slot the hardware slot on which the event occurred.
1352      * @param event the event that occurred, as one of the SocketKeepalive.ERROR_*
1353      *              or SocketKeepalive.SUCCESS constants.
1354      */
sendSocketKeepaliveEvent(int slot, @SocketKeepalive.KeepaliveEvent int event)1355     public final void sendSocketKeepaliveEvent(int slot,
1356             @SocketKeepalive.KeepaliveEvent int event) {
1357         queueOrSendMessage(reg -> reg.sendSocketKeepaliveEvent(slot, event));
1358     }
1359     /** @hide TODO delete once callers have moved to sendSocketKeepaliveEvent */
onSocketKeepaliveEvent(int slot, int reason)1360     public void onSocketKeepaliveEvent(int slot, int reason) {
1361         sendSocketKeepaliveEvent(slot, reason);
1362     }
1363 
1364     /**
1365      * Called by ConnectivityService to add specific packet filter to network hardware to block
1366      * replies (e.g., TCP ACKs) matching the sent keepalive packets. Implementations that support
1367      * this feature must override this method.
1368      *
1369      * @param slot the hardware slot on which the keepalive should be sent.
1370      * @param packet the packet that is being sent.
1371      */
onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet)1372     public void onAddKeepalivePacketFilter(int slot, @NonNull KeepalivePacketData packet) {
1373         Message msg = mHandler.obtainMessage(CMD_ADD_KEEPALIVE_PACKET_FILTER, slot, 0, packet);
1374         addKeepalivePacketFilter(msg);
1375         msg.recycle();
1376     }
1377     /** @hide TODO delete once subclasses have moved to onAddKeepalivePacketFilter */
addKeepalivePacketFilter(Message msg)1378     protected void addKeepalivePacketFilter(Message msg) {
1379     }
1380 
1381     /**
1382      * Called by ConnectivityService to remove a packet filter installed with
1383      * {@link #addKeepalivePacketFilter(Message)}. Implementations that support this feature
1384      * must override this method.
1385      *
1386      * @param slot the hardware slot on which the keepalive is being sent.
1387      */
onRemoveKeepalivePacketFilter(int slot)1388     public void onRemoveKeepalivePacketFilter(int slot) {
1389         Message msg = mHandler.obtainMessage(CMD_REMOVE_KEEPALIVE_PACKET_FILTER, slot, 0, null);
1390         removeKeepalivePacketFilter(msg);
1391         msg.recycle();
1392     }
1393     /** @hide TODO delete once subclasses have moved to onRemoveKeepalivePacketFilter */
removeKeepalivePacketFilter(Message msg)1394     protected void removeKeepalivePacketFilter(Message msg) {
1395     }
1396 
1397     /**
1398      * Called by ConnectivityService to inform this network agent of signal strength thresholds
1399      * that when crossed should trigger a system wakeup and a NetworkCapabilities update.
1400      *
1401      * When the system updates the list of thresholds that should wake up the CPU for a
1402      * given agent it will call this method on the agent. The agent that implement this
1403      * should implement it in hardware so as to ensure the CPU will be woken up on breach.
1404      * Agents are expected to react to a breach by sending an updated NetworkCapabilities
1405      * object with the appropriate signal strength to sendNetworkCapabilities.
1406      *
1407      * The specific units are bearer-dependent. See details on the units and requests in
1408      * {@link NetworkCapabilities.Builder#setSignalStrength}.
1409      *
1410      * @param thresholds the array of thresholds that should trigger wakeups.
1411      */
onSignalStrengthThresholdsUpdated(@onNull int[] thresholds)1412     public void onSignalStrengthThresholdsUpdated(@NonNull int[] thresholds) {
1413         setSignalStrengthThresholds(thresholds);
1414     }
1415     /** @hide TODO delete once subclasses have moved to onSetSignalStrengthThresholds */
setSignalStrengthThresholds(int[] thresholds)1416     protected void setSignalStrengthThresholds(int[] thresholds) {
1417     }
1418 
1419     /**
1420      * Called when the user asks to not stay connected to this network because it was found to not
1421      * provide Internet access.  Usually followed by call to {@code unwanted}.  The transport is
1422      * responsible for making sure the device does not automatically reconnect to the same network
1423      * after the {@code unwanted} call.
1424      */
onAutomaticReconnectDisabled()1425     public void onAutomaticReconnectDisabled() {
1426         preventAutomaticReconnect();
1427     }
1428     /** @hide TODO delete once subclasses have moved to onAutomaticReconnectDisabled */
preventAutomaticReconnect()1429     protected void preventAutomaticReconnect() {
1430     }
1431 
1432     /**
1433      * Called when a qos callback is registered with a filter.
1434      * @param qosCallbackId the id for the callback registered
1435      * @param filter the filter being registered
1436      */
onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter)1437     public void onQosCallbackRegistered(final int qosCallbackId, final @NonNull QosFilter filter) {
1438     }
1439 
1440     /**
1441      * Called when a qos callback is registered with a filter.
1442      * <p/>
1443      * Any QoS events that are sent with the same callback id after this method is called
1444      * are a no-op.
1445      *
1446      * @param qosCallbackId the id for the callback being unregistered
1447      */
onQosCallbackUnregistered(final int qosCallbackId)1448     public void onQosCallbackUnregistered(final int qosCallbackId) {
1449     }
1450 
1451 
1452     /**
1453      * Sends the attributes of Qos Session back to the Application
1454      *
1455      * @param qosCallbackId the callback id that the session belongs to
1456      * @param sessionId the unique session id across all Qos Sessions
1457      * @param attributes the attributes of the Qos Session
1458      */
sendQosSessionAvailable(final int qosCallbackId, final int sessionId, @NonNull final QosSessionAttributes attributes)1459     public final void sendQosSessionAvailable(final int qosCallbackId, final int sessionId,
1460             @NonNull final QosSessionAttributes attributes) {
1461         Objects.requireNonNull(attributes, "The attributes must be non-null");
1462         if (attributes instanceof EpsBearerQosSessionAttributes) {
1463             queueOrSendMessage(ra -> ra.sendEpsQosSessionAvailable(qosCallbackId,
1464                     new QosSession(sessionId, QosSession.TYPE_EPS_BEARER),
1465                     (EpsBearerQosSessionAttributes)attributes));
1466         } else if (attributes instanceof NrQosSessionAttributes) {
1467             queueOrSendMessage(ra -> ra.sendNrQosSessionAvailable(qosCallbackId,
1468                     new QosSession(sessionId, QosSession.TYPE_NR_BEARER),
1469                     (NrQosSessionAttributes)attributes));
1470         }
1471     }
1472 
1473     /**
1474      * Sends event that the Qos Session was lost.
1475      *
1476      * @param qosCallbackId the callback id that the session belongs to
1477      * @param sessionId the unique session id across all Qos Sessions
1478      * @param qosSessionType the session type {@code QosSesson#QosSessionType}
1479      */
sendQosSessionLost(final int qosCallbackId, final int sessionId, final int qosSessionType)1480     public final void sendQosSessionLost(final int qosCallbackId,
1481             final int sessionId, final int qosSessionType) {
1482         queueOrSendMessage(ra -> ra.sendQosSessionLost(qosCallbackId,
1483                 new QosSession(sessionId, qosSessionType)));
1484     }
1485 
1486     /**
1487      * Sends the exception type back to the application.
1488      *
1489      * The NetworkAgent should not send anymore messages with this id.
1490      *
1491      * @param qosCallbackId the callback id this exception belongs to
1492      * @param exceptionType the type of exception
1493      */
sendQosCallbackError(final int qosCallbackId, @QosCallbackException.ExceptionType final int exceptionType)1494     public final void sendQosCallbackError(final int qosCallbackId,
1495             @QosCallbackException.ExceptionType final int exceptionType) {
1496         queueOrSendMessage(ra -> ra.sendQosCallbackError(qosCallbackId, exceptionType));
1497     }
1498 
1499     /**
1500      * Set the linger duration for this network agent.
1501      * @param duration the delay between the moment the network becomes unneeded and the
1502      *                 moment the network is disconnected or moved into the background.
1503      *                 Note that If this duration has greater than millisecond precision, then
1504      *                 the internal implementation will drop any excess precision.
1505      */
setLingerDuration(@onNull final Duration duration)1506     public void setLingerDuration(@NonNull final Duration duration) {
1507         Objects.requireNonNull(duration);
1508         final long durationMs = duration.toMillis();
1509         if (durationMs < MIN_LINGER_TIMER_MS || durationMs > Integer.MAX_VALUE) {
1510             throw new IllegalArgumentException("Duration must be within ["
1511                     + MIN_LINGER_TIMER_MS + "," + Integer.MAX_VALUE + "]ms");
1512         }
1513         queueOrSendMessage(ra -> ra.sendLingerDuration((int) durationMs));
1514     }
1515 
1516     /**
1517      * Add a DSCP Policy.
1518      * @param policy the DSCP policy to be added.
1519      */
sendAddDscpPolicy(@onNull final DscpPolicy policy)1520     public void sendAddDscpPolicy(@NonNull final DscpPolicy policy) {
1521         Objects.requireNonNull(policy);
1522         queueOrSendMessage(ra -> ra.sendAddDscpPolicy(policy));
1523     }
1524 
1525     /**
1526      * Remove the specified DSCP policy.
1527      * @param policyId the ID corresponding to a specific DSCP Policy.
1528      */
sendRemoveDscpPolicy(final int policyId)1529     public void sendRemoveDscpPolicy(final int policyId) {
1530         queueOrSendMessage(ra -> ra.sendRemoveDscpPolicy(policyId));
1531     }
1532 
1533     /**
1534      * Remove all the DSCP policies on this network.
1535      */
sendRemoveAllDscpPolicies()1536     public void sendRemoveAllDscpPolicies() {
1537         queueOrSendMessage(ra -> ra.sendRemoveAllDscpPolicies());
1538     }
1539 
1540     /** @hide */
log(final String s)1541     protected void log(final String s) {
1542         Log.d(LOG_TAG, "NetworkAgent: " + s);
1543     }
1544 }
1545