blob: 0706e755d133385cb3357a1d5cf97129d568bfa1 [file] [log] [blame]
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001/*
Wink Saville6e809972010-09-21 09:15:35 -07002 * Copyright (C) 2010 The Android Open Source Project
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07003 *
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
17package android.net;
18
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -070019import android.annotation.NonNull;
Jeff Sharkey9da2f1e2014-08-14 12:55:00 -070020import android.annotation.Nullable;
paulhu7610bc72018-12-12 17:52:57 +080021import android.annotation.SystemApi;
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +090022import android.annotation.TestApi;
Mathew Inwoodfa3a7462018-08-08 14:52:47 +010023import android.annotation.UnsupportedAppUsage;
Mathew Inwood55418ea2018-12-20 15:30:45 +000024import android.os.Build;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070025import android.os.Parcel;
Rubin Xu1bb5c082017-09-05 18:40:49 +010026import android.os.Parcelable;
John Wang4e900092011-04-04 12:35:42 -070027import android.text.TextUtils;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070028
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080029import java.net.Inet4Address;
Lorenzo Colitti4faa0272013-08-08 11:00:12 +090030import java.net.Inet6Address;
Rubin Xu1bb5c082017-09-05 18:40:49 +010031import java.net.InetAddress;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070032import java.net.UnknownHostException;
33import java.util.ArrayList;
34import java.util.Collection;
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070035import java.util.Collections;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080036import java.util.Hashtable;
Robert Greenwaltdf2b8782014-06-06 10:30:11 -070037import java.util.List;
Lorenzo Colittic17a1b92014-06-12 23:10:17 +090038import java.util.Objects;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090039import java.util.StringJoiner;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070040
41/**
Robert Greenwalt37e65eb2010-08-30 10:56:47 -070042 * Describes the properties of a network link.
Robert Greenwalt992564e2011-02-09 13:56:06 -080043 *
44 * A link represents a connection to a network.
45 * It may have multiple addresses and multiple gateways,
Robert Greenwalt4f05d552014-05-18 22:01:38 -070046 * multiple dns servers but only one http proxy and one
47 * network interface.
Robert Greenwalt992564e2011-02-09 13:56:06 -080048 *
Robert Greenwalt4f05d552014-05-18 22:01:38 -070049 * Note that this is just a holder of data. Modifying it
50 * does not affect live networks.
Robert Greenwalt992564e2011-02-09 13:56:06 -080051 *
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070052 */
Robert Greenwalte595b972014-06-12 16:24:38 -070053public final class LinkProperties implements Parcelable {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080054 // The interface described by the network link.
Mathew Inwood55418ea2018-12-20 15:30:45 +000055 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt4717c262012-10-31 14:32:53 -070056 private String mIfaceName;
paulhud9736de2019-03-08 16:35:20 +080057 private final ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
58 private final ArrayList<InetAddress> mDnses = new ArrayList<>();
Hongshikfa425012018-06-28 20:42:19 +090059 // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service.
paulhud9736de2019-03-08 16:35:20 +080060 private final ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>();
61 private final ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
dalykd9201342018-01-17 14:20:55 -050062 private boolean mUsePrivateDns;
63 private String mPrivateDnsServerName;
Robert Greenwalt8058f622012-11-09 10:52:27 -080064 private String mDomains;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090065 private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
Jason Monk207900c2014-04-25 15:00:09 -040066 private ProxyInfo mHttpProxy;
sy.yun9d9b74a2013-09-02 05:24:09 +090067 private int mMtu;
Robert Greenwalt3f05bf42014-08-06 12:00:25 -070068 // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
69 private String mTcpBufferSizes;
Lorenzo Colitti59b34472019-01-08 09:58:59 +090070 private IpPrefix mNat64Prefix;
Valentin Iftimec86ebba2019-09-24 13:32:13 +020071 private boolean mWakeOnLanSupported;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -070072
w1997615afd812014-08-05 15:18:11 -070073 private static final int MIN_MTU = 68;
74 private static final int MIN_MTU_V6 = 1280;
75 private static final int MAX_MTU = 10000;
76
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080077 // Stores the properties of links that are "stacked" above this link.
78 // Indexed by interface name to allow modification and to prevent duplicates being added.
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090079 private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -080080
Robert Greenwaltdf2b8782014-06-06 10:30:11 -070081 /**
82 * @hide
83 */
Robert Greenwalt0a46db52011-07-14 14:28:05 -070084 public static class CompareResult<T> {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +090085 public final List<T> removed = new ArrayList<>();
86 public final List<T> added = new ArrayList<>();
Rubin Xu2fc72f72017-08-22 16:35:52 +010087
88 public CompareResult() {}
89
90 public CompareResult(Collection<T> oldItems, Collection<T> newItems) {
91 if (oldItems != null) {
92 removed.addAll(oldItems);
93 }
94 if (newItems != null) {
95 for (T newItem : newItems) {
96 if (!removed.remove(newItem)) {
97 added.add(newItem);
98 }
99 }
100 }
101 }
Wink Savillee8222252011-07-13 13:44:13 -0700102
103 @Override
104 public String toString() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900105 return "removed=[" + TextUtils.join(",", removed)
106 + "] added=[" + TextUtils.join(",", added)
107 + "]";
Wink Savillee8222252011-07-13 13:44:13 -0700108 }
109 }
110
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700111 /**
112 * @hide
113 */
Artur Satayevfc46be72019-11-04 17:50:59 +0000114 @UnsupportedAppUsage(implicitMember =
115 "values()[Landroid/net/LinkProperties$ProvisioningChange;")
Erik Klinecd7ed162015-05-21 16:15:02 +0900116 public enum ProvisioningChange {
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100117 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900118 STILL_NOT_PROVISIONED,
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100119 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900120 LOST_PROVISIONING,
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100121 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900122 GAINED_PROVISIONING,
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100123 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900124 STILL_PROVISIONED,
125 }
126
127 /**
128 * Compare the provisioning states of two LinkProperties instances.
129 *
130 * @hide
131 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100132 @UnsupportedAppUsage
Erik Klinecd7ed162015-05-21 16:15:02 +0900133 public static ProvisioningChange compareProvisioning(
134 LinkProperties before, LinkProperties after) {
135 if (before.isProvisioned() && after.isProvisioned()) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900136 // On dual-stack networks, DHCPv4 renewals can occasionally fail.
Erik Klinecd7ed162015-05-21 16:15:02 +0900137 // When this happens, IPv6-reachable services continue to function
138 // normally but IPv4-only services (naturally) fail.
139 //
140 // When an application using an IPv4-only service reports a bad
141 // network condition to the framework, attempts to re-validate
142 // the network succeed (since we support IPv6-only networks) and
143 // nothing is changed.
144 //
145 // For users, this is confusing and unexpected behaviour, and is
146 // not necessarily easy to diagnose. Therefore, we treat changing
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900147 // from a dual-stack network to an IPv6-only network equivalent to
Erik Klinecd7ed162015-05-21 16:15:02 +0900148 // a total loss of provisioning.
149 //
150 // For one such example of this, see b/18867306.
151 //
Erik Kline1ad4e222015-08-14 12:16:55 +0900152 // Additionally, losing IPv6 provisioning can result in TCP
153 // connections getting stuck until timeouts fire and other
154 // baffling failures. Therefore, loss of either IPv4 or IPv6 on a
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900155 // previously dual-stack network is deemed a lost of provisioning.
paulhud9736de2019-03-08 16:35:20 +0800156 if ((before.isIpv4Provisioned() && !after.isIpv4Provisioned())
157 || (before.isIpv6Provisioned() && !after.isIpv6Provisioned())) {
Erik Klinecd7ed162015-05-21 16:15:02 +0900158 return ProvisioningChange.LOST_PROVISIONING;
159 }
160 return ProvisioningChange.STILL_PROVISIONED;
161 } else if (before.isProvisioned() && !after.isProvisioned()) {
162 return ProvisioningChange.LOST_PROVISIONING;
163 } else if (!before.isProvisioned() && after.isProvisioned()) {
164 return ProvisioningChange.GAINED_PROVISIONING;
165 } else { // !before.isProvisioned() && !after.isProvisioned()
166 return ProvisioningChange.STILL_NOT_PROVISIONED;
167 }
168 }
169
170 /**
paulhud9736de2019-03-08 16:35:20 +0800171 * Constructs a new {@code LinkProperties} with default values.
Erik Klinecd7ed162015-05-21 16:15:02 +0900172 */
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700173 public LinkProperties() {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700174 }
175
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700176 /**
177 * @hide
178 */
Remi NGUYEN VAN299a7cc2019-01-23 21:35:52 +0900179 @SystemApi
180 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800181 public LinkProperties(@Nullable LinkProperties source) {
Irfan Sheriffef6c1432010-08-30 20:37:17 -0700182 if (source != null) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900183 mIfaceName = source.mIfaceName;
184 mLinkAddresses.addAll(source.mLinkAddresses);
185 mDnses.addAll(source.mDnses);
186 mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
dalykd9201342018-01-17 14:20:55 -0500187 mUsePrivateDns = source.mUsePrivateDns;
188 mPrivateDnsServerName = source.mPrivateDnsServerName;
Hongshikfa425012018-06-28 20:42:19 +0900189 mPcscfs.addAll(source.mPcscfs);
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900190 mDomains = source.mDomains;
191 mRoutes.addAll(source.mRoutes);
192 mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800193 for (LinkProperties l: source.mStackedLinks.values()) {
194 addStackedLink(l);
195 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900196 setMtu(source.mMtu);
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700197 mTcpBufferSizes = source.mTcpBufferSizes;
Remi NGUYEN VANb68c3492019-01-16 15:27:27 +0900198 mNat64Prefix = source.mNat64Prefix;
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200199 mWakeOnLanSupported = source.mWakeOnLanSupported;
Irfan Sheriffef6c1432010-08-30 20:37:17 -0700200 }
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700201 }
202
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700203 /**
204 * Sets the interface name for this link. All {@link RouteInfo} already set for this
205 * will have their interface changed to match this new value.
206 *
207 * @param iface The name of the network interface used for this link.
208 */
paulhud9736de2019-03-08 16:35:20 +0800209 public void setInterfaceName(@Nullable String iface) {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700210 mIfaceName = iface;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900211 ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800212 for (RouteInfo route : mRoutes) {
213 newRoutes.add(routeWithInterface(route));
214 }
215 mRoutes = newRoutes;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700216 }
217
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700218 /**
219 * Gets the interface name for this link. May be {@code null} if not set.
220 *
221 * @return The interface name set for this link or {@code null}.
222 */
Jeff Sharkey9da2f1e2014-08-14 12:55:00 -0700223 public @Nullable String getInterfaceName() {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700224 return mIfaceName;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700225 }
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700226
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700227 /**
228 * @hide
229 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100230 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +0800231 public @NonNull List<String> getAllInterfaceNames() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900232 List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
233 if (mIfaceName != null) interfaceNames.add(mIfaceName);
Lorenzo Colitti4aa9bcf2013-03-20 19:22:58 +0900234 for (LinkProperties stacked: mStackedLinks.values()) {
235 interfaceNames.addAll(stacked.getAllInterfaceNames());
236 }
237 return interfaceNames;
238 }
239
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900240 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700241 * Returns all the addresses on this link. We often think of a link having a single address,
242 * however, particularly with Ipv6 several addresses are typical. Note that the
243 * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include
244 * prefix lengths for each address. This is a simplified utility alternative to
245 * {@link LinkProperties#getLinkAddresses}.
246 *
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900247 * @return An unmodifiable {@link List} of {@link InetAddress} for this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700248 * @hide
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900249 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100250 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +0800251 public @NonNull List<InetAddress> getAddresses() {
252 final List<InetAddress> addresses = new ArrayList<>();
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700253 for (LinkAddress linkAddress : mLinkAddresses) {
254 addresses.add(linkAddress.getAddress());
255 }
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700256 return Collections.unmodifiableList(addresses);
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700257 }
258
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900259 /**
260 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700261 * @hide
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900262 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100263 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +0800264 public @NonNull List<InetAddress> getAllAddresses() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900265 List<InetAddress> addresses = new ArrayList<>();
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900266 for (LinkAddress linkAddress : mLinkAddresses) {
267 addresses.add(linkAddress.getAddress());
268 }
269 for (LinkProperties stacked: mStackedLinks.values()) {
270 addresses.addAll(stacked.getAllAddresses());
271 }
272 return addresses;
273 }
274
Lorenzo Colitti64483942013-11-15 18:43:52 +0900275 private int findLinkAddressIndex(LinkAddress address) {
276 for (int i = 0; i < mLinkAddresses.size(); i++) {
277 if (mLinkAddresses.get(i).isSameAddressAs(address)) {
278 return i;
279 }
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900280 }
Lorenzo Colitti64483942013-11-15 18:43:52 +0900281 return -1;
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900282 }
283
284 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700285 * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the
286 * same address/prefix does not already exist. If it does exist it is replaced.
Lorenzo Colitti64483942013-11-15 18:43:52 +0900287 * @param address The {@code LinkAddress} to add.
288 * @return true if {@code address} was added or updated, false otherwise.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700289 * @hide
Lorenzo Colitti64483942013-11-15 18:43:52 +0900290 */
Remi NGUYEN VAN5c5f1ba2019-01-29 12:08:43 +0900291 @SystemApi
292 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800293 public boolean addLinkAddress(@NonNull LinkAddress address) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900294 if (address == null) {
295 return false;
296 }
297 int i = findLinkAddressIndex(address);
298 if (i < 0) {
299 // Address was not present. Add it.
300 mLinkAddresses.add(address);
301 return true;
302 } else if (mLinkAddresses.get(i).equals(address)) {
303 // Address was present and has same properties. Do nothing.
304 return false;
305 } else {
306 // Address was present and has different properties. Update it.
307 mLinkAddresses.set(i, address);
308 return true;
309 }
310 }
311
312 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700313 * Removes a {@link LinkAddress} from this {@code LinkProperties}. Specifically, matches
314 * and {@link LinkAddress} with the same address and prefix.
315 *
316 * @param toRemove A {@link LinkAddress} specifying the address to remove.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900317 * @return true if the address was removed, false if it did not exist.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700318 * @hide
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900319 */
Remi NGUYEN VAN5c5f1ba2019-01-29 12:08:43 +0900320 @SystemApi
321 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800322 public boolean removeLinkAddress(@NonNull LinkAddress toRemove) {
Lorenzo Colitti64483942013-11-15 18:43:52 +0900323 int i = findLinkAddressIndex(toRemove);
324 if (i >= 0) {
325 mLinkAddresses.remove(i);
326 return true;
327 }
328 return false;
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700329 }
330
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900331 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700332 * Returns all the {@link LinkAddress} on this link. Typically a link will have
333 * one IPv4 address and one or more IPv6 addresses.
334 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700335 * @return An unmodifiable {@link List} of {@link LinkAddress} for this link.
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900336 */
paulhud9736de2019-03-08 16:35:20 +0800337 public @NonNull List<LinkAddress> getLinkAddresses() {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700338 return Collections.unmodifiableList(mLinkAddresses);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700339 }
340
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900341 /**
342 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700343 * @hide
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900344 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100345 @UnsupportedAppUsage
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700346 public List<LinkAddress> getAllLinkAddresses() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900347 List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +0900348 for (LinkProperties stacked: mStackedLinks.values()) {
349 addresses.addAll(stacked.getAllLinkAddresses());
350 }
351 return addresses;
352 }
353
Lorenzo Colitti22f407b2013-08-23 20:54:49 +0900354 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700355 * Replaces the {@link LinkAddress} in this {@code LinkProperties} with
356 * the given {@link Collection} of {@link LinkAddress}.
357 *
358 * @param addresses The {@link Collection} of {@link LinkAddress} to set in this
359 * object.
Lorenzo Colitti22f407b2013-08-23 20:54:49 +0900360 */
paulhud9736de2019-03-08 16:35:20 +0800361 public void setLinkAddresses(@NonNull Collection<LinkAddress> addresses) {
Lorenzo Colitti22f407b2013-08-23 20:54:49 +0900362 mLinkAddresses.clear();
363 for (LinkAddress address: addresses) {
364 addLinkAddress(address);
365 }
366 }
367
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700368 /**
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900369 * Adds the given {@link InetAddress} to the list of DNS servers, if not present.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700370 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700371 * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900372 * @return true if the DNS server was added, false if it was already present.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700373 * @hide
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700374 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900375 @TestApi
376 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800377 public boolean addDnsServer(@NonNull InetAddress dnsServer) {
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900378 if (dnsServer != null && !mDnses.contains(dnsServer)) {
379 mDnses.add(dnsServer);
380 return true;
381 }
382 return false;
383 }
384
385 /**
Erik Klinecd7ed162015-05-21 16:15:02 +0900386 * Removes the given {@link InetAddress} from the list of DNS servers.
387 *
388 * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers.
389 * @return true if the DNS server was removed, false if it did not exist.
390 * @hide
391 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900392 @TestApi
393 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800394 public boolean removeDnsServer(@NonNull InetAddress dnsServer) {
paulhu3d67f532019-03-22 16:35:06 +0800395 return mDnses.remove(dnsServer);
Erik Klinecd7ed162015-05-21 16:15:02 +0900396 }
397
398 /**
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900399 * Replaces the DNS servers in this {@code LinkProperties} with
400 * the given {@link Collection} of {@link InetAddress} objects.
401 *
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900402 * @param dnsServers The {@link Collection} of DNS servers to set in this object.
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900403 */
paulhud9736de2019-03-08 16:35:20 +0800404 public void setDnsServers(@NonNull Collection<InetAddress> dnsServers) {
Lorenzo Colitti309a75d2014-06-24 00:34:39 +0900405 mDnses.clear();
406 for (InetAddress dnsServer: dnsServers) {
407 addDnsServer(dnsServer);
408 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700409 }
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700410
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700411 /**
Sreeram Ramachandrancc91c7b2014-06-03 18:41:43 -0700412 * Returns all the {@link InetAddress} for DNS servers on this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700413 *
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900414 * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700415 * this link.
416 */
paulhud9736de2019-03-08 16:35:20 +0800417 public @NonNull List<InetAddress> getDnsServers() {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700418 return Collections.unmodifiableList(mDnses);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700419 }
420
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700421 /**
dalykd9201342018-01-17 14:20:55 -0500422 * Set whether private DNS is currently in use on this network.
423 *
424 * @param usePrivateDns The private DNS state.
425 * @hide
426 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900427 @TestApi
428 @SystemApi
dalykd9201342018-01-17 14:20:55 -0500429 public void setUsePrivateDns(boolean usePrivateDns) {
430 mUsePrivateDns = usePrivateDns;
431 }
432
433 /**
434 * Returns whether private DNS is currently in use on this network. When
435 * private DNS is in use, applications must not send unencrypted DNS
436 * queries as doing so could reveal private user information. Furthermore,
437 * if private DNS is in use and {@link #getPrivateDnsServerName} is not
438 * {@code null}, DNS queries must be sent to the specified DNS server.
439 *
440 * @return {@code true} if private DNS is in use, {@code false} otherwise.
441 */
442 public boolean isPrivateDnsActive() {
443 return mUsePrivateDns;
444 }
445
446 /**
447 * Set the name of the private DNS server to which private DNS queries
448 * should be sent when in strict mode. This value should be {@code null}
449 * when private DNS is off or in opportunistic mode.
450 *
451 * @param privateDnsServerName The private DNS server name.
452 * @hide
453 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900454 @TestApi
455 @SystemApi
dalykd9201342018-01-17 14:20:55 -0500456 public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
457 mPrivateDnsServerName = privateDnsServerName;
458 }
459
460 /**
461 * Returns the private DNS server name that is in use. If not {@code null},
462 * private DNS is in strict mode. In this mode, applications should ensure
463 * that all DNS queries are encrypted and sent to this hostname and that
464 * queries are only sent if the hostname's certificate is valid. If
465 * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private
466 * DNS is in opportunistic mode, and applications should ensure that DNS
467 * queries are encrypted and sent to a DNS server returned by
468 * {@link #getDnsServers}. System DNS will handle each of these cases
469 * correctly, but applications implementing their own DNS lookups must make
470 * sure to follow these requirements.
471 *
472 * @return The private DNS server name.
473 */
474 public @Nullable String getPrivateDnsServerName() {
475 return mPrivateDnsServerName;
476 }
477
478 /**
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900479 * Adds the given {@link InetAddress} to the list of validated private DNS servers,
480 * if not present. This is distinct from the server name in that these are actually
481 * resolved addresses.
482 *
483 * @param dnsServer The {@link InetAddress} to add to the list of validated private DNS servers.
484 * @return true if the DNS server was added, false if it was already present.
485 * @hide
486 */
paulhud9736de2019-03-08 16:35:20 +0800487 public boolean addValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) {
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900488 if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) {
489 mValidatedPrivateDnses.add(dnsServer);
490 return true;
491 }
492 return false;
493 }
494
495 /**
496 * Removes the given {@link InetAddress} from the list of validated private DNS servers.
497 *
498 * @param dnsServer The {@link InetAddress} to remove from the list of validated private DNS
499 * servers.
500 * @return true if the DNS server was removed, false if it did not exist.
501 * @hide
502 */
paulhud9736de2019-03-08 16:35:20 +0800503 public boolean removeValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) {
504 return mValidatedPrivateDnses.remove(dnsServer);
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900505 }
506
507 /**
508 * Replaces the validated private DNS servers in this {@code LinkProperties} with
509 * the given {@link Collection} of {@link InetAddress} objects.
510 *
511 * @param dnsServers The {@link Collection} of validated private DNS servers to set in this
512 * object.
513 * @hide
514 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900515 @TestApi
516 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800517 public void setValidatedPrivateDnsServers(@NonNull Collection<InetAddress> dnsServers) {
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900518 mValidatedPrivateDnses.clear();
519 for (InetAddress dnsServer: dnsServers) {
520 addValidatedPrivateDnsServer(dnsServer);
521 }
522 }
523
524 /**
525 * Returns all the {@link InetAddress} for validated private DNS servers on this link.
526 * These are resolved from the private DNS server name.
527 *
paulhud9736de2019-03-08 16:35:20 +0800528 * @return An unmodifiable {@link List} of {@link InetAddress} for validated private
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900529 * DNS servers on this link.
530 * @hide
531 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900532 @TestApi
533 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800534 public @NonNull List<InetAddress> getValidatedPrivateDnsServers() {
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900535 return Collections.unmodifiableList(mValidatedPrivateDnses);
536 }
537
538 /**
Hongshikfa425012018-06-28 20:42:19 +0900539 * Adds the given {@link InetAddress} to the list of PCSCF servers, if not present.
540 *
541 * @param pcscfServer The {@link InetAddress} to add to the list of PCSCF servers.
542 * @return true if the PCSCF server was added, false otherwise.
543 * @hide
544 */
paulhud9736de2019-03-08 16:35:20 +0800545 public boolean addPcscfServer(@NonNull InetAddress pcscfServer) {
Hongshikfa425012018-06-28 20:42:19 +0900546 if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) {
547 mPcscfs.add(pcscfServer);
548 return true;
549 }
550 return false;
551 }
552
553 /**
554 * Removes the given {@link InetAddress} from the list of PCSCF servers.
555 *
paulhud9736de2019-03-08 16:35:20 +0800556 * @param pcscfServer The {@link InetAddress} to remove from the list of PCSCF servers.
Hongshikfa425012018-06-28 20:42:19 +0900557 * @return true if the PCSCF server was removed, false otherwise.
558 * @hide
559 */
paulhud9736de2019-03-08 16:35:20 +0800560 public boolean removePcscfServer(@NonNull InetAddress pcscfServer) {
561 return mPcscfs.remove(pcscfServer);
Hongshikfa425012018-06-28 20:42:19 +0900562 }
563
564 /**
565 * Replaces the PCSCF servers in this {@code LinkProperties} with
566 * the given {@link Collection} of {@link InetAddress} objects.
567 *
paulhud9736de2019-03-08 16:35:20 +0800568 * @param pcscfServers The {@link Collection} of PCSCF servers to set in this object.
Hongshikfa425012018-06-28 20:42:19 +0900569 * @hide
570 */
Remi NGUYEN VAN299a7cc2019-01-23 21:35:52 +0900571 @SystemApi
572 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800573 public void setPcscfServers(@NonNull Collection<InetAddress> pcscfServers) {
Hongshikfa425012018-06-28 20:42:19 +0900574 mPcscfs.clear();
575 for (InetAddress pcscfServer: pcscfServers) {
576 addPcscfServer(pcscfServer);
577 }
578 }
579
580 /**
581 * Returns all the {@link InetAddress} for PCSCF servers on this link.
582 *
583 * @return An unmodifiable {@link List} of {@link InetAddress} for PCSCF servers on
584 * this link.
585 * @hide
586 */
Remi NGUYEN VAN299a7cc2019-01-23 21:35:52 +0900587 @SystemApi
588 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800589 public @NonNull List<InetAddress> getPcscfServers() {
Hongshikfa425012018-06-28 20:42:19 +0900590 return Collections.unmodifiableList(mPcscfs);
591 }
592
593 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700594 * Sets the DNS domain search path used on this link.
595 *
596 * @param domains A {@link String} listing in priority order the comma separated
597 * domains to search when resolving host names on this link.
598 */
paulhud9736de2019-03-08 16:35:20 +0800599 public void setDomains(@Nullable String domains) {
Robert Greenwalt8058f622012-11-09 10:52:27 -0800600 mDomains = domains;
601 }
602
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700603 /**
paulhud9736de2019-03-08 16:35:20 +0800604 * Get the DNS domains search path set for this link. May be {@code null} if not set.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700605 *
paulhud9736de2019-03-08 16:35:20 +0800606 * @return A {@link String} containing the comma separated domains to search when resolving host
607 * names on this link or {@code null}.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700608 */
paulhud9736de2019-03-08 16:35:20 +0800609 public @Nullable String getDomains() {
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700610 return mDomains;
611 }
612
613 /**
614 * Sets the Maximum Transmission Unit size to use on this link. This should not be used
615 * unless the system default (1500) is incorrect. Values less than 68 or greater than
616 * 10000 will be ignored.
617 *
618 * @param mtu The MTU to use for this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700619 */
sy.yun9d9b74a2013-09-02 05:24:09 +0900620 public void setMtu(int mtu) {
621 mMtu = mtu;
622 }
623
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700624 /**
625 * Gets any non-default MTU size set for this link. Note that if the default is being used
626 * this will return 0.
627 *
628 * @return The mtu value set for this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700629 */
sy.yun9d9b74a2013-09-02 05:24:09 +0900630 public int getMtu() {
631 return mMtu;
632 }
633
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700634 /**
635 * Sets the tcp buffers sizes to be used when this link is the system default.
636 * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max".
637 *
638 * @param tcpBufferSizes The tcp buffers sizes to use.
639 *
640 * @hide
641 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900642 @TestApi
643 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800644 public void setTcpBufferSizes(@Nullable String tcpBufferSizes) {
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700645 mTcpBufferSizes = tcpBufferSizes;
646 }
647
648 /**
paulhud9736de2019-03-08 16:35:20 +0800649 * Gets the tcp buffer sizes. May be {@code null} if not set.
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700650 *
paulhud9736de2019-03-08 16:35:20 +0800651 * @return the tcp buffer sizes to use when this link is the system default or {@code null}.
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700652 *
653 * @hide
654 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900655 @TestApi
656 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800657 public @Nullable String getTcpBufferSizes() {
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700658 return mTcpBufferSizes;
659 }
660
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800661 private RouteInfo routeWithInterface(RouteInfo route) {
662 return new RouteInfo(
663 route.getDestination(),
664 route.getGateway(),
Lorenzo Colitti4b0f8e62014-09-19 01:49:05 +0900665 mIfaceName,
666 route.getType());
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700667 }
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800668
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700669 /**
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900670 * Adds a {@link RouteInfo} to this {@code LinkProperties}, if not present. If the
671 * {@link RouteInfo} had an interface name set and that differs from the interface set for this
672 * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown. The proper
673 * course is to add either un-named or properly named {@link RouteInfo}.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700674 *
675 * @param route A {@link RouteInfo} to add to this object.
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900676 * @return {@code false} if the route was already present, {@code true} if it was added.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700677 */
paulhud9736de2019-03-08 16:35:20 +0800678 public boolean addRoute(@NonNull RouteInfo route) {
679 String routeIface = route.getInterface();
680 if (routeIface != null && !routeIface.equals(mIfaceName)) {
681 throw new IllegalArgumentException(
682 "Route added with non-matching interface: " + routeIface
683 + " vs. " + mIfaceName);
684 }
685 route = routeWithInterface(route);
686 if (!mRoutes.contains(route)) {
687 mRoutes.add(route);
688 return true;
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800689 }
Lorenzo Colittic17a1b92014-06-12 23:10:17 +0900690 return false;
691 }
692
693 /**
694 * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must
695 * specify an interface and the interface must match the interface of this
696 * {@code LinkProperties}, or it will not be removed.
697 *
698 * @return {@code true} if the route was removed, {@code false} if it was not present.
699 *
700 * @hide
701 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900702 @TestApi
703 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800704 public boolean removeRoute(@NonNull RouteInfo route) {
705 return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route);
Lorenzo Colitti45b9a5b2013-03-08 11:30:39 -0800706 }
707
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800708 /**
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700709 * Returns all the {@link RouteInfo} set on this link.
710 *
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700711 * @return An unmodifiable {@link List} of {@link RouteInfo} for this link.
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800712 */
paulhud9736de2019-03-08 16:35:20 +0800713 public @NonNull List<RouteInfo> getRoutes() {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700714 return Collections.unmodifiableList(mRoutes);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700715 }
716
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800717 /**
Rubin Xu1bb5c082017-09-05 18:40:49 +0100718 * Make sure this LinkProperties instance contains routes that cover the local subnet
719 * of its link addresses. Add any route that is missing.
720 * @hide
721 */
722 public void ensureDirectlyConnectedRoutes() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900723 for (LinkAddress addr : mLinkAddresses) {
Rubin Xu1bb5c082017-09-05 18:40:49 +0100724 addRoute(new RouteInfo(addr, null, mIfaceName));
725 }
726 }
727
728 /**
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800729 * Returns all the routes on this link and all the links stacked above it.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700730 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800731 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100732 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +0800733 public @NonNull List<RouteInfo> getAllRoutes() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900734 List<RouteInfo> routes = new ArrayList<>(mRoutes);
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800735 for (LinkProperties stacked: mStackedLinks.values()) {
736 routes.addAll(stacked.getAllRoutes());
737 }
Robert Greenwalt6629bcd2013-03-15 11:28:50 -0700738 return routes;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800739 }
740
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700741 /**
742 * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none.
743 * Note that Http Proxies are only a hint - the system recommends their use, but it does
744 * not enforce it and applications may ignore them.
745 *
Erik Klineb36a3132015-06-26 19:21:34 +0900746 * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700747 */
paulhud9736de2019-03-08 16:35:20 +0800748 public void setHttpProxy(@Nullable ProxyInfo proxy) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700749 mHttpProxy = proxy;
750 }
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700751
752 /**
753 * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link.
754 *
paulhud9736de2019-03-08 16:35:20 +0800755 * @return The {@link ProxyInfo} set on this link or {@code null}.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700756 */
paulhud9736de2019-03-08 16:35:20 +0800757 public @Nullable ProxyInfo getHttpProxy() {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700758 return mHttpProxy;
759 }
760
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800761 /**
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900762 * Returns the NAT64 prefix in use on this link, if any.
763 *
paulhud9736de2019-03-08 16:35:20 +0800764 * @return the NAT64 prefix or {@code null}.
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900765 * @hide
766 */
Remi NGUYEN VAN299a7cc2019-01-23 21:35:52 +0900767 @SystemApi
768 @TestApi
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900769 public @Nullable IpPrefix getNat64Prefix() {
770 return mNat64Prefix;
771 }
772
773 /**
774 * Sets the NAT64 prefix in use on this link.
775 *
776 * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the
paulhud9736de2019-03-08 16:35:20 +0800777 * 128-bit IPv6 address) are supported or {@code null} for no prefix.
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900778 *
779 * @param prefix the NAT64 prefix.
780 * @hide
781 */
Remi NGUYEN VAN299a7cc2019-01-23 21:35:52 +0900782 @SystemApi
783 @TestApi
paulhud9736de2019-03-08 16:35:20 +0800784 public void setNat64Prefix(@Nullable IpPrefix prefix) {
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900785 if (prefix != null && prefix.getPrefixLength() != 96) {
786 throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix);
787 }
788 mNat64Prefix = prefix; // IpPrefix objects are immutable.
789 }
790
791 /**
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800792 * Adds a stacked link.
793 *
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900794 * If there is already a stacked link with the same interface name as link,
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800795 * that link is replaced with link. Otherwise, link is added to the list
paulhud9736de2019-03-08 16:35:20 +0800796 * of stacked links.
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800797 *
798 * @param link The link to add.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900799 * @return true if the link was stacked, false otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700800 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800801 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100802 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +0800803 public boolean addStackedLink(@NonNull LinkProperties link) {
804 if (link.getInterfaceName() != null) {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800805 mStackedLinks.put(link.getInterfaceName(), link);
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900806 return true;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800807 }
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900808 return false;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800809 }
810
811 /**
812 * Removes a stacked link.
813 *
Lorenzo Colittif3cab632014-10-20 11:08:03 +0900814 * If there is a stacked link with the given interface name, it is
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800815 * removed. Otherwise, nothing changes.
816 *
Lorenzo Colittif3cab632014-10-20 11:08:03 +0900817 * @param iface The interface name of the link to remove.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +0900818 * @return true if the link was removed, false otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700819 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800820 */
paulhud9736de2019-03-08 16:35:20 +0800821 public boolean removeStackedLink(@NonNull String iface) {
822 LinkProperties removed = mStackedLinks.remove(iface);
823 return removed != null;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800824 }
825
826 /**
827 * Returns all the links stacked on top of this link.
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700828 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800829 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +0100830 @UnsupportedAppUsage
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700831 public @NonNull List<LinkProperties> getStackedLinks() {
832 if (mStackedLinks.isEmpty()) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900833 return Collections.emptyList();
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700834 }
paulhud9736de2019-03-08 16:35:20 +0800835 final List<LinkProperties> stacked = new ArrayList<>();
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800836 for (LinkProperties link : mStackedLinks.values()) {
Jeff Sharkeyeb2c2c72014-08-11 15:22:51 -0700837 stacked.add(new LinkProperties(link));
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800838 }
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700839 return Collections.unmodifiableList(stacked);
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800840 }
841
Robert Greenwalt4f05d552014-05-18 22:01:38 -0700842 /**
843 * Clears this object to its initial state.
844 */
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700845 public void clear() {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -0700846 mIfaceName = null;
Wink Savillee8222252011-07-13 13:44:13 -0700847 mLinkAddresses.clear();
848 mDnses.clear();
dalykd9201342018-01-17 14:20:55 -0500849 mUsePrivateDns = false;
850 mPrivateDnsServerName = null;
Hongshikfa425012018-06-28 20:42:19 +0900851 mPcscfs.clear();
Robert Greenwalt8058f622012-11-09 10:52:27 -0800852 mDomains = null;
Wink Savillee8222252011-07-13 13:44:13 -0700853 mRoutes.clear();
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700854 mHttpProxy = null;
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800855 mStackedLinks.clear();
sy.yun9d9b74a2013-09-02 05:24:09 +0900856 mMtu = 0;
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700857 mTcpBufferSizes = null;
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900858 mNat64Prefix = null;
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200859 mWakeOnLanSupported = false;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700860 }
861
862 /**
863 * Implement the Parcelable interface
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700864 */
865 public int describeContents() {
866 return 0;
867 }
868
Wink Saville1f6408a2010-08-27 11:15:18 -0700869 @Override
Robert Greenwalt37e65eb2010-08-30 10:56:47 -0700870 public String toString() {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900871 // Space as a separator, so no need for spaces at start/end of the individual fragments.
872 final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700873
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900874 if (mIfaceName != null) {
875 resultJoiner.add("InterfaceName:");
876 resultJoiner.add(mIfaceName);
877 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700878
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900879 resultJoiner.add("LinkAddresses: [");
880 if (!mLinkAddresses.isEmpty()) {
881 resultJoiner.add(TextUtils.join(",", mLinkAddresses));
882 }
883 resultJoiner.add("]");
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700884
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900885 resultJoiner.add("DnsAddresses: [");
886 if (!mDnses.isEmpty()) {
887 resultJoiner.add(TextUtils.join(",", mDnses));
888 }
889 resultJoiner.add("]");
dalykd9201342018-01-17 14:20:55 -0500890
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900891 if (mUsePrivateDns) {
892 resultJoiner.add("UsePrivateDns: true");
893 }
894
Chalard Jeanfaaf2fe2018-06-07 13:28:09 +0900895 if (mPrivateDnsServerName != null) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900896 resultJoiner.add("PrivateDnsServerName:");
897 resultJoiner.add(mPrivateDnsServerName);
dalykd9201342018-01-17 14:20:55 -0500898 }
899
Hongshikfa425012018-06-28 20:42:19 +0900900 if (!mPcscfs.isEmpty()) {
901 resultJoiner.add("PcscfAddresses: [");
902 resultJoiner.add(TextUtils.join(",", mPcscfs));
903 resultJoiner.add("]");
904 }
905
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900906 if (!mValidatedPrivateDnses.isEmpty()) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900907 final StringJoiner validatedPrivateDnsesJoiner =
908 new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]");
909 for (final InetAddress addr : mValidatedPrivateDnses) {
910 validatedPrivateDnsesJoiner.add(addr.getHostAddress());
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900911 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900912 resultJoiner.add(validatedPrivateDnsesJoiner.toString());
Chalard Jean03dbf6b2018-04-11 16:36:41 +0900913 }
914
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900915 resultJoiner.add("Domains:");
916 resultJoiner.add(mDomains);
Robert Greenwalt8058f622012-11-09 10:52:27 -0800917
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900918 resultJoiner.add("MTU:");
919 resultJoiner.add(Integer.toString(mMtu));
sy.yun9d9b74a2013-09-02 05:24:09 +0900920
Valentin Iftimec86ebba2019-09-24 13:32:13 +0200921 if (mWakeOnLanSupported) {
922 resultJoiner.add("WakeOnLanSupported: true");
923 }
924
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700925 if (mTcpBufferSizes != null) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900926 resultJoiner.add("TcpBufferSizes:");
927 resultJoiner.add(mTcpBufferSizes);
Robert Greenwalt3f05bf42014-08-06 12:00:25 -0700928 }
929
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900930 resultJoiner.add("Routes: [");
931 if (!mRoutes.isEmpty()) {
932 resultJoiner.add(TextUtils.join(",", mRoutes));
933 }
934 resultJoiner.add("]");
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700935
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900936 if (mHttpProxy != null) {
937 resultJoiner.add("HttpProxy:");
938 resultJoiner.add(mHttpProxy.toString());
939 }
940
Lorenzo Colitti59b34472019-01-08 09:58:59 +0900941 if (mNat64Prefix != null) {
942 resultJoiner.add("Nat64Prefix:");
943 resultJoiner.add(mNat64Prefix.toString());
944 }
945
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900946 final Collection<LinkProperties> stackedLinksValues = mStackedLinks.values();
947 if (!stackedLinksValues.isEmpty()) {
948 final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]");
949 for (final LinkProperties lp : stackedLinksValues) {
950 stackedLinksJoiner.add("[ " + lp + " ]");
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800951 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900952 resultJoiner.add(stackedLinksJoiner.toString());
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800953 }
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +0900954
955 return resultJoiner.toString();
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800956 }
957
958 /**
959 * Returns true if this link has an IPv4 address.
960 *
961 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -0700962 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800963 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +0900964 @TestApi
965 @SystemApi
paulhud9736de2019-03-08 16:35:20 +0800966 public boolean hasIpv4Address() {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800967 for (LinkAddress address : mLinkAddresses) {
Hugo Benichibd87a392017-10-10 16:29:06 +0900968 if (address.getAddress() instanceof Inet4Address) {
969 return true;
970 }
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -0800971 }
972 return false;
Robert Greenwalt47f69fe2010-06-15 15:43:39 -0700973 }
974
Wink Savillee8222252011-07-13 13:44:13 -0700975 /**
paulhud9736de2019-03-08 16:35:20 +0800976 * For backward compatibility.
977 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
978 * just yet.
979 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
980 * @hide
981 */
982 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
983 public boolean hasIPv4Address() {
984 return hasIpv4Address();
985 }
986
987 /**
Lorenzo Colitti87cfc702015-07-27 16:35:33 +0900988 * Returns true if this link or any of its stacked interfaces has an IPv4 address.
989 *
990 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
991 */
paulhud9736de2019-03-08 16:35:20 +0800992 private boolean hasIpv4AddressOnInterface(String iface) {
Lorenzo Colitti89b63922015-07-30 23:41:43 +0900993 // mIfaceName can be null.
paulhud9736de2019-03-08 16:35:20 +0800994 return (Objects.equals(iface, mIfaceName) && hasIpv4Address())
995 || (iface != null && mStackedLinks.containsKey(iface)
996 && mStackedLinks.get(iface).hasIpv4Address());
Lorenzo Colitti87cfc702015-07-27 16:35:33 +0900997 }
998
999 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001000 * Returns true if this link has a global preferred IPv6 address.
Lorenzo Colitti4faa0272013-08-08 11:00:12 +09001001 *
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001002 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
Robert Greenwaltdf2b8782014-06-06 10:30:11 -07001003 * @hide
Lorenzo Colitti4faa0272013-08-08 11:00:12 +09001004 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +09001005 @TestApi
1006 @SystemApi
paulhud9736de2019-03-08 16:35:20 +08001007 public boolean hasGlobalIpv6Address() {
Lorenzo Colitti4faa0272013-08-08 11:00:12 +09001008 for (LinkAddress address : mLinkAddresses) {
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001009 if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
Lorenzo Colitti4faa0272013-08-08 11:00:12 +09001010 return true;
1011 }
1012 }
1013 return false;
1014 }
1015
1016 /**
paulhud9736de2019-03-08 16:35:20 +08001017 * For backward compatibility.
1018 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1019 * just yet.
1020 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
1021 * @hide
1022 */
1023 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1024 public boolean hasGlobalIPv6Address() {
1025 return hasGlobalIpv6Address();
1026 }
1027
1028 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001029 * Returns true if this link has an IPv4 default route.
1030 *
1031 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
1032 * @hide
1033 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001034 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001035 public boolean hasIpv4DefaultRoute() {
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001036 for (RouteInfo r : mRoutes) {
Hugo Benichibd87a392017-10-10 16:29:06 +09001037 if (r.isIPv4Default()) {
1038 return true;
1039 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001040 }
1041 return false;
1042 }
1043
1044 /**
paulhud9736de2019-03-08 16:35:20 +08001045 * For backward compatibility.
1046 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1047 * just yet.
1048 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
1049 * @hide
1050 */
1051 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1052 public boolean hasIPv4DefaultRoute() {
1053 return hasIpv4DefaultRoute();
1054 }
1055
1056 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001057 * Returns true if this link has an IPv6 default route.
1058 *
1059 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
1060 * @hide
1061 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +09001062 @TestApi
1063 @SystemApi
paulhud9736de2019-03-08 16:35:20 +08001064 public boolean hasIpv6DefaultRoute() {
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001065 for (RouteInfo r : mRoutes) {
Hugo Benichibd87a392017-10-10 16:29:06 +09001066 if (r.isIPv6Default()) {
1067 return true;
1068 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001069 }
1070 return false;
1071 }
1072
1073 /**
paulhud9736de2019-03-08 16:35:20 +08001074 * For backward compatibility.
1075 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1076 * just yet.
1077 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
1078 * @hide
1079 */
1080 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1081 public boolean hasIPv6DefaultRoute() {
1082 return hasIpv6DefaultRoute();
1083 }
1084
1085 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001086 * Returns true if this link has an IPv4 DNS server.
1087 *
1088 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
1089 * @hide
1090 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001091 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001092 public boolean hasIpv4DnsServer() {
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001093 for (InetAddress ia : mDnses) {
Hugo Benichibd87a392017-10-10 16:29:06 +09001094 if (ia instanceof Inet4Address) {
1095 return true;
1096 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001097 }
1098 return false;
1099 }
1100
1101 /**
paulhud9736de2019-03-08 16:35:20 +08001102 * For backward compatibility.
1103 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1104 * just yet.
1105 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
1106 * @hide
1107 */
1108 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1109 public boolean hasIPv4DnsServer() {
1110 return hasIpv4DnsServer();
1111 }
1112
1113 /**
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001114 * Returns true if this link has an IPv6 DNS server.
1115 *
1116 * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
1117 * @hide
1118 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001119 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001120 public boolean hasIpv6DnsServer() {
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001121 for (InetAddress ia : mDnses) {
Hugo Benichibd87a392017-10-10 16:29:06 +09001122 if (ia instanceof Inet6Address) {
1123 return true;
1124 }
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001125 }
1126 return false;
1127 }
1128
1129 /**
paulhud9736de2019-03-08 16:35:20 +08001130 * For backward compatibility.
1131 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1132 * just yet.
1133 * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
1134 * @hide
1135 */
1136 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1137 public boolean hasIPv6DnsServer() {
1138 return hasIpv6DnsServer();
1139 }
1140
1141 /**
Hongshikfa425012018-06-28 20:42:19 +09001142 * Returns true if this link has an IPv4 PCSCF server.
1143 *
1144 * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise.
1145 * @hide
1146 */
paulhud9736de2019-03-08 16:35:20 +08001147 public boolean hasIpv4PcscfServer() {
Hongshikfa425012018-06-28 20:42:19 +09001148 for (InetAddress ia : mPcscfs) {
1149 if (ia instanceof Inet4Address) {
1150 return true;
1151 }
1152 }
1153 return false;
1154 }
1155
1156 /**
1157 * Returns true if this link has an IPv6 PCSCF server.
1158 *
1159 * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise.
1160 * @hide
1161 */
paulhud9736de2019-03-08 16:35:20 +08001162 public boolean hasIpv6PcscfServer() {
Hongshikfa425012018-06-28 20:42:19 +09001163 for (InetAddress ia : mPcscfs) {
1164 if (ia instanceof Inet6Address) {
1165 return true;
1166 }
1167 }
1168 return false;
1169 }
1170
1171 /**
Erik Klined3b9fd32014-10-24 21:50:20 +09001172 * Returns true if this link is provisioned for global IPv4 connectivity.
1173 * This requires an IP address, default route, and DNS server.
1174 *
1175 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Klinecd7ed162015-05-21 16:15:02 +09001176 * @hide
Erik Klined3b9fd32014-10-24 21:50:20 +09001177 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +09001178 @TestApi
1179 @SystemApi
paulhud9736de2019-03-08 16:35:20 +08001180 public boolean isIpv4Provisioned() {
1181 return (hasIpv4Address()
1182 && hasIpv4DefaultRoute()
1183 && hasIpv4DnsServer());
Erik Klined3b9fd32014-10-24 21:50:20 +09001184 }
1185
1186 /**
1187 * Returns true if this link is provisioned for global IPv6 connectivity.
1188 * This requires an IP address, default route, and DNS server.
1189 *
1190 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Klinecd7ed162015-05-21 16:15:02 +09001191 * @hide
Erik Klined3b9fd32014-10-24 21:50:20 +09001192 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +09001193 @TestApi
1194 @SystemApi
paulhud9736de2019-03-08 16:35:20 +08001195 public boolean isIpv6Provisioned() {
1196 return (hasGlobalIpv6Address()
1197 && hasIpv6DefaultRoute()
1198 && hasIpv6DnsServer());
Erik Klined3b9fd32014-10-24 21:50:20 +09001199 }
1200
1201 /**
paulhud9736de2019-03-08 16:35:20 +08001202 * For backward compatibility.
1203 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1204 * just yet.
1205 * @return {@code true} if the link is provisioned, {@code false} otherwise.
1206 * @hide
1207 */
1208 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1209 public boolean isIPv6Provisioned() {
1210 return isIpv6Provisioned();
1211 }
1212
1213
1214 /**
Erik Klined3b9fd32014-10-24 21:50:20 +09001215 * Returns true if this link is provisioned for global connectivity,
1216 * for at least one Internet Protocol family.
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001217 *
1218 * @return {@code true} if the link is provisioned, {@code false} otherwise.
1219 * @hide
1220 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +09001221 @TestApi
1222 @SystemApi
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001223 public boolean isProvisioned() {
paulhud9736de2019-03-08 16:35:20 +08001224 return (isIpv4Provisioned() || isIpv6Provisioned());
Lorenzo Colitti76ea6c62014-06-23 22:33:43 +09001225 }
1226
1227 /**
Erik Klineb36a3132015-06-26 19:21:34 +09001228 * Evaluate whether the {@link InetAddress} is considered reachable.
1229 *
1230 * @return {@code true} if the given {@link InetAddress} is considered reachable,
1231 * {@code false} otherwise.
1232 * @hide
1233 */
Remi NGUYEN VAN94a05572019-01-20 12:38:10 +09001234 @TestApi
1235 @SystemApi
paulhud9736de2019-03-08 16:35:20 +08001236 public boolean isReachable(@NonNull InetAddress ip) {
Erik Klineb36a3132015-06-26 19:21:34 +09001237 final List<RouteInfo> allRoutes = getAllRoutes();
1238 // If we don't have a route to this IP address, it's not reachable.
1239 final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip);
1240 if (bestRoute == null) {
1241 return false;
1242 }
1243
1244 // TODO: better source address evaluation for destination addresses.
1245
1246 if (ip instanceof Inet4Address) {
1247 // For IPv4, it suffices for now to simply have any address.
paulhud9736de2019-03-08 16:35:20 +08001248 return hasIpv4AddressOnInterface(bestRoute.getInterface());
Erik Klineb36a3132015-06-26 19:21:34 +09001249 } else if (ip instanceof Inet6Address) {
1250 if (ip.isLinkLocalAddress()) {
1251 // For now, just make sure link-local destinations have
1252 // scopedIds set, since transmits will generally fail otherwise.
1253 // TODO: verify it matches the ifindex of one of the interfaces.
1254 return (((Inet6Address)ip).getScopeId() != 0);
1255 } else {
1256 // For non-link-local destinations check that either the best route
1257 // is directly connected or that some global preferred address exists.
1258 // TODO: reconsider all cases (disconnected ULA networks, ...).
paulhud9736de2019-03-08 16:35:20 +08001259 return (!bestRoute.hasGateway() || hasGlobalIpv6Address());
Erik Klineb36a3132015-06-26 19:21:34 +09001260 }
1261 }
1262
1263 return false;
1264 }
1265
1266 /**
Wink Savillee8222252011-07-13 13:44:13 -07001267 * Compares this {@code LinkProperties} interface name against the target
1268 *
1269 * @param target LinkProperties to compare.
1270 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001271 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001272 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001273 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001274 public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) {
Wink Savillee8222252011-07-13 13:44:13 -07001275 return TextUtils.equals(getInterfaceName(), target.getInterfaceName());
1276 }
1277
1278 /**
Robert Greenwalt4717c262012-10-31 14:32:53 -07001279 * Compares this {@code LinkProperties} interface addresses against the target
Wink Savillee8222252011-07-13 13:44:13 -07001280 *
1281 * @param target LinkProperties to compare.
1282 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001283 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001284 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001285 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001286 public boolean isIdenticalAddresses(@NonNull LinkProperties target) {
Wink Savillee8222252011-07-13 13:44:13 -07001287 Collection<InetAddress> targetAddresses = target.getAddresses();
1288 Collection<InetAddress> sourceAddresses = getAddresses();
1289 return (sourceAddresses.size() == targetAddresses.size()) ?
1290 sourceAddresses.containsAll(targetAddresses) : false;
1291 }
1292
1293 /**
1294 * Compares this {@code LinkProperties} DNS addresses against the target
1295 *
1296 * @param target LinkProperties to compare.
1297 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001298 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001299 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001300 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001301 public boolean isIdenticalDnses(@NonNull LinkProperties target) {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -07001302 Collection<InetAddress> targetDnses = target.getDnsServers();
Robert Greenwalt8058f622012-11-09 10:52:27 -08001303 String targetDomains = target.getDomains();
1304 if (mDomains == null) {
1305 if (targetDomains != null) return false;
1306 } else {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001307 if (!mDomains.equals(targetDomains)) return false;
Robert Greenwalt8058f622012-11-09 10:52:27 -08001308 }
Wink Savillee8222252011-07-13 13:44:13 -07001309 return (mDnses.size() == targetDnses.size()) ?
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001310 mDnses.containsAll(targetDnses) : false;
Wink Savillee8222252011-07-13 13:44:13 -07001311 }
1312
1313 /**
dalykd9201342018-01-17 14:20:55 -05001314 * Compares this {@code LinkProperties} private DNS settings against the
1315 * target.
1316 *
1317 * @param target LinkProperties to compare.
1318 * @return {@code true} if both are identical, {@code false} otherwise.
1319 * @hide
1320 */
paulhud9736de2019-03-08 16:35:20 +08001321 public boolean isIdenticalPrivateDns(@NonNull LinkProperties target) {
dalykd9201342018-01-17 14:20:55 -05001322 return (isPrivateDnsActive() == target.isPrivateDnsActive()
1323 && TextUtils.equals(getPrivateDnsServerName(),
1324 target.getPrivateDnsServerName()));
1325 }
1326
1327 /**
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001328 * Compares this {@code LinkProperties} validated private DNS addresses against
1329 * the target
1330 *
1331 * @param target LinkProperties to compare.
1332 * @return {@code true} if both are identical, {@code false} otherwise.
1333 * @hide
1334 */
paulhud9736de2019-03-08 16:35:20 +08001335 public boolean isIdenticalValidatedPrivateDnses(@NonNull LinkProperties target) {
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001336 Collection<InetAddress> targetDnses = target.getValidatedPrivateDnsServers();
1337 return (mValidatedPrivateDnses.size() == targetDnses.size())
1338 ? mValidatedPrivateDnses.containsAll(targetDnses) : false;
1339 }
1340
1341 /**
Hongshikfa425012018-06-28 20:42:19 +09001342 * Compares this {@code LinkProperties} PCSCF addresses against the target
1343 *
1344 * @param target LinkProperties to compare.
1345 * @return {@code true} if both are identical, {@code false} otherwise.
1346 * @hide
1347 */
paulhud9736de2019-03-08 16:35:20 +08001348 public boolean isIdenticalPcscfs(@NonNull LinkProperties target) {
Hongshikfa425012018-06-28 20:42:19 +09001349 Collection<InetAddress> targetPcscfs = target.getPcscfServers();
1350 return (mPcscfs.size() == targetPcscfs.size()) ?
1351 mPcscfs.containsAll(targetPcscfs) : false;
1352 }
1353
1354 /**
Wink Savillee8222252011-07-13 13:44:13 -07001355 * Compares this {@code LinkProperties} Routes against the target
1356 *
1357 * @param target LinkProperties to compare.
1358 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001359 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001360 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001361 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001362 public boolean isIdenticalRoutes(@NonNull LinkProperties target) {
Wink Savillee8222252011-07-13 13:44:13 -07001363 Collection<RouteInfo> targetRoutes = target.getRoutes();
1364 return (mRoutes.size() == targetRoutes.size()) ?
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001365 mRoutes.containsAll(targetRoutes) : false;
Wink Savillee8222252011-07-13 13:44:13 -07001366 }
1367
1368 /**
1369 * Compares this {@code LinkProperties} HttpProxy against the target
1370 *
1371 * @param target LinkProperties to compare.
1372 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001373 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001374 */
Mathew Inwood55418ea2018-12-20 15:30:45 +00001375 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
paulhud9736de2019-03-08 16:35:20 +08001376 public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) {
Wink Savillee8222252011-07-13 13:44:13 -07001377 return getHttpProxy() == null ? target.getHttpProxy() == null :
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001378 getHttpProxy().equals(target.getHttpProxy());
Wink Savillee8222252011-07-13 13:44:13 -07001379 }
John Wang4e900092011-04-04 12:35:42 -07001380
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001381 /**
1382 * Compares this {@code LinkProperties} stacked links against the target
1383 *
1384 * @param target LinkProperties to compare.
1385 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001386 * @hide
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001387 */
Mathew Inwoodfa3a7462018-08-08 14:52:47 +01001388 @UnsupportedAppUsage
paulhud9736de2019-03-08 16:35:20 +08001389 public boolean isIdenticalStackedLinks(@NonNull LinkProperties target) {
Lorenzo Colitti213f98b2013-04-01 10:47:43 +09001390 if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001391 return false;
1392 }
1393 for (LinkProperties stacked : mStackedLinks.values()) {
1394 // Hashtable values can never be null.
1395 String iface = stacked.getInterfaceName();
1396 if (!stacked.equals(target.mStackedLinks.get(iface))) {
1397 return false;
1398 }
1399 }
1400 return true;
1401 }
1402
sy.yun9d9b74a2013-09-02 05:24:09 +09001403 /**
1404 * Compares this {@code LinkProperties} MTU against the target
1405 *
Ying Wangd57de6a2013-09-06 22:53:16 -07001406 * @param target LinkProperties to compare.
sy.yun9d9b74a2013-09-02 05:24:09 +09001407 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001408 * @hide
sy.yun9d9b74a2013-09-02 05:24:09 +09001409 */
paulhud9736de2019-03-08 16:35:20 +08001410 public boolean isIdenticalMtu(@NonNull LinkProperties target) {
sy.yun9d9b74a2013-09-02 05:24:09 +09001411 return getMtu() == target.getMtu();
1412 }
1413
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001414 /**
1415 * Compares this {@code LinkProperties} Tcp buffer sizes against the target.
1416 *
1417 * @param target LinkProperties to compare.
1418 * @return {@code true} if both are identical, {@code false} otherwise.
1419 * @hide
1420 */
paulhud9736de2019-03-08 16:35:20 +08001421 public boolean isIdenticalTcpBufferSizes(@NonNull LinkProperties target) {
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001422 return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes);
1423 }
1424
John Wang4e900092011-04-04 12:35:42 -07001425 /**
Lorenzo Colitti59b34472019-01-08 09:58:59 +09001426 * Compares this {@code LinkProperties} NAT64 prefix against the target.
1427 *
1428 * @param target LinkProperties to compare.
1429 * @return {@code true} if both are identical, {@code false} otherwise.
1430 * @hide
1431 */
paulhud9736de2019-03-08 16:35:20 +08001432 public boolean isIdenticalNat64Prefix(@NonNull LinkProperties target) {
Lorenzo Colitti59b34472019-01-08 09:58:59 +09001433 return Objects.equals(mNat64Prefix, target.mNat64Prefix);
1434 }
1435
1436 /**
Valentin Iftimec86ebba2019-09-24 13:32:13 +02001437 * Compares this {@code LinkProperties} WakeOnLan supported against the target.
1438 *
1439 * @param target LinkProperties to compare.
1440 * @return {@code true} if both are identical, {@code false} otherwise.
1441 * @hide
1442 */
1443 public boolean isIdenticalWakeOnLan(LinkProperties target) {
1444 return isWakeOnLanSupported() == target.isWakeOnLanSupported();
1445 }
1446
1447 /**
1448 * Set whether the network interface supports WakeOnLAN
1449 *
1450 * @param supported WakeOnLAN supported value
1451 *
1452 * @hide
1453 */
1454 public void setWakeOnLanSupported(boolean supported) {
1455 mWakeOnLanSupported = supported;
1456 }
1457
1458 /**
1459 * Returns whether the network interface supports WakeOnLAN
1460 *
1461 * @return {@code true} if interface supports WakeOnLAN, {@code false} otherwise.
1462 */
1463 public boolean isWakeOnLanSupported() {
1464 return mWakeOnLanSupported;
1465 }
1466
1467 /**
John Wang4e900092011-04-04 12:35:42 -07001468 * Compares this {@code LinkProperties} instance against the target
1469 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
1470 * all their fields are equal in values.
1471 *
1472 * For collection fields, such as mDnses, containsAll() is used to check
1473 * if two collections contains the same elements, independent of order.
1474 * There are two thoughts regarding containsAll()
1475 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
1476 * 2. Worst case performance is O(n^2).
1477 *
1478 * @param obj the object to be tested for equality.
1479 * @return {@code true} if both objects are equal, {@code false} otherwise.
1480 */
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001481 @Override
John Wang4e900092011-04-04 12:35:42 -07001482 public boolean equals(Object obj) {
1483 if (this == obj) return true;
1484
1485 if (!(obj instanceof LinkProperties)) return false;
1486
John Wang4e900092011-04-04 12:35:42 -07001487 LinkProperties target = (LinkProperties) obj;
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001488 /*
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001489 * This method does not check that stacked interfaces are equal, because
1490 * stacked interfaces are not so much a property of the link as a
1491 * description of connections between links.
1492 */
dalykd9201342018-01-17 14:20:55 -05001493 return isIdenticalInterfaceName(target)
1494 && isIdenticalAddresses(target)
1495 && isIdenticalDnses(target)
1496 && isIdenticalPrivateDns(target)
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001497 && isIdenticalValidatedPrivateDnses(target)
Hongshikfa425012018-06-28 20:42:19 +09001498 && isIdenticalPcscfs(target)
dalykd9201342018-01-17 14:20:55 -05001499 && isIdenticalRoutes(target)
1500 && isIdenticalHttpProxy(target)
1501 && isIdenticalStackedLinks(target)
1502 && isIdenticalMtu(target)
Lorenzo Colitti59b34472019-01-08 09:58:59 +09001503 && isIdenticalTcpBufferSizes(target)
Valentin Iftimec86ebba2019-09-24 13:32:13 +02001504 && isIdenticalNat64Prefix(target)
1505 && isIdenticalWakeOnLan(target);
Wink Savillee8222252011-07-13 13:44:13 -07001506 }
John Wang4e900092011-04-04 12:35:42 -07001507
Wink Savillee8222252011-07-13 13:44:13 -07001508 /**
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001509 * Compares the addresses in this LinkProperties with another
1510 * LinkProperties, examining only addresses on the base link.
Wink Savillee8222252011-07-13 13:44:13 -07001511 *
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001512 * @param target a LinkProperties with the new list of addresses
1513 * @return the differences between the addresses.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001514 * @hide
Wink Savillee8222252011-07-13 13:44:13 -07001515 */
paulhud9736de2019-03-08 16:35:20 +08001516 public @NonNull CompareResult<LinkAddress> compareAddresses(@Nullable LinkProperties target) {
Wink Savillee8222252011-07-13 13:44:13 -07001517 /*
1518 * Duplicate the LinkAddresses into removed, we will be removing
1519 * address which are common between mLinkAddresses and target
1520 * leaving the addresses that are different. And address which
1521 * are in target but not in mLinkAddresses are placed in the
1522 * addedAddresses.
1523 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001524 return new CompareResult<>(mLinkAddresses,
1525 target != null ? target.getLinkAddresses() : null);
John Wang4e900092011-04-04 12:35:42 -07001526 }
1527
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001528 /**
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001529 * Compares the DNS addresses in this LinkProperties with another
1530 * LinkProperties, examining only DNS addresses on the base link.
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001531 *
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001532 * @param target a LinkProperties with the new list of dns addresses
1533 * @return the differences between the DNS addresses.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001534 * @hide
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001535 */
paulhud9736de2019-03-08 16:35:20 +08001536 public @NonNull CompareResult<InetAddress> compareDnses(@Nullable LinkProperties target) {
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001537 /*
1538 * Duplicate the InetAddresses into removed, we will be removing
1539 * dns address which are common between mDnses and target
1540 * leaving the addresses that are different. And dns address which
1541 * are in target but not in mDnses are placed in the
1542 * addedAddresses.
1543 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001544 return new CompareResult<>(mDnses, target != null ? target.getDnsServers() : null);
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001545 }
1546
1547 /**
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001548 * Compares the validated private DNS addresses in this LinkProperties with another
1549 * LinkProperties.
1550 *
1551 * @param target a LinkProperties with the new list of validated private dns addresses
1552 * @return the differences between the DNS addresses.
1553 * @hide
1554 */
paulhud9736de2019-03-08 16:35:20 +08001555 public @NonNull CompareResult<InetAddress> compareValidatedPrivateDnses(
1556 @Nullable LinkProperties target) {
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001557 return new CompareResult<>(mValidatedPrivateDnses,
1558 target != null ? target.getValidatedPrivateDnsServers() : null);
1559 }
1560
1561 /**
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001562 * Compares all routes in this LinkProperties with another LinkProperties,
1563 * examining both the the base link and all stacked links.
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001564 *
Lorenzo Colittid1e0fae2013-07-31 23:23:21 +09001565 * @param target a LinkProperties with the new list of routes
1566 * @return the differences between the routes.
Robert Greenwalt4f05d552014-05-18 22:01:38 -07001567 * @hide
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001568 */
paulhud9736de2019-03-08 16:35:20 +08001569 public @NonNull CompareResult<RouteInfo> compareAllRoutes(@Nullable LinkProperties target) {
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001570 /*
1571 * Duplicate the RouteInfos into removed, we will be removing
Lorenzo Colitti1994bc12013-03-08 19:11:40 -08001572 * routes which are common between mRoutes and target
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001573 * leaving the routes that are different. And route address which
1574 * are in target but not in mRoutes are placed in added.
1575 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001576 return new CompareResult<>(getAllRoutes(), target != null ? target.getAllRoutes() : null);
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001577 }
1578
Paul Jensen992f2522014-04-28 10:33:11 -04001579 /**
1580 * Compares all interface names in this LinkProperties with another
1581 * LinkProperties, examining both the the base link and all stacked links.
1582 *
1583 * @param target a LinkProperties with the new list of interface names
1584 * @return the differences between the interface names.
1585 * @hide
1586 */
paulhud9736de2019-03-08 16:35:20 +08001587 public @NonNull CompareResult<String> compareAllInterfaceNames(
1588 @Nullable LinkProperties target) {
Paul Jensen992f2522014-04-28 10:33:11 -04001589 /*
1590 * Duplicate the interface names into removed, we will be removing
1591 * interface names which are common between this and target
1592 * leaving the interface names that are different. And interface names which
1593 * are in target but not in this are placed in added.
1594 */
Rubin Xu2fc72f72017-08-22 16:35:52 +01001595 return new CompareResult<>(getAllInterfaceNames(),
1596 target != null ? target.getAllInterfaceNames() : null);
Paul Jensen992f2522014-04-28 10:33:11 -04001597 }
1598
Robert Greenwalt0a46db52011-07-14 14:28:05 -07001599
John Wang4e900092011-04-04 12:35:42 -07001600 /**
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001601 * Generate hashcode based on significant fields
1602 *
John Wang4e900092011-04-04 12:35:42 -07001603 * Equal objects must produce the same hash code, while unequal objects
1604 * may have the same hash codes.
1605 */
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001606 @Override
John Wang4e900092011-04-04 12:35:42 -07001607 public int hashCode() {
1608 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
1609 + mLinkAddresses.size() * 31
1610 + mDnses.size() * 37
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001611 + mValidatedPrivateDnses.size() * 61
Robert Greenwalt8058f622012-11-09 10:52:27 -08001612 + ((null == mDomains) ? 0 : mDomains.hashCode())
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001613 + mRoutes.size() * 41
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001614 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
sy.yun9d9b74a2013-09-02 05:24:09 +09001615 + mStackedLinks.hashCode() * 47)
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001616 + mMtu * 51
dalykd9201342018-01-17 14:20:55 -05001617 + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
1618 + (mUsePrivateDns ? 57 : 0)
Hongshikfa425012018-06-28 20:42:19 +09001619 + mPcscfs.size() * 67
Lorenzo Colitti59b34472019-01-08 09:58:59 +09001620 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
Valentin Iftimec86ebba2019-09-24 13:32:13 +02001621 + Objects.hash(mNat64Prefix)
1622 + (mWakeOnLanSupported ? 71 : 0);
John Wang4e900092011-04-04 12:35:42 -07001623 }
1624
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001625 /**
1626 * Implement the Parcelable interface.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001627 */
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001628 public void writeToParcel(Parcel dest, int flags) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001629 dest.writeString(getInterfaceName());
Irfan Sheriffed5d7d12010-10-01 16:08:28 -07001630 dest.writeInt(mLinkAddresses.size());
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001631 for (LinkAddress linkAddress : mLinkAddresses) {
Irfan Sheriffed5d7d12010-10-01 16:08:28 -07001632 dest.writeParcelable(linkAddress, flags);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001633 }
Irfan Sheriffed5d7d12010-10-01 16:08:28 -07001634
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001635 dest.writeInt(mDnses.size());
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001636 for (InetAddress d : mDnses) {
1637 dest.writeByteArray(d.getAddress());
1638 }
1639 dest.writeInt(mValidatedPrivateDnses.size());
1640 for (InetAddress d : mValidatedPrivateDnses) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001641 dest.writeByteArray(d.getAddress());
1642 }
dalykd9201342018-01-17 14:20:55 -05001643 dest.writeBoolean(mUsePrivateDns);
1644 dest.writeString(mPrivateDnsServerName);
Hongshikfa425012018-06-28 20:42:19 +09001645 dest.writeInt(mPcscfs.size());
1646 for (InetAddress d : mPcscfs) {
1647 dest.writeByteArray(d.getAddress());
1648 }
Robert Greenwalt8058f622012-11-09 10:52:27 -08001649 dest.writeString(mDomains);
sy.yun9d9b74a2013-09-02 05:24:09 +09001650 dest.writeInt(mMtu);
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001651 dest.writeString(mTcpBufferSizes);
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001652 dest.writeInt(mRoutes.size());
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001653 for (RouteInfo route : mRoutes) {
Robert Greenwaltaa70f102011-04-28 14:28:50 -07001654 dest.writeParcelable(route, flags);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001655 }
Robert Greenwalt992564e2011-02-09 13:56:06 -08001656
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001657 if (mHttpProxy != null) {
1658 dest.writeByte((byte)1);
1659 dest.writeParcelable(mHttpProxy, flags);
1660 } else {
1661 dest.writeByte((byte)0);
1662 }
Lorenzo Colitti59b34472019-01-08 09:58:59 +09001663 dest.writeParcelable(mNat64Prefix, 0);
1664
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001665 ArrayList<LinkProperties> stackedLinks = new ArrayList<>(mStackedLinks.values());
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001666 dest.writeList(stackedLinks);
Valentin Iftimec86ebba2019-09-24 13:32:13 +02001667
1668 dest.writeBoolean(mWakeOnLanSupported);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001669 }
1670
1671 /**
1672 * Implement the Parcelable interface.
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001673 */
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -07001674 public static final @android.annotation.NonNull Creator<LinkProperties> CREATOR =
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001675 new Creator<LinkProperties>() {
1676 public LinkProperties createFromParcel(Parcel in) {
1677 LinkProperties netProp = new LinkProperties();
Robert Greenwalt4717c262012-10-31 14:32:53 -07001678
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001679 String iface = in.readString();
1680 if (iface != null) {
Robert Greenwalt4717c262012-10-31 14:32:53 -07001681 netProp.setInterfaceName(iface);
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001682 }
1683 int addressCount = in.readInt();
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001684 for (int i = 0; i < addressCount; i++) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001685 netProp.addLinkAddress(in.readParcelable(null));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001686 }
1687 addressCount = in.readInt();
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001688 for (int i = 0; i < addressCount; i++) {
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001689 try {
Robert Greenwaltdf2b8782014-06-06 10:30:11 -07001690 netProp.addDnsServer(InetAddress.getByAddress(in.createByteArray()));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001691 } catch (UnknownHostException e) { }
1692 }
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001693 addressCount = in.readInt();
1694 for (int i = 0; i < addressCount; i++) {
1695 try {
1696 netProp.addValidatedPrivateDnsServer(
1697 InetAddress.getByAddress(in.createByteArray()));
1698 } catch (UnknownHostException e) { }
1699 }
dalykd9201342018-01-17 14:20:55 -05001700 netProp.setUsePrivateDns(in.readBoolean());
1701 netProp.setPrivateDnsServerName(in.readString());
Hongshikfa425012018-06-28 20:42:19 +09001702 addressCount = in.readInt();
1703 for (int i = 0; i < addressCount; i++) {
1704 try {
1705 netProp.addPcscfServer(InetAddress.getByAddress(in.createByteArray()));
1706 } catch (UnknownHostException e) { }
1707 }
Robert Greenwalt8058f622012-11-09 10:52:27 -08001708 netProp.setDomains(in.readString());
sy.yun9d9b74a2013-09-02 05:24:09 +09001709 netProp.setMtu(in.readInt());
Robert Greenwalt3f05bf42014-08-06 12:00:25 -07001710 netProp.setTcpBufferSizes(in.readString());
Robert Greenwalt992564e2011-02-09 13:56:06 -08001711 addressCount = in.readInt();
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001712 for (int i = 0; i < addressCount; i++) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001713 netProp.addRoute(in.readParcelable(null));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001714 }
1715 if (in.readByte() == 1) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001716 netProp.setHttpProxy(in.readParcelable(null));
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001717 }
Lorenzo Colitti59b34472019-01-08 09:58:59 +09001718 netProp.setNat64Prefix(in.readParcelable(null));
Lorenzo Colitti419a4ce2013-03-07 10:59:25 -08001719 ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
1720 in.readList(stackedLinks, LinkProperties.class.getClassLoader());
1721 for (LinkProperties stackedLink: stackedLinks) {
1722 netProp.addStackedLink(stackedLink);
1723 }
Valentin Iftimec86ebba2019-09-24 13:32:13 +02001724 netProp.setWakeOnLanSupported(in.readBoolean());
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001725 return netProp;
1726 }
1727
Robert Greenwalt37e65eb2010-08-30 10:56:47 -07001728 public LinkProperties[] newArray(int size) {
1729 return new LinkProperties[size];
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001730 }
1731 };
w1997615afd812014-08-05 15:18:11 -07001732
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001733 /**
1734 * Check the valid MTU range based on IPv4 or IPv6.
1735 * @hide
1736 */
1737 public static boolean isValidMtu(int mtu, boolean ipv6) {
1738 if (ipv6) {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001739 return mtu >= MIN_MTU_V6 && mtu <= MAX_MTU;
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001740 } else {
Chalard Jeanb8cfa1d2018-06-07 13:27:00 +09001741 return mtu >= MIN_MTU && mtu <= MAX_MTU;
w1997615afd812014-08-05 15:18:11 -07001742 }
Chalard Jean03dbf6b2018-04-11 16:36:41 +09001743 }
Robert Greenwalt47f69fe2010-06-15 15:43:39 -07001744}