Merge "Reapply "Add LocalNetworkConfig"" into main
This commit is contained in:
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.
|
||||
*
|
||||
|
||||
@@ -166,6 +166,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;
|
||||
@@ -1798,7 +1799,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);
|
||||
@@ -4169,6 +4170,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;
|
||||
@@ -8130,13 +8136,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");
|
||||
@@ -8154,12 +8165,20 @@ public class ConnectivityService extends IConnectivityManager.Stub
|
||||
// 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);
|
||||
}
|
||||
@@ -8167,7 +8186,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
|
||||
@@ -8175,6 +8195,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
|
||||
@@ -8182,9 +8203,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)
|
||||
@@ -8919,6 +8940,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).
|
||||
*
|
||||
|
||||
@@ -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;
|
||||
@@ -173,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
|
||||
@@ -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,6 +629,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
|
||||
networkInfo = info;
|
||||
linkProperties = lp;
|
||||
networkCapabilities = nc;
|
||||
this.localNetworkConfig = localNetworkConfig;
|
||||
networkAgentConfig = config;
|
||||
mConnService = connService;
|
||||
mConnServiceDeps = deps;
|
||||
@@ -904,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,
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -12833,7 +12833,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)
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ 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
|
||||
@@ -48,6 +49,8 @@ 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)
|
||||
@@ -93,9 +96,9 @@ class CSLocalAgentCreationTests(
|
||||
addCapability(NET_CAPABILITY_LOCAL_NETWORK)
|
||||
}.build()
|
||||
val localAgent = if (sdkLevel >= VERSION_V || sdkLevel == VERSION_U && isTv) {
|
||||
Agent(nc = ncTemplate, score = keepConnectedScore())
|
||||
Agent(nc = ncTemplate, score = keepConnectedScore(), lnc = defaultLnc())
|
||||
} else {
|
||||
assertFailsWith<IllegalArgumentException> { Agent(nc = ncTemplate) }
|
||||
assertFailsWith<IllegalArgumentException> { Agent(nc = ncTemplate, lnc = defaultLnc()) }
|
||||
netdInOrder.verify(netd, never()).networkCreate(any())
|
||||
return
|
||||
}
|
||||
@@ -111,4 +114,18 @@ class CSLocalAgentCreationTests(
|
||||
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