Merge "Ignore ipv6 tx traffic on clat uid."
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index 4714587..61d5a91 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -27,6 +27,7 @@
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
+import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.os.Handler;
@@ -187,13 +188,19 @@
* is for a network to which the connectivity manager was failing over
* following a disconnect on another network.
* Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public static final String EXTRA_IS_FAILOVER = "isFailover";
/**
* The lookup key for a {@link NetworkInfo} object. This is supplied when
* there is another network that it may be possible to connect to. Retrieve with
* {@link android.content.Intent#getParcelableExtra(String)}.
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public static final String EXTRA_OTHER_NETWORK_INFO = "otherNetwork";
/**
* The lookup key for a boolean that indicates whether there is a
@@ -214,7 +221,10 @@
* may be passed up from the lower networking layers, and its
* meaning may be specific to a particular network type. Retrieve
* it with {@link android.content.Intent#getStringExtra(String)}.
+ *
+ * @deprecated See {@link NetworkInfo#getExtraInfo()}.
*/
+ @Deprecated
public static final String EXTRA_EXTRA_INFO = "extraInfo";
/**
* The lookup key for an int that provides information about
@@ -895,7 +905,9 @@
*
* @return a {@link NetworkInfo} object for the current default network
* or {@code null} if no default network is currently active
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public NetworkInfo getActiveNetworkInfo() {
try {
@@ -1079,7 +1091,9 @@
* @return a {@link NetworkInfo} object for the requested
* network or {@code null} if the {@code Network}
* is not valid.
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
@RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
public NetworkInfo getNetworkInfo(Network network) {
return getNetworkInfoForUid(network, Process.myUid(), false);
@@ -2755,7 +2769,7 @@
}
/** {@hide} */
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void unregisterNetworkFactory(Messenger messenger) {
try {
mService.unregisterNetworkFactory(messenger);
diff --git a/core/java/android/net/InetAddresses.java b/core/java/android/net/InetAddresses.java
new file mode 100644
index 0000000..8e6c69a
--- /dev/null
+++ b/core/java/android/net/InetAddresses.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.net;
+
+import libcore.net.InetAddressUtils;
+
+import java.net.InetAddress;
+
+/**
+ * Utility methods for {@link InetAddress} implementations.
+ */
+public class InetAddresses {
+
+ private InetAddresses() {}
+
+ /**
+ * Checks to see if the {@code address} is a numeric address (such as {@code "192.0.2.1"} or
+ * {@code "2001:db8::1:2"}).
+ *
+ * <p>A numeric address is either an IPv4 address containing exactly 4 decimal numbers or an
+ * IPv6 numeric address. IPv4 addresses that consist of either hexadecimal or octal digits or
+ * do not have exactly 4 numbers are not treated as numeric.
+ *
+ * <p>This method will never do a DNS lookup.
+ *
+ * @param address the address to parse.
+ * @return true if the supplied address is numeric, false otherwise.
+ */
+ public static boolean isNumericAddress(String address) {
+ return InetAddressUtils.isNumericAddress(address);
+ }
+
+ /**
+ * Returns an InetAddress corresponding to the given numeric address (such
+ * as {@code "192.168.0.1"} or {@code "2001:4860:800d::68"}).
+ *
+ * <p>See {@link #isNumericAddress(String)} (String)} for a definition as to what constitutes a
+ * numeric address.
+ *
+ * <p>This method will never do a DNS lookup.
+ *
+ * @param address the address to parse, must be numeric.
+ * @return an {@link InetAddress} instance corresponding to the address.
+ * @throws IllegalArgumentException if {@code address} is not a numeric address.
+ */
+ public static InetAddress parseNumericAddress(String address) {
+ return InetAddressUtils.parseNumericAddress(address);
+ }
+}
diff --git a/core/java/android/net/LinkAddress.java b/core/java/android/net/LinkAddress.java
index 77562db..b40f15a 100644
--- a/core/java/android/net/LinkAddress.java
+++ b/core/java/android/net/LinkAddress.java
@@ -27,6 +27,7 @@
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Pair;
@@ -56,13 +57,13 @@
/**
* IPv4 or IPv6 address.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private InetAddress address;
/**
* Prefix length.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private int prefixLength;
/**
diff --git a/core/java/android/net/LinkProperties.java b/core/java/android/net/LinkProperties.java
index 1b9a66c..3a79206 100644
--- a/core/java/android/net/LinkProperties.java
+++ b/core/java/android/net/LinkProperties.java
@@ -18,7 +18,9 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.text.TextUtils;
@@ -49,7 +51,7 @@
*/
public final class LinkProperties implements Parcelable {
// The interface described by the network link.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private String mIfaceName;
private ArrayList<LinkAddress> mLinkAddresses = new ArrayList<>();
private ArrayList<InetAddress> mDnses = new ArrayList<>();
@@ -161,7 +163,7 @@
/**
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public LinkProperties() {
}
@@ -195,7 +197,7 @@
* @param iface The name of the network interface used for this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setInterfaceName(String iface) {
mIfaceName = iface;
ArrayList<RouteInfo> newRoutes = new ArrayList<>(mRoutes.size());
@@ -346,7 +348,7 @@
* object.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setLinkAddresses(Collection<LinkAddress> addresses) {
mLinkAddresses.clear();
for (LinkAddress address: addresses) {
@@ -392,7 +394,7 @@
* @param dnsServers The {@link Collection} of DNS servers to set in this object.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setDnsServers(Collection<InetAddress> dnsServers) {
mDnses.clear();
for (InetAddress dnsServer: dnsServers) {
@@ -529,7 +531,7 @@
* domains to search when resolving host names on this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setDomains(String domains) {
mDomains = domains;
}
@@ -552,7 +554,7 @@
* @param mtu The MTU to use for this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setMtu(int mtu) {
mMtu = mtu;
}
@@ -562,9 +564,7 @@
* this will return 0.
*
* @return The mtu value set for this link.
- * @hide
*/
- @UnsupportedAppUsage
public int getMtu() {
return mMtu;
}
@@ -613,7 +613,7 @@
*
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public boolean addRoute(RouteInfo route) {
if (route != null) {
String routeIface = route.getInterface();
@@ -688,7 +688,7 @@
* @param proxy A {@link ProxyInfo} defining the HTTP Proxy to use on this link.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void setHttpProxy(ProxyInfo proxy) {
mHttpProxy = proxy;
}
@@ -760,7 +760,7 @@
* Clears this object to its initial state.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public void clear() {
mIfaceName = null;
mLinkAddresses.clear();
@@ -1137,7 +1137,7 @@
* @return {@code true} if both are identical, {@code false} otherwise.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public boolean isIdenticalHttpProxy(LinkProperties target) {
return getHttpProxy() == null ? target.getHttpProxy() == null :
getHttpProxy().equals(target.getHttpProxy());
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 114b423..99bfc14 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -19,6 +19,7 @@
import android.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.net.ConnectivityManager.PacketKeepalive;
+import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
@@ -352,7 +353,7 @@
/**
* Called by the bearer code when it has new NetworkInfo data.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public void sendNetworkInfo(NetworkInfo networkInfo) {
queueOrSendMessage(EVENT_NETWORK_INFO_CHANGED, new NetworkInfo(networkInfo));
}
diff --git a/core/java/android/net/NetworkCapabilities.java b/core/java/android/net/NetworkCapabilities.java
index 0c44a56..1b44c92 100644
--- a/core/java/android/net/NetworkCapabilities.java
+++ b/core/java/android/net/NetworkCapabilities.java
@@ -931,7 +931,7 @@
* Returns a transport-specific information container. The application may cast this
* container to a concrete sub-class based on its knowledge of the network request. The
* application should be able to deal with a {@code null} return value or an invalid case,
- * e.g. use {@code instanceof} operation to verify expected type.
+ * e.g. use {@code instanceof} operator to verify expected type.
*
* @return A concrete implementation of the {@link TransportInfo} class or null if not
* available for the network.
@@ -1017,7 +1017,7 @@
* @return The bearer-specific signal strength.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public int getSignalStrength() {
return mSignalStrength;
}
@@ -1467,7 +1467,7 @@
appendStringRepresentationOfBitMaskToStringBuilder(sb, mNetworkCapabilities,
NetworkCapabilities::capabilityNameOf, "&");
}
- if (0 != mNetworkCapabilities) {
+ if (0 != mUnwantedNetworkCapabilities) {
sb.append(" Unwanted: ");
appendStringRepresentationOfBitMaskToStringBuilder(sb, mUnwantedNetworkCapabilities,
NetworkCapabilities::capabilityNameOf, "&");
diff --git a/core/java/android/net/NetworkInfo.java b/core/java/android/net/NetworkInfo.java
index 1a1d2d3..89d9961 100644
--- a/core/java/android/net/NetworkInfo.java
+++ b/core/java/android/net/NetworkInfo.java
@@ -28,7 +28,20 @@
* Describes the status of a network interface.
* <p>Use {@link ConnectivityManager#getActiveNetworkInfo()} to get an instance that represents
* the current network connection.
+ *
+ * @deprecated Callers should instead use the {@link ConnectivityManager.NetworkCallback} API to
+ * learn about connectivity changes, or switch to use
+ * {@link ConnectivityManager#getNetworkCapabilities} or
+ * {@link ConnectivityManager#getLinkProperties} to get information synchronously. Keep
+ * in mind that while callbacks are guaranteed to be called for every event in order,
+ * synchronous calls have no such constraints, and as such it is unadvisable to use the
+ * synchronous methods inside the callbacks as they will often not offer a view of
+ * networking that is consistent (that is: they may return a past or a future state with
+ * respect to the event being processed by the callback). Instead, callers are advised
+ * to only use the arguments of the callbacks, possibly memorizing the specific bits of
+ * information they need to keep from one callback to another.
*/
+@Deprecated
public class NetworkInfo implements Parcelable {
/**
@@ -52,7 +65,10 @@
* <tr><td><code>FAILED</code></td><td><code>DISCONNECTED</code></td></tr>
* <tr><td><code>BLOCKED</code></td><td><code>DISCONNECTED</code></td></tr>
* </table>
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public enum State {
CONNECTING, CONNECTED, SUSPENDED, DISCONNECTING, DISCONNECTED, UNKNOWN
}
@@ -61,7 +77,10 @@
* The fine-grained state of a network connection. This level of detail
* is probably of interest to few applications. Most should use
* {@link android.net.NetworkInfo.State State} instead.
+ *
+ * @deprecated See {@link NetworkInfo}.
*/
+ @Deprecated
public enum DetailedState {
/** Ready to start data connection setup. */
IDLE,
@@ -463,8 +482,10 @@
* Set the extraInfo field.
* @param extraInfo an optional {@code String} providing addditional network state
* information passed up from the lower networking layers.
+ * @deprecated See {@link NetworkInfo#getExtraInfo}.
* @hide
*/
+ @Deprecated
public void setExtraInfo(String extraInfo) {
synchronized (this) {
this.mExtraInfo = extraInfo;
@@ -488,7 +509,10 @@
* Report the extra information about the network state, if any was
* provided by the lower networking layers.
* @return the extra information, or null if not available
+ * @deprecated Use other services e.g. WifiManager to get additional information passed up from
+ * the lower networking layers.
*/
+ @Deprecated
public String getExtraInfo() {
synchronized (this) {
return mExtraInfo;
diff --git a/core/java/android/net/NetworkRequest.java b/core/java/android/net/NetworkRequest.java
index 04b6b44..9508217 100644
--- a/core/java/android/net/NetworkRequest.java
+++ b/core/java/android/net/NetworkRequest.java
@@ -17,9 +17,11 @@
package android.net;
import android.annotation.NonNull;
+import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
import android.net.NetworkCapabilities.Transport;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Process;
@@ -56,7 +58,7 @@
* Causes CONNECTIVITY_ACTION broadcasts to be sent.
* @hide
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
public final int legacyType;
/**
@@ -344,7 +346,7 @@
* @param signalStrength the bearer-specific signal strength.
* @hide
*/
- @UnsupportedAppUsage
+ @SystemApi
public Builder setSignalStrength(int signalStrength) {
mNetworkCapabilities.setSignalStrength(signalStrength);
return this;
diff --git a/core/java/android/net/NetworkUtils.java b/core/java/android/net/NetworkUtils.java
index 34e9476..c0aa4a6 100644
--- a/core/java/android/net/NetworkUtils.java
+++ b/core/java/android/net/NetworkUtils.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.util.Log;
import android.util.Pair;
@@ -294,8 +295,10 @@
* @param addrString
* @return the InetAddress
* @hide
+ * @deprecated Use {@link InetAddresses#parseNumericAddress(String)}, if possible.
*/
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+ @Deprecated
public static InetAddress numericToInetAddress(String addrString)
throws IllegalArgumentException {
return InetAddress.parseNumericAddress(addrString);
diff --git a/core/java/android/net/RouteInfo.java b/core/java/android/net/RouteInfo.java
index 3e73d3d..37ab9ff 100644
--- a/core/java/android/net/RouteInfo.java
+++ b/core/java/android/net/RouteInfo.java
@@ -17,6 +17,7 @@
package android.net;
import android.annotation.UnsupportedAppUsage;
+import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
@@ -81,7 +82,7 @@
// Derived data members.
// TODO: remove these.
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private final boolean mIsHost;
private final boolean mHasGateway;
@@ -265,7 +266,7 @@
}
}
- @UnsupportedAppUsage
+ @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
private boolean isHost() {
return (mDestination.getAddress() instanceof Inet4Address &&
mDestination.getPrefixLength() == 32) ||
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 14503f9..66ceae4 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -902,6 +902,7 @@
// Listen to package add and removal events for all users.
intentFilter = new IntentFilter();
intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
+ intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED);
intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
intentFilter.addDataScheme("package");
mContext.registerReceiverAsUser(
@@ -1967,6 +1968,7 @@
void systemReady() {
mProxyTracker.loadGlobalProxy();
registerNetdEventCallback();
+ mTethering.systemReady();
synchronized (this) {
mSystemReady = true;
@@ -4203,12 +4205,46 @@
mPermissionMonitor.onPackageAdded(packageName, uid);
}
- private void onPackageRemoved(String packageName, int uid) {
+ private void onPackageReplaced(String packageName, int uid) {
+ if (TextUtils.isEmpty(packageName) || uid < 0) {
+ Slog.wtf(TAG, "Invalid package in onPackageReplaced: " + packageName + " | " + uid);
+ return;
+ }
+ final int userId = UserHandle.getUserId(uid);
+ synchronized (mVpns) {
+ final Vpn vpn = mVpns.get(userId);
+ if (vpn == null) {
+ return;
+ }
+ // Legacy always-on VPN won't be affected since the package name is not set.
+ if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName)) {
+ Slog.d(TAG, "Restarting always-on VPN package " + packageName + " for user "
+ + userId);
+ vpn.startAlwaysOnVpn();
+ }
+ }
+ }
+
+ private void onPackageRemoved(String packageName, int uid, boolean isReplacing) {
if (TextUtils.isEmpty(packageName) || uid < 0) {
Slog.wtf(TAG, "Invalid package in onPackageRemoved: " + packageName + " | " + uid);
return;
}
mPermissionMonitor.onPackageRemoved(uid);
+
+ final int userId = UserHandle.getUserId(uid);
+ synchronized (mVpns) {
+ final Vpn vpn = mVpns.get(userId);
+ if (vpn == null) {
+ return;
+ }
+ // Legacy always-on VPN won't be affected since the package name is not set.
+ if (TextUtils.equals(vpn.getAlwaysOnPackage(), packageName) && !isReplacing) {
+ Slog.d(TAG, "Removing always-on VPN package " + packageName + " for user "
+ + userId);
+ vpn.setAlwaysOnPackage(null, false);
+ }
+ }
}
private void onUserUnlocked(int userId) {
@@ -4245,8 +4281,12 @@
onUserUnlocked(userId);
} else if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
onPackageAdded(packageName, uid);
+ } else if (Intent.ACTION_PACKAGE_REPLACED.equals(action)) {
+ onPackageReplaced(packageName, uid);
} else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
- onPackageRemoved(packageName, uid);
+ final boolean isReplacing = intent.getBooleanExtra(
+ Intent.EXTRA_REPLACING, false);
+ onPackageRemoved(packageName, uid, isReplacing);
}
}
};
@@ -5674,7 +5714,6 @@
// This should never fail. Specifying an already in use NetID will cause failure.
if (networkAgent.isVPN()) {
mNMS.createVirtualNetwork(networkAgent.network.netId,
- !networkAgent.linkProperties.getDnsServers().isEmpty(),
(networkAgent.networkMisc == null ||
!networkAgent.networkMisc.allowBypass));
} else {
diff --git a/services/core/java/com/android/server/connectivity/ProxyTracker.java b/services/core/java/com/android/server/connectivity/ProxyTracker.java
index 15468ff..fdddccd 100644
--- a/services/core/java/com/android/server/connectivity/ProxyTracker.java
+++ b/services/core/java/com/android/server/connectivity/ProxyTracker.java
@@ -208,7 +208,10 @@
public void sendProxyBroadcast() {
final ProxyInfo defaultProxy = getDefaultProxy();
final ProxyInfo proxyInfo = null != defaultProxy ? defaultProxy : new ProxyInfo("", 0, "");
- if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)) return;
+ if (mPacManager.setCurrentProxyScriptUrl(proxyInfo)
+ == PacManager.ToSendOrNotToSendBroadcast.DONT_SEND_BROADCAST) {
+ return;
+ }
if (DBG) Slog.d(TAG, "sending Proxy Broadcast for " + proxyInfo);
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING |
diff --git a/tests/net/java/android/net/NetworkCapabilitiesTest.java b/tests/net/java/android/net/NetworkCapabilitiesTest.java
index 50aef1d..84f7359 100644
--- a/tests/net/java/android/net/NetworkCapabilitiesTest.java
+++ b/tests/net/java/android/net/NetworkCapabilitiesTest.java
@@ -474,7 +474,7 @@
new StringNetworkSpecifier("specs"));
try {
nc2.addTransportType(TRANSPORT_WIFI);
- fail("Cannot set NetworkSpecifier on a NetworkCapability with multiple transports!");
+ fail("Cannot set a second TransportType of a network which has a NetworkSpecifier!");
} catch (IllegalStateException expected) {
// empty
}
@@ -500,16 +500,23 @@
// empty
});
NetworkCapabilities nc2 = new NetworkCapabilities();
+ // new TransportInfo so that object is not #equals to nc1's TransportInfo (that's where
+ // combine fails)
nc2.setTransportInfo(new TransportInfo() {
// empty
});
try {
nc1.combineCapabilities(nc2);
- fail("Should not be able to combine NetworkCaabilities which contain TransportInfos");
+ fail("Should not be able to combine NetworkCabilities which contain TransportInfos");
} catch (IllegalStateException expected) {
// empty
}
+
+ // verify that can combine with identical TransportInfo objects
+ NetworkCapabilities nc3 = new NetworkCapabilities();
+ nc3.setTransportInfo(nc1.getTransportInfo());
+ nc1.combineCapabilities(nc3);
}
private void assertEqualsThroughMarshalling(NetworkCapabilities netCap) {