Merge master@5428150 into git_qt-dev-plus-aosp.

Change-Id: If790e058d4ec8a5024363b6aa1354a356c2f2d76
BUG: 129345239
This commit is contained in:
Bill Rassieur
2019-04-02 18:31:08 +00:00
23 changed files with 727 additions and 302 deletions

View File

@@ -1934,6 +1934,8 @@ public class ConnectivityManager {
@NonNull Callback callback) {
ParcelFileDescriptor dup;
try {
// Dup is needed here as the pfd inside the socket is owned by the IpSecService,
// which cannot be obtained by the app process.
dup = ParcelFileDescriptor.dup(socket.getFileDescriptor());
} catch (IOException ignored) {
// Construct an invalid fd, so that if the user later calls start(), it will fail with
@@ -1975,6 +1977,7 @@ public class ConnectivityManager {
@NonNull Callback callback) {
ParcelFileDescriptor dup;
try {
// TODO: Consider remove unnecessary dup.
dup = pfd.dup();
} catch (IOException ignored) {
// Construct an invalid fd, so that if the user later calls start(), it will fail with
@@ -3231,7 +3234,7 @@ public class ConnectivityManager {
*
* @hide
*/
public void onPreCheck(Network network) {}
public void onPreCheck(@NonNull Network network) {}
/**
* Called when the framework connects and has declared a new network ready for use.
@@ -3244,8 +3247,9 @@ public class ConnectivityManager {
* @param blocked Whether access to the {@link Network} is blocked due to system policy.
* @hide
*/
public void onAvailable(Network network, NetworkCapabilities networkCapabilities,
LinkProperties linkProperties, boolean blocked) {
public void onAvailable(@NonNull Network network,
@NonNull NetworkCapabilities networkCapabilities,
@NonNull LinkProperties linkProperties, boolean blocked) {
// Internally only this method is called when a new network is available, and
// it calls the callback in the same way and order that older versions used
// to call so as not to change the behavior.
@@ -3269,7 +3273,7 @@ public class ConnectivityManager {
*
* @param network The {@link Network} of the satisfying network.
*/
public void onAvailable(Network network) {}
public void onAvailable(@NonNull Network network) {}
/**
* Called when the network is about to be disconnected. Often paired with an
@@ -3285,7 +3289,7 @@ public class ConnectivityManager {
* network connected. Note that the network may suffer a
* hard loss at any time.
*/
public void onLosing(Network network, int maxMsToLive) {}
public void onLosing(@NonNull Network network, int maxMsToLive) {}
/**
* Called when the framework has a hard loss of the network or when the
@@ -3293,7 +3297,7 @@ public class ConnectivityManager {
*
* @param network The {@link Network} lost.
*/
public void onLost(Network network) {}
public void onLost(@NonNull Network network) {}
/**
* Called if no network is found in the timeout time specified in
@@ -3313,8 +3317,8 @@ public class ConnectivityManager {
* @param networkCapabilities The new {@link android.net.NetworkCapabilities} for this
* network.
*/
public void onCapabilitiesChanged(Network network,
NetworkCapabilities networkCapabilities) {}
public void onCapabilitiesChanged(@NonNull Network network,
@NonNull NetworkCapabilities networkCapabilities) {}
/**
* Called when the network the framework connected to for this request
@@ -3323,7 +3327,8 @@ public class ConnectivityManager {
* @param network The {@link Network} whose link properties have changed.
* @param linkProperties The new {@link LinkProperties} for this network.
*/
public void onLinkPropertiesChanged(Network network, LinkProperties linkProperties) {}
public void onLinkPropertiesChanged(@NonNull Network network,
@NonNull LinkProperties linkProperties) {}
/**
* Called when the network the framework connected to for this request
@@ -3334,7 +3339,7 @@ public class ConnectivityManager {
* a tunnel, etc.
* @hide
*/
public void onNetworkSuspended(Network network) {}
public void onNetworkSuspended(@NonNull Network network) {}
/**
* Called when the network the framework connected to for this request
@@ -3342,7 +3347,7 @@ public class ConnectivityManager {
* preceded by a matching {@link NetworkCallback#onNetworkSuspended} call.
* @hide
*/
public void onNetworkResumed(Network network) {}
public void onNetworkResumed(@NonNull Network network) {}
/**
* Called when access to the specified network is blocked or unblocked.

View File

@@ -22,6 +22,10 @@ import static android.net.NetworkUtils.resNetworkResult;
import static android.net.NetworkUtils.resNetworkSend;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
import static android.system.OsConstants.AF_INET;
import static android.system.OsConstants.AF_INET6;
import static android.system.OsConstants.IPPROTO_UDP;
import static android.system.OsConstants.SOCK_DGRAM;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
@@ -30,12 +34,18 @@ import android.annotation.Nullable;
import android.os.CancellationSignal;
import android.os.Looper;
import android.system.ErrnoException;
import android.system.Os;
import android.util.Log;
import libcore.io.IoUtils;
import java.io.FileDescriptor;
import java.io.IOException;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
@@ -52,6 +62,7 @@ public final class DnsResolver {
private static final String TAG = "DnsResolver";
private static final int FD_EVENTS = EVENT_INPUT | EVENT_ERROR;
private static final int MAXPACKET = 8 * 1024;
private static final int SLEEP_TIME_MS = 2;
@IntDef(prefix = { "CLASS_" }, value = {
CLASS_IN
@@ -188,9 +199,9 @@ public final class DnsResolver {
* Send a raw DNS query.
* The answer will be provided asynchronously through the provided {@link AnswerCallback}.
*
* @param network {@link Network} specifying which network for querying.
* @param network {@link Network} specifying which network to query on.
* {@code null} for query on default network.
* @param query blob message
* @param query blob message to query
* @param flags flags as a combination of the FLAGS_* constants
* @param executor The {@link Executor} that the callback should be executed on.
* @param cancellationSignal used by the caller to signal if the query should be
@@ -205,26 +216,32 @@ public final class DnsResolver {
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
return;
}
final Object lock = new Object();
final FileDescriptor queryfd;
try {
queryfd = resNetworkSend((network != null
? network.netId : NETID_UNSET), query, query.length, flags);
} catch (ErrnoException e) {
callback.onQueryException(e);
executor.execute(() -> {
callback.onQueryException(e);
});
return;
}
maybeAddCancellationSignal(cancellationSignal, queryfd);
registerFDListener(executor, queryfd, callback);
synchronized (lock) {
registerFDListener(executor, queryfd, callback, cancellationSignal, lock);
if (cancellationSignal == null) return;
addCancellationSignal(cancellationSignal, queryfd, lock);
}
}
/**
* Send a DNS query with the specified name, class and query type.
* The answer will be provided asynchronously through the provided {@link AnswerCallback}.
*
* @param network {@link Network} specifying which network for querying.
* @param network {@link Network} specifying which network to query on.
* {@code null} for query on default network.
* @param domain domain name for querying
* @param domain domain name to query
* @param nsClass dns class as one of the CLASS_* constants
* @param nsType dns resource record (RR) type as one of the TYPE_* constants
* @param flags flags as a combination of the FLAGS_* constants
@@ -242,40 +259,187 @@ public final class DnsResolver {
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
return;
}
final Object lock = new Object();
final FileDescriptor queryfd;
try {
queryfd = resNetworkQuery((network != null
? network.netId : NETID_UNSET), domain, nsClass, nsType, flags);
} catch (ErrnoException e) {
callback.onQueryException(e);
executor.execute(() -> {
callback.onQueryException(e);
});
return;
}
synchronized (lock) {
registerFDListener(executor, queryfd, callback, cancellationSignal, lock);
if (cancellationSignal == null) return;
addCancellationSignal(cancellationSignal, queryfd, lock);
}
}
maybeAddCancellationSignal(cancellationSignal, queryfd);
registerFDListener(executor, queryfd, callback);
private class InetAddressAnswerAccumulator extends InetAddressAnswerCallback {
private final List<InetAddress> mAllAnswers;
private ParseException mParseException;
private ErrnoException mErrnoException;
private final InetAddressAnswerCallback mUserCallback;
private final int mTargetAnswerCount;
private int mReceivedAnswerCount = 0;
InetAddressAnswerAccumulator(int size, @NonNull InetAddressAnswerCallback callback) {
mTargetAnswerCount = size;
mAllAnswers = new ArrayList<>();
mUserCallback = callback;
}
private boolean maybeReportException() {
if (mErrnoException != null) {
mUserCallback.onQueryException(mErrnoException);
return true;
}
if (mParseException != null) {
mUserCallback.onParseException(mParseException);
return true;
}
return false;
}
private void maybeReportAnswer() {
if (++mReceivedAnswerCount != mTargetAnswerCount) return;
if (mAllAnswers.isEmpty() && maybeReportException()) return;
// TODO: Do RFC6724 sort.
mUserCallback.onAnswer(mAllAnswers);
}
@Override
public void onAnswer(@NonNull List<InetAddress> answer) {
mAllAnswers.addAll(answer);
maybeReportAnswer();
}
@Override
public void onParseException(@NonNull ParseException e) {
mParseException = e;
maybeReportAnswer();
}
@Override
public void onQueryException(@NonNull ErrnoException e) {
mErrnoException = e;
maybeReportAnswer();
}
}
/**
* Send a DNS query with the specified name, get back a set of InetAddresses asynchronously.
* The answer will be provided asynchronously through the provided
* {@link InetAddressAnswerCallback}.
*
* @param network {@link Network} specifying which network to query on.
* {@code null} for query on default network.
* @param domain domain name to query
* @param flags flags as a combination of the FLAGS_* constants
* @param executor The {@link Executor} that the callback should be executed on.
* @param cancellationSignal used by the caller to signal if the query should be
* cancelled. May be {@code null}.
* @param callback an {@link InetAddressAnswerCallback} which will be called to notify the
* caller of the result of dns query.
*/
public void query(@Nullable Network network, @NonNull String domain, @QueryFlag int flags,
@NonNull @CallbackExecutor Executor executor,
@Nullable CancellationSignal cancellationSignal,
@NonNull InetAddressAnswerCallback callback) {
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
return;
}
final Object lock = new Object();
final boolean queryIpv6 = haveIpv6(network);
final boolean queryIpv4 = haveIpv4(network);
final FileDescriptor v4fd;
final FileDescriptor v6fd;
int queryCount = 0;
if (queryIpv6) {
try {
v6fd = resNetworkQuery((network != null
? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_AAAA, flags);
} catch (ErrnoException e) {
executor.execute(() -> {
callback.onQueryException(e);
});
return;
}
queryCount++;
} else v6fd = null;
// TODO: Use device flag to control the sleep time.
// Avoiding gateways drop packets if queries are sent too close together
try {
Thread.sleep(SLEEP_TIME_MS);
} catch (InterruptedException ex) { }
if (queryIpv4) {
try {
v4fd = resNetworkQuery((network != null
? network.netId : NETID_UNSET), domain, CLASS_IN, TYPE_A, flags);
} catch (ErrnoException e) {
if (queryIpv6) resNetworkCancel(v6fd); // Closes fd, marks it invalid.
executor.execute(() -> {
callback.onQueryException(e);
});
return;
}
queryCount++;
} else v4fd = null;
final InetAddressAnswerAccumulator accumulator =
new InetAddressAnswerAccumulator(queryCount, callback);
synchronized (lock) {
if (queryIpv6) {
registerFDListener(executor, v6fd, accumulator, cancellationSignal, lock);
}
if (queryIpv4) {
registerFDListener(executor, v4fd, accumulator, cancellationSignal, lock);
}
if (cancellationSignal == null) return;
cancellationSignal.setOnCancelListener(() -> {
synchronized (lock) {
if (queryIpv4) cancelQuery(v4fd);
if (queryIpv6) cancelQuery(v6fd);
}
});
}
}
private <T> void registerFDListener(@NonNull Executor executor,
@NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback) {
@NonNull FileDescriptor queryfd, @NonNull AnswerCallback<T> answerCallback,
@Nullable CancellationSignal cancellationSignal, @NonNull Object lock) {
Looper.getMainLooper().getQueue().addOnFileDescriptorEventListener(
queryfd,
FD_EVENTS,
(fd, events) -> {
executor.execute(() -> {
byte[] answerbuf = null;
try {
answerbuf = resNetworkResult(fd);
} catch (ErrnoException e) {
Log.e(TAG, "resNetworkResult:" + e.toString());
answerCallback.onQueryException(e);
return;
}
synchronized (lock) {
if (cancellationSignal != null && cancellationSignal.isCanceled()) {
return;
}
byte[] answerbuf = null;
try {
answerbuf = resNetworkResult(fd); // Closes fd, marks it invalid.
} catch (ErrnoException e) {
Log.e(TAG, "resNetworkResult:" + e.toString());
answerCallback.onQueryException(e);
return;
}
try {
answerCallback.onAnswer(
answerCallback.parser.parse(answerbuf));
} catch (ParseException e) {
answerCallback.onParseException(e);
try {
answerCallback.onAnswer(
answerCallback.parser.parse(answerbuf));
} catch (ParseException e) {
answerCallback.onParseException(e);
}
}
});
// Unregister this fd listener
@@ -283,15 +447,51 @@ public final class DnsResolver {
});
}
private void maybeAddCancellationSignal(@Nullable CancellationSignal cancellationSignal,
@NonNull FileDescriptor queryfd) {
if (cancellationSignal == null) return;
cancellationSignal.setOnCancelListener(
() -> {
Looper.getMainLooper().getQueue()
.removeOnFileDescriptorEventListener(queryfd);
resNetworkCancel(queryfd);
});
private void cancelQuery(@NonNull FileDescriptor queryfd) {
if (!queryfd.valid()) return;
Looper.getMainLooper().getQueue().removeOnFileDescriptorEventListener(queryfd);
resNetworkCancel(queryfd); // Closes fd, marks it invalid.
}
private void addCancellationSignal(@NonNull CancellationSignal cancellationSignal,
@NonNull FileDescriptor queryfd, @NonNull Object lock) {
cancellationSignal.setOnCancelListener(() -> {
synchronized (lock) {
cancelQuery(queryfd);
}
});
}
// These two functions match the behaviour of have_ipv4 and have_ipv6 in the native resolver.
private boolean haveIpv4(@Nullable Network network) {
final SocketAddress addrIpv4 =
new InetSocketAddress(InetAddresses.parseNumericAddress("8.8.8.8"), 0);
return checkConnectivity(network, AF_INET, addrIpv4);
}
private boolean haveIpv6(@Nullable Network network) {
final SocketAddress addrIpv6 =
new InetSocketAddress(InetAddresses.parseNumericAddress("2000::"), 0);
return checkConnectivity(network, AF_INET6, addrIpv6);
}
private boolean checkConnectivity(@Nullable Network network,
int domain, @NonNull SocketAddress addr) {
final FileDescriptor socket;
try {
socket = Os.socket(domain, SOCK_DGRAM, IPPROTO_UDP);
} catch (ErrnoException e) {
return false;
}
try {
if (network != null) network.bindSocket(socket);
Os.connect(socket, addr);
} catch (IOException | ErrnoException e) {
return false;
} finally {
IoUtils.closeQuietly(socket);
}
return true;
}
private static class DnsAddressAnswer extends DnsPacket {

View File

@@ -16,6 +16,7 @@
package android.net;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -71,7 +72,7 @@ public final class IpPrefix implements Parcelable {
*
* @hide
*/
public IpPrefix(@NonNull byte[] address, int prefixLength) {
public IpPrefix(@NonNull byte[] address, @IntRange(from = 0, to = 128) int prefixLength) {
this.address = address.clone();
this.prefixLength = prefixLength;
checkAndMaskAddressAndPrefixLength();
@@ -88,7 +89,7 @@ public final class IpPrefix implements Parcelable {
*/
@SystemApi
@TestApi
public IpPrefix(@NonNull InetAddress address, int prefixLength) {
public IpPrefix(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength) {
// We don't reuse the (byte[], int) constructor because it calls clone() on the byte array,
// which is unnecessary because getAddress() already returns a clone.
this.address = address.getAddress();
@@ -150,13 +151,13 @@ public final class IpPrefix implements Parcelable {
*
* @return the address in the form of a byte array.
*/
public InetAddress getAddress() {
public @NonNull InetAddress getAddress() {
try {
return InetAddress.getByAddress(address);
} catch (UnknownHostException e) {
// Cannot happen. InetAddress.getByAddress can only throw an exception if the byte
// array is the wrong length, but we check that in the constructor.
return null;
throw new IllegalArgumentException("Address is invalid");
}
}
@@ -166,7 +167,7 @@ public final class IpPrefix implements Parcelable {
*
* @return the address in the form of a byte array.
*/
public byte[] getRawAddress() {
public @NonNull byte[] getRawAddress() {
return address.clone();
}
@@ -175,6 +176,7 @@ public final class IpPrefix implements Parcelable {
*
* @return the prefix length.
*/
@IntRange(from = 0, to = 128)
public int getPrefixLength() {
return prefixLength;
}
@@ -183,10 +185,10 @@ public final class IpPrefix implements Parcelable {
* Determines whether the prefix contains the specified address.
*
* @param address An {@link InetAddress} to test.
* @return {@code true} if the prefix covers the given address.
* @return {@code true} if the prefix covers the given address. {@code false} otherwise.
*/
public boolean contains(InetAddress address) {
byte[] addrBytes = (address == null) ? null : address.getAddress();
public boolean contains(@NonNull InetAddress address) {
byte[] addrBytes = address.getAddress();
if (addrBytes == null || addrBytes.length != this.address.length) {
return false;
}
@@ -201,7 +203,7 @@ public final class IpPrefix implements Parcelable {
* @param otherPrefix the prefix to test
* @hide
*/
public boolean containsPrefix(IpPrefix otherPrefix) {
public boolean containsPrefix(@NonNull IpPrefix otherPrefix) {
if (otherPrefix.getPrefixLength() < prefixLength) return false;
final byte[] otherAddress = otherPrefix.getRawAddress();
NetworkUtils.maskRawAddress(otherAddress, prefixLength);

View File

@@ -25,6 +25,7 @@ import static android.system.OsConstants.RT_SCOPE_LINK;
import static android.system.OsConstants.RT_SCOPE_SITE;
import static android.system.OsConstants.RT_SCOPE_UNIVERSE;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
@@ -170,7 +171,7 @@ public class LinkAddress implements Parcelable {
* Constructs a new {@code LinkAddress} from an {@code InetAddress} and prefix length, with
* the specified flags and scope. Flags and scope are not checked for validity.
* @param address The IP address.
* @param prefixLength The prefix length.
* @param prefixLength The prefix length. Must be &gt;= 0 and &lt;= (32 or 128) (IPv4 or IPv6).
* @param flags A bitmask of {@code IFA_F_*} values representing properties of the address.
* @param scope An integer defining the scope in which the address is unique (e.g.,
* {@link OsConstants#RT_SCOPE_LINK} or {@link OsConstants#RT_SCOPE_SITE}).
@@ -178,7 +179,8 @@ public class LinkAddress implements Parcelable {
*/
@SystemApi
@TestApi
public LinkAddress(InetAddress address, int prefixLength, int flags, int scope) {
public LinkAddress(@NonNull InetAddress address, @IntRange(from = 0, to = 128) int prefixLength,
int flags, int scope) {
init(address, prefixLength, flags, scope);
}
@@ -186,12 +188,13 @@ public class LinkAddress implements Parcelable {
* Constructs a new {@code LinkAddress} from an {@code InetAddress} and a prefix length.
* The flags are set to zero and the scope is determined from the address.
* @param address The IP address.
* @param prefixLength The prefix length.
* @param prefixLength The prefix length. Must be &gt;= 0 and &lt;= (32 or 128) (IPv4 or IPv6).
* @hide
*/
@SystemApi
@TestApi
public LinkAddress(@NonNull InetAddress address, int prefixLength) {
public LinkAddress(@NonNull InetAddress address,
@IntRange(from = 0, to = 128) int prefixLength) {
this(address, prefixLength, 0, 0);
this.scope = scopeForUnicastAddress(address);
}
@@ -202,7 +205,7 @@ public class LinkAddress implements Parcelable {
* @param interfaceAddress The interface address.
* @hide
*/
public LinkAddress(InterfaceAddress interfaceAddress) {
public LinkAddress(@NonNull InterfaceAddress interfaceAddress) {
this(interfaceAddress.getAddress(),
interfaceAddress.getNetworkPrefixLength());
}
@@ -306,6 +309,7 @@ public class LinkAddress implements Parcelable {
/**
* Returns the prefix length of this {@code LinkAddress}.
*/
@IntRange(from = 0, to = 128)
public int getPrefixLength() {
return prefixLength;
}
@@ -316,6 +320,7 @@ public class LinkAddress implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
@IntRange(from = 0, to = 128)
public int getNetworkPrefixLength() {
return getPrefixLength();
}

View File

@@ -316,9 +316,6 @@ public final class LinkProperties implements Parcelable {
@SystemApi
@TestApi
public boolean removeLinkAddress(@NonNull LinkAddress toRemove) {
if (toRemove == null) {
return false;
}
int i = findLinkAddressIndex(toRemove);
if (i >= 0) {
mLinkAddresses.remove(i);
@@ -391,10 +388,7 @@ public final class LinkProperties implements Parcelable {
@TestApi
@SystemApi
public boolean removeDnsServer(@NonNull InetAddress dnsServer) {
if (dnsServer != null) {
return mDnses.remove(dnsServer);
}
return false;
return mDnses.remove(dnsServer);
}
/**

View File

@@ -17,6 +17,7 @@
package android.net;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.annotation.UnsupportedAppUsage;
import android.net.NetworkCapabilities.NetCapability;
@@ -343,10 +344,14 @@ public class NetworkRequest implements Parcelable {
* current value. A value of {@code SIGNAL_STRENGTH_UNSPECIFIED} means no value when
* received and has no effect when requesting a callback.
*
* <p>This method requires the caller to hold the
* {@link android.Manifest.permission#NETWORK_SIGNAL_STRENGTH_WAKEUP} permission
*
* @param signalStrength the bearer-specific signal strength.
* @hide
*/
@SystemApi
@RequiresPermission(android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP)
public @NonNull Builder setSignalStrength(int signalStrength) {
mNetworkCapabilities.setSignalStrength(signalStrength);
return this;

View File

@@ -16,6 +16,8 @@
package android.net;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.annotation.TestApi;
@@ -24,6 +26,8 @@ import android.os.Build;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
@@ -51,20 +55,32 @@ import java.util.Objects;
* (IPv4 or IPv6).
*/
public final class RouteInfo implements Parcelable {
/** @hide */
@IntDef(value = {
RTN_UNICAST,
RTN_UNREACHABLE,
RTN_THROW,
})
@Retention(RetentionPolicy.SOURCE)
public @interface RouteType {}
/**
* The IP destination address for this route.
*/
@NonNull
private final IpPrefix mDestination;
/**
* The gateway address for this route.
*/
@UnsupportedAppUsage
@Nullable
private final InetAddress mGateway;
/**
* The interface for this route.
*/
@Nullable
private final String mInterface;
@@ -108,13 +124,14 @@ public final class RouteInfo implements Parcelable {
* @param destination the destination prefix
* @param gateway the IP address to route packets through
* @param iface the interface name to send packets on
* @param type the type of this route
*
* @hide
*/
@SystemApi
@TestApi
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
@Nullable String iface, int type) {
@Nullable String iface, @RouteType int type) {
switch (type) {
case RTN_UNICAST:
case RTN_UNREACHABLE:
@@ -173,10 +190,24 @@ public final class RouteInfo implements Parcelable {
}
/**
* @hide
* Constructs a {@code RouteInfo} object.
*
* If destination is null, then gateway must be specified and the
* constructed route is either the IPv4 default route <code>0.0.0.0</code>
* if the gateway is an instance of {@link Inet4Address}, or the IPv6 default
* route <code>::/0</code> if gateway is an instance of {@link Inet6Address}.
* <p>
* Destination and gateway may not both be null.
*
* @param destination the destination address and prefix in an {@link IpPrefix}
* @param gateway the {@link InetAddress} to route packets through
* @param iface the interface name to send packets on
*
* @hide
*/
@UnsupportedAppUsage
public RouteInfo(IpPrefix destination, InetAddress gateway, String iface) {
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway,
@Nullable String iface) {
this(destination, gateway, iface, RTN_UNICAST);
}
@@ -184,7 +215,8 @@ public final class RouteInfo implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
public RouteInfo(LinkAddress destination, InetAddress gateway, String iface) {
public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway,
@Nullable String iface) {
this(destination == null ? null :
new IpPrefix(destination.getAddress(), destination.getPrefixLength()),
gateway, iface);
@@ -205,7 +237,7 @@ public final class RouteInfo implements Parcelable {
*
* @hide
*/
public RouteInfo(IpPrefix destination, InetAddress gateway) {
public RouteInfo(@Nullable IpPrefix destination, @Nullable InetAddress gateway) {
this(destination, gateway, null);
}
@@ -215,7 +247,7 @@ public final class RouteInfo implements Parcelable {
* TODO: Remove this.
*/
@UnsupportedAppUsage
public RouteInfo(LinkAddress destination, InetAddress gateway) {
public RouteInfo(@Nullable LinkAddress destination, @Nullable InetAddress gateway) {
this(destination, gateway, null);
}
@@ -227,7 +259,7 @@ public final class RouteInfo implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
public RouteInfo(InetAddress gateway) {
public RouteInfo(@NonNull InetAddress gateway) {
this((IpPrefix) null, gateway, null);
}
@@ -239,35 +271,36 @@ public final class RouteInfo implements Parcelable {
*
* @hide
*/
public RouteInfo(IpPrefix destination) {
public RouteInfo(@NonNull IpPrefix destination) {
this(destination, null, null);
}
/**
* @hide
*/
public RouteInfo(LinkAddress destination) {
public RouteInfo(@NonNull LinkAddress destination) {
this(destination, null, null);
}
/**
* @hide
*/
public RouteInfo(IpPrefix destination, int type) {
public RouteInfo(@NonNull IpPrefix destination, @RouteType int type) {
this(destination, null, null, type);
}
/**
* @hide
*/
public static RouteInfo makeHostRoute(InetAddress host, String iface) {
public static RouteInfo makeHostRoute(@NonNull InetAddress host, @Nullable String iface) {
return makeHostRoute(host, null, iface);
}
/**
* @hide
*/
public static RouteInfo makeHostRoute(InetAddress host, InetAddress gateway, String iface) {
public static RouteInfo makeHostRoute(@Nullable InetAddress host, @Nullable InetAddress gateway,
@Nullable String iface) {
if (host == null) return null;
if (host instanceof Inet4Address) {
@@ -290,6 +323,7 @@ public final class RouteInfo implements Parcelable {
*
* @return {@link IpPrefix} specifying the destination. This is never {@code null}.
*/
@NonNull
public IpPrefix getDestination() {
return mDestination;
}
@@ -298,6 +332,7 @@ public final class RouteInfo implements Parcelable {
* TODO: Convert callers to use IpPrefix and then remove.
* @hide
*/
@NonNull
public LinkAddress getDestinationLinkAddress() {
return new LinkAddress(mDestination.getAddress(), mDestination.getPrefixLength());
}
@@ -308,6 +343,7 @@ public final class RouteInfo implements Parcelable {
* @return {@link InetAddress} specifying the gateway or next hop. This may be
* {@code null} for a directly-connected route."
*/
@Nullable
public InetAddress getGateway() {
return mGateway;
}
@@ -317,6 +353,7 @@ public final class RouteInfo implements Parcelable {
*
* @return The name of the interface used for this route.
*/
@Nullable
public String getInterface() {
return mInterface;
}
@@ -330,6 +367,7 @@ public final class RouteInfo implements Parcelable {
*/
@TestApi
@SystemApi
@RouteType
public int getType() {
return mType;
}
@@ -401,6 +439,7 @@ public final class RouteInfo implements Parcelable {
* @hide
*/
@UnsupportedAppUsage
@Nullable
public static RouteInfo selectBestRoute(Collection<RouteInfo> routes, InetAddress dest) {
if ((routes == null) || (dest == null)) return null;

View File

@@ -19,14 +19,17 @@ package android.net.apf;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.content.Context;
import android.content.res.Resources;
import android.os.Parcel;
import android.os.Parcelable;
import com.android.internal.R;
/**
* APF program support capabilities.
* APF program support capabilities. APF stands for Android Packet Filtering and it is a flexible
* way to drop unwanted network packets to save power.
*
* See documentation at hardware/google/apf/apf.h
*
* This class is immutable.
* @hide
@@ -104,10 +107,11 @@ public final class ApfCapabilities implements Parcelable {
}
/**
* Returns true if the APF interpreter advertises support for the data buffer access opcodes
* LDDW and STDW.
* Determines whether the APF interpreter advertises support for the data buffer access opcodes
* LDDW (LoaD Data Word) and STDW (STore Data Word). Full LDDW (LoaD Data Word) and
* STDW (STore Data Word) support is present from APFv4 on.
*
* Full LDDW and STDW support is present from APFv4 on.
* @return {@code true} if the IWifiStaIface#readApfPacketFilterData is supported.
*/
public boolean hasDataAccess() {
return apfVersionSupported >= 4;
@@ -116,14 +120,14 @@ public final class ApfCapabilities implements Parcelable {
/**
* @return Whether the APF Filter in the device should filter out IEEE 802.3 Frames.
*/
public static boolean getApfDrop8023Frames(@NonNull Context context) {
return context.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
public static boolean getApfDrop8023Frames() {
return Resources.getSystem().getBoolean(R.bool.config_apfDrop802_3Frames);
}
/**
* @return An array of blacklisted EtherType, packets with EtherTypes within it will be dropped.
*/
public static @NonNull int[] getApfEthTypeBlackList(@NonNull Context context) {
return context.getResources().getIntArray(R.array.config_apfEthTypeBlackList);
public static @NonNull int[] getApfEtherTypeBlackList() {
return Resources.getSystem().getIntArray(R.array.config_apfEthTypeBlackList);
}
}

View File

@@ -470,6 +470,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz,
std::vector<uint8_t> buf(MAXPACKETSIZE, 0);
int res = resNetworkResult(fd, &rcode, buf.data(), MAXPACKETSIZE);
jniSetFileDescriptorOfFD(env, javaFd, -1);
if (res < 0) {
throwErrnoException(env, "resNetworkResult", -res);
return nullptr;
@@ -490,6 +491,7 @@ static jbyteArray android_net_utils_resNetworkResult(JNIEnv *env, jobject thiz,
static void android_net_utils_resNetworkCancel(JNIEnv *env, jobject thiz, jobject javaFd) {
int fd = jniGetFDFromFileDescriptor(env, javaFd);
resNetworkCancel(fd);
jniSetFileDescriptorOfFD(env, javaFd, -1);
}
static jobject android_net_utils_getTcpRepairWindow(JNIEnv *env, jobject thiz, jobject javaFd) {

View File

@@ -63,6 +63,7 @@ import android.net.ConnectionInfo;
import android.net.ConnectivityManager;
import android.net.ICaptivePortal;
import android.net.IConnectivityManager;
import android.net.IDnsResolver;
import android.net.IIpConnectivityMetrics;
import android.net.INetd;
import android.net.INetdEventCallback;
@@ -294,6 +295,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
private INetworkManagementService mNMS;
@VisibleForTesting
protected IDnsResolver mDnsResolver;
@VisibleForTesting
protected INetd mNetd;
private INetworkStatsService mStatsService;
private INetworkPolicyManager mPolicyManager;
@@ -525,6 +528,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
return sMagicDecoderRing.get(what, Integer.toString(what));
}
private static IDnsResolver getDnsResolver() {
return IDnsResolver.Stub
.asInterface(ServiceManager.getService("dnsresolver"));
}
/** Handler thread used for both of the handlers below. */
@VisibleForTesting
protected final HandlerThread mHandlerThread;
@@ -810,13 +818,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
public ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager) {
this(context, netManager, statsService, policyManager, new IpConnectivityLog());
this(context, netManager, statsService, policyManager,
getDnsResolver(), new IpConnectivityLog());
}
@VisibleForTesting
protected ConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
IpConnectivityLog logger) {
IDnsResolver dnsresolver, IpConnectivityLog logger) {
if (DBG) log("ConnectivityService starting up");
mSystemProperties = getSystemProperties();
@@ -853,6 +862,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mPolicyManagerInternal = checkNotNull(
LocalServices.getService(NetworkPolicyManagerInternal.class),
"missing NetworkPolicyManagerInternal");
mDnsResolver = checkNotNull(dnsresolver, "missing IDnsResolver");
mProxyTracker = makeProxyTracker();
mNetd = NetdService.getInstance();
@@ -1006,7 +1016,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
mMultipathPolicyTracker = new MultipathPolicyTracker(mContext, mHandler);
mDnsManager = new DnsManager(mContext, mNMS, mSystemProperties);
mDnsManager = new DnsManager(mContext, mDnsResolver, mSystemProperties);
registerPrivateDnsSettingsCallbacks();
}
@@ -1882,6 +1892,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
return false;
}
private boolean checkAnyPermissionOf(int pid, int uid, String... permissions) {
for (String permission : permissions) {
if (mContext.checkPermission(permission, pid, uid) == PERMISSION_GRANTED) {
return true;
}
}
return false;
}
private void enforceAnyPermissionOf(String... permissions) {
if (!checkAnyPermissionOf(permissions)) {
throw new SecurityException("Requires one of the following permissions: "
@@ -1956,6 +1975,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private boolean checkNetworkSignalStrengthWakeupPermission(int pid, int uid) {
return checkAnyPermissionOf(pid, uid,
android.Manifest.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP,
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK);
}
private void enforceConnectivityRestrictedNetworksPermission() {
try {
mContext.enforceCallingOrSelfPermission(
@@ -3021,9 +3046,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
// NetworkFactories, so network traffic isn't interrupted for an unnecessarily
// long time.
try {
mNMS.removeNetwork(nai.network.netId);
} catch (Exception e) {
loge("Exception removing network: " + e);
mNetd.networkDestroy(nai.network.netId);
} catch (RemoteException | ServiceSpecificException e) {
loge("Exception destroying network: " + e);
}
mDnsManager.removeNetwork(nai.network);
}
@@ -3728,16 +3753,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
break;
}
case EVENT_SYSTEM_READY: {
for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
// Might have been called already in handleRegisterNetworkAgent since
// mSystemReady is set before sending EVENT_SYSTEM_READY, but calling
// this several times is fine.
try {
nai.networkMonitor().notifySystemReady();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
mMultipathPolicyTracker.start();
break;
}
@@ -4952,13 +4967,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
// This checks that the passed capabilities either do not request a specific SSID, or the
// calling app has permission to do so.
// This checks that the passed capabilities either do not request a specific SSID/SignalStrength
// , or the calling app has permission to do so.
private void ensureSufficientPermissionsForRequest(NetworkCapabilities nc,
int callerPid, int callerUid) {
if (null != nc.getSSID() && !checkSettingsPermission(callerPid, callerUid)) {
throw new SecurityException("Insufficient permissions to request a specific SSID");
}
if (nc.hasSignalStrength()
&& !checkNetworkSignalStrengthWakeupPermission(callerPid, callerUid)) {
throw new SecurityException(
"Insufficient permissions to request a specific signal strength");
}
}
private ArrayList<Integer> getSignalStrengthThresholds(NetworkAgentInfo nai) {
@@ -5372,10 +5393,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities);
final NetworkAgentInfo nai = new NetworkAgentInfo(messenger, new AsyncChannel(),
new Network(reserveNetId()), new NetworkInfo(networkInfo), lp, nc, currentScore,
mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mNMS,
factorySerialNumber);
mContext, mTrackerHandler, new NetworkMisc(networkMisc), this, mNetd, mDnsResolver,
mNMS, factorySerialNumber);
// Make sure the network capabilities reflect what the agent info says.
nai.networkCapabilities = mixInCapabilities(nai, nc);
nai.setNetworkCapabilities(mixInCapabilities(nai, nc));
final String extraInfo = networkInfo.getExtraInfo();
final String name = TextUtils.isEmpty(extraInfo)
? nai.networkCapabilities.getSSID() : extraInfo;
@@ -5406,15 +5427,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
synchronized (mNetworkForNetId) {
mNetworkForNetId.put(nai.network.netId, nai);
}
synchronized (this) {
if (mSystemReady) {
try {
networkMonitor.notifySystemReady();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
}
}
try {
networkMonitor.start();
@@ -5468,12 +5480,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
// Start or stop DNS64 detection and 464xlat according to network state.
networkAgent.clatd.update();
notifyIfacesChangedForNetworkStats();
try {
networkAgent.networkMonitor().notifyLinkPropertiesChanged(newLp);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
if (networkAgent.everConnected) {
try {
networkAgent.networkMonitor().notifyLinkPropertiesChanged();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
notifyNetworkCallbacks(networkAgent, ConnectivityManager.CALLBACK_IP_CHANGED);
}
}
@@ -5701,7 +5713,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
final NetworkCapabilities prevNc;
synchronized (nai) {
prevNc = nai.networkCapabilities;
nai.networkCapabilities = newNc;
nai.setNetworkCapabilities(newNc);
}
updateUids(nai, prevNc, newNc);
@@ -5716,11 +5728,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
// If the requestable capabilities have changed or the score changed, we can't have been
// called by rematchNetworkAndRequests, so it's safe to start a rematch.
rematchAllNetworksAndRequests(nai, oldScore);
try {
nai.networkMonitor().notifyNetworkCapabilitiesChanged();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
@@ -5979,11 +5986,6 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
if (capabilitiesChanged) {
try {
nai.networkMonitor().notifyNetworkCapabilitiesChanged();
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}
notifyNetworkCallbacks(nai, ConnectivityManager.CALLBACK_CAP_CHANGED);
}
@@ -6392,7 +6394,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (networkAgent.networkMisc.acceptPartialConnectivity) {
networkAgent.networkMonitor().setAcceptPartialConnectivity();
}
networkAgent.networkMonitor().notifyNetworkConnected();
networkAgent.networkMonitor().notifyNetworkConnected(
networkAgent.linkProperties, networkAgent.networkCapabilities);
} catch (RemoteException e) {
e.rethrowFromSystemServer();
}

View File

@@ -30,13 +30,15 @@ import static android.provider.Settings.Global.PRIVATE_DNS_SPECIFIER;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.net.IDnsResolver;
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkUtils;
import android.net.Uri;
import android.net.shared.PrivateDnsConfig;
import android.os.Binder;
import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
@@ -229,7 +231,7 @@ public class DnsManager {
private final Context mContext;
private final ContentResolver mContentResolver;
private final INetworkManagementService mNMS;
private final IDnsResolver mDnsResolver;
private final MockableSystemProperties mSystemProperties;
// TODO: Replace these Maps with SparseArrays.
private final Map<Integer, PrivateDnsConfig> mPrivateDnsMap;
@@ -243,10 +245,10 @@ public class DnsManager {
private String mPrivateDnsMode;
private String mPrivateDnsSpecifier;
public DnsManager(Context ctx, INetworkManagementService nms, MockableSystemProperties sp) {
public DnsManager(Context ctx, IDnsResolver dnsResolver, MockableSystemProperties sp) {
mContext = ctx;
mContentResolver = mContext.getContentResolver();
mNMS = nms;
mDnsResolver = dnsResolver;
mSystemProperties = sp;
mPrivateDnsMap = new HashMap<>();
mPrivateDnsValidationMap = new HashMap<>();
@@ -260,6 +262,12 @@ public class DnsManager {
}
public void removeNetwork(Network network) {
try {
mDnsResolver.clearResolverConfiguration(network.netId);
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error clearing DNS configuration: " + e);
return;
}
mPrivateDnsMap.remove(network.netId);
mPrivateDnsValidationMap.remove(network.netId);
}
@@ -344,10 +352,12 @@ public class DnsManager {
Slog.d(TAG, String.format("setDnsConfigurationForNetwork(%d, %s, %s, %s, %s, %s)",
netId, Arrays.toString(assignedServers), Arrays.toString(domainStrs),
Arrays.toString(params), tlsHostname, Arrays.toString(tlsServers)));
final String[] tlsFingerprints = new String[0];
try {
mNMS.setDnsConfigurationForNetwork(
netId, assignedServers, domainStrs, params, tlsHostname, tlsServers);
} catch (Exception e) {
mDnsResolver.setResolverConfiguration(
netId, assignedServers, domainStrs, params,
tlsHostname, tlsServers, tlsFingerprints);
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error setting DNS configuration: " + e);
return;
}

View File

@@ -132,6 +132,7 @@ public class KeepaliveTracker {
private static final int NOT_STARTED = 1;
private static final int STARTING = 2;
private static final int STARTED = 3;
private static final int STOPPING = 4;
private int mStartedState = NOT_STARTED;
KeepaliveInfo(@NonNull ISocketKeepaliveCallback callback,
@@ -154,12 +155,19 @@ public class KeepaliveTracker {
// keepalives are sent cannot be reused by another app even if the fd gets closed by
// the user. A null is acceptable here for backward compatibility of PacketKeepalive
// API.
// TODO: don't accept null fd after legacy packetKeepalive API is removed.
try {
if (fd != null) {
mFd = Os.dup(fd);
} else {
Log.d(TAG, "uid/pid " + mUid + "/" + mPid + " calls with null fd");
Log.d(TAG, toString() + " calls with null fd");
if (!mPrivileged) {
throw new SecurityException(
"null fd is not allowed for unprivileged access.");
}
if (mType == TYPE_TCP) {
throw new IllegalArgumentException(
"null fd is not allowed for tcp socket keepalives.");
}
mFd = null;
}
} catch (ErrnoException e) {
@@ -307,6 +315,7 @@ public class KeepaliveTracker {
}
}
if (NOT_STARTED != mStartedState) {
mStartedState = STOPPING;
Log.d(TAG, "Stopping keepalive " + mSlot + " on " + mNai.name());
if (mType == TYPE_NATT) {
mNai.asyncChannel.sendMessage(CMD_STOP_SOCKET_KEEPALIVE, mSlot);
@@ -449,8 +458,8 @@ public class KeepaliveTracker {
ki = mKeepalives.get(nai).get(slot);
} catch(NullPointerException e) {}
if (ki == null) {
Log.e(TAG, "Event " + message.what + " for unknown keepalive " + slot + " on "
+ nai.name());
Log.e(TAG, "Event " + message.what + "," + slot + "," + reason
+ " for unknown keepalive " + slot + " on " + nai.name());
return;
}
@@ -469,27 +478,30 @@ public class KeepaliveTracker {
// messages in order.
// TODO : clarify this code and get rid of mStartedState. Using a StateMachine is an
// option.
if (reason == SUCCESS && KeepaliveInfo.STARTING == ki.mStartedState) {
// Keepalive successfully started.
if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
ki.mStartedState = KeepaliveInfo.STARTED;
try {
ki.mCallback.onStarted(slot);
} catch (RemoteException e) {
Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
}
} else {
// Keepalive successfully stopped, or error.
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
if (reason == SUCCESS) {
// The message indicated success stopping : don't call handleStopKeepalive.
if (DBG) Log.d(TAG, "Successfully stopped keepalive " + slot + " on " + nai.name());
if (KeepaliveInfo.STARTING == ki.mStartedState) {
if (SUCCESS == reason) {
// Keepalive successfully started.
if (DBG) Log.d(TAG, "Started keepalive " + slot + " on " + nai.name());
ki.mStartedState = KeepaliveInfo.STARTED;
try {
ki.mCallback.onStarted(slot);
} catch (RemoteException e) {
Log.w(TAG, "Discarded onStarted(" + slot + ") callback");
}
} else {
// The message indicated some error trying to start or during the course of
// keepalive : do call handleStopKeepalive.
Log.d(TAG, "Failed to start keepalive " + slot + " on " + nai.name()
+ ": " + reason);
// The message indicated some error trying to start: do call handleStopKeepalive.
handleStopKeepalive(nai, slot, reason);
if (DBG) Log.d(TAG, "Keepalive " + slot + " on " + nai.name() + " error " + reason);
}
} else if (KeepaliveInfo.STOPPING == ki.mStartedState) {
// The message indicated result of stopping : don't call handleStopKeepalive.
Log.d(TAG, "Stopped keepalive " + slot + " on " + nai.name()
+ " stopped: " + reason);
ki.mStartedState = KeepaliveInfo.NOT_STARTED;
} else {
Log.wtf(TAG, "Event " + message.what + "," + slot + "," + reason
+ " for keepalive in wrong state: " + ki.toString());
}
}
@@ -531,7 +543,8 @@ public class KeepaliveTracker {
try {
ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
KeepaliveInfo.TYPE_NATT, fd);
} catch (InvalidSocketException e) {
} catch (InvalidSocketException | IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Fail to construct keepalive", e);
notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
return;
}
@@ -570,7 +583,8 @@ public class KeepaliveTracker {
try {
ki = new KeepaliveInfo(cb, nai, packet, intervalSeconds,
KeepaliveInfo.TYPE_TCP, fd);
} catch (InvalidSocketException e) {
} catch (InvalidSocketException | IllegalArgumentException | SecurityException e) {
Log.e(TAG, "Fail to construct keepalive e=" + e);
notifyErrorCallback(cb, ERROR_INVALID_SOCKET);
return;
}

View File

@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import android.net.ConnectivityManager;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.InetAddresses;
import android.net.InterfaceConfiguration;
@@ -65,6 +66,7 @@ public class Nat464Xlat extends BaseNetworkObserver {
NetworkInfo.State.SUSPENDED,
};
private final IDnsResolver mDnsResolver;
private final INetd mNetd;
private final INetworkManagementService mNMService;
@@ -84,7 +86,9 @@ public class Nat464Xlat extends BaseNetworkObserver {
private Inet6Address mIPv6Address;
private State mState = State.IDLE;
public Nat464Xlat(NetworkAgentInfo nai, INetd netd, INetworkManagementService nmService) {
public Nat464Xlat(NetworkAgentInfo nai, INetd netd, IDnsResolver dnsResolver,
INetworkManagementService nmService) {
mDnsResolver = dnsResolver;
mNetd = netd;
mNMService = nmService;
mNetwork = nai;
@@ -269,7 +273,7 @@ public class Nat464Xlat extends BaseNetworkObserver {
private void startPrefixDiscovery() {
try {
mNetd.resolverStartPrefix64Discovery(getNetId());
mDnsResolver.startPrefix64Discovery(getNetId());
mState = State.DISCOVERING;
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error starting prefix discovery on netId " + getNetId() + ": " + e);
@@ -278,7 +282,7 @@ public class Nat464Xlat extends BaseNetworkObserver {
private void stopPrefixDiscovery() {
try {
mNetd.resolverStopPrefix64Discovery(getNetId());
mDnsResolver.stopPrefix64Discovery(getNetId());
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Error stopping prefix discovery on netId " + getNetId() + ": " + e);
}

View File

@@ -17,6 +17,7 @@
package com.android.server.connectivity;
import android.content.Context;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.LinkProperties;
@@ -29,6 +30,7 @@ import android.net.NetworkState;
import android.os.Handler;
import android.os.INetworkManagementService;
import android.os.Messenger;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
@@ -120,7 +122,8 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
// This Network object is always valid.
public final Network network;
public LinkProperties linkProperties;
// This should only be modified via ConnectivityService.updateCapabilities().
// This should only be modified by ConnectivityService, via setNetworkCapabilities().
// TODO: make this private with a getter.
public NetworkCapabilities networkCapabilities;
public final NetworkMisc networkMisc;
// Indicates if netd has been told to create this Network. From this point on the appropriate
@@ -255,7 +258,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
public NetworkAgentInfo(Messenger messenger, AsyncChannel ac, Network net, NetworkInfo info,
LinkProperties lp, NetworkCapabilities nc, int score, Context context, Handler handler,
NetworkMisc misc, ConnectivityService connService, INetd netd,
INetworkManagementService nms, int factorySerialNumber) {
IDnsResolver dnsResolver, INetworkManagementService nms, int factorySerialNumber) {
this.messenger = messenger;
asyncChannel = ac;
network = net;
@@ -263,7 +266,7 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
linkProperties = lp;
networkCapabilities = nc;
currentScore = score;
clatd = new Nat464Xlat(this, netd, nms);
clatd = new Nat464Xlat(this, netd, dnsResolver, nms);
mConnService = connService;
mContext = context;
mHandler = handler;
@@ -278,6 +281,25 @@ public class NetworkAgentInfo implements Comparable<NetworkAgentInfo> {
mNetworkMonitor = networkMonitor;
}
/**
* Set the NetworkCapabilities on this NetworkAgentInfo. Also attempts to notify NetworkMonitor
* of the new capabilities, if NetworkMonitor has been created.
*
* <p>If {@link NetworkMonitor#notifyNetworkCapabilitiesChanged(NetworkCapabilities)} fails,
* the exception is logged but not reported to callers.
*/
public void setNetworkCapabilities(NetworkCapabilities nc) {
networkCapabilities = nc;
final INetworkMonitor nm = mNetworkMonitor;
if (nm != null) {
try {
nm.notifyNetworkCapabilitiesChanged(nc);
} catch (RemoteException e) {
Log.e(TAG, "Error notifying NetworkMonitor of updated NetworkCapabilities", e);
}
}
}
public ConnectivityService connService() {
return mConnService;
}

View File

@@ -19,6 +19,7 @@ package com.android.server.connectivity;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.telephony.SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
import android.app.Notification;
import android.app.NotificationManager;
@@ -26,9 +27,12 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.res.Resources;
import android.net.NetworkSpecifier;
import android.net.StringNetworkSpecifier;
import android.net.wifi.WifiInfo;
import android.os.UserHandle;
import android.telephony.AccessNetworkConstants.TransportType;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Slog;
@@ -195,7 +199,20 @@ public class NetworkNotificationManager {
title = r.getString(R.string.network_available_sign_in, 0);
// TODO: Change this to pull from NetworkInfo once a printable
// name has been added to it
details = mTelephonyManager.getNetworkOperatorName();
NetworkSpecifier specifier = nai.networkCapabilities.getNetworkSpecifier();
int subId = SubscriptionManager.DEFAULT_SUBSCRIPTION_ID;
if (specifier instanceof StringNetworkSpecifier) {
try {
subId = Integer.parseInt(
((StringNetworkSpecifier) specifier).specifier);
} catch (NumberFormatException e) {
Slog.e(TAG, "NumberFormatException on "
+ ((StringNetworkSpecifier) specifier).specifier);
}
}
details = mTelephonyManager.createForSubscriptionId(subId)
.getNetworkOperatorName();
break;
default:
title = r.getString(R.string.network_available_sign_in, 0);

View File

@@ -22,6 +22,7 @@ import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.Manifest.permission.INTERNET;
import static android.Manifest.permission.NETWORK_STACK;
import static android.Manifest.permission.UPDATE_DEVICE_STATS;
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
import static android.content.pm.PackageManager.GET_PERMISSIONS;
import static android.content.pm.PackageManager.MATCH_ANY_USER;
import static android.os.Process.INVALID_UID;
@@ -42,13 +43,15 @@ import android.os.INetworkManagementService;
import android.os.RemoteException;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.ArraySet;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.SparseIntArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.server.LocalServices;
import com.android.server.SystemConfig;
import java.util.ArrayList;
import java.util.HashMap;
@@ -83,41 +86,32 @@ public class PermissionMonitor {
private final Map<Integer, Boolean> mApps = new HashMap<>();
private class PackageListObserver implements PackageManagerInternal.PackageListObserver {
@Override
public void onPackageAdded(String packageName, int uid) {
final PackageInfo app = getPackageInfo(packageName);
if (app == null) {
Slog.wtf(TAG, "Failed to get information of installed package: " + packageName);
return;
}
if (uid == INVALID_UID) {
Slog.wtf(TAG, "Failed to get the uid of installed package: " + packageName
+ "uid: " + uid);
return;
}
if (app.requestedPermissions == null) {
return;
}
sendPackagePermissionsForUid(uid,
getNetdPermissionMask(app.requestedPermissions));
}
@Override
public void onPackageRemoved(String packageName, int uid) {
private int getPermissionForUid(int uid) {
int permission = 0;
// If there are still packages remain under the same uid, check the permission of the
// remaining packages. We only remove the permission for a given uid when all packages
// for that uid no longer have that permission.
// Check all the packages for this UID. The UID has the permission if any of the
// packages in it has the permission.
String[] packages = mPackageManager.getPackagesForUid(uid);
if (packages != null && packages.length > 0) {
for (String name : packages) {
final PackageInfo app = getPackageInfo(name);
if (app != null && app.requestedPermissions != null) {
permission |= getNetdPermissionMask(app.requestedPermissions);
permission |= getNetdPermissionMask(app.requestedPermissions,
app.requestedPermissionsFlags);
}
}
}
sendPackagePermissionsForUid(uid, permission);
return permission;
}
@Override
public void onPackageAdded(String packageName, int uid) {
sendPackagePermissionsForUid(uid, getPermissionForUid(uid));
}
@Override
public void onPackageRemoved(String packageName, int uid) {
sendPackagePermissionsForUid(uid, getPermissionForUid(uid));
}
}
@@ -167,12 +161,9 @@ public class PermissionMonitor {
}
//TODO: unify the management of the permissions into one codepath.
if (app.requestedPermissions != null) {
int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions);
if (otherNetdPerms != 0) {
netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
}
}
int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions,
app.requestedPermissionsFlags);
netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms);
}
List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users
@@ -182,6 +173,23 @@ public class PermissionMonitor {
}
}
final SparseArray<ArraySet<String>> systemPermission =
SystemConfig.getInstance().getSystemPermissions();
for (int i = 0; i < systemPermission.size(); i++) {
ArraySet<String> perms = systemPermission.valueAt(i);
int uid = systemPermission.keyAt(i);
int netdPermission = 0;
// Get the uids of native services that have UPDATE_DEVICE_STATS permission.
if (perms != null) {
netdPermission |= perms.contains(UPDATE_DEVICE_STATS)
? INetd.PERMISSION_UPDATE_DEVICE_STATS : 0;
}
// For internet permission, the native services have their own selinux domains and
// sepolicy will control the socket creation during run time. netd cannot block the
// socket creation based on the permission information here.
netdPermission |= INetd.PERMISSION_INTERNET;
netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission);
}
log("Users: " + mUsers.size() + ", Apps: " + mApps.size());
update(mUsers, mApps, true);
sendPackagePermissionsToNetd(netdPermsUids);
@@ -403,13 +411,17 @@ public class PermissionMonitor {
}
}
private static int getNetdPermissionMask(String[] requestedPermissions) {
private static int getNetdPermissionMask(String[] requestedPermissions,
int[] requestedPermissionsFlags) {
int permissions = 0;
for (String permissionName : requestedPermissions) {
if (permissionName.equals(INTERNET)) {
if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions;
for (int i = 0; i < requestedPermissions.length; i++) {
if (requestedPermissions[i].equals(INTERNET)
&& ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
permissions |= INetd.PERMISSION_INTERNET;
}
if (permissionName.equals(UPDATE_DEVICE_STATS)) {
if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS)
&& ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
permissions |= INetd.PERMISSION_UPDATE_DEVICE_STATS;
}
}

View File

@@ -231,7 +231,6 @@ public class IpPrefixTest {
assertFalse(p.contains(Address("2001:db8:f00::ace:d00e")));
assertFalse(p.contains(Address("2001:db8:f00::bad:d00d")));
assertFalse(p.contains(Address("2001:4868:4860::8888")));
assertFalse(p.contains((InetAddress)null));
assertFalse(p.contains(Address("8.8.8.8")));
p = new IpPrefix("192.0.2.0/23");

View File

@@ -44,6 +44,8 @@ public class ParcelableTests {
assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable())));
builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("1.2.3.4"));
// lease will expire in two hours
builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 7_200_000);
// groupHint stays null this time around
builder.setDnsAddresses(Collections.emptyList());
builder.setMtu(18);
@@ -51,6 +53,7 @@ public class ParcelableTests {
assertEquals(in, new NetworkAttributes(parcelingRoundTrip(in.toParcelable())));
builder.setAssignedV4Address((Inet4Address) Inet4Address.getByName("6.7.8.9"));
builder.setAssignedV4AddressExpiry(System.currentTimeMillis() + 3_600_000);
builder.setGroupHint("groupHint");
builder.setDnsAddresses(Arrays.asList(
InetAddress.getByName("ACA1:652B:0911:DE8F:1200:115E:913B:AA2A"),
@@ -66,7 +69,7 @@ public class ParcelableTests {
// Verify that this test does not miss any new field added later.
// If any field is added to NetworkAttributes it must be tested here for parceling
// roundtrip.
assertEquals(4, Arrays.stream(NetworkAttributes.class.getDeclaredFields())
assertEquals(5, Arrays.stream(NetworkAttributes.class.getDeclaredFields())
.filter(f -> !Modifier.isStatic(f.getModifiers())).count());
}

View File

@@ -104,6 +104,7 @@ import android.net.ConnectivityManager.PacketKeepalive;
import android.net.ConnectivityManager.PacketKeepaliveCallback;
import android.net.ConnectivityManager.TooManyRequestsException;
import android.net.ConnectivityThread;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.INetworkMonitor;
import android.net.INetworkMonitorCallbacks;
@@ -212,7 +213,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
@@ -241,6 +241,7 @@ public class ConnectivityServiceTest {
private static final String CLAT_PREFIX = "v4-";
private static final String MOBILE_IFNAME = "test_rmnet_data0";
private static final String WIFI_IFNAME = "test_wlan0";
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private MockContext mServiceContext;
private WrappedConnectivityService mService;
@@ -257,6 +258,7 @@ public class ConnectivityServiceTest {
@Mock INetworkManagementService mNetworkManagementService;
@Mock INetworkStatsService mStatsService;
@Mock INetworkPolicyManager mNpm;
@Mock IDnsResolver mMockDnsResolver;
@Mock INetd mMockNetd;
@Mock NetworkStackClient mNetworkStack;
@@ -497,9 +499,8 @@ public class ConnectivityServiceTest {
};
try {
doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected();
doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
doAnswer(validateAnswer).when(mNetworkMonitor).setAcceptPartialConnectivity();
} catch (RemoteException e) {
fail(e.getMessage());
}
@@ -1055,8 +1056,8 @@ public class ConnectivityServiceTest {
public WrappedConnectivityService(Context context, INetworkManagementService netManager,
INetworkStatsService statsService, INetworkPolicyManager policyManager,
IpConnectivityLog log, INetd netd) {
super(context, netManager, statsService, policyManager, log);
IpConnectivityLog log, INetd netd, IDnsResolver dnsResolver) {
super(context, netManager, statsService, policyManager, dnsResolver, log);
mNetd = netd;
mLingerDelayMs = TEST_LINGER_DELAY_MS;
}
@@ -1220,7 +1221,8 @@ public class ConnectivityServiceTest {
mStatsService,
mNpm,
mock(IpConnectivityLog.class),
mMockNetd);
mMockNetd,
mMockDnsResolver);
final ArgumentCaptor<INetworkPolicyListener> policyListenerCaptor =
ArgumentCaptor.forClass(INetworkPolicyListener.class);
@@ -2554,8 +2556,7 @@ public class ConnectivityServiceTest {
verifyActiveNetwork(TRANSPORT_CELLULAR);
}
// TODO(b/128426024): deflake and re-enable
// @Test
@Test
public void testPartialConnectivity() {
// Register network callback.
NetworkRequest request = new NetworkRequest.Builder()
@@ -2579,20 +2580,24 @@ public class ConnectivityServiceTest {
assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.assertNoCallback();
// With HTTPS probe disabled, NetworkMonitor should pass the network validation with http
// probe.
mWiFiNetworkAgent.setNetworkValid();
// If the user chooses yes to use this partial connectivity wifi, switch the default
// network to wifi and check if wifi becomes valid or not.
mCm.setAcceptPartialConnectivity(mWiFiNetworkAgent.getNetwork(), true /* accept */,
false /* always */);
// With https probe disabled, NetworkMonitor should pass the network validation with http
// probe.
mWiFiNetworkAgent.setNetworkValid();
// If user accepts partial connectivity network,
// NetworkMonitor#setAcceptPartialConnectivity() should be called too.
waitForIdle();
try {
verify(mWiFiNetworkAgent.mNetworkMonitor,
timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
} catch (RemoteException e) {
fail(e.getMessage());
}
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
NetworkCapabilities nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED,
mWiFiNetworkAgent);
@@ -2622,6 +2627,15 @@ public class ConnectivityServiceTest {
// acceptUnvalidated is also used as setting for accepting partial networks.
mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
mWiFiNetworkAgent.connect(true);
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
// ConnectivityService#updateNetworkInfo().
waitForIdle();
try {
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
} catch (RemoteException e) {
fail(e.getMessage());
}
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
@@ -2636,23 +2650,33 @@ public class ConnectivityServiceTest {
// NET_CAPABILITY_PARTIAL_CONNECTIVITY.
mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
// Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
// So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
// to ConnectivityService first then send VALID. Once NetworkMonitor support
// multi-testResult, this test case also need to be changed to meet the new design.
mWiFiNetworkAgent.connectWithPartialConnectivity();
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
// TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
// NetworkMonitor detects partial connectivity
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
mWiFiNetworkAgent.setNetworkValid();
// If user accepted partial connectivity network before,
// NetworkMonitor#setAcceptPartialConnectivity() will be called in
// ConnectivityService#updateNetworkInfo().
waitForIdle();
try {
verify(mWiFiNetworkAgent.mNetworkMonitor,
timeout(TIMEOUT_MS).times(1)).setAcceptPartialConnectivity();
verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
} catch (RemoteException e) {
fail(e.getMessage());
}
callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
// Wifi should be the default network.
// TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
// NetworkMonitor detects partial connectivity
assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
mWiFiNetworkAgent.setNetworkValid();
// Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
// validated.
mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
mWiFiNetworkAgent.disconnect();
callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
}
@Test
@@ -3022,6 +3046,47 @@ public class ConnectivityServiceTest {
}
}
@Test
public void testInvalidSignalStrength() {
NetworkRequest r = new NetworkRequest.Builder()
.addCapability(NET_CAPABILITY_INTERNET)
.addTransportType(TRANSPORT_WIFI)
.setSignalStrength(-75)
.build();
// Registering a NetworkCallback with signal strength but w/o NETWORK_SIGNAL_STRENGTH_WAKEUP
// permission should get SecurityException.
try {
mCm.registerNetworkCallback(r, new NetworkCallback());
fail("Expected SecurityException filing a callback with signal strength");
} catch (SecurityException expected) {
// expected
}
try {
mCm.registerNetworkCallback(r, PendingIntent.getService(
mServiceContext, 0, new Intent(), 0));
fail("Expected SecurityException filing a callback with signal strength");
} catch (SecurityException expected) {
// expected
}
// Requesting a Network with signal strength should get IllegalArgumentException.
try {
mCm.requestNetwork(r, new NetworkCallback());
fail("Expected IllegalArgumentException filing a request with signal strength");
} catch (IllegalArgumentException expected) {
// expected
}
try {
mCm.requestNetwork(r, PendingIntent.getService(
mServiceContext, 0, new Intent(), 0));
fail("Expected IllegalArgumentException filing a request with signal strength");
} catch (IllegalArgumentException expected) {
// expected
}
}
@Test
public void testRegisterDefaultNetworkCallback() throws Exception {
final TestNetworkCallback defaultNetworkCallback = new TestNetworkCallback();
@@ -4022,8 +4087,13 @@ public class ConnectivityServiceTest {
callback3.expectStopped();
}
@FunctionalInterface
private interface ThrowingConsumer<T> {
void accept(T t) throws Exception;
}
// Helper method to prepare the executor and run test
private void runTestWithSerialExecutors(Consumer<Executor> functor) {
private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
final Executor executorInline = (Runnable r) -> r.run();
functor.accept(executorSingleThread);
@@ -4032,23 +4102,15 @@ public class ConnectivityServiceTest {
}
@Test
public void testNattSocketKeepalives() {
runTestWithSerialExecutors(executor -> {
try {
doTestNattSocketKeepalivesWithExecutor(executor);
doTestNattSocketKeepalivesFdWithExecutor(executor);
} catch (Exception e) {
fail(e.getMessage());
}
});
public void testNattSocketKeepalives() throws Exception {
runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesWithExecutor(executor));
runTestWithSerialExecutors(executor -> doTestNattSocketKeepalivesFdWithExecutor(executor));
}
private void doTestNattSocketKeepalivesWithExecutor(Executor executor) throws Exception {
// TODO: 1. Move this outside of ConnectivityServiceTest.
// 2. Make test to verify that Nat-T keepalive socket is created by IpSecService.
// 3. Mock ipsec service.
// 4. Find a free port instead of a fixed port.
final int srcPort = 12345;
final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
final InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
final InetAddress myIPv6 = InetAddress.getByName("2001:db8::1");
@@ -4059,7 +4121,8 @@ public class ConnectivityServiceTest {
final int invalidKaInterval = 9;
final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
final int srcPort = testSocket.getPort();
LinkProperties lp = new LinkProperties();
lp.setInterfaceName("wlan12");
@@ -4179,6 +4242,7 @@ public class ConnectivityServiceTest {
// Check that keepalive slots start from 1 and increment. The first one gets slot 1.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(1);
int srcPort2 = 0;
try (SocketKeepalive ka = mCm.createSocketKeepalive(
myNet, testSocket, myIPv4, dstIPv4, executor, callback)) {
ka.start(validKaInterval);
@@ -4186,7 +4250,8 @@ public class ConnectivityServiceTest {
// The second one gets slot 2.
mWiFiNetworkAgent.setExpectedKeepaliveSlot(2);
final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket(6789);
final UdpEncapsulationSocket testSocket2 = mIpSec.openUdpEncapsulationSocket();
srcPort2 = testSocket2.getPort();
TestSocketKeepaliveCallback callback2 = new TestSocketKeepaliveCallback(executor);
try (SocketKeepalive ka2 = mCm.createSocketKeepalive(
myNet, testSocket2, myIPv4, dstIPv4, executor, callback2)) {
@@ -4204,20 +4269,18 @@ public class ConnectivityServiceTest {
}
}
// Check that there is no port leaked after all keepalives and sockets are closed.
assertFalse(isUdpPortInUse(srcPort));
assertFalse(isUdpPortInUse(srcPort2));
mWiFiNetworkAgent.disconnect();
waitFor(mWiFiNetworkAgent.getDisconnectedCV());
mWiFiNetworkAgent = null;
}
@Test
public void testTcpSocketKeepalives() {
runTestWithSerialExecutors(executor -> {
try {
doTestTcpSocketKeepalivesWithExecutor(executor);
} catch (Exception e) {
fail(e.getMessage());
}
});
public void testTcpSocketKeepalives() throws Exception {
runTestWithSerialExecutors(executor -> doTestTcpSocketKeepalivesWithExecutor(executor));
}
private void doTestTcpSocketKeepalivesWithExecutor(Executor executor) throws Exception {
@@ -4292,7 +4355,6 @@ public class ConnectivityServiceTest {
}
private void doTestNattSocketKeepalivesFdWithExecutor(Executor executor) throws Exception {
final int srcPort = 12345;
final InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
final InetAddress anyIPv4 = InetAddress.getByName("0.0.0.0");
final InetAddress dstIPv4 = InetAddress.getByName("8.8.8.8");
@@ -4311,7 +4373,8 @@ public class ConnectivityServiceTest {
// Prepare the target file descriptor, keep only one instance.
final IpSecManager mIpSec = (IpSecManager) mContext.getSystemService(Context.IPSEC_SERVICE);
final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket(srcPort);
final UdpEncapsulationSocket testSocket = mIpSec.openUdpEncapsulationSocket();
final int srcPort = testSocket.getPort();
final ParcelFileDescriptor testPfd =
ParcelFileDescriptor.dup(testSocket.getFileDescriptor());
testSocket.close();
@@ -4759,14 +4822,14 @@ public class ConnectivityServiceTest {
ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
// Clear any interactions that occur as a result of CS starting up.
reset(mNetworkManagementService);
reset(mMockDnsResolver);
final String[] EMPTY_STRING_ARRAY = new String[0];
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
waitForIdle();
verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
verifyNoMoreInteractions(mNetworkManagementService);
verify(mMockDnsResolver, never()).setResolverConfiguration(
anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""),
eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
verifyNoMoreInteractions(mMockDnsResolver);
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -4783,28 +4846,29 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.connect(false);
waitForIdle();
// CS tells netd about the empty DNS config for this network.
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
reset(mNetworkManagementService);
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""),
eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
reset(mMockDnsResolver);
cellLp.addDnsServer(InetAddress.getByName("2001:db8::1"));
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(""), tlsServers.capture());
eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
assertEquals(1, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "2001:db8::1"));
// Opportunistic mode.
assertTrue(ArrayUtils.contains(tlsServers.getValue(), "2001:db8::1"));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
cellLp.addDnsServer(InetAddress.getByName("192.0.2.1"));
mCellNetworkAgent.sendLinkProperties(cellLp);
waitForIdle();
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(""), tlsServers.capture());
eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
@@ -4812,7 +4876,7 @@ public class ConnectivityServiceTest {
assertEquals(2, tlsServers.getValue().length);
assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
final String TLS_SPECIFIER = "tls.example.com";
final String TLS_SERVER6 = "2001:db8:53::53";
@@ -4822,22 +4886,21 @@ public class ConnectivityServiceTest {
new PrivateDnsConfig(TLS_SPECIFIER, TLS_IPS).toParcel());
waitForIdle();
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(TLS_SPECIFIER), eq(TLS_SERVERS));
eq(TLS_SPECIFIER), eq(TLS_SERVERS), eq(EMPTY_STRING_ARRAY));
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
}
@Test
public void testPrivateDnsSettingsChange() throws Exception {
final String[] EMPTY_STRING_ARRAY = new String[0];
ArgumentCaptor<String[]> tlsServers = ArgumentCaptor.forClass(String[].class);
// Clear any interactions that occur as a result of CS starting up.
reset(mNetworkManagementService);
reset(mMockDnsResolver);
// The default on Android is opportunistic mode ("Automatic").
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
@@ -4850,9 +4913,10 @@ public class ConnectivityServiceTest {
mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
waitForIdle();
// CS tells netd about the empty DNS config for this network.
verify(mNetworkManagementService, never()).setDnsConfigurationForNetwork(
anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""), eq(EMPTY_STRING_ARRAY));
verifyNoMoreInteractions(mNetworkManagementService);
verify(mMockDnsResolver, never()).setResolverConfiguration(
anyInt(), eq(EMPTY_STRING_ARRAY), any(), any(), eq(""),
eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
verifyNoMoreInteractions(mMockDnsResolver);
final LinkProperties cellLp = new LinkProperties();
cellLp.setInterfaceName(MOBILE_IFNAME);
@@ -4871,9 +4935,9 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(false);
waitForIdle();
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(""), tlsServers.capture());
eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
@@ -4881,7 +4945,7 @@ public class ConnectivityServiceTest {
assertEquals(2, tlsServers.getValue().length);
assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
cellNetworkCallback.expectCallback(CallbackState.AVAILABLE, mCellNetworkAgent);
cellNetworkCallback.expectCallback(CallbackState.NETWORK_CAPABILITIES,
mCellNetworkAgent);
@@ -4893,26 +4957,26 @@ public class ConnectivityServiceTest {
assertNull(((LinkProperties)cbi.arg).getPrivateDnsServerName());
setPrivateDnsSettings(PRIVATE_DNS_MODE_OFF, "ignored.example.com");
verify(mNetworkManagementService, times(1)).setDnsConfigurationForNetwork(
verify(mMockDnsResolver, times(1)).setResolverConfiguration(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(""), eq(EMPTY_STRING_ARRAY));
eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
cellNetworkCallback.assertNoCallback();
setPrivateDnsSettings(PRIVATE_DNS_MODE_OPPORTUNISTIC, "ignored.example.com");
verify(mNetworkManagementService, atLeastOnce()).setDnsConfigurationForNetwork(
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
anyInt(), mStringArrayCaptor.capture(), any(), any(),
eq(""), tlsServers.capture());
eq(""), tlsServers.capture(), eq(EMPTY_STRING_ARRAY));
assertEquals(2, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.containsAll(mStringArrayCaptor.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
assertEquals(2, tlsServers.getValue().length);
assertTrue(ArrayUtils.containsAll(tlsServers.getValue(),
new String[]{"2001:db8::1", "192.0.2.1"}));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
cellNetworkCallback.assertNoCallback();
setPrivateDnsSettings(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME, "strict.example.com");
@@ -5743,6 +5807,7 @@ public class ConnectivityServiceTest {
cellLp.addRoute(new RouteInfo((IpPrefix) null, myIpv6.getAddress(), MOBILE_IFNAME));
cellLp.addRoute(new RouteInfo(myIpv6, null, MOBILE_IFNAME));
reset(mNetworkManagementService);
reset(mMockDnsResolver);
when(mNetworkManagementService.getInterfaceConfig(CLAT_PREFIX + MOBILE_IFNAME))
.thenReturn(getClatInterfaceConfig(myIpv4));
@@ -5750,7 +5815,7 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.sendLinkProperties(cellLp);
mCellNetworkAgent.connect(true);
networkCallback.expectAvailableThenValidatedCallbacks(mCellNetworkAgent);
verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
// Switching default network updates TCP buffer sizes.
verifyTcpBufferSizeChange(ConnectivityService.DEFAULT_TCP_BUFFER_SIZES);
@@ -5760,17 +5825,22 @@ public class ConnectivityServiceTest {
cellLp.addLinkAddress(myIpv4);
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, atLeastOnce()).setResolverConfiguration(
eq(cellNetId), eq(EMPTY_STRING_ARRAY), any(), any(),
eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
verifyNoMoreInteractions(mMockNetd);
verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockNetd);
reset(mMockDnsResolver);
// Remove IPv4 address. Expect prefix discovery to be started again.
cellLp.removeLinkAddress(myIpv4);
cellLp.removeRoute(new RouteInfo(myIpv4, null, MOBILE_IFNAME));
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
// When NAT64 prefix discovery succeeds, LinkProperties are updated and clatd is started.
Nat464Xlat clat = mService.getNat464Xlat(mCellNetworkAgent);
@@ -5800,6 +5870,12 @@ public class ConnectivityServiceTest {
assertNotEquals(stackedLpsAfterChange, Collections.EMPTY_LIST);
assertEquals(makeClatLinkProperties(myIpv4), stackedLpsAfterChange.get(0));
verify(mMockDnsResolver, times(1)).setResolverConfiguration(
eq(cellNetId), mStringArrayCaptor.capture(), any(), any(),
eq(""), eq(EMPTY_STRING_ARRAY), eq(EMPTY_STRING_ARRAY));
assertEquals(1, mStringArrayCaptor.getValue().length);
assertTrue(ArrayUtils.contains(mStringArrayCaptor.getValue(), "8.8.8.8"));
// Add ipv4 address, expect that clatd and prefix discovery are stopped and stacked
// linkproperties are cleaned up.
cellLp.addLinkAddress(myIpv4);
@@ -5807,7 +5883,7 @@ public class ConnectivityServiceTest {
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
verify(mMockNetd, times(1)).clatdStop(MOBILE_IFNAME);
verify(mMockNetd, times(1)).resolverStopPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, times(1)).stopPrefix64Discovery(cellNetId);
// As soon as stop is called, the linkproperties lose the stacked interface.
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
@@ -5822,7 +5898,9 @@ public class ConnectivityServiceTest {
networkCallback.assertNoCallback();
verifyNoMoreInteractions(mMockNetd);
verifyNoMoreInteractions(mMockDnsResolver);
reset(mMockNetd);
reset(mMockDnsResolver);
// Stopping prefix discovery causes netd to tell us that the NAT64 prefix is gone.
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, false /* added */,
@@ -5836,7 +5914,7 @@ public class ConnectivityServiceTest {
cellLp.removeDnsServer(InetAddress.getByName("8.8.8.8"));
mCellNetworkAgent.sendLinkProperties(cellLp);
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
verify(mMockNetd, times(1)).resolverStartPrefix64Discovery(cellNetId);
verify(mMockDnsResolver, times(1)).startPrefix64Discovery(cellNetId);
mService.mNetdEventCallback.onNat64PrefixEvent(cellNetId, true /* added */,
kNat64PrefixString, 96);
networkCallback.expectCallback(CallbackState.LINK_PROPERTIES, mCellNetworkAgent);
@@ -5919,6 +5997,7 @@ public class ConnectivityServiceTest {
// Disconnect cell
reset(mNetworkManagementService);
reset(mMockNetd);
mCellNetworkAgent.disconnect();
networkCallback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
// LOST callback is triggered earlier than removing idle timer. Broadcast should also be
@@ -5926,8 +6005,9 @@ public class ConnectivityServiceTest {
// unexpectedly before network being removed.
waitForIdle();
verify(mNetworkManagementService, times(0)).removeIdleTimer(eq(MOBILE_IFNAME));
verify(mNetworkManagementService, times(1)).removeNetwork(
eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockNetd, times(1)).networkDestroy(eq(mCellNetworkAgent.getNetwork().netId));
verify(mMockDnsResolver, times(1))
.clearResolverConfiguration(eq(mCellNetworkAgent.getNetwork().netId));
// Disconnect wifi
ConditionVariable cv = waitForConnectivityBroadcasts(1);

View File

@@ -29,13 +29,13 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.net.IDnsResolver;
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
import android.net.Network;
import android.net.RouteInfo;
import android.net.shared.PrivateDnsConfig;
import android.os.INetworkManagementService;
import android.provider.Settings;
import android.test.mock.MockContentResolver;
@@ -73,7 +73,7 @@ public class DnsManagerTest {
MockContentResolver mContentResolver;
@Mock Context mCtx;
@Mock INetworkManagementService mNMService;
@Mock IDnsResolver mMockDnsResolver;
@Mock MockableSystemProperties mSystemProperties;
@Before
@@ -83,7 +83,7 @@ public class DnsManagerTest {
mContentResolver.addProvider(Settings.AUTHORITY,
new FakeSettingsProvider());
when(mCtx.getContentResolver()).thenReturn(mContentResolver);
mDnsManager = new DnsManager(mCtx, mNMService, mSystemProperties);
mDnsManager = new DnsManager(mCtx, mMockDnsResolver, mSystemProperties);
// Clear the private DNS settings
Settings.Global.putString(mContentResolver, PRIVATE_DNS_DEFAULT_MODE, "");

View File

@@ -32,6 +32,7 @@ import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -69,6 +70,7 @@ public class LingerMonitorTest {
LingerMonitor mMonitor;
@Mock ConnectivityService mConnService;
@Mock IDnsResolver mDnsResolver;
@Mock INetd mNetd;
@Mock INetworkManagementService mNMS;
@Mock Context mCtx;
@@ -353,7 +355,7 @@ public class LingerMonitorTest {
caps.addCapability(0);
caps.addTransportType(transport);
NetworkAgentInfo nai = new NetworkAgentInfo(null, null, new Network(netId), info, null,
caps, 50, mCtx, null, mMisc, mConnService, mNetd, mNMS,
caps, 50, mCtx, null, mMisc, mConnService, mNetd, mDnsResolver, mNMS,
NetworkFactory.SerialNumber.NONE);
nai.everValidated = true;
return nai;

View File

@@ -27,6 +27,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.mockito.Mockito.when;
import android.net.ConnectivityManager;
import android.net.IDnsResolver;
import android.net.INetd;
import android.net.InterfaceConfiguration;
import android.net.IpPrefix;
@@ -63,6 +64,7 @@ public class Nat464XlatTest {
@Mock ConnectivityService mConnectivity;
@Mock NetworkMisc mMisc;
@Mock IDnsResolver mDnsResolver;
@Mock INetd mNetd;
@Mock INetworkManagementService mNms;
@Mock InterfaceConfiguration mConfig;
@@ -72,7 +74,7 @@ public class Nat464XlatTest {
Handler mHandler;
Nat464Xlat makeNat464Xlat() {
return new Nat464Xlat(mNai, mNetd, mNms) {
return new Nat464Xlat(mNai, mNetd, mDnsResolver, mNms) {
@Override protected int getNetId() {
return NETID;
}
@@ -205,7 +207,7 @@ public class Nat464XlatTest {
verify(mNms).unregisterObserver(eq(nat));
assertTrue(c.getValue().getStackedLinks().isEmpty());
assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
verify(mDnsResolver).stopPrefix64Discovery(eq(NETID));
assertIdle(nat);
// Stacked interface removed notification arrives and is ignored.
@@ -331,7 +333,7 @@ public class Nat464XlatTest {
verify(mNetd).clatdStop(eq(BASE_IFACE));
verify(mConnectivity, times(2)).handleUpdateLinkProperties(eq(mNai), c.capture());
verify(mNms).unregisterObserver(eq(nat));
verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
verify(mDnsResolver).stopPrefix64Discovery(eq(NETID));
assertTrue(c.getValue().getStackedLinks().isEmpty());
assertFalse(c.getValue().getAllInterfaceNames().contains(STACKED_IFACE));
assertIdle(nat);
@@ -358,7 +360,7 @@ public class Nat464XlatTest {
verify(mNetd).clatdStop(eq(BASE_IFACE));
verify(mNms).unregisterObserver(eq(nat));
verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
verify(mDnsResolver).stopPrefix64Discovery(eq(NETID));
assertIdle(nat);
// In-flight interface up notification arrives: no-op
@@ -390,7 +392,7 @@ public class Nat464XlatTest {
verify(mNetd).clatdStop(eq(BASE_IFACE));
verify(mNms).unregisterObserver(eq(nat));
verify(mNetd).resolverStopPrefix64Discovery(eq(NETID));
verify(mDnsResolver).stopPrefix64Discovery(eq(NETID));
assertIdle(nat);
verifyNoMoreInteractions(mNetd, mNms, mConnectivity);

View File

@@ -57,6 +57,7 @@ public class NetworkAttributesTest {
final NetworkAttributes na =
new NetworkAttributes(
(Inet4Address) Inet4Address.getByAddress(new byte[] {1, 2, 3, 4}),
System.currentTimeMillis() + 7_200_000,
"some hint",
Arrays.asList(Inet4Address.getByAddress(new byte[] {5, 6, 7, 8}),
Inet4Address.getByAddress(new byte[] {9, 0, 1, 2})),