Merge changes If8097d58,Ic8ec4587,If37b26fa
* changes: APIs to enable data stall handling in VCN Perform MOBIKE when data stall is suspected on VCN network Add VCN gateway option to enable data stall handling
This commit is contained in:
@@ -27303,13 +27303,17 @@ package android.net.vcn {
|
|||||||
method @IntRange(from=0x500) public int getMaxMtu();
|
method @IntRange(from=0x500) public int getMaxMtu();
|
||||||
method @NonNull public long[] getRetryIntervalsMillis();
|
method @NonNull public long[] getRetryIntervalsMillis();
|
||||||
method @NonNull public java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities();
|
method @NonNull public java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate> getVcnUnderlyingNetworkPriorities();
|
||||||
|
method public boolean hasGatewayOption(int);
|
||||||
|
field public static final int VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY = 0; // 0x0
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final class VcnGatewayConnectionConfig.Builder {
|
public static final class VcnGatewayConnectionConfig.Builder {
|
||||||
ctor public VcnGatewayConnectionConfig.Builder(@NonNull String, @NonNull android.net.ipsec.ike.IkeTunnelConnectionParams);
|
ctor public VcnGatewayConnectionConfig.Builder(@NonNull String, @NonNull android.net.ipsec.ike.IkeTunnelConnectionParams);
|
||||||
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addExposedCapability(int);
|
||||||
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder addGatewayOption(int);
|
||||||
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig build();
|
||||||
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeExposedCapability(int);
|
||||||
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder removeGatewayOption(int);
|
||||||
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=0x500) int);
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setMaxMtu(@IntRange(from=0x500) int);
|
||||||
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryIntervalsMillis(@NonNull long[]);
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setRetryIntervalsMillis(@NonNull long[]);
|
||||||
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setVcnUnderlyingNetworkPriorities(@NonNull java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate>);
|
method @NonNull public android.net.vcn.VcnGatewayConnectionConfig.Builder setVcnUnderlyingNetworkPriorities(@NonNull java.util.List<android.net.vcn.VcnUnderlyingNetworkTemplate>);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ import java.lang.annotation.RetentionPolicy;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -130,6 +131,30 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
})
|
})
|
||||||
public @interface VcnSupportedCapability {}
|
public @interface VcnSupportedCapability {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Perform mobility update to attempt recovery from suspected data stalls.
|
||||||
|
*
|
||||||
|
* <p>If set, the gatway connection will monitor the data stall detection of the VCN network.
|
||||||
|
* When there is a suspected data stall, the gateway connection will attempt recovery by
|
||||||
|
* performing a mobility update on the underlying IKE session.
|
||||||
|
*/
|
||||||
|
public static final int VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY = 0;
|
||||||
|
|
||||||
|
/** @hide */
|
||||||
|
@Retention(RetentionPolicy.SOURCE)
|
||||||
|
@IntDef(
|
||||||
|
prefix = {"VCN_GATEWAY_OPTION_"},
|
||||||
|
value = {
|
||||||
|
VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY,
|
||||||
|
})
|
||||||
|
public @interface VcnGatewayOption {}
|
||||||
|
|
||||||
|
private static final Set<Integer> ALLOWED_GATEWAY_OPTIONS = new ArraySet<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
ALLOWED_GATEWAY_OPTIONS.add(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY);
|
||||||
|
}
|
||||||
|
|
||||||
private static final int DEFAULT_MAX_MTU = 1500;
|
private static final int DEFAULT_MAX_MTU = 1500;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -201,6 +226,9 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
|
private static final String RETRY_INTERVAL_MS_KEY = "mRetryIntervalsMs";
|
||||||
@NonNull private final long[] mRetryIntervalsMs;
|
@NonNull private final long[] mRetryIntervalsMs;
|
||||||
|
|
||||||
|
private static final String GATEWAY_OPTIONS_KEY = "mGatewayOptions";
|
||||||
|
@NonNull private final Set<Integer> mGatewayOptions;
|
||||||
|
|
||||||
/** Builds a VcnGatewayConnectionConfig with the specified parameters. */
|
/** Builds a VcnGatewayConnectionConfig with the specified parameters. */
|
||||||
private VcnGatewayConnectionConfig(
|
private VcnGatewayConnectionConfig(
|
||||||
@NonNull String gatewayConnectionName,
|
@NonNull String gatewayConnectionName,
|
||||||
@@ -208,12 +236,14 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
@NonNull Set<Integer> exposedCapabilities,
|
@NonNull Set<Integer> exposedCapabilities,
|
||||||
@NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
|
@NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
|
||||||
@NonNull long[] retryIntervalsMs,
|
@NonNull long[] retryIntervalsMs,
|
||||||
@IntRange(from = MIN_MTU_V6) int maxMtu) {
|
@IntRange(from = MIN_MTU_V6) int maxMtu,
|
||||||
|
@NonNull Set<Integer> gatewayOptions) {
|
||||||
mGatewayConnectionName = gatewayConnectionName;
|
mGatewayConnectionName = gatewayConnectionName;
|
||||||
mTunnelConnectionParams = tunnelConnectionParams;
|
mTunnelConnectionParams = tunnelConnectionParams;
|
||||||
mExposedCapabilities = new TreeSet(exposedCapabilities);
|
mExposedCapabilities = new TreeSet(exposedCapabilities);
|
||||||
mRetryIntervalsMs = retryIntervalsMs;
|
mRetryIntervalsMs = retryIntervalsMs;
|
||||||
mMaxMtu = maxMtu;
|
mMaxMtu = maxMtu;
|
||||||
|
mGatewayOptions = Collections.unmodifiableSet(new HashSet(gatewayOptions));
|
||||||
|
|
||||||
mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates);
|
mUnderlyingNetworkTemplates = new ArrayList<>(underlyingNetworkTemplates);
|
||||||
if (mUnderlyingNetworkTemplates.isEmpty()) {
|
if (mUnderlyingNetworkTemplates.isEmpty()) {
|
||||||
@@ -256,6 +286,20 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
VcnUnderlyingNetworkTemplate::fromPersistableBundle);
|
VcnUnderlyingNetworkTemplate::fromPersistableBundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final PersistableBundle gatewayOptionsBundle = in.getPersistableBundle(GATEWAY_OPTIONS_KEY);
|
||||||
|
|
||||||
|
if (gatewayOptionsBundle == null) {
|
||||||
|
// GATEWAY_OPTIONS_KEY was added in Android U. Thus VcnGatewayConnectionConfig created
|
||||||
|
// on old platforms will not have this data and will be assigned with the default value
|
||||||
|
mGatewayOptions = Collections.emptySet();
|
||||||
|
} else {
|
||||||
|
mGatewayOptions =
|
||||||
|
new HashSet<>(
|
||||||
|
PersistableBundleUtils.toList(
|
||||||
|
gatewayOptionsBundle,
|
||||||
|
PersistableBundleUtils.INTEGER_DESERIALIZER));
|
||||||
|
}
|
||||||
|
|
||||||
mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
|
mRetryIntervalsMs = in.getLongArray(RETRY_INTERVAL_MS_KEY);
|
||||||
mMaxMtu = in.getInt(MAX_MTU_KEY);
|
mMaxMtu = in.getInt(MAX_MTU_KEY);
|
||||||
|
|
||||||
@@ -279,6 +323,10 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
|
|
||||||
Preconditions.checkArgument(
|
Preconditions.checkArgument(
|
||||||
mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
|
mMaxMtu >= MIN_MTU_V6, "maxMtu must be at least IPv6 min MTU (1280)");
|
||||||
|
|
||||||
|
for (int option : mGatewayOptions) {
|
||||||
|
validateGatewayOption(option);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void checkValidCapability(int capability) {
|
private static void checkValidCapability(int capability) {
|
||||||
@@ -315,6 +363,12 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void validateGatewayOption(int option) {
|
||||||
|
if (!ALLOWED_GATEWAY_OPTIONS.contains(option)) {
|
||||||
|
throw new IllegalArgumentException("Invalid vcn gateway option: " + option);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the configured Gateway Connection name.
|
* Returns the configured Gateway Connection name.
|
||||||
*
|
*
|
||||||
@@ -398,6 +452,19 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
return mMaxMtu;
|
return mMaxMtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the given VCN gateway option is enabled.
|
||||||
|
*
|
||||||
|
* @param option the option to check.
|
||||||
|
* @throws IllegalArgumentException if the provided option is invalid.
|
||||||
|
* @see Builder#addGatewayOption(int)
|
||||||
|
* @see Builder#removeGatewayOption(int)
|
||||||
|
*/
|
||||||
|
public boolean hasGatewayOption(@VcnGatewayOption int option) {
|
||||||
|
validateGatewayOption(option);
|
||||||
|
return mGatewayOptions.contains(option);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts this config to a PersistableBundle.
|
* Converts this config to a PersistableBundle.
|
||||||
*
|
*
|
||||||
@@ -418,11 +485,16 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
PersistableBundleUtils.fromList(
|
PersistableBundleUtils.fromList(
|
||||||
mUnderlyingNetworkTemplates,
|
mUnderlyingNetworkTemplates,
|
||||||
VcnUnderlyingNetworkTemplate::toPersistableBundle);
|
VcnUnderlyingNetworkTemplate::toPersistableBundle);
|
||||||
|
final PersistableBundle gatewayOptionsBundle =
|
||||||
|
PersistableBundleUtils.fromList(
|
||||||
|
new ArrayList<>(mGatewayOptions),
|
||||||
|
PersistableBundleUtils.INTEGER_SERIALIZER);
|
||||||
|
|
||||||
result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
|
result.putString(GATEWAY_CONNECTION_NAME_KEY, mGatewayConnectionName);
|
||||||
result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
|
result.putPersistableBundle(TUNNEL_CONNECTION_PARAMS_KEY, tunnelConnectionParamsBundle);
|
||||||
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
|
result.putPersistableBundle(EXPOSED_CAPABILITIES_KEY, exposedCapsBundle);
|
||||||
result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle);
|
result.putPersistableBundle(UNDERLYING_NETWORK_TEMPLATES_KEY, networkTemplatesBundle);
|
||||||
|
result.putPersistableBundle(GATEWAY_OPTIONS_KEY, gatewayOptionsBundle);
|
||||||
result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
|
result.putLongArray(RETRY_INTERVAL_MS_KEY, mRetryIntervalsMs);
|
||||||
result.putInt(MAX_MTU_KEY, mMaxMtu);
|
result.putInt(MAX_MTU_KEY, mMaxMtu);
|
||||||
|
|
||||||
@@ -437,7 +509,8 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
mExposedCapabilities,
|
mExposedCapabilities,
|
||||||
mUnderlyingNetworkTemplates,
|
mUnderlyingNetworkTemplates,
|
||||||
Arrays.hashCode(mRetryIntervalsMs),
|
Arrays.hashCode(mRetryIntervalsMs),
|
||||||
mMaxMtu);
|
mMaxMtu,
|
||||||
|
mGatewayOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -452,7 +525,8 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
&& mExposedCapabilities.equals(rhs.mExposedCapabilities)
|
&& mExposedCapabilities.equals(rhs.mExposedCapabilities)
|
||||||
&& mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates)
|
&& mUnderlyingNetworkTemplates.equals(rhs.mUnderlyingNetworkTemplates)
|
||||||
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
|
&& Arrays.equals(mRetryIntervalsMs, rhs.mRetryIntervalsMs)
|
||||||
&& mMaxMtu == rhs.mMaxMtu;
|
&& mMaxMtu == rhs.mMaxMtu
|
||||||
|
&& mGatewayOptions.equals(rhs.mGatewayOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -470,6 +544,8 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
|
@NonNull private long[] mRetryIntervalsMs = DEFAULT_RETRY_INTERVALS_MS;
|
||||||
private int mMaxMtu = DEFAULT_MAX_MTU;
|
private int mMaxMtu = DEFAULT_MAX_MTU;
|
||||||
|
|
||||||
|
@NonNull private final Set<Integer> mGatewayOptions = new ArraySet<>();
|
||||||
|
|
||||||
// TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
|
// TODO: (b/175829816) Consider VCN-exposed capabilities that may be transport dependent.
|
||||||
// Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
|
// Consider the case where the VCN might only expose MMS on WiFi, but defer to MMS
|
||||||
// when on Cell.
|
// when on Cell.
|
||||||
@@ -627,6 +703,34 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables the specified VCN gateway option.
|
||||||
|
*
|
||||||
|
* @param option the option to be enabled
|
||||||
|
* @return this {@link Builder} instance, for chaining
|
||||||
|
* @throws IllegalArgumentException if the provided option is invalid
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Builder addGatewayOption(@VcnGatewayOption int option) {
|
||||||
|
validateGatewayOption(option);
|
||||||
|
mGatewayOptions.add(option);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets (disables) the specified VCN gateway option.
|
||||||
|
*
|
||||||
|
* @param option the option to be disabled
|
||||||
|
* @return this {@link Builder} instance, for chaining
|
||||||
|
* @throws IllegalArgumentException if the provided option is invalid
|
||||||
|
*/
|
||||||
|
@NonNull
|
||||||
|
public Builder removeGatewayOption(@VcnGatewayOption int option) {
|
||||||
|
validateGatewayOption(option);
|
||||||
|
mGatewayOptions.remove(option);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Builds and validates the VcnGatewayConnectionConfig.
|
* Builds and validates the VcnGatewayConnectionConfig.
|
||||||
*
|
*
|
||||||
@@ -640,7 +744,8 @@ public final class VcnGatewayConnectionConfig {
|
|||||||
mExposedCapabilities,
|
mExposedCapabilities,
|
||||||
mUnderlyingNetworkTemplates,
|
mUnderlyingNetworkTemplates,
|
||||||
mRetryIntervalsMs,
|
mRetryIntervalsMs,
|
||||||
mMaxMtu);
|
mMaxMtu,
|
||||||
|
mGatewayOptions);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
|
|||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
|
import static android.net.ipsec.ike.exceptions.IkeProtocolException.ERROR_TYPE_AUTHENTICATION_FAILED;
|
||||||
|
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
|
||||||
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_CONFIG_ERROR;
|
||||||
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_INTERNAL_ERROR;
|
||||||
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
|
import static android.net.vcn.VcnManager.VCN_ERROR_CODE_NETWORK_ERROR;
|
||||||
@@ -36,6 +37,8 @@ import static com.android.server.VcnManagementService.VDBG;
|
|||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.annotation.Nullable;
|
import android.annotation.Nullable;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityDiagnosticsManager;
|
||||||
|
import android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
import android.net.IpPrefix;
|
import android.net.IpPrefix;
|
||||||
@@ -50,6 +53,7 @@ import android.net.NetworkAgent;
|
|||||||
import android.net.NetworkAgentConfig;
|
import android.net.NetworkAgentConfig;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.NetworkProvider;
|
import android.net.NetworkProvider;
|
||||||
|
import android.net.NetworkRequest;
|
||||||
import android.net.NetworkScore;
|
import android.net.NetworkScore;
|
||||||
import android.net.RouteInfo;
|
import android.net.RouteInfo;
|
||||||
import android.net.TelephonyNetworkSpecifier;
|
import android.net.TelephonyNetworkSpecifier;
|
||||||
@@ -546,6 +550,39 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sent when there is a suspected data stall on a network
|
||||||
|
*
|
||||||
|
* <p>Only relevant in the Connected state.
|
||||||
|
*
|
||||||
|
* @param arg1 The "all" token; this signal is always honored.
|
||||||
|
* @param obj @NonNull An EventDataStallSuspectedInfo instance with relevant data.
|
||||||
|
*/
|
||||||
|
private static final int EVENT_DATA_STALL_SUSPECTED = 13;
|
||||||
|
|
||||||
|
private static class EventDataStallSuspectedInfo implements EventInfo {
|
||||||
|
@NonNull public final Network network;
|
||||||
|
|
||||||
|
EventDataStallSuspectedInfo(@NonNull Network network) {
|
||||||
|
this.network = network;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(network);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(@Nullable Object other) {
|
||||||
|
if (!(other instanceof EventDataStallSuspectedInfo)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
final EventDataStallSuspectedInfo rhs = (EventDataStallSuspectedInfo) other;
|
||||||
|
return Objects.equals(network, rhs.network);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
@NonNull
|
@NonNull
|
||||||
final DisconnectedState mDisconnectedState = new DisconnectedState();
|
final DisconnectedState mDisconnectedState = new DisconnectedState();
|
||||||
@@ -578,10 +615,13 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
@NonNull
|
@NonNull
|
||||||
private final VcnUnderlyingNetworkControllerCallback mUnderlyingNetworkControllerCallback;
|
private final VcnUnderlyingNetworkControllerCallback mUnderlyingNetworkControllerCallback;
|
||||||
|
|
||||||
|
@NonNull private final VcnConnectivityDiagnosticsCallback mConnectivityDiagnosticsCallback;
|
||||||
|
|
||||||
private final boolean mIsMobileDataEnabled;
|
private final boolean mIsMobileDataEnabled;
|
||||||
|
|
||||||
@NonNull private final IpSecManager mIpSecManager;
|
@NonNull private final IpSecManager mIpSecManager;
|
||||||
@NonNull private final ConnectivityManager mConnectivityManager;
|
@NonNull private final ConnectivityManager mConnectivityManager;
|
||||||
|
@NonNull private final ConnectivityDiagnosticsManager mConnectivityDiagnosticsManager;
|
||||||
|
|
||||||
@Nullable private IpSecTunnelInterface mTunnelIface = null;
|
@Nullable private IpSecTunnelInterface mTunnelIface = null;
|
||||||
|
|
||||||
@@ -748,6 +788,20 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
mUnderlyingNetworkControllerCallback);
|
mUnderlyingNetworkControllerCallback);
|
||||||
mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
|
mIpSecManager = mVcnContext.getContext().getSystemService(IpSecManager.class);
|
||||||
mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
|
mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
|
||||||
|
mConnectivityDiagnosticsManager =
|
||||||
|
mVcnContext.getContext().getSystemService(ConnectivityDiagnosticsManager.class);
|
||||||
|
|
||||||
|
mConnectivityDiagnosticsCallback = new VcnConnectivityDiagnosticsCallback();
|
||||||
|
|
||||||
|
if (mConnectionConfig.hasGatewayOption(
|
||||||
|
VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY)) {
|
||||||
|
final NetworkRequest diagRequest =
|
||||||
|
new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build();
|
||||||
|
mConnectivityDiagnosticsManager.registerConnectivityDiagnosticsCallback(
|
||||||
|
diagRequest,
|
||||||
|
new HandlerExecutor(new Handler(vcnContext.getLooper())),
|
||||||
|
mConnectivityDiagnosticsCallback);
|
||||||
|
}
|
||||||
|
|
||||||
addState(mDisconnectedState);
|
addState(mDisconnectedState);
|
||||||
addState(mDisconnectingState);
|
addState(mDisconnectingState);
|
||||||
@@ -810,6 +864,9 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
mUnderlyingNetworkController.teardown();
|
mUnderlyingNetworkController.teardown();
|
||||||
|
|
||||||
mGatewayStatusCallback.onQuit();
|
mGatewayStatusCallback.onQuit();
|
||||||
|
|
||||||
|
mConnectivityDiagnosticsManager.unregisterConnectivityDiagnosticsCallback(
|
||||||
|
mConnectivityDiagnosticsCallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -828,6 +885,20 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
sendMessageAndAcquireWakeLock(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL);
|
sendMessageAndAcquireWakeLock(EVENT_SUBSCRIPTIONS_CHANGED, TOKEN_ALL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class VcnConnectivityDiagnosticsCallback extends ConnectivityDiagnosticsCallback {
|
||||||
|
@Override
|
||||||
|
public void onDataStallSuspected(ConnectivityDiagnosticsManager.DataStallReport report) {
|
||||||
|
mVcnContext.ensureRunningOnLooperThread();
|
||||||
|
|
||||||
|
final Network network = report.getNetwork();
|
||||||
|
logInfo("Data stall suspected on " + network);
|
||||||
|
sendMessageAndAcquireWakeLock(
|
||||||
|
EVENT_DATA_STALL_SUSPECTED,
|
||||||
|
TOKEN_ALL,
|
||||||
|
new EventDataStallSuspectedInfo(network));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private class VcnUnderlyingNetworkControllerCallback
|
private class VcnUnderlyingNetworkControllerCallback
|
||||||
implements UnderlyingNetworkControllerCallback {
|
implements UnderlyingNetworkControllerCallback {
|
||||||
@Override
|
@Override
|
||||||
@@ -1367,7 +1438,8 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
case EVENT_SUBSCRIPTIONS_CHANGED: // Fallthrough
|
case EVENT_SUBSCRIPTIONS_CHANGED: // Fallthrough
|
||||||
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: // Fallthrough
|
case EVENT_SAFE_MODE_TIMEOUT_EXCEEDED: // Fallthrough
|
||||||
case EVENT_MIGRATION_COMPLETED: // Fallthrough
|
case EVENT_MIGRATION_COMPLETED: // Fallthrough
|
||||||
case EVENT_IKE_CONNECTION_INFO_CHANGED:
|
case EVENT_IKE_CONNECTION_INFO_CHANGED: // Fallthrough
|
||||||
|
case EVENT_DATA_STALL_SUSPECTED:
|
||||||
logUnexpectedEvent(msg.what);
|
logUnexpectedEvent(msg.what);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1925,6 +1997,11 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
mIkeConnectionInfo =
|
mIkeConnectionInfo =
|
||||||
((EventIkeConnectionInfoChangedInfo) msg.obj).ikeConnectionInfo;
|
((EventIkeConnectionInfoChangedInfo) msg.obj).ikeConnectionInfo;
|
||||||
break;
|
break;
|
||||||
|
case EVENT_DATA_STALL_SUSPECTED:
|
||||||
|
final Network networkWithDataStall =
|
||||||
|
((EventDataStallSuspectedInfo) msg.obj).network;
|
||||||
|
handleDataStallSuspected(networkWithDataStall);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
logUnhandledMessage(msg);
|
logUnhandledMessage(msg);
|
||||||
break;
|
break;
|
||||||
@@ -1985,6 +2062,15 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleDataStallSuspected(Network networkWithDataStall) {
|
||||||
|
if (mUnderlying != null
|
||||||
|
&& mNetworkAgent != null
|
||||||
|
&& mNetworkAgent.getNetwork().equals(networkWithDataStall)) {
|
||||||
|
logInfo("Perform Mobility update to recover from suspected data stall");
|
||||||
|
mIkeSession.setNetwork(mUnderlying.network);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected void setupInterfaceAndNetworkAgent(
|
protected void setupInterfaceAndNetworkAgent(
|
||||||
int token,
|
int token,
|
||||||
@NonNull IpSecTunnelInterface tunnelIface,
|
@NonNull IpSecTunnelInterface tunnelIface,
|
||||||
@@ -2423,6 +2509,11 @@ public class VcnGatewayConnection extends StateMachine {
|
|||||||
return mUnderlyingNetworkControllerCallback;
|
return mUnderlyingNetworkControllerCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
|
ConnectivityDiagnosticsCallback getConnectivityDiagnosticsCallback() {
|
||||||
|
return mConnectivityDiagnosticsCallback;
|
||||||
|
}
|
||||||
|
|
||||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||||
UnderlyingNetworkRecord getUnderlyingNetwork() {
|
UnderlyingNetworkRecord getUnderlyingNetwork() {
|
||||||
return mUnderlying;
|
return mUnderlying;
|
||||||
|
|||||||
@@ -19,9 +19,11 @@ package android.net.vcn;
|
|||||||
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
|
import static android.net.ipsec.ike.IkeSessionParams.IKE_OPTION_MOBIKE;
|
||||||
import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES;
|
import static android.net.vcn.VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES;
|
||||||
import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_TEMPLATES_KEY;
|
import static android.net.vcn.VcnGatewayConnectionConfig.UNDERLYING_NETWORK_TEMPLATES_KEY;
|
||||||
|
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotEquals;
|
import static org.junit.Assert.assertNotEquals;
|
||||||
import static org.junit.Assert.assertNotSame;
|
import static org.junit.Assert.assertNotSame;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
@@ -42,7 +44,9 @@ import org.junit.runner.RunWith;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -79,6 +83,9 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
};
|
};
|
||||||
public static final int MAX_MTU = 1360;
|
public static final int MAX_MTU = 1360;
|
||||||
|
|
||||||
|
private static final Set<Integer> GATEWAY_OPTIONS =
|
||||||
|
Collections.singleton(VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY);
|
||||||
|
|
||||||
public static final IkeTunnelConnectionParams TUNNEL_CONNECTION_PARAMS =
|
public static final IkeTunnelConnectionParams TUNNEL_CONNECTION_PARAMS =
|
||||||
TunnelConnectionParamsUtilsTest.buildTestParams();
|
TunnelConnectionParamsUtilsTest.buildTestParams();
|
||||||
|
|
||||||
@@ -109,10 +116,16 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
TUNNEL_CONNECTION_PARAMS);
|
TUNNEL_CONNECTION_PARAMS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(
|
private static VcnGatewayConnectionConfig buildTestConfigWithExposedCapsAndOptions(
|
||||||
VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) {
|
VcnGatewayConnectionConfig.Builder builder,
|
||||||
|
Set<Integer> gatewayOptions,
|
||||||
|
int... exposedCaps) {
|
||||||
builder.setRetryIntervalsMillis(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU);
|
builder.setRetryIntervalsMillis(RETRY_INTERVALS_MS).setMaxMtu(MAX_MTU);
|
||||||
|
|
||||||
|
for (int option : gatewayOptions) {
|
||||||
|
builder.addGatewayOption(option);
|
||||||
|
}
|
||||||
|
|
||||||
for (int caps : exposedCaps) {
|
for (int caps : exposedCaps) {
|
||||||
builder.addExposedCapability(caps);
|
builder.addExposedCapability(caps);
|
||||||
}
|
}
|
||||||
@@ -120,11 +133,28 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(
|
||||||
|
VcnGatewayConnectionConfig.Builder builder, int... exposedCaps) {
|
||||||
|
return buildTestConfigWithExposedCapsAndOptions(
|
||||||
|
builder, Collections.emptySet(), exposedCaps);
|
||||||
|
}
|
||||||
|
|
||||||
// Public for use in VcnGatewayConnectionTest
|
// Public for use in VcnGatewayConnectionTest
|
||||||
public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) {
|
public static VcnGatewayConnectionConfig buildTestConfigWithExposedCaps(int... exposedCaps) {
|
||||||
return buildTestConfigWithExposedCaps(newBuilder(), exposedCaps);
|
return buildTestConfigWithExposedCaps(newBuilder(), exposedCaps);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions(
|
||||||
|
VcnGatewayConnectionConfig.Builder builder, Set<Integer> gatewayOptions) {
|
||||||
|
return buildTestConfigWithExposedCapsAndOptions(builder, gatewayOptions, EXPOSED_CAPS);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public for use in VcnGatewayConnectionTest
|
||||||
|
public static VcnGatewayConnectionConfig buildTestConfigWithGatewayOptions(
|
||||||
|
Set<Integer> gatewayOptions) {
|
||||||
|
return buildTestConfigWithExposedCapsAndOptions(newBuilder(), gatewayOptions, EXPOSED_CAPS);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuilderRequiresNonNullGatewayConnectionName() {
|
public void testBuilderRequiresNonNullGatewayConnectionName() {
|
||||||
try {
|
try {
|
||||||
@@ -210,6 +240,15 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderRequiresValidOption() {
|
||||||
|
try {
|
||||||
|
newBuilder().addGatewayOption(-1);
|
||||||
|
fail("Expected exception due to the invalid VCN gateway option");
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testBuilderAndGetters() {
|
public void testBuilderAndGetters() {
|
||||||
final VcnGatewayConnectionConfig config = buildTestConfig();
|
final VcnGatewayConnectionConfig config = buildTestConfig();
|
||||||
@@ -225,6 +264,20 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
|
|
||||||
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
|
assertArrayEquals(RETRY_INTERVALS_MS, config.getRetryIntervalsMillis());
|
||||||
assertEquals(MAX_MTU, config.getMaxMtu());
|
assertEquals(MAX_MTU, config.getMaxMtu());
|
||||||
|
|
||||||
|
assertFalse(
|
||||||
|
config.hasGatewayOption(
|
||||||
|
VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBuilderAndGettersWithOptions() {
|
||||||
|
final VcnGatewayConnectionConfig config =
|
||||||
|
buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS);
|
||||||
|
|
||||||
|
for (int option : GATEWAY_OPTIONS) {
|
||||||
|
assertTrue(config.hasGatewayOption(option));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -234,6 +287,14 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
|
assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testPersistableBundleWithOptions() {
|
||||||
|
final VcnGatewayConnectionConfig config =
|
||||||
|
buildTestConfigWithGatewayOptions(GATEWAY_OPTIONS);
|
||||||
|
|
||||||
|
assertEquals(config, new VcnGatewayConnectionConfig(config.toPersistableBundle()));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() {
|
public void testParsePersistableBundleWithoutVcnUnderlyingNetworkTemplates() {
|
||||||
PersistableBundle configBundle = buildTestConfig().toPersistableBundle();
|
PersistableBundle configBundle = buildTestConfig().toPersistableBundle();
|
||||||
@@ -318,4 +379,27 @@ public class VcnGatewayConnectionConfigTest {
|
|||||||
assertNotEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesNotEqual);
|
assertNotEquals(UNDERLYING_NETWORK_TEMPLATES, networkTemplatesNotEqual);
|
||||||
assertNotEquals(config, configNotEqual);
|
assertNotEquals(config, configNotEqual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static VcnGatewayConnectionConfig buildConfigWithGatewayOptionsForEqualityTest(
|
||||||
|
Set<Integer> gatewayOptions) {
|
||||||
|
return buildTestConfigWithGatewayOptions(
|
||||||
|
new VcnGatewayConnectionConfig.Builder(
|
||||||
|
"buildConfigWithGatewayOptionsForEqualityTest", TUNNEL_CONNECTION_PARAMS),
|
||||||
|
gatewayOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testVcnGatewayOptionsEquality() throws Exception {
|
||||||
|
final VcnGatewayConnectionConfig config =
|
||||||
|
buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS);
|
||||||
|
|
||||||
|
final VcnGatewayConnectionConfig configEqual =
|
||||||
|
buildConfigWithGatewayOptionsForEqualityTest(GATEWAY_OPTIONS);
|
||||||
|
|
||||||
|
final VcnGatewayConnectionConfig configNotEqual =
|
||||||
|
buildConfigWithGatewayOptionsForEqualityTest(Collections.emptySet());
|
||||||
|
|
||||||
|
assertEquals(config, configEqual);
|
||||||
|
assertNotEquals(config, configNotEqual);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -50,9 +50,11 @@ import static org.mockito.Mockito.when;
|
|||||||
|
|
||||||
import static java.util.Collections.singletonList;
|
import static java.util.Collections.singletonList;
|
||||||
|
|
||||||
|
import android.net.ConnectivityDiagnosticsManager.DataStallReport;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
|
import android.net.Network;
|
||||||
import android.net.NetworkAgent;
|
import android.net.NetworkAgent;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
import android.net.ipsec.ike.ChildSaProposal;
|
import android.net.ipsec.ike.ChildSaProposal;
|
||||||
@@ -63,10 +65,12 @@ import android.net.ipsec.ike.exceptions.IkeProtocolException;
|
|||||||
import android.net.vcn.VcnGatewayConnectionConfig;
|
import android.net.vcn.VcnGatewayConnectionConfig;
|
||||||
import android.net.vcn.VcnGatewayConnectionConfigTest;
|
import android.net.vcn.VcnGatewayConnectionConfigTest;
|
||||||
import android.net.vcn.VcnManager.VcnErrorCode;
|
import android.net.vcn.VcnManager.VcnErrorCode;
|
||||||
|
import android.os.PersistableBundle;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
|
||||||
import com.android.server.vcn.util.MtuUtils;
|
import com.android.server.vcn.util.MtuUtils;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -88,6 +92,7 @@ import java.util.function.Consumer;
|
|||||||
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
|
public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnectionTestBase {
|
||||||
private VcnIkeSession mIkeSession;
|
private VcnIkeSession mIkeSession;
|
||||||
private VcnNetworkAgent mNetworkAgent;
|
private VcnNetworkAgent mNetworkAgent;
|
||||||
|
private Network mVcnNetwork;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
@@ -98,6 +103,9 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
.when(mDeps)
|
.when(mDeps)
|
||||||
.newNetworkAgent(any(), any(), any(), any(), any(), any(), any(), any(), any());
|
.newNetworkAgent(any(), any(), any(), any(), any(), any(), any(), any(), any());
|
||||||
|
|
||||||
|
mVcnNetwork = mock(Network.class);
|
||||||
|
doReturn(mVcnNetwork).when(mNetworkAgent).getNetwork();
|
||||||
|
|
||||||
mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1);
|
mGatewayConnection.setUnderlyingNetwork(TEST_UNDERLYING_NETWORK_RECORD_1);
|
||||||
|
|
||||||
mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network);
|
mIkeSession = mGatewayConnection.buildIkeSession(TEST_UNDERLYING_NETWORK_RECORD_1.network);
|
||||||
@@ -166,6 +174,56 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||||||
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void verifyDataStallTriggersMigration(
|
||||||
|
UnderlyingNetworkRecord networkRecord,
|
||||||
|
Network networkWithDataStall,
|
||||||
|
boolean expectMobilityUpdate)
|
||||||
|
throws Exception {
|
||||||
|
mGatewayConnection.setUnderlyingNetwork(networkRecord);
|
||||||
|
triggerChildOpened();
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
final DataStallReport report =
|
||||||
|
new DataStallReport(
|
||||||
|
networkWithDataStall,
|
||||||
|
1234 /* reportTimestamp */,
|
||||||
|
1 /* detectionMethod */,
|
||||||
|
new LinkProperties(),
|
||||||
|
new NetworkCapabilities(),
|
||||||
|
new PersistableBundle());
|
||||||
|
|
||||||
|
mGatewayConnection.getConnectivityDiagnosticsCallback().onDataStallSuspected(report);
|
||||||
|
mTestLooper.dispatchAll();
|
||||||
|
|
||||||
|
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
||||||
|
|
||||||
|
if (expectMobilityUpdate) {
|
||||||
|
verify(mIkeSession).setNetwork(networkRecord.network);
|
||||||
|
} else {
|
||||||
|
verify(mIkeSession, never()).setNetwork(any(Network.class));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataStallTriggersMigration() throws Exception {
|
||||||
|
verifyDataStallTriggersMigration(
|
||||||
|
TEST_UNDERLYING_NETWORK_RECORD_1, mVcnNetwork, true /* expectMobilityUpdate */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataStallWontTriggerMigrationWhenOnOtherNetwork() throws Exception {
|
||||||
|
verifyDataStallTriggersMigration(
|
||||||
|
TEST_UNDERLYING_NETWORK_RECORD_1,
|
||||||
|
mock(Network.class),
|
||||||
|
false /* expectMobilityUpdate */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataStallWontTriggerMigrationWhenUnderlyingNetworkLost() throws Exception {
|
||||||
|
verifyDataStallTriggersMigration(
|
||||||
|
null /* networkRecord */, mock(Network.class), false /* expectMobilityUpdate */);
|
||||||
|
}
|
||||||
|
|
||||||
private void verifyVcnTransformsApplied(
|
private void verifyVcnTransformsApplied(
|
||||||
VcnGatewayConnection vcnGatewayConnection, boolean expectForwardTransform)
|
VcnGatewayConnection vcnGatewayConnection, boolean expectForwardTransform)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_ROAMING;
|
|||||||
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
|
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_VCN_MANAGED;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
|
||||||
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
|
||||||
|
import static android.net.vcn.VcnGatewayConnectionConfig.VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY;
|
||||||
|
|
||||||
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
|
import static com.android.server.vcn.VcnGatewayConnection.DUMMY_ADDR;
|
||||||
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
|
import static com.android.server.vcn.VcnGatewayConnection.VcnChildSessionConfiguration;
|
||||||
@@ -34,20 +35,25 @@ import static org.junit.Assert.assertArrayEquals;
|
|||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyLong;
|
import static org.mockito.ArgumentMatchers.anyLong;
|
||||||
import static org.mockito.Matchers.eq;
|
import static org.mockito.ArgumentMatchers.eq;
|
||||||
import static org.mockito.Mockito.CALLS_REAL_METHODS;
|
import static org.mockito.Mockito.CALLS_REAL_METHODS;
|
||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.mock;
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
import static org.mockito.Mockito.times;
|
import static org.mockito.Mockito.times;
|
||||||
import static org.mockito.Mockito.verify;
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
|
import android.net.ConnectivityDiagnosticsManager.ConnectivityDiagnosticsCallback;
|
||||||
import android.net.IpSecManager;
|
import android.net.IpSecManager;
|
||||||
import android.net.LinkAddress;
|
import android.net.LinkAddress;
|
||||||
import android.net.LinkProperties;
|
import android.net.LinkProperties;
|
||||||
import android.net.Network;
|
import android.net.Network;
|
||||||
import android.net.NetworkCapabilities;
|
import android.net.NetworkCapabilities;
|
||||||
|
import android.net.NetworkRequest;
|
||||||
import android.net.TelephonyNetworkSpecifier;
|
import android.net.TelephonyNetworkSpecifier;
|
||||||
|
import android.net.vcn.VcnGatewayConnectionConfig;
|
||||||
import android.net.vcn.VcnGatewayConnectionConfigTest;
|
import android.net.vcn.VcnGatewayConnectionConfigTest;
|
||||||
import android.net.vcn.VcnTransportInfo;
|
import android.net.vcn.VcnTransportInfo;
|
||||||
import android.net.wifi.WifiInfo;
|
import android.net.wifi.WifiInfo;
|
||||||
@@ -64,6 +70,7 @@ import com.android.server.vcn.routeselection.UnderlyingNetworkRecord;
|
|||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -71,7 +78,9 @@ import java.util.Collections;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
|
||||||
/** Tests for TelephonySubscriptionTracker */
|
/** Tests for TelephonySubscriptionTracker */
|
||||||
@RunWith(AndroidJUnit4.class)
|
@RunWith(AndroidJUnit4.class)
|
||||||
@@ -287,5 +296,60 @@ public class VcnGatewayConnectionTest extends VcnGatewayConnectionTestBase {
|
|||||||
verify(vcnNetworkAgent).unregister();
|
verify(vcnNetworkAgent).unregister();
|
||||||
|
|
||||||
verifyWakeLockReleased();
|
verifyWakeLockReleased();
|
||||||
|
|
||||||
|
verify(mConnDiagMgr)
|
||||||
|
.unregisterConnectivityDiagnosticsCallback(
|
||||||
|
mGatewayConnection.getConnectivityDiagnosticsCallback());
|
||||||
|
}
|
||||||
|
|
||||||
|
private VcnGatewayConnection buildConnectionWithDataStallHandling(
|
||||||
|
boolean datatStallHandlingEnabled) throws Exception {
|
||||||
|
Set<Integer> options =
|
||||||
|
datatStallHandlingEnabled
|
||||||
|
? Collections.singleton(
|
||||||
|
VCN_GATEWAY_OPTION_ENABLE_DATA_STALL_RECOVERY_WITH_MOBILITY)
|
||||||
|
: Collections.emptySet();
|
||||||
|
final VcnGatewayConnectionConfig gatewayConfig =
|
||||||
|
VcnGatewayConnectionConfigTest.buildTestConfigWithGatewayOptions(options);
|
||||||
|
final VcnGatewayConnection gatewayConnection =
|
||||||
|
new VcnGatewayConnection(
|
||||||
|
mVcnContext,
|
||||||
|
TEST_SUB_GRP,
|
||||||
|
TEST_SUBSCRIPTION_SNAPSHOT,
|
||||||
|
gatewayConfig,
|
||||||
|
mGatewayStatusCallback,
|
||||||
|
true /* isMobileDataEnabled */,
|
||||||
|
mDeps);
|
||||||
|
return gatewayConnection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataStallHandlingEnabled() throws Exception {
|
||||||
|
final VcnGatewayConnection gatewayConnection =
|
||||||
|
buildConnectionWithDataStallHandling(true /* datatStallHandlingEnabled */);
|
||||||
|
|
||||||
|
final ArgumentCaptor<NetworkRequest> networkRequestCaptor =
|
||||||
|
ArgumentCaptor.forClass(NetworkRequest.class);
|
||||||
|
verify(mConnDiagMgr)
|
||||||
|
.registerConnectivityDiagnosticsCallback(
|
||||||
|
networkRequestCaptor.capture(),
|
||||||
|
any(Executor.class),
|
||||||
|
eq(gatewayConnection.getConnectivityDiagnosticsCallback()));
|
||||||
|
|
||||||
|
final NetworkRequest nr = networkRequestCaptor.getValue();
|
||||||
|
final NetworkRequest expected =
|
||||||
|
new NetworkRequest.Builder().addTransportType(TRANSPORT_CELLULAR).build();
|
||||||
|
assertEquals(expected, nr);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testDataStallHandlingDisabled() throws Exception {
|
||||||
|
buildConnectionWithDataStallHandling(false /* datatStallHandlingEnabled */);
|
||||||
|
|
||||||
|
verify(mConnDiagMgr, never())
|
||||||
|
.registerConnectivityDiagnosticsCallback(
|
||||||
|
any(NetworkRequest.class),
|
||||||
|
any(Executor.class),
|
||||||
|
any(ConnectivityDiagnosticsCallback.class));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ import static org.mockito.Mockito.verifyNoMoreInteractions;
|
|||||||
|
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityDiagnosticsManager;
|
||||||
import android.net.ConnectivityManager;
|
import android.net.ConnectivityManager;
|
||||||
import android.net.InetAddresses;
|
import android.net.InetAddresses;
|
||||||
import android.net.IpSecConfig;
|
import android.net.IpSecConfig;
|
||||||
@@ -157,6 +158,7 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
|
|
||||||
@NonNull protected final IpSecService mIpSecSvc;
|
@NonNull protected final IpSecService mIpSecSvc;
|
||||||
@NonNull protected final ConnectivityManager mConnMgr;
|
@NonNull protected final ConnectivityManager mConnMgr;
|
||||||
|
@NonNull protected final ConnectivityDiagnosticsManager mConnDiagMgr;
|
||||||
|
|
||||||
@NonNull protected final IkeSessionConnectionInfo mIkeConnectionInfo;
|
@NonNull protected final IkeSessionConnectionInfo mIkeConnectionInfo;
|
||||||
@NonNull protected final IkeSessionConfiguration mIkeSessionConfiguration;
|
@NonNull protected final IkeSessionConfiguration mIkeSessionConfiguration;
|
||||||
@@ -186,6 +188,13 @@ public class VcnGatewayConnectionTestBase {
|
|||||||
VcnTestUtils.setupSystemService(
|
VcnTestUtils.setupSystemService(
|
||||||
mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
|
mContext, mConnMgr, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
|
||||||
|
|
||||||
|
mConnDiagMgr = mock(ConnectivityDiagnosticsManager.class);
|
||||||
|
VcnTestUtils.setupSystemService(
|
||||||
|
mContext,
|
||||||
|
mConnDiagMgr,
|
||||||
|
Context.CONNECTIVITY_DIAGNOSTICS_SERVICE,
|
||||||
|
ConnectivityDiagnosticsManager.class);
|
||||||
|
|
||||||
mIkeConnectionInfo =
|
mIkeConnectionInfo =
|
||||||
new IkeSessionConnectionInfo(TEST_ADDR, TEST_ADDR_2, mock(Network.class));
|
new IkeSessionConnectionInfo(TEST_ADDR, TEST_ADDR_2, mock(Network.class));
|
||||||
mIkeSessionConfiguration = new IkeSessionConfiguration.Builder(mIkeConnectionInfo).build();
|
mIkeSessionConfiguration = new IkeSessionConfiguration.Builder(mIkeConnectionInfo).build();
|
||||||
|
|||||||
Reference in New Issue
Block a user