blob: e41ed72b259cfb05bdb5d4f2ca659159eeb9698e [file] [log] [blame]
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001/*
Wink Saville17465432010-09-21 09:15:35 -07002 * Copyright (C) 2010 The Android Open Source Project
Robert Greenwalta7dfbd32010-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 Sharkey0aef9342014-08-11 15:22:51 -070019import android.annotation.NonNull;
Jeff Sharkeyf2ceed82014-08-14 12:55:00 -070020import android.annotation.Nullable;
paulhu058120d2018-12-12 17:52:57 +080021import android.annotation.SystemApi;
Artur Satayev9c2add62019-12-10 17:47:52 +000022import android.compat.annotation.UnsupportedAppUsage;
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +000023import android.os.Build;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070024import android.os.Parcel;
Rubin Xuffd77d82017-09-05 18:40:49 +010025import android.os.Parcelable;
John Wang3e567d52011-04-04 12:35:42 -070026import android.text.TextUtils;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070027
Chalard Jean79162542020-08-19 16:07:22 +090028import com.android.net.module.util.LinkPropertiesUtils;
29
Lorenzo Colittic0803122013-03-07 10:59:25 -080030import java.net.Inet4Address;
Lorenzo Colitti09de4182013-08-08 11:00:12 +090031import java.net.Inet6Address;
Rubin Xuffd77d82017-09-05 18:40:49 +010032import java.net.InetAddress;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070033import java.net.UnknownHostException;
34import java.util.ArrayList;
35import java.util.Collection;
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -070036import java.util.Collections;
Lorenzo Colittic0803122013-03-07 10:59:25 -080037import java.util.Hashtable;
Robert Greenwalt69aceaf2014-06-06 10:30:11 -070038import java.util.List;
Lorenzo Colitti36ddd9d2014-06-12 23:10:17 +090039import java.util.Objects;
Chalard Jeand51966a2018-06-07 13:27:00 +090040import java.util.StringJoiner;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070041
42/**
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -070043 * Describes the properties of a network link.
Robert Greenwalt5c733972011-02-09 13:56:06 -080044 *
45 * A link represents a connection to a network.
46 * It may have multiple addresses and multiple gateways,
Robert Greenwalteaa84d52014-05-18 22:01:38 -070047 * multiple dns servers but only one http proxy and one
48 * network interface.
Robert Greenwalt5c733972011-02-09 13:56:06 -080049 *
Robert Greenwalteaa84d52014-05-18 22:01:38 -070050 * Note that this is just a holder of data. Modifying it
51 * does not affect live networks.
Robert Greenwalt5c733972011-02-09 13:56:06 -080052 *
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070053 */
Robert Greenwaltc4920a52014-06-12 16:24:38 -070054public final class LinkProperties implements Parcelable {
Lorenzo Colittic0803122013-03-07 10:59:25 -080055 // The interface described by the network link.
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +000056 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
Robert Greenwalt462e5702012-10-31 14:32:53 -070057 private String mIfaceName;
paulhucbbc3db2019-03-08 16:35:20 +080058 private final ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
59 private final ArrayList<InetAddress> mDnses = new ArrayList<>();
Hongshike2d7cf52018-06-28 20:42:19 +090060 // PCSCF addresses are addresses of SIP proxies that only exist for the IMS core service.
paulhucbbc3db2019-03-08 16:35:20 +080061 private final ArrayList<InetAddress> mPcscfs = new ArrayList<InetAddress>();
62 private final ArrayList<InetAddress> mValidatedPrivateDnses = new ArrayList<>();
dalyk7643abc2018-01-17 14:20:55 -050063 private boolean mUsePrivateDns;
64 private String mPrivateDnsServerName;
Robert Greenwaltcd277852012-11-09 10:52:27 -080065 private String mDomains;
Chalard Jeand51966a2018-06-07 13:27:00 +090066 private ArrayList<RouteInfo> mRoutes = new ArrayList<>();
ruibin zhangca75bc82019-05-23 19:35:30 +080067 private Inet4Address mDhcpServerAddress;
Jason Monk4d5e20f2014-04-25 15:00:09 -040068 private ProxyInfo mHttpProxy;
sy.yun4aa73922013-09-02 05:24:09 +090069 private int mMtu;
Robert Greenwaltdebf0e02014-08-06 12:00:25 -070070 // in the format "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max"
71 private String mTcpBufferSizes;
Lorenzo Colitti981b34f2019-01-08 09:58:59 +090072 private IpPrefix mNat64Prefix;
Valentin Iftime9fa35092019-09-24 13:32:13 +020073 private boolean mWakeOnLanSupported;
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +090074 private Uri mCaptivePortalApiUrl;
75 private CaptivePortalData mCaptivePortalData;
76
77 /**
78 * Indicates whether parceling should preserve fields that are set based on permissions of
79 * the process receiving the {@link LinkProperties}.
80 */
81 private final transient boolean mParcelSensitiveFields;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -070082
w19976e714f1d2014-08-05 15:18:11 -070083 private static final int MIN_MTU = 68;
Benedict Wongf3215112020-11-19 00:17:29 -080084
Remi NGUYEN VAN00c5e702020-11-30 16:35:43 +090085 private static final int MIN_MTU_V6 = 1280;
Benedict Wongf3215112020-11-19 00:17:29 -080086
w19976e714f1d2014-08-05 15:18:11 -070087 private static final int MAX_MTU = 10000;
88
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +090089 private static final int INET6_ADDR_LENGTH = 16;
90
Lorenzo Colittic0803122013-03-07 10:59:25 -080091 // Stores the properties of links that are "stacked" above this link.
92 // Indexed by interface name to allow modification and to prevent duplicates being added.
Chalard Jeand51966a2018-06-07 13:27:00 +090093 private Hashtable<String, LinkProperties> mStackedLinks = new Hashtable<>();
Lorenzo Colittic0803122013-03-07 10:59:25 -080094
Robert Greenwalt69aceaf2014-06-06 10:30:11 -070095 /**
96 * @hide
97 */
Artur Satayev56cb6bb2019-11-04 17:50:59 +000098 @UnsupportedAppUsage(implicitMember =
99 "values()[Landroid/net/LinkProperties$ProvisioningChange;")
Erik Kline04612b02015-05-21 16:15:02 +0900100 public enum ProvisioningChange {
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100101 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900102 STILL_NOT_PROVISIONED,
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100103 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900104 LOST_PROVISIONING,
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100105 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900106 GAINED_PROVISIONING,
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100107 @UnsupportedAppUsage
Erik Kline04612b02015-05-21 16:15:02 +0900108 STILL_PROVISIONED,
109 }
110
111 /**
112 * Compare the provisioning states of two LinkProperties instances.
113 *
114 * @hide
115 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000116 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Erik Kline04612b02015-05-21 16:15:02 +0900117 public static ProvisioningChange compareProvisioning(
118 LinkProperties before, LinkProperties after) {
119 if (before.isProvisioned() && after.isProvisioned()) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900120 // On dual-stack networks, DHCPv4 renewals can occasionally fail.
Erik Kline04612b02015-05-21 16:15:02 +0900121 // When this happens, IPv6-reachable services continue to function
122 // normally but IPv4-only services (naturally) fail.
123 //
124 // When an application using an IPv4-only service reports a bad
125 // network condition to the framework, attempts to re-validate
126 // the network succeed (since we support IPv6-only networks) and
127 // nothing is changed.
128 //
129 // For users, this is confusing and unexpected behaviour, and is
130 // not necessarily easy to diagnose. Therefore, we treat changing
Chalard Jeand51966a2018-06-07 13:27:00 +0900131 // from a dual-stack network to an IPv6-only network equivalent to
Erik Kline04612b02015-05-21 16:15:02 +0900132 // a total loss of provisioning.
133 //
134 // For one such example of this, see b/18867306.
135 //
Erik Klineaa8f8f32015-08-14 12:16:55 +0900136 // Additionally, losing IPv6 provisioning can result in TCP
137 // connections getting stuck until timeouts fire and other
138 // baffling failures. Therefore, loss of either IPv4 or IPv6 on a
Chalard Jeand51966a2018-06-07 13:27:00 +0900139 // previously dual-stack network is deemed a lost of provisioning.
paulhucbbc3db2019-03-08 16:35:20 +0800140 if ((before.isIpv4Provisioned() && !after.isIpv4Provisioned())
141 || (before.isIpv6Provisioned() && !after.isIpv6Provisioned())) {
Erik Kline04612b02015-05-21 16:15:02 +0900142 return ProvisioningChange.LOST_PROVISIONING;
143 }
144 return ProvisioningChange.STILL_PROVISIONED;
145 } else if (before.isProvisioned() && !after.isProvisioned()) {
146 return ProvisioningChange.LOST_PROVISIONING;
147 } else if (!before.isProvisioned() && after.isProvisioned()) {
148 return ProvisioningChange.GAINED_PROVISIONING;
149 } else { // !before.isProvisioned() && !after.isProvisioned()
150 return ProvisioningChange.STILL_NOT_PROVISIONED;
151 }
152 }
153
154 /**
paulhucbbc3db2019-03-08 16:35:20 +0800155 * Constructs a new {@code LinkProperties} with default values.
Erik Kline04612b02015-05-21 16:15:02 +0900156 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700157 public LinkProperties() {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900158 mParcelSensitiveFields = false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700159 }
160
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700161 /**
162 * @hide
163 */
Remi NGUYEN VANd9f75862019-01-23 21:35:52 +0900164 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800165 public LinkProperties(@Nullable LinkProperties source) {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900166 this(source, false /* parcelSensitiveFields */);
167 }
168
Remi NGUYEN VAN8dd694d2020-03-16 14:48:37 +0900169 /**
170 * Create a copy of a {@link LinkProperties} that may preserve fields that were set
171 * based on the permissions of the process that originally received it.
172 *
173 * <p>By default {@link LinkProperties} does not preserve such fields during parceling, as
174 * they should not be shared outside of the process that receives them without appropriate
175 * checks.
176 * @param parcelSensitiveFields Whether the sensitive fields should be kept when parceling
177 * @hide
178 */
179 @SystemApi
Remi NGUYEN VAN8dd694d2020-03-16 14:48:37 +0900180 public LinkProperties(@Nullable LinkProperties source, boolean parcelSensitiveFields) {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900181 mParcelSensitiveFields = parcelSensitiveFields;
182 if (source == null) return;
183 mIfaceName = source.mIfaceName;
184 mLinkAddresses.addAll(source.mLinkAddresses);
185 mDnses.addAll(source.mDnses);
186 mValidatedPrivateDnses.addAll(source.mValidatedPrivateDnses);
187 mUsePrivateDns = source.mUsePrivateDns;
188 mPrivateDnsServerName = source.mPrivateDnsServerName;
189 mPcscfs.addAll(source.mPcscfs);
190 mDomains = source.mDomains;
191 mRoutes.addAll(source.mRoutes);
192 mHttpProxy = (source.mHttpProxy == null) ? null : new ProxyInfo(source.mHttpProxy);
193 for (LinkProperties l: source.mStackedLinks.values()) {
194 addStackedLink(l);
Irfan Sherifffd151ec2010-08-30 20:37:17 -0700195 }
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900196 setMtu(source.mMtu);
197 setDhcpServerAddress(source.getDhcpServerAddress());
198 mTcpBufferSizes = source.mTcpBufferSizes;
199 mNat64Prefix = source.mNat64Prefix;
200 mWakeOnLanSupported = source.mWakeOnLanSupported;
201 mCaptivePortalApiUrl = source.mCaptivePortalApiUrl;
202 mCaptivePortalData = source.mCaptivePortalData;
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700203 }
204
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700205 /**
206 * Sets the interface name for this link. All {@link RouteInfo} already set for this
207 * will have their interface changed to match this new value.
208 *
209 * @param iface The name of the network interface used for this link.
210 */
paulhucbbc3db2019-03-08 16:35:20 +0800211 public void setInterfaceName(@Nullable String iface) {
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700212 mIfaceName = iface;
Chalard Jeand51966a2018-06-07 13:27:00 +0900213 ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800214 for (RouteInfo route : mRoutes) {
215 newRoutes.add(routeWithInterface(route));
216 }
217 mRoutes = newRoutes;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700218 }
219
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700220 /**
221 * Gets the interface name for this link. May be {@code null} if not set.
222 *
223 * @return The interface name set for this link or {@code null}.
224 */
Jeff Sharkeyf2ceed82014-08-14 12:55:00 -0700225 public @Nullable String getInterfaceName() {
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700226 return mIfaceName;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700227 }
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700228
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700229 /**
230 * @hide
231 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800232 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800233 public @NonNull List<String> getAllInterfaceNames() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900234 List<String> interfaceNames = new ArrayList<>(mStackedLinks.size() + 1);
235 if (mIfaceName != null) interfaceNames.add(mIfaceName);
Lorenzo Colitti63839822013-03-20 19:22:58 +0900236 for (LinkProperties stacked: mStackedLinks.values()) {
237 interfaceNames.addAll(stacked.getAllInterfaceNames());
238 }
239 return interfaceNames;
240 }
241
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900242 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700243 * Returns all the addresses on this link. We often think of a link having a single address,
244 * however, particularly with Ipv6 several addresses are typical. Note that the
245 * {@code LinkProperties} actually contains {@link LinkAddress} objects which also include
246 * prefix lengths for each address. This is a simplified utility alternative to
247 * {@link LinkProperties#getLinkAddresses}.
248 *
Chalard Jeand51966a2018-06-07 13:27:00 +0900249 * @return An unmodifiable {@link List} of {@link InetAddress} for this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700250 * @hide
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900251 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800252 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800253 public @NonNull List<InetAddress> getAddresses() {
254 final List<InetAddress> addresses = new ArrayList<>();
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700255 for (LinkAddress linkAddress : mLinkAddresses) {
256 addresses.add(linkAddress.getAddress());
257 }
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700258 return Collections.unmodifiableList(addresses);
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700259 }
260
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900261 /**
262 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700263 * @hide
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900264 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100265 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +0800266 public @NonNull List<InetAddress> getAllAddresses() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900267 List<InetAddress> addresses = new ArrayList<>();
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900268 for (LinkAddress linkAddress : mLinkAddresses) {
269 addresses.add(linkAddress.getAddress());
270 }
271 for (LinkProperties stacked: mStackedLinks.values()) {
272 addresses.addAll(stacked.getAllAddresses());
273 }
274 return addresses;
275 }
276
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900277 private int findLinkAddressIndex(LinkAddress address) {
278 for (int i = 0; i < mLinkAddresses.size(); i++) {
279 if (mLinkAddresses.get(i).isSameAddressAs(address)) {
280 return i;
281 }
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900282 }
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900283 return -1;
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900284 }
285
286 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700287 * Adds a {@link LinkAddress} to this {@code LinkProperties} if a {@link LinkAddress} of the
288 * same address/prefix does not already exist. If it does exist it is replaced.
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900289 * @param address The {@code LinkAddress} to add.
290 * @return true if {@code address} was added or updated, false otherwise.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700291 * @hide
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900292 */
Remi NGUYEN VANc7fe99f2019-01-29 12:08:43 +0900293 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800294 public boolean addLinkAddress(@NonNull LinkAddress address) {
Lorenzo Colitti61b65822013-11-15 18:43:52 +0900295 if (address == null) {
296 return false;
297 }
298 int i = findLinkAddressIndex(address);
299 if (i < 0) {
300 // Address was not present. Add it.
301 mLinkAddresses.add(address);
302 return true;
303 } else if (mLinkAddresses.get(i).equals(address)) {
304 // Address was present and has same properties. Do nothing.
305 return false;
306 } else {
307 // Address was present and has different properties. Update it.
308 mLinkAddresses.set(i, address);
309 return true;
310 }
311 }
312
313 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700314 * Removes a {@link LinkAddress} from this {@code LinkProperties}. Specifically, matches
315 * and {@link LinkAddress} with the same address and prefix.
316 *
317 * @param toRemove A {@link LinkAddress} specifying the address to remove.
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900318 * @return true if the address was removed, false if it did not exist.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700319 * @hide
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900320 */
Remi NGUYEN VANc7fe99f2019-01-29 12:08:43 +0900321 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800322 public boolean removeLinkAddress(@NonNull LinkAddress toRemove) {
Lorenzo Colitti61b65822013-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 Sherifffb7c9642010-10-01 16:08:28 -0700329 }
330
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900331 /**
Robert Greenwalteaa84d52014-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 Greenwalt69aceaf2014-06-06 10:30:11 -0700335 * @return An unmodifiable {@link List} of {@link LinkAddress} for this link.
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900336 */
paulhucbbc3db2019-03-08 16:35:20 +0800337 public @NonNull List<LinkAddress> getLinkAddresses() {
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700338 return Collections.unmodifiableList(mLinkAddresses);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700339 }
340
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900341 /**
342 * Returns all the addresses on this link and all the links stacked above it.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700343 * @hide
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900344 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800345 @SystemApi
346 public @NonNull List<LinkAddress> getAllLinkAddresses() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900347 List<LinkAddress> addresses = new ArrayList<>(mLinkAddresses);
Lorenzo Colittie1b47422013-07-31 23:23:21 +0900348 for (LinkProperties stacked: mStackedLinks.values()) {
349 addresses.addAll(stacked.getAllLinkAddresses());
350 }
351 return addresses;
352 }
353
Lorenzo Colitti174782b2013-08-23 20:54:49 +0900354 /**
Robert Greenwalteaa84d52014-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 Colitti174782b2013-08-23 20:54:49 +0900360 */
paulhucbbc3db2019-03-08 16:35:20 +0800361 public void setLinkAddresses(@NonNull Collection<LinkAddress> addresses) {
Lorenzo Colitti174782b2013-08-23 20:54:49 +0900362 mLinkAddresses.clear();
363 for (LinkAddress address: addresses) {
364 addLinkAddress(address);
365 }
366 }
367
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700368 /**
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900369 * Adds the given {@link InetAddress} to the list of DNS servers, if not present.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700370 *
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700371 * @param dnsServer The {@link InetAddress} to add to the list of DNS servers.
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900372 * @return true if the DNS server was added, false if it was already present.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700373 * @hide
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700374 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900375 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800376 public boolean addDnsServer(@NonNull InetAddress dnsServer) {
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900377 if (dnsServer != null && !mDnses.contains(dnsServer)) {
378 mDnses.add(dnsServer);
379 return true;
380 }
381 return false;
382 }
383
384 /**
Erik Kline04612b02015-05-21 16:15:02 +0900385 * Removes the given {@link InetAddress} from the list of DNS servers.
386 *
387 * @param dnsServer The {@link InetAddress} to remove from the list of DNS servers.
388 * @return true if the DNS server was removed, false if it did not exist.
389 * @hide
390 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900391 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800392 public boolean removeDnsServer(@NonNull InetAddress dnsServer) {
paulhu1a407652019-03-22 16:35:06 +0800393 return mDnses.remove(dnsServer);
Erik Kline04612b02015-05-21 16:15:02 +0900394 }
395
396 /**
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900397 * Replaces the DNS servers in this {@code LinkProperties} with
398 * the given {@link Collection} of {@link InetAddress} objects.
399 *
Chalard Jean299d8562018-04-11 16:36:41 +0900400 * @param dnsServers The {@link Collection} of DNS servers to set in this object.
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900401 */
paulhucbbc3db2019-03-08 16:35:20 +0800402 public void setDnsServers(@NonNull Collection<InetAddress> dnsServers) {
Lorenzo Colitti131eb312014-06-24 00:34:39 +0900403 mDnses.clear();
404 for (InetAddress dnsServer: dnsServers) {
405 addDnsServer(dnsServer);
406 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700407 }
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700408
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700409 /**
Sreeram Ramachandran887d7b12014-06-03 18:41:43 -0700410 * Returns all the {@link InetAddress} for DNS servers on this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700411 *
Chalard Jeand51966a2018-06-07 13:27:00 +0900412 * @return An unmodifiable {@link List} of {@link InetAddress} for DNS servers on
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700413 * this link.
414 */
paulhucbbc3db2019-03-08 16:35:20 +0800415 public @NonNull List<InetAddress> getDnsServers() {
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700416 return Collections.unmodifiableList(mDnses);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700417 }
418
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700419 /**
dalyk7643abc2018-01-17 14:20:55 -0500420 * Set whether private DNS is currently in use on this network.
421 *
422 * @param usePrivateDns The private DNS state.
423 * @hide
424 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900425 @SystemApi
dalyk7643abc2018-01-17 14:20:55 -0500426 public void setUsePrivateDns(boolean usePrivateDns) {
427 mUsePrivateDns = usePrivateDns;
428 }
429
430 /**
431 * Returns whether private DNS is currently in use on this network. When
432 * private DNS is in use, applications must not send unencrypted DNS
433 * queries as doing so could reveal private user information. Furthermore,
434 * if private DNS is in use and {@link #getPrivateDnsServerName} is not
435 * {@code null}, DNS queries must be sent to the specified DNS server.
436 *
437 * @return {@code true} if private DNS is in use, {@code false} otherwise.
438 */
439 public boolean isPrivateDnsActive() {
440 return mUsePrivateDns;
441 }
442
443 /**
444 * Set the name of the private DNS server to which private DNS queries
445 * should be sent when in strict mode. This value should be {@code null}
446 * when private DNS is off or in opportunistic mode.
447 *
448 * @param privateDnsServerName The private DNS server name.
449 * @hide
450 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900451 @SystemApi
dalyk7643abc2018-01-17 14:20:55 -0500452 public void setPrivateDnsServerName(@Nullable String privateDnsServerName) {
453 mPrivateDnsServerName = privateDnsServerName;
454 }
455
456 /**
ruibin zhangca75bc82019-05-23 19:35:30 +0800457 * Set DHCP server address.
458 *
459 * @param serverAddress the server address to set.
460 */
461 public void setDhcpServerAddress(@Nullable Inet4Address serverAddress) {
462 mDhcpServerAddress = serverAddress;
463 }
464
465 /**
466 * Get DHCP server address
467 *
468 * @return The current DHCP server address.
469 */
470 public @Nullable Inet4Address getDhcpServerAddress() {
471 return mDhcpServerAddress;
472 }
473
474 /**
dalyk7643abc2018-01-17 14:20:55 -0500475 * Returns the private DNS server name that is in use. If not {@code null},
476 * private DNS is in strict mode. In this mode, applications should ensure
477 * that all DNS queries are encrypted and sent to this hostname and that
478 * queries are only sent if the hostname's certificate is valid. If
479 * {@code null} and {@link #isPrivateDnsActive} is {@code true}, private
480 * DNS is in opportunistic mode, and applications should ensure that DNS
481 * queries are encrypted and sent to a DNS server returned by
482 * {@link #getDnsServers}. System DNS will handle each of these cases
483 * correctly, but applications implementing their own DNS lookups must make
484 * sure to follow these requirements.
485 *
486 * @return The private DNS server name.
487 */
488 public @Nullable String getPrivateDnsServerName() {
489 return mPrivateDnsServerName;
490 }
491
492 /**
Chalard Jean299d8562018-04-11 16:36:41 +0900493 * Adds the given {@link InetAddress} to the list of validated private DNS servers,
494 * if not present. This is distinct from the server name in that these are actually
495 * resolved addresses.
496 *
497 * @param dnsServer The {@link InetAddress} to add to the list of validated private DNS servers.
498 * @return true if the DNS server was added, false if it was already present.
499 * @hide
500 */
paulhucbbc3db2019-03-08 16:35:20 +0800501 public boolean addValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) {
Chalard Jean299d8562018-04-11 16:36:41 +0900502 if (dnsServer != null && !mValidatedPrivateDnses.contains(dnsServer)) {
503 mValidatedPrivateDnses.add(dnsServer);
504 return true;
505 }
506 return false;
507 }
508
509 /**
510 * Removes the given {@link InetAddress} from the list of validated private DNS servers.
511 *
512 * @param dnsServer The {@link InetAddress} to remove from the list of validated private DNS
513 * servers.
514 * @return true if the DNS server was removed, false if it did not exist.
515 * @hide
516 */
paulhucbbc3db2019-03-08 16:35:20 +0800517 public boolean removeValidatedPrivateDnsServer(@NonNull InetAddress dnsServer) {
518 return mValidatedPrivateDnses.remove(dnsServer);
Chalard Jean299d8562018-04-11 16:36:41 +0900519 }
520
521 /**
522 * Replaces the validated private DNS servers in this {@code LinkProperties} with
523 * the given {@link Collection} of {@link InetAddress} objects.
524 *
525 * @param dnsServers The {@link Collection} of validated private DNS servers to set in this
526 * object.
527 * @hide
528 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900529 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800530 public void setValidatedPrivateDnsServers(@NonNull Collection<InetAddress> dnsServers) {
Chalard Jean299d8562018-04-11 16:36:41 +0900531 mValidatedPrivateDnses.clear();
532 for (InetAddress dnsServer: dnsServers) {
533 addValidatedPrivateDnsServer(dnsServer);
534 }
535 }
536
537 /**
538 * Returns all the {@link InetAddress} for validated private DNS servers on this link.
539 * These are resolved from the private DNS server name.
540 *
paulhucbbc3db2019-03-08 16:35:20 +0800541 * @return An unmodifiable {@link List} of {@link InetAddress} for validated private
Chalard Jean299d8562018-04-11 16:36:41 +0900542 * DNS servers on this link.
543 * @hide
544 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900545 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800546 public @NonNull List<InetAddress> getValidatedPrivateDnsServers() {
Chalard Jean299d8562018-04-11 16:36:41 +0900547 return Collections.unmodifiableList(mValidatedPrivateDnses);
548 }
549
550 /**
Hongshike2d7cf52018-06-28 20:42:19 +0900551 * Adds the given {@link InetAddress} to the list of PCSCF servers, if not present.
552 *
553 * @param pcscfServer The {@link InetAddress} to add to the list of PCSCF servers.
554 * @return true if the PCSCF server was added, false otherwise.
555 * @hide
556 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800557 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800558 public boolean addPcscfServer(@NonNull InetAddress pcscfServer) {
Hongshike2d7cf52018-06-28 20:42:19 +0900559 if (pcscfServer != null && !mPcscfs.contains(pcscfServer)) {
560 mPcscfs.add(pcscfServer);
561 return true;
562 }
563 return false;
564 }
565
566 /**
567 * Removes the given {@link InetAddress} from the list of PCSCF servers.
568 *
paulhucbbc3db2019-03-08 16:35:20 +0800569 * @param pcscfServer The {@link InetAddress} to remove from the list of PCSCF servers.
Hongshike2d7cf52018-06-28 20:42:19 +0900570 * @return true if the PCSCF server was removed, false otherwise.
571 * @hide
572 */
paulhucbbc3db2019-03-08 16:35:20 +0800573 public boolean removePcscfServer(@NonNull InetAddress pcscfServer) {
574 return mPcscfs.remove(pcscfServer);
Hongshike2d7cf52018-06-28 20:42:19 +0900575 }
576
577 /**
578 * Replaces the PCSCF servers in this {@code LinkProperties} with
579 * the given {@link Collection} of {@link InetAddress} objects.
580 *
paulhucbbc3db2019-03-08 16:35:20 +0800581 * @param pcscfServers The {@link Collection} of PCSCF servers to set in this object.
Hongshike2d7cf52018-06-28 20:42:19 +0900582 * @hide
583 */
Remi NGUYEN VANd9f75862019-01-23 21:35:52 +0900584 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800585 public void setPcscfServers(@NonNull Collection<InetAddress> pcscfServers) {
Hongshike2d7cf52018-06-28 20:42:19 +0900586 mPcscfs.clear();
587 for (InetAddress pcscfServer: pcscfServers) {
588 addPcscfServer(pcscfServer);
589 }
590 }
591
592 /**
593 * Returns all the {@link InetAddress} for PCSCF servers on this link.
594 *
595 * @return An unmodifiable {@link List} of {@link InetAddress} for PCSCF servers on
596 * this link.
597 * @hide
598 */
Remi NGUYEN VANd9f75862019-01-23 21:35:52 +0900599 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800600 public @NonNull List<InetAddress> getPcscfServers() {
Hongshike2d7cf52018-06-28 20:42:19 +0900601 return Collections.unmodifiableList(mPcscfs);
602 }
603
604 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700605 * Sets the DNS domain search path used on this link.
606 *
607 * @param domains A {@link String} listing in priority order the comma separated
608 * domains to search when resolving host names on this link.
609 */
paulhucbbc3db2019-03-08 16:35:20 +0800610 public void setDomains(@Nullable String domains) {
Robert Greenwaltcd277852012-11-09 10:52:27 -0800611 mDomains = domains;
612 }
613
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700614 /**
paulhucbbc3db2019-03-08 16:35:20 +0800615 * Get the DNS domains search path set for this link. May be {@code null} if not set.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700616 *
paulhucbbc3db2019-03-08 16:35:20 +0800617 * @return A {@link String} containing the comma separated domains to search when resolving host
618 * names on this link or {@code null}.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700619 */
paulhucbbc3db2019-03-08 16:35:20 +0800620 public @Nullable String getDomains() {
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700621 return mDomains;
622 }
623
624 /**
625 * Sets the Maximum Transmission Unit size to use on this link. This should not be used
626 * unless the system default (1500) is incorrect. Values less than 68 or greater than
627 * 10000 will be ignored.
628 *
629 * @param mtu The MTU to use for this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700630 */
sy.yun4aa73922013-09-02 05:24:09 +0900631 public void setMtu(int mtu) {
632 mMtu = mtu;
633 }
634
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700635 /**
636 * Gets any non-default MTU size set for this link. Note that if the default is being used
637 * this will return 0.
638 *
639 * @return The mtu value set for this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700640 */
sy.yun4aa73922013-09-02 05:24:09 +0900641 public int getMtu() {
642 return mMtu;
643 }
644
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700645 /**
646 * Sets the tcp buffers sizes to be used when this link is the system default.
647 * Should be of the form "rmem_min,rmem_def,rmem_max,wmem_min,wmem_def,wmem_max".
648 *
649 * @param tcpBufferSizes The tcp buffers sizes to use.
650 *
651 * @hide
652 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900653 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800654 public void setTcpBufferSizes(@Nullable String tcpBufferSizes) {
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700655 mTcpBufferSizes = tcpBufferSizes;
656 }
657
658 /**
paulhucbbc3db2019-03-08 16:35:20 +0800659 * Gets the tcp buffer sizes. May be {@code null} if not set.
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700660 *
paulhucbbc3db2019-03-08 16:35:20 +0800661 * @return the tcp buffer sizes to use when this link is the system default or {@code null}.
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700662 *
663 * @hide
664 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900665 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800666 public @Nullable String getTcpBufferSizes() {
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700667 return mTcpBufferSizes;
668 }
669
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800670 private RouteInfo routeWithInterface(RouteInfo route) {
671 return new RouteInfo(
672 route.getDestination(),
673 route.getGateway(),
Lorenzo Colitti21290342014-09-19 01:49:05 +0900674 mIfaceName,
Tyler Weare4314862019-12-05 14:55:30 -0800675 route.getType(),
676 route.getMtu());
677 }
678
junyulaia1493a52020-03-23 20:49:43 +0800679 private int findRouteIndexByRouteKey(RouteInfo route) {
Tyler Weare4314862019-12-05 14:55:30 -0800680 for (int i = 0; i < mRoutes.size(); i++) {
junyulaia1493a52020-03-23 20:49:43 +0800681 if (mRoutes.get(i).getRouteKey().equals(route.getRouteKey())) {
Tyler Weare4314862019-12-05 14:55:30 -0800682 return i;
683 }
684 }
685 return -1;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700686 }
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800687
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700688 /**
Tyler Weare4314862019-12-05 14:55:30 -0800689 * Adds a {@link RouteInfo} to this {@code LinkProperties}, if a {@link RouteInfo}
junyulaia1493a52020-03-23 20:49:43 +0800690 * with the same {@link RouteInfo.RouteKey} with different properties
691 * (e.g., different MTU), it will be updated. If the {@link RouteInfo} had an
692 * interface name set and that differs from the interface set for this
693 * {@code LinkProperties} an {@link IllegalArgumentException} will be thrown.
694 * The proper course is to add either un-named or properly named {@link RouteInfo}.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700695 *
696 * @param route A {@link RouteInfo} to add to this object.
Tyler Weare4314862019-12-05 14:55:30 -0800697 * @return {@code true} was added or updated, false otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700698 */
paulhucbbc3db2019-03-08 16:35:20 +0800699 public boolean addRoute(@NonNull RouteInfo route) {
700 String routeIface = route.getInterface();
701 if (routeIface != null && !routeIface.equals(mIfaceName)) {
702 throw new IllegalArgumentException(
703 "Route added with non-matching interface: " + routeIface
704 + " vs. " + mIfaceName);
705 }
706 route = routeWithInterface(route);
Tyler Weare4314862019-12-05 14:55:30 -0800707
junyulaia1493a52020-03-23 20:49:43 +0800708 int i = findRouteIndexByRouteKey(route);
Tyler Weare4314862019-12-05 14:55:30 -0800709 if (i == -1) {
710 // Route was not present. Add it.
paulhucbbc3db2019-03-08 16:35:20 +0800711 mRoutes.add(route);
712 return true;
Tyler Weare4314862019-12-05 14:55:30 -0800713 } else if (mRoutes.get(i).equals(route)) {
714 // Route was present and has same properties. Do nothing.
715 return false;
716 } else {
717 // Route was present and has different properties. Update it.
718 mRoutes.set(i, route);
719 return true;
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800720 }
Lorenzo Colitti36ddd9d2014-06-12 23:10:17 +0900721 }
722
723 /**
724 * Removes a {@link RouteInfo} from this {@code LinkProperties}, if present. The route must
725 * specify an interface and the interface must match the interface of this
726 * {@code LinkProperties}, or it will not be removed.
727 *
Tyler Weare4314862019-12-05 14:55:30 -0800728 * @param route A {@link RouteInfo} specifying the route to remove.
Lorenzo Colitti36ddd9d2014-06-12 23:10:17 +0900729 * @return {@code true} if the route was removed, {@code false} if it was not present.
730 *
731 * @hide
732 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +0900733 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800734 public boolean removeRoute(@NonNull RouteInfo route) {
735 return Objects.equals(mIfaceName, route.getInterface()) && mRoutes.remove(route);
Lorenzo Colitti73b97852013-03-08 11:30:39 -0800736 }
737
Lorenzo Colittic0803122013-03-07 10:59:25 -0800738 /**
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700739 * Returns all the {@link RouteInfo} set on this link.
740 *
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700741 * @return An unmodifiable {@link List} of {@link RouteInfo} for this link.
Lorenzo Colittic0803122013-03-07 10:59:25 -0800742 */
paulhucbbc3db2019-03-08 16:35:20 +0800743 public @NonNull List<RouteInfo> getRoutes() {
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700744 return Collections.unmodifiableList(mRoutes);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700745 }
746
Lorenzo Colittic0803122013-03-07 10:59:25 -0800747 /**
Rubin Xuffd77d82017-09-05 18:40:49 +0100748 * Make sure this LinkProperties instance contains routes that cover the local subnet
749 * of its link addresses. Add any route that is missing.
750 * @hide
751 */
752 public void ensureDirectlyConnectedRoutes() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900753 for (LinkAddress addr : mLinkAddresses) {
Rubin Xuffd77d82017-09-05 18:40:49 +0100754 addRoute(new RouteInfo(addr, null, mIfaceName));
755 }
756 }
757
758 /**
Lorenzo Colittic0803122013-03-07 10:59:25 -0800759 * Returns all the routes on this link and all the links stacked above it.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700760 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800761 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +0800762 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +0800763 public @NonNull List<RouteInfo> getAllRoutes() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900764 List<RouteInfo> routes = new ArrayList<>(mRoutes);
Lorenzo Colittic0803122013-03-07 10:59:25 -0800765 for (LinkProperties stacked: mStackedLinks.values()) {
766 routes.addAll(stacked.getAllRoutes());
767 }
Robert Greenwaltf3385082013-03-15 11:28:50 -0700768 return routes;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800769 }
770
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700771 /**
772 * Sets the recommended {@link ProxyInfo} to use on this link, or {@code null} for none.
773 * Note that Http Proxies are only a hint - the system recommends their use, but it does
774 * not enforce it and applications may ignore them.
775 *
Erik Klinea923dba2015-06-26 19:21:34 +0900776 * @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700777 */
paulhucbbc3db2019-03-08 16:35:20 +0800778 public void setHttpProxy(@Nullable ProxyInfo proxy) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700779 mHttpProxy = proxy;
780 }
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700781
782 /**
783 * Gets the recommended {@link ProxyInfo} (or {@code null}) set on this link.
784 *
paulhucbbc3db2019-03-08 16:35:20 +0800785 * @return The {@link ProxyInfo} set on this link or {@code null}.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700786 */
paulhucbbc3db2019-03-08 16:35:20 +0800787 public @Nullable ProxyInfo getHttpProxy() {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700788 return mHttpProxy;
789 }
790
Lorenzo Colittic0803122013-03-07 10:59:25 -0800791 /**
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900792 * Returns the NAT64 prefix in use on this link, if any.
793 *
paulhucbbc3db2019-03-08 16:35:20 +0800794 * @return the NAT64 prefix or {@code null}.
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900795 */
796 public @Nullable IpPrefix getNat64Prefix() {
797 return mNat64Prefix;
798 }
799
800 /**
801 * Sets the NAT64 prefix in use on this link.
802 *
803 * Currently, only 96-bit prefixes (i.e., where the 32-bit IPv4 address is at the end of the
paulhucbbc3db2019-03-08 16:35:20 +0800804 * 128-bit IPv6 address) are supported or {@code null} for no prefix.
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900805 *
806 * @param prefix the NAT64 prefix.
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900807 */
paulhucbbc3db2019-03-08 16:35:20 +0800808 public void setNat64Prefix(@Nullable IpPrefix prefix) {
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900809 if (prefix != null && prefix.getPrefixLength() != 96) {
810 throw new IllegalArgumentException("Only 96-bit prefixes are supported: " + prefix);
811 }
812 mNat64Prefix = prefix; // IpPrefix objects are immutable.
813 }
814
815 /**
Lorenzo Colittic0803122013-03-07 10:59:25 -0800816 * Adds a stacked link.
817 *
Chalard Jeand51966a2018-06-07 13:27:00 +0900818 * If there is already a stacked link with the same interface name as link,
Lorenzo Colittic0803122013-03-07 10:59:25 -0800819 * that link is replaced with link. Otherwise, link is added to the list
paulhucbbc3db2019-03-08 16:35:20 +0800820 * of stacked links.
Lorenzo Colittic0803122013-03-07 10:59:25 -0800821 *
822 * @param link The link to add.
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900823 * @return true if the link was stacked, false otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700824 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800825 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +0100826 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +0800827 public boolean addStackedLink(@NonNull LinkProperties link) {
828 if (link.getInterfaceName() != null) {
Lorenzo Colittic0803122013-03-07 10:59:25 -0800829 mStackedLinks.put(link.getInterfaceName(), link);
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900830 return true;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800831 }
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900832 return false;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800833 }
834
835 /**
836 * Removes a stacked link.
837 *
Lorenzo Colitti38258432014-10-20 11:08:03 +0900838 * If there is a stacked link with the given interface name, it is
Lorenzo Colittic0803122013-03-07 10:59:25 -0800839 * removed. Otherwise, nothing changes.
840 *
Lorenzo Colitti38258432014-10-20 11:08:03 +0900841 * @param iface The interface name of the link to remove.
Lorenzo Colitti09de4182013-08-08 11:00:12 +0900842 * @return true if the link was removed, false otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700843 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800844 */
paulhucbbc3db2019-03-08 16:35:20 +0800845 public boolean removeStackedLink(@NonNull String iface) {
846 LinkProperties removed = mStackedLinks.remove(iface);
847 return removed != null;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800848 }
849
850 /**
851 * Returns all the links stacked on top of this link.
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700852 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -0800853 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +0000854 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jeff Sharkey0aef9342014-08-11 15:22:51 -0700855 public @NonNull List<LinkProperties> getStackedLinks() {
856 if (mStackedLinks.isEmpty()) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900857 return Collections.emptyList();
Jeff Sharkey0aef9342014-08-11 15:22:51 -0700858 }
paulhucbbc3db2019-03-08 16:35:20 +0800859 final List<LinkProperties> stacked = new ArrayList<>();
Lorenzo Colittic0803122013-03-07 10:59:25 -0800860 for (LinkProperties link : mStackedLinks.values()) {
Jeff Sharkey0aef9342014-08-11 15:22:51 -0700861 stacked.add(new LinkProperties(link));
Lorenzo Colittic0803122013-03-07 10:59:25 -0800862 }
Robert Greenwalt69aceaf2014-06-06 10:30:11 -0700863 return Collections.unmodifiableList(stacked);
Lorenzo Colittic0803122013-03-07 10:59:25 -0800864 }
865
Robert Greenwalteaa84d52014-05-18 22:01:38 -0700866 /**
867 * Clears this object to its initial state.
868 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700869 public void clear() {
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900870 if (mParcelSensitiveFields) {
871 throw new UnsupportedOperationException(
872 "Cannot clear LinkProperties when parcelSensitiveFields is set");
873 }
874
Irfan Sherifffb7c9642010-10-01 16:08:28 -0700875 mIfaceName = null;
Wink Saville051a6642011-07-13 13:44:13 -0700876 mLinkAddresses.clear();
877 mDnses.clear();
dalyk7643abc2018-01-17 14:20:55 -0500878 mUsePrivateDns = false;
879 mPrivateDnsServerName = null;
Hongshike2d7cf52018-06-28 20:42:19 +0900880 mPcscfs.clear();
Robert Greenwaltcd277852012-11-09 10:52:27 -0800881 mDomains = null;
Wink Saville051a6642011-07-13 13:44:13 -0700882 mRoutes.clear();
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700883 mHttpProxy = null;
Lorenzo Colittic0803122013-03-07 10:59:25 -0800884 mStackedLinks.clear();
sy.yun4aa73922013-09-02 05:24:09 +0900885 mMtu = 0;
ruibin zhangca75bc82019-05-23 19:35:30 +0800886 mDhcpServerAddress = null;
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700887 mTcpBufferSizes = null;
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900888 mNat64Prefix = null;
Valentin Iftime9fa35092019-09-24 13:32:13 +0200889 mWakeOnLanSupported = false;
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900890 mCaptivePortalApiUrl = null;
891 mCaptivePortalData = null;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700892 }
893
894 /**
895 * Implement the Parcelable interface
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700896 */
897 public int describeContents() {
898 return 0;
899 }
900
Wink Saville7d857902010-08-27 11:15:18 -0700901 @Override
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -0700902 public String toString() {
Chalard Jeand51966a2018-06-07 13:27:00 +0900903 // Space as a separator, so no need for spaces at start/end of the individual fragments.
904 final StringJoiner resultJoiner = new StringJoiner(" ", "{", "}");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700905
Chalard Jeand51966a2018-06-07 13:27:00 +0900906 if (mIfaceName != null) {
907 resultJoiner.add("InterfaceName:");
908 resultJoiner.add(mIfaceName);
909 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700910
Chalard Jeand51966a2018-06-07 13:27:00 +0900911 resultJoiner.add("LinkAddresses: [");
912 if (!mLinkAddresses.isEmpty()) {
913 resultJoiner.add(TextUtils.join(",", mLinkAddresses));
914 }
915 resultJoiner.add("]");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700916
Chalard Jeand51966a2018-06-07 13:27:00 +0900917 resultJoiner.add("DnsAddresses: [");
918 if (!mDnses.isEmpty()) {
919 resultJoiner.add(TextUtils.join(",", mDnses));
920 }
921 resultJoiner.add("]");
dalyk7643abc2018-01-17 14:20:55 -0500922
Chalard Jeand51966a2018-06-07 13:27:00 +0900923 if (mUsePrivateDns) {
924 resultJoiner.add("UsePrivateDns: true");
925 }
926
Chalard Jeand3930f12018-06-07 13:28:09 +0900927 if (mPrivateDnsServerName != null) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900928 resultJoiner.add("PrivateDnsServerName:");
929 resultJoiner.add(mPrivateDnsServerName);
dalyk7643abc2018-01-17 14:20:55 -0500930 }
931
Hongshike2d7cf52018-06-28 20:42:19 +0900932 if (!mPcscfs.isEmpty()) {
933 resultJoiner.add("PcscfAddresses: [");
934 resultJoiner.add(TextUtils.join(",", mPcscfs));
935 resultJoiner.add("]");
936 }
937
Chalard Jean299d8562018-04-11 16:36:41 +0900938 if (!mValidatedPrivateDnses.isEmpty()) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900939 final StringJoiner validatedPrivateDnsesJoiner =
940 new StringJoiner(",", "ValidatedPrivateDnsAddresses: [", "]");
941 for (final InetAddress addr : mValidatedPrivateDnses) {
942 validatedPrivateDnsesJoiner.add(addr.getHostAddress());
Chalard Jean299d8562018-04-11 16:36:41 +0900943 }
Chalard Jeand51966a2018-06-07 13:27:00 +0900944 resultJoiner.add(validatedPrivateDnsesJoiner.toString());
Chalard Jean299d8562018-04-11 16:36:41 +0900945 }
946
Chalard Jeand51966a2018-06-07 13:27:00 +0900947 resultJoiner.add("Domains:");
948 resultJoiner.add(mDomains);
Robert Greenwaltcd277852012-11-09 10:52:27 -0800949
Chalard Jeand51966a2018-06-07 13:27:00 +0900950 resultJoiner.add("MTU:");
951 resultJoiner.add(Integer.toString(mMtu));
sy.yun4aa73922013-09-02 05:24:09 +0900952
Valentin Iftime9fa35092019-09-24 13:32:13 +0200953 if (mWakeOnLanSupported) {
954 resultJoiner.add("WakeOnLanSupported: true");
955 }
956
ruibin zhangca75bc82019-05-23 19:35:30 +0800957 if (mDhcpServerAddress != null) {
958 resultJoiner.add("ServerAddress:");
959 resultJoiner.add(mDhcpServerAddress.toString());
960 }
961
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +0900962 if (mCaptivePortalApiUrl != null) {
963 resultJoiner.add("CaptivePortalApiUrl: " + mCaptivePortalApiUrl);
964 }
965
966 if (mCaptivePortalData != null) {
967 resultJoiner.add("CaptivePortalData: " + mCaptivePortalData);
968 }
969
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700970 if (mTcpBufferSizes != null) {
Chalard Jeand51966a2018-06-07 13:27:00 +0900971 resultJoiner.add("TcpBufferSizes:");
972 resultJoiner.add(mTcpBufferSizes);
Robert Greenwaltdebf0e02014-08-06 12:00:25 -0700973 }
974
Chalard Jeand51966a2018-06-07 13:27:00 +0900975 resultJoiner.add("Routes: [");
976 if (!mRoutes.isEmpty()) {
977 resultJoiner.add(TextUtils.join(",", mRoutes));
978 }
979 resultJoiner.add("]");
Robert Greenwalta7dfbd32010-06-15 15:43:39 -0700980
Chalard Jeand51966a2018-06-07 13:27:00 +0900981 if (mHttpProxy != null) {
982 resultJoiner.add("HttpProxy:");
983 resultJoiner.add(mHttpProxy.toString());
984 }
985
Lorenzo Colitti981b34f2019-01-08 09:58:59 +0900986 if (mNat64Prefix != null) {
987 resultJoiner.add("Nat64Prefix:");
988 resultJoiner.add(mNat64Prefix.toString());
989 }
990
Chalard Jeand51966a2018-06-07 13:27:00 +0900991 final Collection<LinkProperties> stackedLinksValues = mStackedLinks.values();
992 if (!stackedLinksValues.isEmpty()) {
993 final StringJoiner stackedLinksJoiner = new StringJoiner(",", "Stacked: [", "]");
994 for (final LinkProperties lp : stackedLinksValues) {
995 stackedLinksJoiner.add("[ " + lp + " ]");
Lorenzo Colittic0803122013-03-07 10:59:25 -0800996 }
Chalard Jeand51966a2018-06-07 13:27:00 +0900997 resultJoiner.add(stackedLinksJoiner.toString());
Lorenzo Colittic0803122013-03-07 10:59:25 -0800998 }
Chalard Jeand51966a2018-06-07 13:27:00 +0900999
1000 return resultJoiner.toString();
Lorenzo Colittic0803122013-03-07 10:59:25 -08001001 }
1002
1003 /**
1004 * Returns true if this link has an IPv4 address.
1005 *
1006 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -07001007 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -08001008 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001009 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001010 public boolean hasIpv4Address() {
Lorenzo Colittic0803122013-03-07 10:59:25 -08001011 for (LinkAddress address : mLinkAddresses) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001012 if (address.getAddress() instanceof Inet4Address) {
1013 return true;
1014 }
Lorenzo Colittic0803122013-03-07 10:59:25 -08001015 }
1016 return false;
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001017 }
1018
Wink Saville051a6642011-07-13 13:44:13 -07001019 /**
paulhucbbc3db2019-03-08 16:35:20 +08001020 * For backward compatibility.
1021 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1022 * just yet.
1023 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
1024 * @hide
1025 */
1026 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1027 public boolean hasIPv4Address() {
1028 return hasIpv4Address();
1029 }
1030
1031 /**
Lorenzo Colitti05a505c2015-07-27 16:35:33 +09001032 * Returns true if this link or any of its stacked interfaces has an IPv4 address.
1033 *
1034 * @return {@code true} if there is an IPv4 address, {@code false} otherwise.
1035 */
paulhucbbc3db2019-03-08 16:35:20 +08001036 private boolean hasIpv4AddressOnInterface(String iface) {
Lorenzo Colitti28bb16c2015-07-30 23:41:43 +09001037 // mIfaceName can be null.
paulhucbbc3db2019-03-08 16:35:20 +08001038 return (Objects.equals(iface, mIfaceName) && hasIpv4Address())
1039 || (iface != null && mStackedLinks.containsKey(iface)
1040 && mStackedLinks.get(iface).hasIpv4Address());
Lorenzo Colitti05a505c2015-07-27 16:35:33 +09001041 }
1042
1043 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001044 * Returns true if this link has a global preferred IPv6 address.
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001045 *
Lorenzo Colittifc854692014-06-23 22:33:43 +09001046 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
Robert Greenwalt69aceaf2014-06-06 10:30:11 -07001047 * @hide
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001048 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001049 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001050 public boolean hasGlobalIpv6Address() {
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001051 for (LinkAddress address : mLinkAddresses) {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001052 if (address.getAddress() instanceof Inet6Address && address.isGlobalPreferred()) {
Lorenzo Colitti09de4182013-08-08 11:00:12 +09001053 return true;
1054 }
1055 }
1056 return false;
1057 }
1058
1059 /**
Rubin Xuab8cf302020-03-30 14:37:05 +01001060 * Returns true if this link has an IPv4 unreachable default route.
1061 *
1062 * @return {@code true} if there is an IPv4 unreachable default route, {@code false} otherwise.
1063 * @hide
1064 */
1065 public boolean hasIpv4UnreachableDefaultRoute() {
1066 for (RouteInfo r : mRoutes) {
1067 if (r.isIPv4UnreachableDefault()) {
1068 return true;
1069 }
1070 }
1071 return false;
1072 }
1073
1074 /**
paulhucbbc3db2019-03-08 16:35:20 +08001075 * For backward compatibility.
1076 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1077 * just yet.
1078 * @return {@code true} if there is a global preferred IPv6 address, {@code false} otherwise.
1079 * @hide
1080 */
1081 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1082 public boolean hasGlobalIPv6Address() {
1083 return hasGlobalIpv6Address();
1084 }
1085
1086 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001087 * Returns true if this link has an IPv4 default route.
1088 *
1089 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
1090 * @hide
1091 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +08001092 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001093 public boolean hasIpv4DefaultRoute() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001094 for (RouteInfo r : mRoutes) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001095 if (r.isIPv4Default()) {
1096 return true;
1097 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001098 }
1099 return false;
1100 }
1101
1102 /**
Rubin Xuab8cf302020-03-30 14:37:05 +01001103 * Returns true if this link has an IPv6 unreachable default route.
1104 *
1105 * @return {@code true} if there is an IPv6 unreachable default route, {@code false} otherwise.
1106 * @hide
1107 */
1108 public boolean hasIpv6UnreachableDefaultRoute() {
1109 for (RouteInfo r : mRoutes) {
1110 if (r.isIPv6UnreachableDefault()) {
1111 return true;
1112 }
1113 }
1114 return false;
1115 }
1116
1117 /**
paulhucbbc3db2019-03-08 16:35:20 +08001118 * For backward compatibility.
1119 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1120 * just yet.
1121 * @return {@code true} if there is an IPv4 default route, {@code false} otherwise.
1122 * @hide
1123 */
1124 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1125 public boolean hasIPv4DefaultRoute() {
1126 return hasIpv4DefaultRoute();
1127 }
1128
1129 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001130 * Returns true if this link has an IPv6 default route.
1131 *
1132 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
1133 * @hide
1134 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001135 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001136 public boolean hasIpv6DefaultRoute() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001137 for (RouteInfo r : mRoutes) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001138 if (r.isIPv6Default()) {
1139 return true;
1140 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001141 }
1142 return false;
1143 }
1144
1145 /**
paulhucbbc3db2019-03-08 16:35:20 +08001146 * For backward compatibility.
1147 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1148 * just yet.
1149 * @return {@code true} if there is an IPv6 default route, {@code false} otherwise.
1150 * @hide
1151 */
1152 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1153 public boolean hasIPv6DefaultRoute() {
1154 return hasIpv6DefaultRoute();
1155 }
1156
1157 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001158 * Returns true if this link has an IPv4 DNS server.
1159 *
1160 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
1161 * @hide
1162 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +08001163 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001164 public boolean hasIpv4DnsServer() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001165 for (InetAddress ia : mDnses) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001166 if (ia instanceof Inet4Address) {
1167 return true;
1168 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001169 }
1170 return false;
1171 }
1172
1173 /**
paulhucbbc3db2019-03-08 16:35:20 +08001174 * For backward compatibility.
1175 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1176 * just yet.
1177 * @return {@code true} if there is an IPv4 DNS server, {@code false} otherwise.
1178 * @hide
1179 */
1180 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1181 public boolean hasIPv4DnsServer() {
1182 return hasIpv4DnsServer();
1183 }
1184
1185 /**
Lorenzo Colittifc854692014-06-23 22:33:43 +09001186 * Returns true if this link has an IPv6 DNS server.
1187 *
1188 * @return {@code true} if there is an IPv6 DNS server, {@code false} otherwise.
1189 * @hide
1190 */
Aaron Huang8d6ae5d2019-10-02 20:07:38 +08001191 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001192 public boolean hasIpv6DnsServer() {
Lorenzo Colittifc854692014-06-23 22:33:43 +09001193 for (InetAddress ia : mDnses) {
Hugo Benichi875e9a42017-10-10 16:29:06 +09001194 if (ia instanceof Inet6Address) {
1195 return true;
1196 }
Lorenzo Colittifc854692014-06-23 22:33:43 +09001197 }
1198 return false;
1199 }
1200
1201 /**
paulhucbbc3db2019-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 there is an IPv6 DNS server, {@code false} otherwise.
1206 * @hide
1207 */
1208 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1209 public boolean hasIPv6DnsServer() {
1210 return hasIpv6DnsServer();
1211 }
1212
1213 /**
Hongshike2d7cf52018-06-28 20:42:19 +09001214 * Returns true if this link has an IPv4 PCSCF server.
1215 *
1216 * @return {@code true} if there is an IPv4 PCSCF server, {@code false} otherwise.
1217 * @hide
1218 */
paulhucbbc3db2019-03-08 16:35:20 +08001219 public boolean hasIpv4PcscfServer() {
Hongshike2d7cf52018-06-28 20:42:19 +09001220 for (InetAddress ia : mPcscfs) {
1221 if (ia instanceof Inet4Address) {
1222 return true;
1223 }
1224 }
1225 return false;
1226 }
1227
1228 /**
1229 * Returns true if this link has an IPv6 PCSCF server.
1230 *
1231 * @return {@code true} if there is an IPv6 PCSCF server, {@code false} otherwise.
1232 * @hide
1233 */
paulhucbbc3db2019-03-08 16:35:20 +08001234 public boolean hasIpv6PcscfServer() {
Hongshike2d7cf52018-06-28 20:42:19 +09001235 for (InetAddress ia : mPcscfs) {
1236 if (ia instanceof Inet6Address) {
1237 return true;
1238 }
1239 }
1240 return false;
1241 }
1242
1243 /**
Erik Kline8b023072014-10-24 21:50:20 +09001244 * Returns true if this link is provisioned for global IPv4 connectivity.
1245 * This requires an IP address, default route, and DNS server.
1246 *
1247 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Kline04612b02015-05-21 16:15:02 +09001248 * @hide
Erik Kline8b023072014-10-24 21:50:20 +09001249 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001250 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001251 public boolean isIpv4Provisioned() {
1252 return (hasIpv4Address()
1253 && hasIpv4DefaultRoute()
1254 && hasIpv4DnsServer());
Erik Kline8b023072014-10-24 21:50:20 +09001255 }
1256
1257 /**
1258 * Returns true if this link is provisioned for global IPv6 connectivity.
1259 * This requires an IP address, default route, and DNS server.
1260 *
1261 * @return {@code true} if the link is provisioned, {@code false} otherwise.
Erik Kline04612b02015-05-21 16:15:02 +09001262 * @hide
Erik Kline8b023072014-10-24 21:50:20 +09001263 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001264 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001265 public boolean isIpv6Provisioned() {
1266 return (hasGlobalIpv6Address()
1267 && hasIpv6DefaultRoute()
1268 && hasIpv6DnsServer());
Erik Kline8b023072014-10-24 21:50:20 +09001269 }
1270
1271 /**
paulhucbbc3db2019-03-08 16:35:20 +08001272 * For backward compatibility.
1273 * This was annotated with @UnsupportedAppUsage in P, so we can't remove the method completely
1274 * just yet.
1275 * @return {@code true} if the link is provisioned, {@code false} otherwise.
1276 * @hide
1277 */
1278 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
1279 public boolean isIPv6Provisioned() {
1280 return isIpv6Provisioned();
1281 }
1282
1283
1284 /**
Erik Kline8b023072014-10-24 21:50:20 +09001285 * Returns true if this link is provisioned for global connectivity,
1286 * for at least one Internet Protocol family.
Lorenzo Colittifc854692014-06-23 22:33:43 +09001287 *
1288 * @return {@code true} if the link is provisioned, {@code false} otherwise.
1289 * @hide
1290 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001291 @SystemApi
Lorenzo Colittifc854692014-06-23 22:33:43 +09001292 public boolean isProvisioned() {
paulhucbbc3db2019-03-08 16:35:20 +08001293 return (isIpv4Provisioned() || isIpv6Provisioned());
Lorenzo Colittifc854692014-06-23 22:33:43 +09001294 }
1295
1296 /**
Erik Klinea923dba2015-06-26 19:21:34 +09001297 * Evaluate whether the {@link InetAddress} is considered reachable.
1298 *
1299 * @return {@code true} if the given {@link InetAddress} is considered reachable,
1300 * {@code false} otherwise.
1301 * @hide
1302 */
Remi NGUYEN VAN109f8d52019-01-20 12:38:10 +09001303 @SystemApi
paulhucbbc3db2019-03-08 16:35:20 +08001304 public boolean isReachable(@NonNull InetAddress ip) {
Erik Klinea923dba2015-06-26 19:21:34 +09001305 final List<RouteInfo> allRoutes = getAllRoutes();
1306 // If we don't have a route to this IP address, it's not reachable.
1307 final RouteInfo bestRoute = RouteInfo.selectBestRoute(allRoutes, ip);
1308 if (bestRoute == null) {
1309 return false;
1310 }
1311
1312 // TODO: better source address evaluation for destination addresses.
1313
1314 if (ip instanceof Inet4Address) {
1315 // For IPv4, it suffices for now to simply have any address.
paulhucbbc3db2019-03-08 16:35:20 +08001316 return hasIpv4AddressOnInterface(bestRoute.getInterface());
Erik Klinea923dba2015-06-26 19:21:34 +09001317 } else if (ip instanceof Inet6Address) {
1318 if (ip.isLinkLocalAddress()) {
1319 // For now, just make sure link-local destinations have
1320 // scopedIds set, since transmits will generally fail otherwise.
1321 // TODO: verify it matches the ifindex of one of the interfaces.
1322 return (((Inet6Address)ip).getScopeId() != 0);
1323 } else {
1324 // For non-link-local destinations check that either the best route
1325 // is directly connected or that some global preferred address exists.
1326 // TODO: reconsider all cases (disconnected ULA networks, ...).
paulhucbbc3db2019-03-08 16:35:20 +08001327 return (!bestRoute.hasGateway() || hasGlobalIpv6Address());
Erik Klinea923dba2015-06-26 19:21:34 +09001328 }
1329 }
1330
1331 return false;
1332 }
1333
1334 /**
Wink Saville051a6642011-07-13 13:44:13 -07001335 * Compares this {@code LinkProperties} interface name against the target
1336 *
1337 * @param target LinkProperties to compare.
1338 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001339 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001340 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001341 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001342 public boolean isIdenticalInterfaceName(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001343 return LinkPropertiesUtils.isIdenticalInterfaceName(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001344 }
1345
1346 /**
ruibin zhangca75bc82019-05-23 19:35:30 +08001347 * Compares this {@code LinkProperties} DHCP server address against the target
1348 *
1349 * @param target LinkProperties to compare.
1350 * @return {@code true} if both are identical, {@code false} otherwise.
1351 * @hide
1352 */
1353 public boolean isIdenticalDhcpServerAddress(@NonNull LinkProperties target) {
1354 return Objects.equals(mDhcpServerAddress, target.mDhcpServerAddress);
1355 }
1356
1357 /**
Robert Greenwalt462e5702012-10-31 14:32:53 -07001358 * Compares this {@code LinkProperties} interface addresses against the target
Wink Saville051a6642011-07-13 13:44:13 -07001359 *
1360 * @param target LinkProperties to compare.
1361 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001362 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001363 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001364 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001365 public boolean isIdenticalAddresses(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001366 return LinkPropertiesUtils.isIdenticalAddresses(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001367 }
1368
1369 /**
1370 * Compares this {@code LinkProperties} DNS addresses against the target
1371 *
1372 * @param target LinkProperties to compare.
1373 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001374 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001375 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001376 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001377 public boolean isIdenticalDnses(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001378 return LinkPropertiesUtils.isIdenticalDnses(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001379 }
1380
1381 /**
dalyk7643abc2018-01-17 14:20:55 -05001382 * Compares this {@code LinkProperties} private DNS settings against the
1383 * target.
1384 *
1385 * @param target LinkProperties to compare.
1386 * @return {@code true} if both are identical, {@code false} otherwise.
1387 * @hide
1388 */
paulhucbbc3db2019-03-08 16:35:20 +08001389 public boolean isIdenticalPrivateDns(@NonNull LinkProperties target) {
dalyk7643abc2018-01-17 14:20:55 -05001390 return (isPrivateDnsActive() == target.isPrivateDnsActive()
1391 && TextUtils.equals(getPrivateDnsServerName(),
1392 target.getPrivateDnsServerName()));
1393 }
1394
1395 /**
Chalard Jean299d8562018-04-11 16:36:41 +09001396 * Compares this {@code LinkProperties} validated private DNS addresses against
1397 * the target
1398 *
1399 * @param target LinkProperties to compare.
1400 * @return {@code true} if both are identical, {@code false} otherwise.
1401 * @hide
1402 */
paulhucbbc3db2019-03-08 16:35:20 +08001403 public boolean isIdenticalValidatedPrivateDnses(@NonNull LinkProperties target) {
Chalard Jean299d8562018-04-11 16:36:41 +09001404 Collection<InetAddress> targetDnses = target.getValidatedPrivateDnsServers();
1405 return (mValidatedPrivateDnses.size() == targetDnses.size())
1406 ? mValidatedPrivateDnses.containsAll(targetDnses) : false;
1407 }
1408
1409 /**
Hongshike2d7cf52018-06-28 20:42:19 +09001410 * Compares this {@code LinkProperties} PCSCF addresses against the target
1411 *
1412 * @param target LinkProperties to compare.
1413 * @return {@code true} if both are identical, {@code false} otherwise.
1414 * @hide
1415 */
paulhucbbc3db2019-03-08 16:35:20 +08001416 public boolean isIdenticalPcscfs(@NonNull LinkProperties target) {
Hongshike2d7cf52018-06-28 20:42:19 +09001417 Collection<InetAddress> targetPcscfs = target.getPcscfServers();
1418 return (mPcscfs.size() == targetPcscfs.size()) ?
1419 mPcscfs.containsAll(targetPcscfs) : false;
1420 }
1421
1422 /**
Wink Saville051a6642011-07-13 13:44:13 -07001423 * Compares this {@code LinkProperties} Routes against the target
1424 *
1425 * @param target LinkProperties to compare.
1426 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001427 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001428 */
Mathew Inwoodc5b9bec2018-08-08 14:52:47 +01001429 @UnsupportedAppUsage
paulhucbbc3db2019-03-08 16:35:20 +08001430 public boolean isIdenticalRoutes(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001431 return LinkPropertiesUtils.isIdenticalRoutes(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001432 }
1433
1434 /**
1435 * Compares this {@code LinkProperties} HttpProxy against the target
1436 *
1437 * @param target LinkProperties to compare.
1438 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001439 * @hide
Wink Saville051a6642011-07-13 13:44:13 -07001440 */
Mathew Inwoodbdfc1fc2018-12-20 15:30:45 +00001441 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
paulhucbbc3db2019-03-08 16:35:20 +08001442 public boolean isIdenticalHttpProxy(@NonNull LinkProperties target) {
Aaron Huang0e1759b2019-12-17 00:33:18 +08001443 return LinkPropertiesUtils.isIdenticalHttpProxy(target, this);
Wink Saville051a6642011-07-13 13:44:13 -07001444 }
John Wang3e567d52011-04-04 12:35:42 -07001445
Lorenzo Colittic0803122013-03-07 10:59:25 -08001446 /**
1447 * Compares this {@code LinkProperties} stacked links against the target
1448 *
1449 * @param target LinkProperties to compare.
1450 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001451 * @hide
Lorenzo Colittic0803122013-03-07 10:59:25 -08001452 */
Mathew Inwoode1a17ba2020-11-04 09:29:36 +00001453 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
paulhucbbc3db2019-03-08 16:35:20 +08001454 public boolean isIdenticalStackedLinks(@NonNull LinkProperties target) {
Lorenzo Colitti89218e52013-04-01 10:47:43 +09001455 if (!mStackedLinks.keySet().equals(target.mStackedLinks.keySet())) {
Lorenzo Colittic0803122013-03-07 10:59:25 -08001456 return false;
1457 }
1458 for (LinkProperties stacked : mStackedLinks.values()) {
1459 // Hashtable values can never be null.
1460 String iface = stacked.getInterfaceName();
1461 if (!stacked.equals(target.mStackedLinks.get(iface))) {
1462 return false;
1463 }
1464 }
1465 return true;
1466 }
1467
sy.yun4aa73922013-09-02 05:24:09 +09001468 /**
1469 * Compares this {@code LinkProperties} MTU against the target
1470 *
Ying Wangcb5620b2013-09-06 22:53:16 -07001471 * @param target LinkProperties to compare.
sy.yun4aa73922013-09-02 05:24:09 +09001472 * @return {@code true} if both are identical, {@code false} otherwise.
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001473 * @hide
sy.yun4aa73922013-09-02 05:24:09 +09001474 */
paulhucbbc3db2019-03-08 16:35:20 +08001475 public boolean isIdenticalMtu(@NonNull LinkProperties target) {
sy.yun4aa73922013-09-02 05:24:09 +09001476 return getMtu() == target.getMtu();
1477 }
1478
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001479 /**
1480 * Compares this {@code LinkProperties} Tcp buffer sizes against the target.
1481 *
1482 * @param target LinkProperties to compare.
1483 * @return {@code true} if both are identical, {@code false} otherwise.
1484 * @hide
1485 */
paulhucbbc3db2019-03-08 16:35:20 +08001486 public boolean isIdenticalTcpBufferSizes(@NonNull LinkProperties target) {
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001487 return Objects.equals(mTcpBufferSizes, target.mTcpBufferSizes);
1488 }
1489
John Wang3e567d52011-04-04 12:35:42 -07001490 /**
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001491 * Compares this {@code LinkProperties} NAT64 prefix against the target.
1492 *
1493 * @param target LinkProperties to compare.
1494 * @return {@code true} if both are identical, {@code false} otherwise.
1495 * @hide
1496 */
paulhucbbc3db2019-03-08 16:35:20 +08001497 public boolean isIdenticalNat64Prefix(@NonNull LinkProperties target) {
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001498 return Objects.equals(mNat64Prefix, target.mNat64Prefix);
1499 }
1500
1501 /**
Valentin Iftime9fa35092019-09-24 13:32:13 +02001502 * Compares this {@code LinkProperties} WakeOnLan supported against the target.
1503 *
1504 * @param target LinkProperties to compare.
1505 * @return {@code true} if both are identical, {@code false} otherwise.
1506 * @hide
1507 */
1508 public boolean isIdenticalWakeOnLan(LinkProperties target) {
1509 return isWakeOnLanSupported() == target.isWakeOnLanSupported();
1510 }
1511
1512 /**
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001513 * Compares this {@code LinkProperties}'s CaptivePortalApiUrl against the target.
1514 *
1515 * @param target LinkProperties to compare.
1516 * @return {@code true} if both are identical, {@code false} otherwise.
1517 * @hide
1518 */
1519 public boolean isIdenticalCaptivePortalApiUrl(LinkProperties target) {
1520 return Objects.equals(mCaptivePortalApiUrl, target.mCaptivePortalApiUrl);
1521 }
1522
1523 /**
1524 * Compares this {@code LinkProperties}'s CaptivePortalData against the target.
1525 *
1526 * @param target LinkProperties to compare.
1527 * @return {@code true} if both are identical, {@code false} otherwise.
1528 * @hide
1529 */
1530 public boolean isIdenticalCaptivePortalData(LinkProperties target) {
1531 return Objects.equals(mCaptivePortalData, target.mCaptivePortalData);
1532 }
1533
1534 /**
Valentin Iftime9fa35092019-09-24 13:32:13 +02001535 * Set whether the network interface supports WakeOnLAN
1536 *
1537 * @param supported WakeOnLAN supported value
1538 *
1539 * @hide
1540 */
1541 public void setWakeOnLanSupported(boolean supported) {
1542 mWakeOnLanSupported = supported;
1543 }
1544
1545 /**
1546 * Returns whether the network interface supports WakeOnLAN
1547 *
1548 * @return {@code true} if interface supports WakeOnLAN, {@code false} otherwise.
1549 */
1550 public boolean isWakeOnLanSupported() {
1551 return mWakeOnLanSupported;
1552 }
1553
1554 /**
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001555 * Set the URL of the captive portal API endpoint to get more information about the network.
1556 * @hide
1557 */
1558 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001559 public void setCaptivePortalApiUrl(@Nullable Uri url) {
1560 mCaptivePortalApiUrl = url;
1561 }
1562
1563 /**
1564 * Get the URL of the captive portal API endpoint to get more information about the network.
1565 *
1566 * <p>This is null unless the application has
1567 * {@link android.Manifest.permission.NETWORK_SETTINGS} or
1568 * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions, and the network provided
1569 * the URL.
1570 * @hide
1571 */
1572 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001573 @Nullable
1574 public Uri getCaptivePortalApiUrl() {
1575 return mCaptivePortalApiUrl;
1576 }
1577
1578 /**
1579 * Set the CaptivePortalData obtained from the captive portal API (RFC7710bis).
1580 * @hide
1581 */
1582 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001583 public void setCaptivePortalData(@Nullable CaptivePortalData data) {
1584 mCaptivePortalData = data;
1585 }
1586
1587 /**
1588 * Get the CaptivePortalData obtained from the captive portal API (RFC7710bis).
1589 *
1590 * <p>This is null unless the application has
1591 * {@link android.Manifest.permission.NETWORK_SETTINGS} or
1592 * {@link NetworkStack#PERMISSION_MAINLINE_NETWORK_STACK} permissions.
1593 * @hide
1594 */
1595 @SystemApi
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001596 @Nullable
1597 public CaptivePortalData getCaptivePortalData() {
1598 return mCaptivePortalData;
1599 }
1600
1601 /**
John Wang3e567d52011-04-04 12:35:42 -07001602 * Compares this {@code LinkProperties} instance against the target
1603 * LinkProperties in {@code obj}. Two LinkPropertieses are equal if
1604 * all their fields are equal in values.
1605 *
1606 * For collection fields, such as mDnses, containsAll() is used to check
1607 * if two collections contains the same elements, independent of order.
1608 * There are two thoughts regarding containsAll()
1609 * 1. Duplicated elements. eg, (A, B, B) and (A, A, B) are equal.
1610 * 2. Worst case performance is O(n^2).
1611 *
1612 * @param obj the object to be tested for equality.
1613 * @return {@code true} if both objects are equal, {@code false} otherwise.
1614 */
Chalard Jeand51966a2018-06-07 13:27:00 +09001615 @Override
Roman Kalukiewicz384a8c62020-10-14 15:59:06 -07001616 public boolean equals(@Nullable Object obj) {
John Wang3e567d52011-04-04 12:35:42 -07001617 if (this == obj) return true;
1618
1619 if (!(obj instanceof LinkProperties)) return false;
1620
John Wang3e567d52011-04-04 12:35:42 -07001621 LinkProperties target = (LinkProperties) obj;
Chalard Jeand51966a2018-06-07 13:27:00 +09001622 /*
Robert Greenwalteaa84d52014-05-18 22:01:38 -07001623 * This method does not check that stacked interfaces are equal, because
1624 * stacked interfaces are not so much a property of the link as a
1625 * description of connections between links.
1626 */
dalyk7643abc2018-01-17 14:20:55 -05001627 return isIdenticalInterfaceName(target)
1628 && isIdenticalAddresses(target)
ruibin zhangca75bc82019-05-23 19:35:30 +08001629 && isIdenticalDhcpServerAddress(target)
dalyk7643abc2018-01-17 14:20:55 -05001630 && isIdenticalDnses(target)
1631 && isIdenticalPrivateDns(target)
Chalard Jean299d8562018-04-11 16:36:41 +09001632 && isIdenticalValidatedPrivateDnses(target)
Hongshike2d7cf52018-06-28 20:42:19 +09001633 && isIdenticalPcscfs(target)
dalyk7643abc2018-01-17 14:20:55 -05001634 && isIdenticalRoutes(target)
1635 && isIdenticalHttpProxy(target)
1636 && isIdenticalStackedLinks(target)
1637 && isIdenticalMtu(target)
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001638 && isIdenticalTcpBufferSizes(target)
Valentin Iftime9fa35092019-09-24 13:32:13 +02001639 && isIdenticalNat64Prefix(target)
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001640 && isIdenticalWakeOnLan(target)
1641 && isIdenticalCaptivePortalApiUrl(target)
1642 && isIdenticalCaptivePortalData(target);
Wink Saville051a6642011-07-13 13:44:13 -07001643 }
John Wang3e567d52011-04-04 12:35:42 -07001644
Wink Saville051a6642011-07-13 13:44:13 -07001645 /**
Chalard Jeand51966a2018-06-07 13:27:00 +09001646 * Generate hashcode based on significant fields
1647 *
John Wang3e567d52011-04-04 12:35:42 -07001648 * Equal objects must produce the same hash code, while unequal objects
1649 * may have the same hash codes.
1650 */
Chalard Jeand51966a2018-06-07 13:27:00 +09001651 @Override
John Wang3e567d52011-04-04 12:35:42 -07001652 public int hashCode() {
1653 return ((null == mIfaceName) ? 0 : mIfaceName.hashCode()
1654 + mLinkAddresses.size() * 31
1655 + mDnses.size() * 37
Chalard Jean299d8562018-04-11 16:36:41 +09001656 + mValidatedPrivateDnses.size() * 61
Robert Greenwaltcd277852012-11-09 10:52:27 -08001657 + ((null == mDomains) ? 0 : mDomains.hashCode())
Robert Greenwalt5a901292011-04-28 14:28:50 -07001658 + mRoutes.size() * 41
Lorenzo Colittic0803122013-03-07 10:59:25 -08001659 + ((null == mHttpProxy) ? 0 : mHttpProxy.hashCode())
sy.yun4aa73922013-09-02 05:24:09 +09001660 + mStackedLinks.hashCode() * 47)
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001661 + mMtu * 51
dalyk7643abc2018-01-17 14:20:55 -05001662 + ((null == mTcpBufferSizes) ? 0 : mTcpBufferSizes.hashCode())
1663 + (mUsePrivateDns ? 57 : 0)
ruibin zhangca75bc82019-05-23 19:35:30 +08001664 + ((null == mDhcpServerAddress) ? 0 : mDhcpServerAddress.hashCode())
Hongshike2d7cf52018-06-28 20:42:19 +09001665 + mPcscfs.size() * 67
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001666 + ((null == mPrivateDnsServerName) ? 0 : mPrivateDnsServerName.hashCode())
Valentin Iftime9fa35092019-09-24 13:32:13 +02001667 + Objects.hash(mNat64Prefix)
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001668 + (mWakeOnLanSupported ? 71 : 0)
1669 + Objects.hash(mCaptivePortalApiUrl, mCaptivePortalData);
John Wang3e567d52011-04-04 12:35:42 -07001670 }
1671
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001672 /**
1673 * Implement the Parcelable interface.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001674 */
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001675 public void writeToParcel(Parcel dest, int flags) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001676 dest.writeString(getInterfaceName());
Irfan Sherifffb7c9642010-10-01 16:08:28 -07001677 dest.writeInt(mLinkAddresses.size());
Chalard Jean299d8562018-04-11 16:36:41 +09001678 for (LinkAddress linkAddress : mLinkAddresses) {
Irfan Sherifffb7c9642010-10-01 16:08:28 -07001679 dest.writeParcelable(linkAddress, flags);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001680 }
Irfan Sherifffb7c9642010-10-01 16:08:28 -07001681
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001682 writeAddresses(dest, mDnses);
1683 writeAddresses(dest, mValidatedPrivateDnses);
dalyk7643abc2018-01-17 14:20:55 -05001684 dest.writeBoolean(mUsePrivateDns);
1685 dest.writeString(mPrivateDnsServerName);
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001686 writeAddresses(dest, mPcscfs);
Robert Greenwaltcd277852012-11-09 10:52:27 -08001687 dest.writeString(mDomains);
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001688 writeAddress(dest, mDhcpServerAddress);
sy.yun4aa73922013-09-02 05:24:09 +09001689 dest.writeInt(mMtu);
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001690 dest.writeString(mTcpBufferSizes);
Robert Greenwalt5a901292011-04-28 14:28:50 -07001691 dest.writeInt(mRoutes.size());
Chalard Jean299d8562018-04-11 16:36:41 +09001692 for (RouteInfo route : mRoutes) {
Robert Greenwalt5a901292011-04-28 14:28:50 -07001693 dest.writeParcelable(route, flags);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001694 }
Robert Greenwalt5c733972011-02-09 13:56:06 -08001695
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001696 if (mHttpProxy != null) {
1697 dest.writeByte((byte)1);
1698 dest.writeParcelable(mHttpProxy, flags);
1699 } else {
1700 dest.writeByte((byte)0);
1701 }
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001702 dest.writeParcelable(mNat64Prefix, 0);
1703
Chalard Jeand51966a2018-06-07 13:27:00 +09001704 ArrayList<LinkProperties> stackedLinks = new ArrayList<>(mStackedLinks.values());
Lorenzo Colittic0803122013-03-07 10:59:25 -08001705 dest.writeList(stackedLinks);
Valentin Iftime9fa35092019-09-24 13:32:13 +02001706
1707 dest.writeBoolean(mWakeOnLanSupported);
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001708 dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalApiUrl : null, 0);
1709 dest.writeParcelable(mParcelSensitiveFields ? mCaptivePortalData : null, 0);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001710 }
1711
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001712 private static void writeAddresses(@NonNull Parcel dest, @NonNull List<InetAddress> list) {
1713 dest.writeInt(list.size());
1714 for (InetAddress d : list) {
1715 writeAddress(dest, d);
1716 }
1717 }
1718
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001719 private static void writeAddress(@NonNull Parcel dest, @Nullable InetAddress addr) {
1720 byte[] addressBytes = (addr == null ? null : addr.getAddress());
1721 dest.writeByteArray(addressBytes);
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001722 if (addr instanceof Inet6Address) {
1723 final Inet6Address v6Addr = (Inet6Address) addr;
1724 final boolean hasScopeId = v6Addr.getScopeId() != 0;
1725 dest.writeBoolean(hasScopeId);
1726 if (hasScopeId) dest.writeInt(v6Addr.getScopeId());
1727 }
1728 }
1729
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001730 @Nullable
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001731 private static InetAddress readAddress(@NonNull Parcel p) throws UnknownHostException {
1732 final byte[] addr = p.createByteArray();
Lorenzo Colitti279a1d62020-01-06 19:43:59 +09001733 if (addr == null) return null;
1734
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001735 if (addr.length == INET6_ADDR_LENGTH) {
1736 final boolean hasScopeId = p.readBoolean();
1737 final int scopeId = hasScopeId ? p.readInt() : 0;
1738 return Inet6Address.getByAddress(null /* host */, addr, scopeId);
1739 }
1740
1741 return InetAddress.getByAddress(addr);
1742 }
1743
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001744 /**
1745 * Implement the Parcelable interface.
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001746 */
Jeff Sharkeyf8525282019-02-28 12:06:45 -07001747 public static final @android.annotation.NonNull Creator<LinkProperties> CREATOR =
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001748 new Creator<LinkProperties>() {
1749 public LinkProperties createFromParcel(Parcel in) {
1750 LinkProperties netProp = new LinkProperties();
Robert Greenwalt462e5702012-10-31 14:32:53 -07001751
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001752 String iface = in.readString();
1753 if (iface != null) {
Robert Greenwalt462e5702012-10-31 14:32:53 -07001754 netProp.setInterfaceName(iface);
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001755 }
1756 int addressCount = in.readInt();
Chalard Jean299d8562018-04-11 16:36:41 +09001757 for (int i = 0; i < addressCount; i++) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001758 netProp.addLinkAddress(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001759 }
1760 addressCount = in.readInt();
Chalard Jean299d8562018-04-11 16:36:41 +09001761 for (int i = 0; i < addressCount; i++) {
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001762 try {
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001763 netProp.addDnsServer(readAddress(in));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001764 } catch (UnknownHostException e) { }
1765 }
Chalard Jean299d8562018-04-11 16:36:41 +09001766 addressCount = in.readInt();
1767 for (int i = 0; i < addressCount; i++) {
1768 try {
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001769 netProp.addValidatedPrivateDnsServer(readAddress(in));
Chalard Jean299d8562018-04-11 16:36:41 +09001770 } catch (UnknownHostException e) { }
1771 }
dalyk7643abc2018-01-17 14:20:55 -05001772 netProp.setUsePrivateDns(in.readBoolean());
1773 netProp.setPrivateDnsServerName(in.readString());
Hongshike2d7cf52018-06-28 20:42:19 +09001774 addressCount = in.readInt();
1775 for (int i = 0; i < addressCount; i++) {
1776 try {
Remi NGUYEN VAN3a59a922019-12-18 14:47:06 +09001777 netProp.addPcscfServer(readAddress(in));
Hongshike2d7cf52018-06-28 20:42:19 +09001778 } catch (UnknownHostException e) { }
1779 }
Robert Greenwaltcd277852012-11-09 10:52:27 -08001780 netProp.setDomains(in.readString());
ruibin zhangca75bc82019-05-23 19:35:30 +08001781 try {
1782 netProp.setDhcpServerAddress((Inet4Address) InetAddress
1783 .getByAddress(in.createByteArray()));
1784 } catch (UnknownHostException e) { }
sy.yun4aa73922013-09-02 05:24:09 +09001785 netProp.setMtu(in.readInt());
Robert Greenwaltdebf0e02014-08-06 12:00:25 -07001786 netProp.setTcpBufferSizes(in.readString());
Robert Greenwalt5c733972011-02-09 13:56:06 -08001787 addressCount = in.readInt();
Chalard Jean299d8562018-04-11 16:36:41 +09001788 for (int i = 0; i < addressCount; i++) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001789 netProp.addRoute(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001790 }
1791 if (in.readByte() == 1) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001792 netProp.setHttpProxy(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001793 }
Lorenzo Colitti981b34f2019-01-08 09:58:59 +09001794 netProp.setNat64Prefix(in.readParcelable(null));
Lorenzo Colittic0803122013-03-07 10:59:25 -08001795 ArrayList<LinkProperties> stackedLinks = new ArrayList<LinkProperties>();
1796 in.readList(stackedLinks, LinkProperties.class.getClassLoader());
1797 for (LinkProperties stackedLink: stackedLinks) {
1798 netProp.addStackedLink(stackedLink);
1799 }
Valentin Iftime9fa35092019-09-24 13:32:13 +02001800 netProp.setWakeOnLanSupported(in.readBoolean());
Remi NGUYEN VAN0a65eed2019-12-17 16:45:42 +09001801
1802 netProp.setCaptivePortalApiUrl(in.readParcelable(null));
1803 netProp.setCaptivePortalData(in.readParcelable(null));
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001804 return netProp;
1805 }
1806
Robert Greenwalt1f1bcfe2010-08-30 10:56:47 -07001807 public LinkProperties[] newArray(int size) {
1808 return new LinkProperties[size];
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001809 }
1810 };
w19976e714f1d2014-08-05 15:18:11 -07001811
Chalard Jean299d8562018-04-11 16:36:41 +09001812 /**
1813 * Check the valid MTU range based on IPv4 or IPv6.
1814 * @hide
1815 */
1816 public static boolean isValidMtu(int mtu, boolean ipv6) {
1817 if (ipv6) {
Chalard Jeand51966a2018-06-07 13:27:00 +09001818 return mtu >= MIN_MTU_V6 && mtu <= MAX_MTU;
Chalard Jean299d8562018-04-11 16:36:41 +09001819 } else {
Chalard Jeand51966a2018-06-07 13:27:00 +09001820 return mtu >= MIN_MTU && mtu <= MAX_MTU;
w19976e714f1d2014-08-05 15:18:11 -07001821 }
Chalard Jean299d8562018-04-11 16:36:41 +09001822 }
Robert Greenwalta7dfbd32010-06-15 15:43:39 -07001823}