Merge changes I3b6ee1db,I70e13303,I6fb7dfe4 into main
* changes: Simplify addRoutesToLocalNetwork calls Add LocalNetworkConfig Tell netd about local networks
This commit is contained in:
@@ -16,8 +16,6 @@
|
||||
|
||||
package android.net.ip;
|
||||
|
||||
import static android.net.RouteInfo.RTN_UNICAST;
|
||||
|
||||
import static com.android.net.module.util.NetworkStackConstants.ETHER_HEADER_LEN;
|
||||
import static com.android.net.module.util.NetworkStackConstants.ETHER_TYPE_IPV6;
|
||||
import static com.android.net.module.util.NetworkStackConstants.ICMPV6_ND_OPTION_MTU;
|
||||
@@ -42,12 +40,13 @@ import android.content.Context;
|
||||
import android.net.INetd;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.MacAddress;
|
||||
import android.net.RouteInfo;
|
||||
import android.net.ip.RouterAdvertisementDaemon.RaParams;
|
||||
import android.os.Handler;
|
||||
import android.os.HandlerThread;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.RemoteException;
|
||||
import android.os.ServiceSpecificException;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.filters.SmallTest;
|
||||
@@ -55,7 +54,6 @@ import androidx.test.runner.AndroidJUnit4;
|
||||
|
||||
import com.android.net.module.util.InterfaceParams;
|
||||
import com.android.net.module.util.Ipv6Utils;
|
||||
import com.android.net.module.util.NetdUtils;
|
||||
import com.android.net.module.util.Struct;
|
||||
import com.android.net.module.util.structs.EthernetHeader;
|
||||
import com.android.net.module.util.structs.Icmpv6Header;
|
||||
@@ -80,7 +78,6 @@ import java.net.Inet6Address;
|
||||
import java.net.InetAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@SmallTest
|
||||
@@ -332,10 +329,12 @@ public final class RouterAdvertisementDaemonTest {
|
||||
// Add a default route "fe80::/64 -> ::" to local network, otherwise, device will fail to
|
||||
// send the unicast RA out due to the ENETUNREACH error(No route to the peer's link-local
|
||||
// address is present).
|
||||
final String iface = mTetheredParams.name;
|
||||
final RouteInfo linkLocalRoute =
|
||||
new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST);
|
||||
NetdUtils.addRoutesToLocalNetwork(sNetd, iface, List.of(linkLocalRoute));
|
||||
try {
|
||||
sNetd.networkAddRoute(INetd.LOCAL_NET_ID, mTetheredParams.name,
|
||||
"fe80::/64", INetd.NEXTHOP_NONE);
|
||||
} catch (RemoteException | ServiceSpecificException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
final ByteBuffer rs = createRsPacket("fe80::1122:3344:5566:7788");
|
||||
mTetheredPacketReader.sendResponse(rs);
|
||||
|
||||
20
framework/aidl-export/android/net/LocalNetworkConfig.aidl
Normal file
20
framework/aidl-export/android/net/LocalNetworkConfig.aidl
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
*
|
||||
* Copyright (C) 2023 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;
|
||||
|
||||
@JavaOnlyStableParcelable parcelable LocalNetworkConfig;
|
||||
@@ -3811,11 +3811,28 @@ public class ConnectivityManager {
|
||||
@RequiresPermission(anyOf = {
|
||||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
|
||||
android.Manifest.permission.NETWORK_FACTORY})
|
||||
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo ni, LinkProperties lp,
|
||||
NetworkCapabilities nc, @NonNull NetworkScore score, NetworkAgentConfig config,
|
||||
int providerId) {
|
||||
public Network registerNetworkAgent(@NonNull INetworkAgent na, @NonNull NetworkInfo ni,
|
||||
@NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
|
||||
@NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId) {
|
||||
return registerNetworkAgent(na, ni, lp, nc, null /* localNetworkConfig */, score, config,
|
||||
providerId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
* Register a NetworkAgent with ConnectivityService.
|
||||
* @return Network corresponding to NetworkAgent.
|
||||
*/
|
||||
@RequiresPermission(anyOf = {
|
||||
NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
|
||||
android.Manifest.permission.NETWORK_FACTORY})
|
||||
public Network registerNetworkAgent(@NonNull INetworkAgent na, @NonNull NetworkInfo ni,
|
||||
@NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
|
||||
@NonNull NetworkAgentConfig config, int providerId) {
|
||||
try {
|
||||
return mService.registerNetworkAgent(na, ni, lp, nc, score, config, providerId);
|
||||
return mService.registerNetworkAgent(na, ni, lp, nc, score, localNetworkConfig, config,
|
||||
providerId);
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.net.INetworkOfferCallback;
|
||||
import android.net.IQosCallback;
|
||||
import android.net.ISocketKeepaliveCallback;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.LocalNetworkConfig;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkAgentConfig;
|
||||
import android.net.NetworkCapabilities;
|
||||
@@ -146,7 +147,8 @@ interface IConnectivityManager
|
||||
void declareNetworkRequestUnfulfillable(in NetworkRequest request);
|
||||
|
||||
Network registerNetworkAgent(in INetworkAgent na, in NetworkInfo ni, in LinkProperties lp,
|
||||
in NetworkCapabilities nc, in NetworkScore score, in NetworkAgentConfig config,
|
||||
in NetworkCapabilities nc, in NetworkScore score,
|
||||
in LocalNetworkConfig localNetworkConfig, in NetworkAgentConfig config,
|
||||
in int factorySerialNumber);
|
||||
|
||||
NetworkRequest requestNetwork(int uid, in NetworkCapabilities networkCapabilities, int reqType,
|
||||
|
||||
@@ -17,6 +17,7 @@ package android.net;
|
||||
|
||||
import android.net.DscpPolicy;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.LocalNetworkConfig;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.NetworkInfo;
|
||||
@@ -34,6 +35,7 @@ oneway interface INetworkAgentRegistry {
|
||||
void sendLinkProperties(in LinkProperties lp);
|
||||
// TODO: consider replacing this by "markConnected()" and removing
|
||||
void sendNetworkInfo(in NetworkInfo info);
|
||||
void sendLocalNetworkConfig(in LocalNetworkConfig config);
|
||||
void sendScore(in NetworkScore score);
|
||||
void sendExplicitlySelected(boolean explicitlySelected, boolean acceptPartial);
|
||||
void sendSocketKeepaliveEvent(int slot, int reason);
|
||||
|
||||
168
framework/src/android/net/LocalNetworkConfig.java
Normal file
168
framework/src/android/net/LocalNetworkConfig.java
Normal file
@@ -0,0 +1,168 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A class to communicate configuration info about a local network through {@link NetworkAgent}.
|
||||
* @hide
|
||||
*/
|
||||
// TODO : @SystemApi
|
||||
public final class LocalNetworkConfig implements Parcelable {
|
||||
@Nullable
|
||||
private final NetworkRequest mUpstreamSelector;
|
||||
|
||||
@NonNull
|
||||
private final MulticastRoutingConfig mUpstreamMulticastRoutingConfig;
|
||||
|
||||
@NonNull
|
||||
private final MulticastRoutingConfig mDownstreamMulticastRoutingConfig;
|
||||
|
||||
private LocalNetworkConfig(@Nullable final NetworkRequest upstreamSelector,
|
||||
@Nullable final MulticastRoutingConfig upstreamConfig,
|
||||
@Nullable final MulticastRoutingConfig downstreamConfig) {
|
||||
mUpstreamSelector = upstreamSelector;
|
||||
if (null != upstreamConfig) {
|
||||
mUpstreamMulticastRoutingConfig = upstreamConfig;
|
||||
} else {
|
||||
mUpstreamMulticastRoutingConfig = MulticastRoutingConfig.CONFIG_FORWARD_NONE;
|
||||
}
|
||||
if (null != downstreamConfig) {
|
||||
mDownstreamMulticastRoutingConfig = downstreamConfig;
|
||||
} else {
|
||||
mDownstreamMulticastRoutingConfig = MulticastRoutingConfig.CONFIG_FORWARD_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the request choosing which network traffic from this network is forwarded to and from.
|
||||
*
|
||||
* This may be null if the local network doesn't forward the traffic anywhere.
|
||||
*/
|
||||
@Nullable
|
||||
public NetworkRequest getUpstreamSelector() {
|
||||
return mUpstreamSelector;
|
||||
}
|
||||
|
||||
public @NonNull MulticastRoutingConfig getUpstreamMulticastRoutingConfig() {
|
||||
return mUpstreamMulticastRoutingConfig;
|
||||
}
|
||||
|
||||
public @NonNull MulticastRoutingConfig getDownstreamMulticastRoutingConfig() {
|
||||
return mDownstreamMulticastRoutingConfig;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(@NonNull final Parcel dest, final int flags) {
|
||||
dest.writeParcelable(mUpstreamSelector, flags);
|
||||
dest.writeParcelable(mUpstreamMulticastRoutingConfig, flags);
|
||||
dest.writeParcelable(mDownstreamMulticastRoutingConfig, flags);
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<LocalNetworkConfig> CREATOR = new Creator<>() {
|
||||
public LocalNetworkConfig createFromParcel(Parcel in) {
|
||||
final NetworkRequest upstreamSelector = in.readParcelable(null);
|
||||
final MulticastRoutingConfig upstreamConfig = in.readParcelable(null);
|
||||
final MulticastRoutingConfig downstreamConfig = in.readParcelable(null);
|
||||
return new LocalNetworkConfig(
|
||||
upstreamSelector, upstreamConfig, downstreamConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
public LocalNetworkConfig[] newArray(final int size) {
|
||||
return new LocalNetworkConfig[size];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
public static final class Builder {
|
||||
@Nullable
|
||||
NetworkRequest mUpstreamSelector;
|
||||
|
||||
@Nullable
|
||||
MulticastRoutingConfig mUpstreamMulticastRoutingConfig;
|
||||
|
||||
@Nullable
|
||||
MulticastRoutingConfig mDownstreamMulticastRoutingConfig;
|
||||
|
||||
/**
|
||||
* Create a Builder
|
||||
*/
|
||||
public Builder() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to choose where this local network should forward its traffic to.
|
||||
*
|
||||
* The system will automatically choose the best network matching the request as an
|
||||
* upstream, and set up forwarding between this local network and the chosen upstream.
|
||||
* If no network matches the request, there is no upstream and the traffic is not forwarded.
|
||||
* The caller can know when this changes by listening to link properties changes of
|
||||
* this network with the {@link android.net.LinkProperties#getForwardedNetwork()} getter.
|
||||
*
|
||||
* Set this to null if the local network shouldn't be forwarded. Default is null.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setUpstreamSelector(@Nullable NetworkRequest upstreamSelector) {
|
||||
mUpstreamSelector = upstreamSelector;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the upstream multicast routing config.
|
||||
*
|
||||
* If null, don't route multicast packets upstream. This is equivalent to a
|
||||
* MulticastRoutingConfig in mode FORWARD_NONE. The default is null.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setUpstreamMulticastRoutingConfig(@Nullable MulticastRoutingConfig cfg) {
|
||||
mUpstreamMulticastRoutingConfig = cfg;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the downstream multicast routing config.
|
||||
*
|
||||
* If null, don't route multicast packets downstream. This is equivalent to a
|
||||
* MulticastRoutingConfig in mode FORWARD_NONE. The default is null.
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setDownstreamMulticastRoutingConfig(@Nullable MulticastRoutingConfig cfg) {
|
||||
mDownstreamMulticastRoutingConfig = cfg;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the LocalNetworkConfig object.
|
||||
*/
|
||||
@NonNull
|
||||
public LocalNetworkConfig build() {
|
||||
return new LocalNetworkConfig(mUpstreamSelector,
|
||||
mUpstreamMulticastRoutingConfig,
|
||||
mDownstreamMulticastRoutingConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
264
framework/src/android/net/MulticastRoutingConfig.java
Normal file
264
framework/src/android/net/MulticastRoutingConfig.java
Normal file
@@ -0,0 +1,264 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.net.Inet6Address;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A class representing a configuration for multicast routing.
|
||||
*
|
||||
* Internal usage to Connectivity
|
||||
* @hide
|
||||
*/
|
||||
// TODO : @SystemApi
|
||||
public class MulticastRoutingConfig implements Parcelable {
|
||||
private static final String TAG = MulticastRoutingConfig.class.getSimpleName();
|
||||
|
||||
/** Do not forward any multicast packets. */
|
||||
public static final int FORWARD_NONE = 0;
|
||||
/**
|
||||
* Forward only multicast packets with destination in the list of listening addresses.
|
||||
* Ignore the min scope.
|
||||
*/
|
||||
public static final int FORWARD_SELECTED = 1;
|
||||
/**
|
||||
* Forward all multicast packets with scope greater or equal than the min scope.
|
||||
* Ignore the list of listening addresses.
|
||||
*/
|
||||
public static final int FORWARD_WITH_MIN_SCOPE = 2;
|
||||
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
@IntDef(prefix = { "FORWARD_" }, value = {
|
||||
FORWARD_NONE,
|
||||
FORWARD_SELECTED,
|
||||
FORWARD_WITH_MIN_SCOPE
|
||||
})
|
||||
public @interface MulticastForwardingMode {}
|
||||
|
||||
/**
|
||||
* Not a multicast scope, for configurations that do not use the min scope.
|
||||
*/
|
||||
public static final int MULTICAST_SCOPE_NONE = -1;
|
||||
|
||||
public static final MulticastRoutingConfig CONFIG_FORWARD_NONE =
|
||||
new MulticastRoutingConfig(FORWARD_NONE, MULTICAST_SCOPE_NONE, null);
|
||||
|
||||
@MulticastForwardingMode
|
||||
private final int mForwardingMode;
|
||||
|
||||
private final int mMinScope;
|
||||
|
||||
@NonNull
|
||||
private final Set<Inet6Address> mListeningAddresses;
|
||||
|
||||
private MulticastRoutingConfig(@MulticastForwardingMode final int mode, final int scope,
|
||||
@Nullable final Set<Inet6Address> addresses) {
|
||||
mForwardingMode = mode;
|
||||
mMinScope = scope;
|
||||
if (null != addresses) {
|
||||
mListeningAddresses = Collections.unmodifiableSet(new ArraySet<>(addresses));
|
||||
} else {
|
||||
mListeningAddresses = Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the forwarding mode.
|
||||
*/
|
||||
@MulticastForwardingMode
|
||||
public int getForwardingMode() {
|
||||
return mForwardingMode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the minimal group address scope that is allowed for forwarding.
|
||||
* If the forwarding mode is not FORWARD_WITH_MIN_SCOPE, will be MULTICAST_SCOPE_NONE.
|
||||
*/
|
||||
public int getMinScope() {
|
||||
return mMinScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the list of group addresses listened by the outgoing interface.
|
||||
* The list will be empty if the forwarding mode is not FORWARD_SELECTED.
|
||||
*/
|
||||
@NonNull
|
||||
public Set<Inet6Address> getMulticastListeningAddresses() {
|
||||
return mListeningAddresses;
|
||||
}
|
||||
|
||||
private MulticastRoutingConfig(Parcel in) {
|
||||
mForwardingMode = in.readInt();
|
||||
mMinScope = in.readInt();
|
||||
final int count = in.readInt();
|
||||
final ArraySet<Inet6Address> listeningAddresses = new ArraySet<>(count);
|
||||
final byte[] buffer = new byte[16]; // Size of an Inet6Address
|
||||
for (int i = 0; i < count; ++i) {
|
||||
in.readByteArray(buffer);
|
||||
try {
|
||||
listeningAddresses.add((Inet6Address) Inet6Address.getByAddress(buffer));
|
||||
} catch (UnknownHostException e) {
|
||||
Log.wtf(TAG, "Can't read inet6address : " + Arrays.toString(buffer));
|
||||
}
|
||||
}
|
||||
mListeningAddresses = Collections.unmodifiableSet(listeningAddresses);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(mForwardingMode);
|
||||
dest.writeInt(mMinScope);
|
||||
dest.writeInt(mListeningAddresses.size());
|
||||
for (final Inet6Address addr : mListeningAddresses) {
|
||||
dest.writeByteArray(addr.getAddress());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static final Creator<MulticastRoutingConfig> CREATOR = new Creator<>() {
|
||||
@Override
|
||||
public MulticastRoutingConfig createFromParcel(Parcel in) {
|
||||
return new MulticastRoutingConfig(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MulticastRoutingConfig[] newArray(int size) {
|
||||
return new MulticastRoutingConfig[size];
|
||||
}
|
||||
};
|
||||
|
||||
public static class Builder {
|
||||
@MulticastForwardingMode
|
||||
private final int mForwardingMode;
|
||||
private int mMinScope;
|
||||
private final ArraySet<Inet6Address> mListeningAddresses;
|
||||
|
||||
private Builder(@MulticastForwardingMode final int mode, int scope) {
|
||||
mForwardingMode = mode;
|
||||
mMinScope = scope;
|
||||
mListeningAddresses = new ArraySet<>();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder that forwards nothing.
|
||||
* No properties can be set on such a builder.
|
||||
*/
|
||||
public static Builder newBuilderForwardingNone() {
|
||||
return new Builder(FORWARD_NONE, MULTICAST_SCOPE_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder that forwards packets above a certain scope
|
||||
*
|
||||
* The scope can be changed on this builder, but not the listening addresses.
|
||||
* @param scope the initial scope
|
||||
*/
|
||||
public static Builder newBuilderWithMinScope(final int scope) {
|
||||
return new Builder(FORWARD_WITH_MIN_SCOPE, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a builder that forwards a specified list of listening addresses.
|
||||
*
|
||||
* Addresses can be added and removed from this builder, but the scope can't be set.
|
||||
*/
|
||||
public static Builder newBuilderWithListeningAddresses() {
|
||||
return new Builder(FORWARD_SELECTED, MULTICAST_SCOPE_NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the minimum scope for this multicast routing config.
|
||||
* This is only meaningful (indeed, allowed) for configs in FORWARD_WITH_MIN_SCOPE mode.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder setMinimumScope(final int scope) {
|
||||
if (FORWARD_WITH_MIN_SCOPE != mForwardingMode) {
|
||||
throw new IllegalArgumentException("Can't set the scope on a builder in mode "
|
||||
+ modeToString(mForwardingMode));
|
||||
}
|
||||
mMinScope = scope;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an address to the set of listening addresses.
|
||||
*
|
||||
* This is only meaningful (indeed, allowed) for configs in FORWARD_SELECTED mode.
|
||||
* If this address was already added, this is a no-op.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder addListeningAddress(@NonNull final Inet6Address address) {
|
||||
if (FORWARD_SELECTED != mForwardingMode) {
|
||||
throw new IllegalArgumentException("Can't add an address on a builder in mode "
|
||||
+ modeToString(mForwardingMode));
|
||||
}
|
||||
// TODO : should we check that this is a multicast address ?
|
||||
mListeningAddresses.add(address);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an address from the set of listening addresses.
|
||||
*
|
||||
* This is only meaningful (indeed, allowed) for configs in FORWARD_SELECTED mode.
|
||||
* If this address was not added, or was already removed, this is a no-op.
|
||||
* @return this builder
|
||||
*/
|
||||
public Builder removeListeningAddress(@NonNull final Inet6Address address) {
|
||||
if (FORWARD_SELECTED != mForwardingMode) {
|
||||
throw new IllegalArgumentException("Can't remove an address on a builder in mode "
|
||||
+ modeToString(mForwardingMode));
|
||||
}
|
||||
mListeningAddresses.remove(address);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the config.
|
||||
*/
|
||||
public MulticastRoutingConfig build() {
|
||||
return new MulticastRoutingConfig(mForwardingMode, mMinScope, mListeningAddresses);
|
||||
}
|
||||
}
|
||||
|
||||
private static String modeToString(@MulticastForwardingMode final int mode) {
|
||||
switch (mode) {
|
||||
case FORWARD_NONE: return "FORWARD_NONE";
|
||||
case FORWARD_SELECTED: return "FORWARD_SELECTED";
|
||||
case FORWARD_WITH_MIN_SCOPE: return "FORWARD_WITH_MIN_SCOPE";
|
||||
default: return "unknown multicast routing mode " + mode;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@ public abstract class NetworkAgent {
|
||||
|
||||
/**
|
||||
* Sent by the NetworkAgent to ConnectivityService to pass the current
|
||||
* NetworkCapabilties.
|
||||
* NetworkCapabilities.
|
||||
* obj = NetworkCapabilities
|
||||
* @hide
|
||||
*/
|
||||
@@ -442,6 +442,14 @@ public abstract class NetworkAgent {
|
||||
*/
|
||||
public static final int EVENT_UNREGISTER_AFTER_REPLACEMENT = BASE + 29;
|
||||
|
||||
/**
|
||||
* Sent by the NetworkAgent to ConnectivityService to pass the new value of the local
|
||||
* network agent config.
|
||||
* obj = {@code Pair<NetworkAgentInfo, LocalNetworkConfig>}
|
||||
* @hide
|
||||
*/
|
||||
public static final int EVENT_LOCAL_NETWORK_CONFIG_CHANGED = BASE + 30;
|
||||
|
||||
/**
|
||||
* DSCP policy was successfully added.
|
||||
*/
|
||||
@@ -517,20 +525,47 @@ public abstract class NetworkAgent {
|
||||
@NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
|
||||
@NonNull NetworkScore score, @NonNull NetworkAgentConfig config,
|
||||
@Nullable NetworkProvider provider) {
|
||||
this(looper, context, logTag, nc, lp, score, config,
|
||||
this(context, looper, logTag, nc, lp, null /* localNetworkConfig */, score, config,
|
||||
provider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new network agent.
|
||||
* @param context a {@link Context} to get system services from.
|
||||
* @param looper the {@link Looper} on which to invoke the callbacks.
|
||||
* @param logTag the tag for logs
|
||||
* @param nc the initial {@link NetworkCapabilities} of this network. Update with
|
||||
* sendNetworkCapabilities.
|
||||
* @param lp the initial {@link LinkProperties} of this network. Update with sendLinkProperties.
|
||||
* @param localNetworkConfig the initial {@link LocalNetworkConfig} of this
|
||||
* network. Update with sendLocalNetworkConfig. Must be
|
||||
* non-null iff the nc have NET_CAPABILITY_LOCAL_NETWORK.
|
||||
* @param score the initial score of this network. Update with sendNetworkScore.
|
||||
* @param config an immutable {@link NetworkAgentConfig} for this agent.
|
||||
* @param provider the {@link NetworkProvider} managing this agent.
|
||||
* @hide
|
||||
*/
|
||||
// TODO : expose
|
||||
public NetworkAgent(@NonNull Context context, @NonNull Looper looper, @NonNull String logTag,
|
||||
@NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
|
||||
@NonNull NetworkAgentConfig config, @Nullable NetworkProvider provider) {
|
||||
this(looper, context, logTag, nc, lp, localNetworkConfig, score, config,
|
||||
provider == null ? NetworkProvider.ID_NONE : provider.getProviderId(),
|
||||
getLegacyNetworkInfo(config));
|
||||
}
|
||||
|
||||
private static class InitialConfiguration {
|
||||
public final Context context;
|
||||
public final NetworkCapabilities capabilities;
|
||||
public final LinkProperties properties;
|
||||
public final NetworkScore score;
|
||||
public final NetworkAgentConfig config;
|
||||
public final NetworkInfo info;
|
||||
@NonNull public final Context context;
|
||||
@NonNull public final NetworkCapabilities capabilities;
|
||||
@NonNull public final LinkProperties properties;
|
||||
@NonNull public final NetworkScore score;
|
||||
@NonNull public final NetworkAgentConfig config;
|
||||
@NonNull public final NetworkInfo info;
|
||||
@Nullable public final LocalNetworkConfig localNetworkConfig;
|
||||
InitialConfiguration(@NonNull Context context, @NonNull NetworkCapabilities capabilities,
|
||||
@NonNull LinkProperties properties, @NonNull NetworkScore score,
|
||||
@NonNull LinkProperties properties,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
|
||||
@NonNull NetworkAgentConfig config, @NonNull NetworkInfo info) {
|
||||
this.context = context;
|
||||
this.capabilities = capabilities;
|
||||
@@ -538,14 +573,15 @@ public abstract class NetworkAgent {
|
||||
this.score = score;
|
||||
this.config = config;
|
||||
this.info = info;
|
||||
this.localNetworkConfig = localNetworkConfig;
|
||||
}
|
||||
}
|
||||
private volatile InitialConfiguration mInitialConfiguration;
|
||||
|
||||
private NetworkAgent(@NonNull Looper looper, @NonNull Context context, @NonNull String logTag,
|
||||
@NonNull NetworkCapabilities nc, @NonNull LinkProperties lp,
|
||||
@NonNull NetworkScore score, @NonNull NetworkAgentConfig config, int providerId,
|
||||
@NonNull NetworkInfo ni) {
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, @NonNull NetworkScore score,
|
||||
@NonNull NetworkAgentConfig config, int providerId, @NonNull NetworkInfo ni) {
|
||||
mHandler = new NetworkAgentHandler(looper);
|
||||
LOG_TAG = logTag;
|
||||
mNetworkInfo = new NetworkInfo(ni);
|
||||
@@ -556,7 +592,7 @@ public abstract class NetworkAgent {
|
||||
|
||||
mInitialConfiguration = new InitialConfiguration(context,
|
||||
new NetworkCapabilities(nc, NetworkCapabilities.REDACT_NONE),
|
||||
new LinkProperties(lp), score, config, ni);
|
||||
new LinkProperties(lp), localNetworkConfig, score, config, ni);
|
||||
}
|
||||
|
||||
private class NetworkAgentHandler extends Handler {
|
||||
@@ -723,7 +759,8 @@ public abstract class NetworkAgent {
|
||||
mNetwork = cm.registerNetworkAgent(new NetworkAgentBinder(mHandler),
|
||||
new NetworkInfo(mInitialConfiguration.info),
|
||||
mInitialConfiguration.properties, mInitialConfiguration.capabilities,
|
||||
mInitialConfiguration.score, mInitialConfiguration.config, providerId);
|
||||
mInitialConfiguration.localNetworkConfig, mInitialConfiguration.score,
|
||||
mInitialConfiguration.config, providerId);
|
||||
mInitialConfiguration = null; // All this memory can now be GC'd
|
||||
}
|
||||
return mNetwork;
|
||||
@@ -1098,6 +1135,18 @@ public abstract class NetworkAgent {
|
||||
queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc));
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called by the agent when the network's {@link LocalNetworkConfig} changes.
|
||||
* @param config the new LocalNetworkConfig
|
||||
* @hide
|
||||
*/
|
||||
public void sendLocalNetworkConfig(@NonNull LocalNetworkConfig config) {
|
||||
Objects.requireNonNull(config);
|
||||
// If the agent doesn't have NET_CAPABILITY_LOCAL_NETWORK, this will be ignored by
|
||||
// ConnectivityService with a Log.wtf.
|
||||
queueOrSendMessage(reg -> reg.sendLocalNetworkConfig(config));
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be called by the agent to update the score of this network.
|
||||
*
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.android.server;
|
||||
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
|
||||
import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
|
||||
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
|
||||
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
|
||||
import static android.content.pm.PackageManager.FEATURE_WATCH;
|
||||
import static android.content.pm.PackageManager.FEATURE_WIFI;
|
||||
import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
|
||||
@@ -67,6 +68,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
|
||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
|
||||
@@ -159,6 +161,7 @@ import android.net.InetAddresses;
|
||||
import android.net.IpMemoryStore;
|
||||
import android.net.IpPrefix;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.LocalNetworkConfig;
|
||||
import android.net.MatchAllNetworkSpecifier;
|
||||
import android.net.NativeNetworkConfig;
|
||||
import android.net.NativeNetworkType;
|
||||
@@ -1773,7 +1776,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
mNoServiceNetwork = new NetworkAgentInfo(null,
|
||||
new Network(INetd.UNREACHABLE_NET_ID),
|
||||
new NetworkInfo(TYPE_NONE, 0, "", ""),
|
||||
new LinkProperties(), new NetworkCapabilities(),
|
||||
new LinkProperties(), new NetworkCapabilities(), null /* localNetworkConfig */,
|
||||
new NetworkScore.Builder().setLegacyInt(0).build(), mContext, null,
|
||||
new NetworkAgentConfig(), this, null, null, 0, INVALID_UID,
|
||||
mLingerDelayMs, mQosCallbackTracker, mDeps);
|
||||
@@ -4121,6 +4124,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
updateNetworkInfo(nai, info);
|
||||
break;
|
||||
}
|
||||
case NetworkAgent.EVENT_LOCAL_NETWORK_CONFIG_CHANGED: {
|
||||
final LocalNetworkConfig config = (LocalNetworkConfig) arg.second;
|
||||
updateLocalNetworkConfig(nai, config);
|
||||
break;
|
||||
}
|
||||
case NetworkAgent.EVENT_NETWORK_SCORE_CHANGED: {
|
||||
updateNetworkScore(nai, (NetworkScore) arg.second);
|
||||
break;
|
||||
@@ -5006,7 +5014,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
!nai.networkAgentConfig.allowBypass /* secure */,
|
||||
getVpnType(nai), nai.networkAgentConfig.excludeLocalRouteVpn);
|
||||
} else {
|
||||
config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.PHYSICAL,
|
||||
final boolean hasLocalCap =
|
||||
nai.networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK);
|
||||
config = new NativeNetworkConfig(nai.network.getNetId(),
|
||||
hasLocalCap ? NativeNetworkType.PHYSICAL_LOCAL : NativeNetworkType.PHYSICAL,
|
||||
getNetworkPermission(nai.networkCapabilities),
|
||||
false /* secure */,
|
||||
VpnManager.TYPE_VPN_NONE,
|
||||
@@ -8056,6 +8067,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
return nai == getDefaultNetwork();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether local agents are supported on this device.
|
||||
*
|
||||
* Local agents are supported from U on TVs, and from V on all devices.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
public boolean areLocalAgentsSupported() {
|
||||
final PackageManager pm = mContext.getPackageManager();
|
||||
// Local agents are supported starting on U on TVs and on V on everything else.
|
||||
return mDeps.isAtLeastV() || (mDeps.isAtLeastU() && pm.hasSystemFeature(FEATURE_LEANBACK));
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a new agent with ConnectivityService to handle a network.
|
||||
*
|
||||
@@ -8067,13 +8090,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
* @param networkCapabilities the initial capabilites of this network. They can be updated
|
||||
* later : see {@link #updateCapabilities}.
|
||||
* @param initialScore the initial score of the network. See {@link NetworkAgentInfo#getScore}.
|
||||
* @param localNetworkConfig config about this local network, or null if not a local network
|
||||
* @param networkAgentConfig metadata about the network. This is never updated.
|
||||
* @param providerId the ID of the provider owning this NetworkAgent.
|
||||
* @return the network created for this agent.
|
||||
*/
|
||||
public Network registerNetworkAgent(INetworkAgent na, NetworkInfo networkInfo,
|
||||
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
|
||||
@NonNull NetworkScore initialScore, NetworkAgentConfig networkAgentConfig,
|
||||
public Network registerNetworkAgent(INetworkAgent na,
|
||||
NetworkInfo networkInfo,
|
||||
LinkProperties linkProperties,
|
||||
NetworkCapabilities networkCapabilities,
|
||||
@NonNull NetworkScore initialScore,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig,
|
||||
NetworkAgentConfig networkAgentConfig,
|
||||
int providerId) {
|
||||
Objects.requireNonNull(networkInfo, "networkInfo must not be null");
|
||||
Objects.requireNonNull(linkProperties, "linkProperties must not be null");
|
||||
@@ -8085,12 +8113,26 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
} else {
|
||||
enforceNetworkFactoryPermission();
|
||||
}
|
||||
final boolean hasLocalCap =
|
||||
networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK);
|
||||
if (hasLocalCap && !areLocalAgentsSupported()) {
|
||||
// Before U, netd doesn't support PHYSICAL_LOCAL networks so this can't work.
|
||||
throw new IllegalArgumentException("Local agents are not supported in this version");
|
||||
}
|
||||
final boolean hasLocalNetworkConfig = null != localNetworkConfig;
|
||||
if (hasLocalCap != hasLocalNetworkConfig) {
|
||||
throw new IllegalArgumentException(null != localNetworkConfig
|
||||
? "Only local network agents can have a LocalNetworkConfig"
|
||||
: "Local network agents must have a LocalNetworkConfig"
|
||||
);
|
||||
}
|
||||
|
||||
final int uid = mDeps.getCallingUid();
|
||||
final long token = Binder.clearCallingIdentity();
|
||||
try {
|
||||
return registerNetworkAgentInternal(na, networkInfo, linkProperties,
|
||||
networkCapabilities, initialScore, networkAgentConfig, providerId, uid);
|
||||
networkCapabilities, initialScore, networkAgentConfig, localNetworkConfig,
|
||||
providerId, uid);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(token);
|
||||
}
|
||||
@@ -8098,7 +8140,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
|
||||
private Network registerNetworkAgentInternal(INetworkAgent na, NetworkInfo networkInfo,
|
||||
LinkProperties linkProperties, NetworkCapabilities networkCapabilities,
|
||||
NetworkScore currentScore, NetworkAgentConfig networkAgentConfig, int providerId,
|
||||
NetworkScore currentScore, NetworkAgentConfig networkAgentConfig,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig, int providerId,
|
||||
int uid) {
|
||||
|
||||
// Make a copy of the passed NI, LP, NC as the caller may hold a reference to them
|
||||
@@ -8106,6 +8149,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
final NetworkInfo niCopy = new NetworkInfo(networkInfo);
|
||||
final NetworkCapabilities ncCopy = new NetworkCapabilities(networkCapabilities);
|
||||
final LinkProperties lpCopy = new LinkProperties(linkProperties);
|
||||
// No need to copy |localNetworkConfiguration| as it is immutable.
|
||||
|
||||
// At this point the capabilities/properties are untrusted and unverified, e.g. checks that
|
||||
// the capabilities' access UIDs comply with security limitations. They will be sanitized
|
||||
@@ -8113,9 +8157,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// because some of the checks must happen on the handler thread.
|
||||
final NetworkAgentInfo nai = new NetworkAgentInfo(na,
|
||||
new Network(mNetIdManager.reserveNetId()), niCopy, lpCopy, ncCopy,
|
||||
currentScore, mContext, mTrackerHandler, new NetworkAgentConfig(networkAgentConfig),
|
||||
this, mNetd, mDnsResolver, providerId, uid, mLingerDelayMs,
|
||||
mQosCallbackTracker, mDeps);
|
||||
localNetworkConfig, currentScore, mContext, mTrackerHandler,
|
||||
new NetworkAgentConfig(networkAgentConfig), this, mNetd, mDnsResolver, providerId,
|
||||
uid, mLingerDelayMs, mQosCallbackTracker, mDeps);
|
||||
|
||||
final String extraInfo = niCopy.getExtraInfo();
|
||||
final String name = TextUtils.isEmpty(extraInfo)
|
||||
@@ -8850,6 +8894,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
updateCapabilities(nai.getScore(), nai, nai.networkCapabilities);
|
||||
}
|
||||
|
||||
private void updateLocalNetworkConfig(@NonNull final NetworkAgentInfo nai,
|
||||
@NonNull final LocalNetworkConfig config) {
|
||||
if (!nai.networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK)) {
|
||||
Log.wtf(TAG, "Ignoring update of a local network info on non-local network " + nai);
|
||||
return;
|
||||
}
|
||||
// TODO : actually apply the diff.
|
||||
nai.localNetworkConfig = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interface which requires VPN isolation (ingress interface filtering).
|
||||
*
|
||||
@@ -9190,7 +9244,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// are Type.LISTEN, but should not have NetworkCallbacks invoked.
|
||||
return;
|
||||
}
|
||||
Bundle bundle = new Bundle();
|
||||
final Bundle bundle = new Bundle();
|
||||
// TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects.
|
||||
// TODO: check if defensive copies of data is needed.
|
||||
final NetworkRequest nrForCallback = nri.getNetworkRequestForCallback();
|
||||
|
||||
@@ -35,6 +35,7 @@ import android.net.INetworkAgent;
|
||||
import android.net.INetworkAgentRegistry;
|
||||
import android.net.INetworkMonitor;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.LocalNetworkConfig;
|
||||
import android.net.NattKeepalivePacketData;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkAgent;
|
||||
@@ -64,7 +65,6 @@ import android.util.SparseArray;
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.internal.util.WakeupMessage;
|
||||
import com.android.modules.utils.build.SdkLevel;
|
||||
import com.android.server.ConnectivityService;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
@@ -174,6 +174,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
// TODO: make this private with a getter.
|
||||
@NonNull public NetworkCapabilities networkCapabilities;
|
||||
@NonNull public final NetworkAgentConfig networkAgentConfig;
|
||||
@Nullable public LocalNetworkConfig localNetworkConfig;
|
||||
|
||||
// Underlying networks declared by the agent.
|
||||
// The networks in this list might be declared by a VPN using setUnderlyingNetworks and are
|
||||
@@ -470,8 +471,8 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
+ networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid());
|
||||
nc.setOwnerUid(networkCapabilities.getOwnerUid());
|
||||
}
|
||||
restrictCapabilitiesFromNetworkAgent(
|
||||
nc, creatorUid, mHasAutomotiveFeature, carrierPrivilegeAuthenticator);
|
||||
restrictCapabilitiesFromNetworkAgent(nc, creatorUid, mHasAutomotiveFeature,
|
||||
mConnServiceDeps, carrierPrivilegeAuthenticator);
|
||||
return nc;
|
||||
}
|
||||
|
||||
@@ -601,6 +602,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
private static final String TAG = ConnectivityService.class.getSimpleName();
|
||||
private static final boolean VDBG = false;
|
||||
private final ConnectivityService mConnService;
|
||||
private final ConnectivityService.Dependencies mConnServiceDeps;
|
||||
private final Context mContext;
|
||||
private final Handler mHandler;
|
||||
private final QosCallbackTracker mQosCallbackTracker;
|
||||
@@ -609,6 +611,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
|
||||
public NetworkAgentInfo(INetworkAgent na, Network net, NetworkInfo info,
|
||||
@NonNull LinkProperties lp, @NonNull NetworkCapabilities nc,
|
||||
@Nullable LocalNetworkConfig localNetworkConfig,
|
||||
@NonNull NetworkScore score, Context context,
|
||||
Handler handler, NetworkAgentConfig config, ConnectivityService connService, INetd netd,
|
||||
IDnsResolver dnsResolver, int factorySerialNumber, int creatorUid,
|
||||
@@ -626,8 +629,10 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
networkInfo = info;
|
||||
linkProperties = lp;
|
||||
networkCapabilities = nc;
|
||||
this.localNetworkConfig = localNetworkConfig;
|
||||
networkAgentConfig = config;
|
||||
mConnService = connService;
|
||||
mConnServiceDeps = deps;
|
||||
setScore(score); // uses members connService, networkCapabilities and networkAgentConfig
|
||||
clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
|
||||
mContext = context;
|
||||
@@ -903,6 +908,12 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
new Pair<>(NetworkAgentInfo.this, info)).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendLocalNetworkConfig(@NonNull final LocalNetworkConfig config) {
|
||||
mHandler.obtainMessage(NetworkAgent.EVENT_LOCAL_NETWORK_CONFIG_CHANGED,
|
||||
new Pair<>(NetworkAgentInfo.this, config)).sendToTarget();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendScore(@NonNull final NetworkScore score) {
|
||||
mHandler.obtainMessage(NetworkAgent.EVENT_NETWORK_SCORE_CHANGED,
|
||||
@@ -1518,23 +1529,26 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
*/
|
||||
public static void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
|
||||
final int creatorUid, final boolean hasAutomotiveFeature,
|
||||
@NonNull final ConnectivityService.Dependencies deps,
|
||||
@Nullable final CarrierPrivilegeAuthenticator authenticator) {
|
||||
if (nc.hasTransport(TRANSPORT_TEST)) {
|
||||
nc.restrictCapabilitiesForTestNetwork(creatorUid);
|
||||
}
|
||||
if (!areAllowedUidsAcceptableFromNetworkAgent(nc, hasAutomotiveFeature, authenticator)) {
|
||||
if (!areAllowedUidsAcceptableFromNetworkAgent(
|
||||
nc, hasAutomotiveFeature, deps, authenticator)) {
|
||||
nc.setAllowedUids(new ArraySet<>());
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean areAllowedUidsAcceptableFromNetworkAgent(
|
||||
@NonNull final NetworkCapabilities nc, final boolean hasAutomotiveFeature,
|
||||
@NonNull final ConnectivityService.Dependencies deps,
|
||||
@Nullable final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {
|
||||
// NCs without access UIDs are fine.
|
||||
if (!nc.hasAllowedUids()) return true;
|
||||
// S and below must never accept access UIDs, even if an agent sends them, because netd
|
||||
// didn't support the required feature in S.
|
||||
if (!SdkLevel.isAtLeastT()) return false;
|
||||
if (!deps.isAtLeastT()) return false;
|
||||
|
||||
// On a non-restricted network, access UIDs make no sense
|
||||
if (nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) return false;
|
||||
|
||||
@@ -159,9 +159,11 @@ public class NetdUtils {
|
||||
throws RemoteException, ServiceSpecificException {
|
||||
netd.tetherInterfaceAdd(iface);
|
||||
networkAddInterface(netd, iface, maxAttempts, pollingIntervalMs);
|
||||
List<RouteInfo> routes = new ArrayList<>();
|
||||
routes.add(new RouteInfo(dest, null, iface, RTN_UNICAST));
|
||||
addRoutesToLocalNetwork(netd, iface, routes);
|
||||
// Activate a route to dest and IPv6 link local.
|
||||
modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID,
|
||||
new RouteInfo(dest, null, iface, RTN_UNICAST));
|
||||
modifyRoute(netd, ModifyOperation.ADD, INetd.LOCAL_NET_ID,
|
||||
new RouteInfo(new IpPrefix("fe80::/64"), null, iface, RTN_UNICAST));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -704,6 +704,7 @@ class NetworkAgentTest {
|
||||
argThat<NetworkInfo> { it.detailedState == NetworkInfo.DetailedState.CONNECTING },
|
||||
any(LinkProperties::class.java),
|
||||
any(NetworkCapabilities::class.java),
|
||||
any(), // LocalNetworkConfig TODO : specify when it's public
|
||||
any(NetworkScore::class.java),
|
||||
any(NetworkAgentConfig::class.java),
|
||||
eq(NetworkProvider.ID_NONE))
|
||||
|
||||
@@ -12819,7 +12819,8 @@ public class ConnectivityServiceTest {
|
||||
|
||||
private NetworkAgentInfo fakeNai(NetworkCapabilities nc, NetworkInfo networkInfo) {
|
||||
return new NetworkAgentInfo(null, new Network(NET_ID), networkInfo, new LinkProperties(),
|
||||
nc, new NetworkScore.Builder().setLegacyInt(0).build(),
|
||||
nc, null /* localNetworkConfig */,
|
||||
new NetworkScore.Builder().setLegacyInt(0).build(),
|
||||
mServiceContext, null, new NetworkAgentConfig(), mService, null, null, 0,
|
||||
INVALID_UID, TEST_LINGER_DELAY_MS, mQosCallbackTracker,
|
||||
new ConnectivityService.Dependencies());
|
||||
|
||||
@@ -372,9 +372,10 @@ public class LingerMonitorTest {
|
||||
caps.addCapability(0);
|
||||
caps.addTransportType(transport);
|
||||
NetworkAgentInfo nai = new NetworkAgentInfo(null, new Network(netId), info,
|
||||
new LinkProperties(), caps, new NetworkScore.Builder().setLegacyInt(50).build(),
|
||||
mCtx, null, new NetworkAgentConfig.Builder().build(), mConnService, mNetd,
|
||||
mDnsResolver, NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS,
|
||||
new LinkProperties(), caps, null /* localNetworkConfiguration */,
|
||||
new NetworkScore.Builder().setLegacyInt(50).build(), mCtx, null,
|
||||
new NetworkAgentConfig.Builder().build(), mConnService, mNetd, mDnsResolver,
|
||||
NetworkProvider.ID_NONE, Binder.getCallingUid(), TEST_LINGER_DELAY_MS,
|
||||
mQosCallbackTracker, new ConnectivityService.Dependencies());
|
||||
if (setEverValidated) {
|
||||
// As tests in this class deal with testing lingering, most tests are interested
|
||||
|
||||
@@ -3004,8 +3004,15 @@ public class VpnTest extends VpnTestBase {
|
||||
profile.mppe = useMppe;
|
||||
|
||||
doReturn(new Network[] { new Network(101) }).when(mConnectivityManager).getAllNetworks();
|
||||
doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(any(), any(),
|
||||
any(), any(), any(), any(), anyInt());
|
||||
doReturn(new Network(102)).when(mConnectivityManager).registerNetworkAgent(
|
||||
any(), // INetworkAgent
|
||||
any(), // NetworkInfo
|
||||
any(), // LinkProperties
|
||||
any(), // NetworkCapabilities
|
||||
any(), // LocalNetworkConfig
|
||||
any(), // NetworkScore
|
||||
any(), // NetworkAgentConfig
|
||||
anyInt()); // provider ID
|
||||
|
||||
final Vpn vpn = startLegacyVpn(createVpn(PRIMARY_USER.id), profile);
|
||||
final TestDeps deps = (TestDeps) vpn.mDeps;
|
||||
@@ -3027,8 +3034,15 @@ public class VpnTest extends VpnTestBase {
|
||||
assertEquals("nomppe", mtpdArgs[argsPrefix.length]);
|
||||
}
|
||||
|
||||
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
|
||||
any(), any(), any(), any(), anyInt());
|
||||
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(
|
||||
any(), // INetworkAgent
|
||||
any(), // NetworkInfo
|
||||
any(), // LinkProperties
|
||||
any(), // NetworkCapabilities
|
||||
any(), // LocalNetworkConfig
|
||||
any(), // NetworkScore
|
||||
any(), // NetworkAgentConfig
|
||||
anyInt()); // provider ID
|
||||
}, () -> { // Cleanup
|
||||
vpn.mVpnRunner.exitVpnRunner();
|
||||
deps.getStateFile().delete(); // set to delete on exit, but this deletes it earlier
|
||||
@@ -3053,7 +3067,7 @@ public class VpnTest extends VpnTestBase {
|
||||
.thenReturn(new Network[] { new Network(101) });
|
||||
|
||||
when(mConnectivityManager.registerNetworkAgent(any(), any(), any(), any(),
|
||||
any(), any(), anyInt())).thenAnswer(invocation -> {
|
||||
any(), any(), any(), anyInt())).thenAnswer(invocation -> {
|
||||
// The runner has registered an agent and is now ready.
|
||||
legacyRunnerReady.open();
|
||||
return new Network(102);
|
||||
@@ -3079,7 +3093,7 @@ public class VpnTest extends VpnTestBase {
|
||||
ArgumentCaptor<NetworkCapabilities> ncCaptor =
|
||||
ArgumentCaptor.forClass(NetworkCapabilities.class);
|
||||
verify(mConnectivityManager, timeout(10_000)).registerNetworkAgent(any(), any(),
|
||||
lpCaptor.capture(), ncCaptor.capture(), any(), any(), anyInt());
|
||||
lpCaptor.capture(), ncCaptor.capture(), any(), any(), any(), anyInt());
|
||||
|
||||
// In this test the expected address is always v4 so /32.
|
||||
// Note that the interface needs to be specified because RouteInfo objects stored in
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.server
|
||||
|
||||
import android.net.LocalNetworkConfig
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
|
||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||
@@ -45,8 +46,9 @@ class CSKeepConnectedTest : CSTest() {
|
||||
.build()
|
||||
val keepConnectedAgent = Agent(nc = nc, score = FromS(NetworkScore.Builder()
|
||||
.setKeepConnectedReason(KEEP_CONNECTED_DOWNSTREAM_NETWORK)
|
||||
.build()))
|
||||
val dontKeepConnectedAgent = Agent(nc = nc)
|
||||
.build()),
|
||||
lnc = LocalNetworkConfig.Builder().build())
|
||||
val dontKeepConnectedAgent = Agent(nc = nc, lnc = LocalNetworkConfig.Builder().build())
|
||||
doTestKeepConnected(keepConnectedAgent, dontKeepConnectedAgent)
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 com.android.server
|
||||
|
||||
import android.content.pm.PackageManager.FEATURE_LEANBACK
|
||||
import android.net.INetd
|
||||
import android.net.LocalNetworkConfig
|
||||
import android.net.NativeNetworkConfig
|
||||
import android.net.NativeNetworkType
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
|
||||
import android.net.NetworkRequest
|
||||
import android.net.NetworkScore
|
||||
import android.net.NetworkScore.KEEP_CONNECTED_FOR_TEST
|
||||
import android.net.VpnManager
|
||||
import android.os.Build
|
||||
import androidx.test.filters.SmallTest
|
||||
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.RecorderCallback.CallbackEntry.Available
|
||||
import com.android.testutils.TestableNetworkCallback
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import org.junit.runners.Parameterized
|
||||
import org.mockito.Mockito.doReturn
|
||||
import org.mockito.Mockito.inOrder
|
||||
import org.mockito.Mockito.never
|
||||
import org.mockito.Mockito.timeout
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
private const val TIMEOUT_MS = 2_000L
|
||||
private const val NO_CALLBACK_TIMEOUT_MS = 200L
|
||||
|
||||
private fun keepConnectedScore() =
|
||||
FromS(NetworkScore.Builder().setKeepConnectedReason(KEEP_CONNECTED_FOR_TEST).build())
|
||||
|
||||
private fun defaultLnc() = LocalNetworkConfig.Builder().build()
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@SmallTest
|
||||
@IgnoreUpTo(Build.VERSION_CODES.R)
|
||||
class CSLocalAgentCreationTests(
|
||||
private val sdkLevel: Int,
|
||||
private val isTv: Boolean,
|
||||
private val addLocalNetCapToRequest: Boolean
|
||||
) : CSTest() {
|
||||
companion object {
|
||||
@JvmStatic
|
||||
@Parameterized.Parameters
|
||||
fun arguments() = listOf(
|
||||
arrayOf(VERSION_V, false /* isTv */, true /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_V, false /* isTv */, false /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_V, true /* isTv */, true /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_V, true /* isTv */, false /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_U, false /* isTv */, true /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_U, false /* isTv */, false /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_U, true /* isTv */, true /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_U, true /* isTv */, false /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_T, false /* isTv */, false /* addLocalNetCapToRequest */),
|
||||
arrayOf(VERSION_T, true /* isTv */, false /* addLocalNetCapToRequest */),
|
||||
)
|
||||
}
|
||||
|
||||
private fun makeNativeNetworkConfigLocal(netId: Int, permission: Int) =
|
||||
NativeNetworkConfig(netId, NativeNetworkType.PHYSICAL_LOCAL, permission,
|
||||
false /* secure */, VpnManager.TYPE_VPN_NONE, false /* excludeLocalRoutes */)
|
||||
|
||||
@Test
|
||||
fun testLocalAgents() {
|
||||
val netdInOrder = inOrder(netd)
|
||||
deps.setBuildSdk(sdkLevel)
|
||||
doReturn(isTv).`when`(packageManager).hasSystemFeature(FEATURE_LEANBACK)
|
||||
val allNetworksCb = TestableNetworkCallback()
|
||||
val request = NetworkRequest.Builder()
|
||||
if (addLocalNetCapToRequest) {
|
||||
request.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||
}
|
||||
cm.registerNetworkCallback(request.build(), allNetworksCb)
|
||||
val ncTemplate = NetworkCapabilities.Builder().run {
|
||||
addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
|
||||
addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||
}.build()
|
||||
val localAgent = if (sdkLevel >= VERSION_V || sdkLevel == VERSION_U && isTv) {
|
||||
Agent(nc = ncTemplate, score = keepConnectedScore(), lnc = defaultLnc())
|
||||
} else {
|
||||
assertFailsWith<IllegalArgumentException> { Agent(nc = ncTemplate, lnc = defaultLnc()) }
|
||||
netdInOrder.verify(netd, never()).networkCreate(any())
|
||||
return
|
||||
}
|
||||
localAgent.connect()
|
||||
netdInOrder.verify(netd).networkCreate(
|
||||
makeNativeNetworkConfigLocal(localAgent.network.netId, INetd.PERMISSION_NONE))
|
||||
if (addLocalNetCapToRequest) {
|
||||
assertEquals(localAgent.network, allNetworksCb.expect<Available>().network)
|
||||
} else {
|
||||
allNetworksCb.assertNoCallback(NO_CALLBACK_TIMEOUT_MS)
|
||||
}
|
||||
cm.unregisterNetworkCallback(allNetworksCb)
|
||||
localAgent.disconnect()
|
||||
netdInOrder.verify(netd, timeout(TIMEOUT_MS)).networkDestroy(localAgent.network.netId)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testBadAgents() {
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
Agent(nc = NetworkCapabilities.Builder()
|
||||
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||
.build(),
|
||||
lnc = null)
|
||||
}
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
Agent(nc = NetworkCapabilities.Builder().build(),
|
||||
lnc = LocalNetworkConfig.Builder().build())
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (C) 2023 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 com.android.server
|
||||
|
||||
import android.net.IpPrefix
|
||||
import android.net.LinkAddress
|
||||
import android.net.LinkProperties
|
||||
import android.net.LocalNetworkConfig
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED
|
||||
import android.net.NetworkCapabilities.TRANSPORT_WIFI
|
||||
import android.net.NetworkRequest
|
||||
import android.net.RouteInfo
|
||||
import android.os.Build
|
||||
import com.android.testutils.DevSdkIgnoreRule
|
||||
import com.android.testutils.DevSdkIgnoreRunner
|
||||
import com.android.testutils.RecorderCallback
|
||||
import com.android.testutils.RecorderCallback.CallbackEntry.Available
|
||||
import com.android.testutils.RecorderCallback.CallbackEntry.BlockedStatus
|
||||
import com.android.testutils.RecorderCallback.CallbackEntry.CapabilitiesChanged
|
||||
import com.android.testutils.RecorderCallback.CallbackEntry.LinkPropertiesChanged
|
||||
import com.android.testutils.TestableNetworkCallback
|
||||
import org.junit.Test
|
||||
import org.junit.runner.RunWith
|
||||
import kotlin.test.assertFailsWith
|
||||
|
||||
private fun nc(transport: Int, vararg caps: Int) = NetworkCapabilities.Builder().apply {
|
||||
addTransportType(transport)
|
||||
caps.forEach {
|
||||
addCapability(it)
|
||||
}
|
||||
// Useful capabilities for everybody
|
||||
addCapability(NET_CAPABILITY_NOT_RESTRICTED)
|
||||
addCapability(NET_CAPABILITY_NOT_SUSPENDED)
|
||||
addCapability(NET_CAPABILITY_NOT_ROAMING)
|
||||
addCapability(NET_CAPABILITY_NOT_VCN_MANAGED)
|
||||
}.build()
|
||||
|
||||
private fun lp(iface: String) = LinkProperties().apply {
|
||||
interfaceName = iface
|
||||
addLinkAddress(LinkAddress(LOCAL_IPV4_ADDRESS, 32))
|
||||
addRoute(RouteInfo(IpPrefix("0.0.0.0/0"), null, null))
|
||||
}
|
||||
|
||||
@RunWith(DevSdkIgnoreRunner::class)
|
||||
@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.TIRAMISU)
|
||||
class CSLocalAgentTests : CSTest() {
|
||||
@Test
|
||||
fun testBadAgents() {
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
Agent(nc = NetworkCapabilities.Builder()
|
||||
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||
.build(),
|
||||
lnc = null)
|
||||
}
|
||||
assertFailsWith<IllegalArgumentException> {
|
||||
Agent(nc = NetworkCapabilities.Builder().build(),
|
||||
lnc = LocalNetworkConfig.Builder().build())
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testUpdateLocalAgentConfig() {
|
||||
deps.setBuildSdk(VERSION_V)
|
||||
|
||||
val cb = TestableNetworkCallback()
|
||||
cm.requestNetwork(NetworkRequest.Builder()
|
||||
.addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||
.build(),
|
||||
cb)
|
||||
|
||||
// Set up a local agent that should forward its traffic to the best DUN upstream.
|
||||
val localAgent = Agent(nc = nc(TRANSPORT_WIFI, NET_CAPABILITY_LOCAL_NETWORK),
|
||||
lp = lp("local0"),
|
||||
lnc = LocalNetworkConfig.Builder().build(),
|
||||
)
|
||||
localAgent.connect()
|
||||
|
||||
cb.expect<Available>(localAgent.network)
|
||||
cb.expect<CapabilitiesChanged>(localAgent.network)
|
||||
cb.expect<LinkPropertiesChanged>(localAgent.network)
|
||||
cb.expect<BlockedStatus>(localAgent.network)
|
||||
|
||||
val newLnc = LocalNetworkConfig.Builder()
|
||||
.setUpstreamSelector(NetworkRequest.Builder()
|
||||
.addTransportType(TRANSPORT_WIFI)
|
||||
.build())
|
||||
.build()
|
||||
localAgent.sendLocalNetworkConfig(newLnc)
|
||||
|
||||
localAgent.disconnect()
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import android.net.ConnectivityManager
|
||||
import android.net.INetworkMonitor
|
||||
import android.net.INetworkMonitorCallbacks
|
||||
import android.net.LinkProperties
|
||||
import android.net.LocalNetworkConfig
|
||||
import android.net.Network
|
||||
import android.net.NetworkAgent
|
||||
import android.net.NetworkAgentConfig
|
||||
@@ -69,6 +70,7 @@ class CSAgentWrapper(
|
||||
nac: NetworkAgentConfig,
|
||||
val nc: NetworkCapabilities,
|
||||
val lp: LinkProperties,
|
||||
val lnc: LocalNetworkConfig?,
|
||||
val score: FromS<NetworkScore>,
|
||||
val provider: NetworkProvider?
|
||||
) : TestableNetworkCallback.HasNetwork {
|
||||
@@ -100,7 +102,7 @@ class CSAgentWrapper(
|
||||
// Create the actual agent. NetworkAgent is abstract, so make an anonymous subclass.
|
||||
if (deps.isAtLeastS()) {
|
||||
agent = object : NetworkAgent(context, csHandlerThread.looper, TAG,
|
||||
nc, lp, score.value, nac, provider) {}
|
||||
nc, lp, lnc, score.value, nac, provider) {}
|
||||
} else {
|
||||
agent = object : NetworkAgent(context, csHandlerThread.looper, TAG,
|
||||
nc, lp, 50 /* score */, nac, provider) {}
|
||||
@@ -165,4 +167,6 @@ class CSAgentWrapper(
|
||||
agent.unregister()
|
||||
cb.eventuallyExpect<Lost> { it.network == agent.network }
|
||||
}
|
||||
|
||||
fun sendLocalNetworkConfig(lnc: LocalNetworkConfig) = agent.sendLocalNetworkConfig(lnc)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ import android.net.ConnectivityManager
|
||||
import android.net.INetd
|
||||
import android.net.InetAddresses
|
||||
import android.net.LinkProperties
|
||||
import android.net.LocalNetworkConfig
|
||||
import android.net.NetworkAgentConfig
|
||||
import android.net.NetworkCapabilities
|
||||
import android.net.NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED
|
||||
@@ -292,10 +293,11 @@ open class CSTest {
|
||||
nc: NetworkCapabilities = defaultNc(),
|
||||
nac: NetworkAgentConfig = emptyAgentConfig(nc.getLegacyType()),
|
||||
lp: LinkProperties = defaultLp(),
|
||||
lnc: LocalNetworkConfig? = null,
|
||||
score: FromS<NetworkScore> = defaultScore(),
|
||||
provider: NetworkProvider? = null
|
||||
) = CSAgentWrapper(context, deps, csHandlerThread, networkStack, nac, nc, lp, score, provider)
|
||||
|
||||
) = CSAgentWrapper(context, deps, csHandlerThread, networkStack,
|
||||
nac, nc, lp, lnc, score, provider)
|
||||
fun Agent(vararg transports: Int, lp: LinkProperties = defaultLp()): CSAgentWrapper {
|
||||
val nc = NetworkCapabilities.Builder().apply {
|
||||
transports.forEach {
|
||||
|
||||
Reference in New Issue
Block a user