Enable NetworkMetricMonitor and support penalizing networks
This CL integrates the IpSecPacketLossDetector into VCN route selection. With this change, when a data stall is reported, the network candidate will be penalized and then deprioritized during network selection. A network candidate will stop being penalized until it hitting a timeout or passing the validation. Bug: 282996138 Test: atest FrameworksVcnTests(new tests), CtsVcnTestCases Change-Id: Ifabd6fdea1d5a4fea40cf929dbab7c26d37274ac
This commit is contained in:
parent
421db12030
commit
ddcf238d5e
9 changed files with 625 additions and 28 deletions
|
|
@ -80,8 +80,6 @@ public class VcnManager {
|
|||
* <p>The VCN will only migrate to a Carrier WiFi network that has a signal strength greater
|
||||
* than, or equal to this threshold.
|
||||
*
|
||||
* <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
|
|
@ -94,8 +92,6 @@ public class VcnManager {
|
|||
* <p>If the VCN's selected Carrier WiFi network has a signal strength less than this threshold,
|
||||
* the VCN will attempt to migrate away from the Carrier WiFi network.
|
||||
*
|
||||
* <p>WARNING: The VCN does not listen for changes to this key made after VCN startup.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
|
|
@ -120,6 +116,15 @@ public class VcnManager {
|
|||
public static final String VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY =
|
||||
"vcn_network_selection_ipsec_packet_loss_percent_threshold";
|
||||
|
||||
/**
|
||||
* Key for the list of timeouts in minute to stop penalizing an underlying network candidate
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public static final String VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY =
|
||||
"vcn_network_selection_penalty_timeout_minutes_list";
|
||||
|
||||
// TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz
|
||||
|
||||
/**
|
||||
|
|
@ -168,6 +173,7 @@ public class VcnManager {
|
|||
VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
|
||||
VCN_NETWORK_SELECTION_POLL_IPSEC_STATE_INTERVAL_SECONDS_KEY,
|
||||
VCN_NETWORK_SELECTION_IPSEC_PACKET_LOSS_PERCENT_THRESHOLD_KEY,
|
||||
VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY,
|
||||
VCN_RESTRICTED_TRANSPORTS_INT_ARRAY_KEY,
|
||||
VCN_SAFE_MODE_TIMEOUT_SECONDS_KEY,
|
||||
VCN_TUNNEL_AGGREGATION_SA_COUNT_MAX_KEY,
|
||||
|
|
|
|||
|
|
@ -1910,6 +1910,12 @@ public class VcnGatewayConnection extends StateMachine {
|
|||
// Transforms do not need to be persisted; the IkeSession will keep them alive
|
||||
mIpSecManager.applyTunnelModeTransform(tunnelIface, direction, transform);
|
||||
|
||||
if (direction == IpSecManager.DIRECTION_IN
|
||||
&& mVcnContext.isFlagNetworkMetricMonitorEnabled()
|
||||
&& mVcnContext.isFlagIpSecTransformStateEnabled()) {
|
||||
mUnderlyingNetworkController.updateInboundTransform(mUnderlying, transform);
|
||||
}
|
||||
|
||||
// For inbound transforms, additionally allow forwarded traffic to bridge to DUN (as
|
||||
// needed)
|
||||
final Set<Integer> exposedCaps = mConnectionConfig.getAllExposedCapabilities();
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ import android.annotation.NonNull;
|
|||
import android.annotation.Nullable;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.ConnectivityManager.NetworkCallback;
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
|
|
@ -52,6 +53,7 @@ import com.android.internal.annotations.VisibleForTesting.Visibility;
|
|||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||
import com.android.server.vcn.VcnContext;
|
||||
import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
|
||||
import com.android.server.vcn.util.LogUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
|
@ -201,6 +203,14 @@ public class UnderlyingNetworkController {
|
|||
NetworkCallback oldWifiExitRssiThresholdCallback = mWifiExitRssiThresholdCallback;
|
||||
List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks);
|
||||
mCellBringupCallbacks.clear();
|
||||
|
||||
if (mVcnContext.isFlagNetworkMetricMonitorEnabled()
|
||||
&& mVcnContext.isFlagIpSecTransformStateEnabled()) {
|
||||
for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) {
|
||||
evaluator.close();
|
||||
}
|
||||
}
|
||||
|
||||
mUnderlyingNetworkRecords.clear();
|
||||
|
||||
// Register new callbacks. Make-before-break; always register new callbacks before removal
|
||||
|
|
@ -417,11 +427,42 @@ public class UnderlyingNetworkController {
|
|||
if (oldSnapshot
|
||||
.getAllSubIdsInGroup(mSubscriptionGroup)
|
||||
.equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) {
|
||||
|
||||
if (mVcnContext.isFlagNetworkMetricMonitorEnabled()
|
||||
&& mVcnContext.isFlagIpSecTransformStateEnabled()) {
|
||||
reevaluateNetworks();
|
||||
}
|
||||
return;
|
||||
}
|
||||
registerOrUpdateNetworkRequests();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pass the IpSecTransform of the VCN to UnderlyingNetworkController for metric monitoring
|
||||
*
|
||||
* <p>Caller MUST call it when IpSecTransforms have been created for VCN creation or migration
|
||||
*/
|
||||
public void updateInboundTransform(
|
||||
@NonNull UnderlyingNetworkRecord currentNetwork, @NonNull IpSecTransform transform) {
|
||||
if (!mVcnContext.isFlagNetworkMetricMonitorEnabled()
|
||||
|| !mVcnContext.isFlagIpSecTransformStateEnabled()) {
|
||||
logWtf("#updateInboundTransform: unexpected call; flags missing");
|
||||
return;
|
||||
}
|
||||
|
||||
Objects.requireNonNull(currentNetwork, "currentNetwork is null");
|
||||
Objects.requireNonNull(transform, "transform is null");
|
||||
|
||||
if (mCurrentRecord == null
|
||||
|| mRouteSelectionCallback == null
|
||||
|| !Objects.equals(currentNetwork.network, mCurrentRecord.network)) {
|
||||
// The caller (VcnGatewayConnection) is out-of-dated. Ignore this call.
|
||||
return;
|
||||
}
|
||||
|
||||
mUnderlyingNetworkRecords.get(mCurrentRecord.network).setInboundTransform(transform);
|
||||
}
|
||||
|
||||
/** Tears down this Tracker, and releases all underlying network requests. */
|
||||
public void teardown() {
|
||||
mVcnContext.ensureRunningOnLooperThread();
|
||||
|
|
@ -438,7 +479,7 @@ public class UnderlyingNetworkController {
|
|||
|
||||
private TreeSet<UnderlyingNetworkEvaluator> getSortedUnderlyingNetworks() {
|
||||
TreeSet<UnderlyingNetworkEvaluator> sorted =
|
||||
new TreeSet<>(UnderlyingNetworkEvaluator.getComparator());
|
||||
new TreeSet<>(UnderlyingNetworkEvaluator.getComparator(mVcnContext));
|
||||
|
||||
for (UnderlyingNetworkEvaluator evaluator : mUnderlyingNetworkRecords.values()) {
|
||||
if (evaluator.getPriorityClass() != NetworkPriorityClassifier.PRIORITY_INVALID) {
|
||||
|
|
@ -525,11 +566,17 @@ public class UnderlyingNetworkController {
|
|||
mConnectionConfig.getVcnUnderlyingNetworkPriorities(),
|
||||
mSubscriptionGroup,
|
||||
mLastSnapshot,
|
||||
mCarrierConfig));
|
||||
mCarrierConfig,
|
||||
new NetworkEvaluatorCallbackImpl()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLost(@NonNull Network network) {
|
||||
if (mVcnContext.isFlagNetworkMetricMonitorEnabled()
|
||||
&& mVcnContext.isFlagIpSecTransformStateEnabled()) {
|
||||
mUnderlyingNetworkRecords.get(network).close();
|
||||
}
|
||||
|
||||
mUnderlyingNetworkRecords.remove(network);
|
||||
|
||||
reevaluateNetworks();
|
||||
|
|
@ -598,6 +645,21 @@ public class UnderlyingNetworkController {
|
|||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
class NetworkEvaluatorCallbackImpl implements NetworkEvaluatorCallback {
|
||||
@Override
|
||||
public void onEvaluationResultChanged() {
|
||||
if (!mVcnContext.isFlagNetworkMetricMonitorEnabled()
|
||||
|| !mVcnContext.isFlagIpSecTransformStateEnabled()) {
|
||||
logWtf("#onEvaluationResultChanged: unexpected call; flags missing");
|
||||
return;
|
||||
}
|
||||
|
||||
mVcnContext.ensureRunningOnLooperThread();
|
||||
reevaluateNetworks();
|
||||
}
|
||||
}
|
||||
|
||||
private String getLogPrefix() {
|
||||
return "("
|
||||
+ LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup)
|
||||
|
|
@ -690,21 +752,22 @@ public class UnderlyingNetworkController {
|
|||
|
||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||
public static class Dependencies {
|
||||
/** Construct a new UnderlyingNetworkEvaluator */
|
||||
public UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator(
|
||||
@NonNull VcnContext vcnContext,
|
||||
@NonNull Network network,
|
||||
@NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
|
||||
@NonNull ParcelUuid subscriptionGroup,
|
||||
@NonNull TelephonySubscriptionSnapshot lastSnapshot,
|
||||
@Nullable PersistableBundleWrapper carrierConfig) {
|
||||
@Nullable PersistableBundleWrapper carrierConfig,
|
||||
@NonNull NetworkEvaluatorCallback evaluatorCallback) {
|
||||
return new UnderlyingNetworkEvaluator(
|
||||
vcnContext,
|
||||
network,
|
||||
underlyingNetworkTemplates,
|
||||
subscriptionGroup,
|
||||
lastSnapshot,
|
||||
carrierConfig);
|
||||
carrierConfig,
|
||||
evaluatorCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,23 +16,32 @@
|
|||
|
||||
package com.android.server.vcn.routeselection;
|
||||
|
||||
import static com.android.server.VcnManagementService.LOCAL_LOG;
|
||||
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
import android.net.vcn.VcnManager;
|
||||
import android.net.vcn.VcnUnderlyingNetworkTemplate;
|
||||
import android.os.Handler;
|
||||
import android.os.ParcelUuid;
|
||||
import android.util.Slog;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.annotations.VisibleForTesting.Visibility;
|
||||
import com.android.internal.util.IndentingPrintWriter;
|
||||
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
|
||||
import com.android.server.vcn.VcnContext;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* UnderlyingNetworkEvaluator evaluates the quality and priority class of a network candidate for
|
||||
|
|
@ -43,20 +52,41 @@ import java.util.Objects;
|
|||
public class UnderlyingNetworkEvaluator {
|
||||
private static final String TAG = UnderlyingNetworkEvaluator.class.getSimpleName();
|
||||
|
||||
private static final int[] PENALTY_TIMEOUT_MINUTES_DEFAULT = new int[] {5};
|
||||
|
||||
@NonNull private final VcnContext mVcnContext;
|
||||
@NonNull private final Handler mHandler;
|
||||
@NonNull private final Object mCancellationToken = new Object();
|
||||
|
||||
@NonNull private final UnderlyingNetworkRecord.Builder mNetworkRecordBuilder;
|
||||
|
||||
@NonNull private final NetworkEvaluatorCallback mEvaluatorCallback;
|
||||
@NonNull private final List<NetworkMetricMonitor> mMetricMonitors = new ArrayList<>();
|
||||
|
||||
@NonNull private final Dependencies mDependencies;
|
||||
|
||||
// TODO: Support back-off timeouts
|
||||
private long mPenalizedTimeoutMs;
|
||||
|
||||
private boolean mIsSelected;
|
||||
private boolean mIsPenalized;
|
||||
private int mPriorityClass = NetworkPriorityClassifier.PRIORITY_INVALID;
|
||||
|
||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||
public UnderlyingNetworkEvaluator(
|
||||
@NonNull VcnContext vcnContext,
|
||||
@NonNull Network network,
|
||||
@NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
|
||||
@NonNull ParcelUuid subscriptionGroup,
|
||||
@NonNull TelephonySubscriptionSnapshot lastSnapshot,
|
||||
@Nullable PersistableBundleWrapper carrierConfig) {
|
||||
@Nullable PersistableBundleWrapper carrierConfig,
|
||||
@NonNull NetworkEvaluatorCallback evaluatorCallback,
|
||||
@NonNull Dependencies dependencies) {
|
||||
mVcnContext = Objects.requireNonNull(vcnContext, "Missing vcnContext");
|
||||
mHandler = new Handler(mVcnContext.getLooper());
|
||||
|
||||
mDependencies = Objects.requireNonNull(dependencies, "Missing dependencies");
|
||||
mEvaluatorCallback = Objects.requireNonNull(evaluatorCallback, "Missing deps");
|
||||
|
||||
Objects.requireNonNull(underlyingNetworkTemplates, "Missing underlyingNetworkTemplates");
|
||||
Objects.requireNonNull(subscriptionGroup, "Missing subscriptionGroup");
|
||||
|
|
@ -66,9 +96,76 @@ public class UnderlyingNetworkEvaluator {
|
|||
new UnderlyingNetworkRecord.Builder(
|
||||
Objects.requireNonNull(network, "Missing network"));
|
||||
mIsSelected = false;
|
||||
mIsPenalized = false;
|
||||
mPenalizedTimeoutMs = getPenaltyTimeoutMs(carrierConfig);
|
||||
|
||||
updatePriorityClass(
|
||||
underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
|
||||
|
||||
if (isIpSecPacketLossDetectorEnabled()) {
|
||||
try {
|
||||
mMetricMonitors.add(
|
||||
mDependencies.newIpSecPacketLossDetector(
|
||||
mVcnContext,
|
||||
mNetworkRecordBuilder.getNetwork(),
|
||||
carrierConfig,
|
||||
new MetricMonitorCallbackImpl()));
|
||||
} catch (IllegalAccessException e) {
|
||||
// No action. Do not add anything to mMetricMonitors
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public UnderlyingNetworkEvaluator(
|
||||
@NonNull VcnContext vcnContext,
|
||||
@NonNull Network network,
|
||||
@NonNull List<VcnUnderlyingNetworkTemplate> underlyingNetworkTemplates,
|
||||
@NonNull ParcelUuid subscriptionGroup,
|
||||
@NonNull TelephonySubscriptionSnapshot lastSnapshot,
|
||||
@Nullable PersistableBundleWrapper carrierConfig,
|
||||
@NonNull NetworkEvaluatorCallback evaluatorCallback) {
|
||||
this(
|
||||
vcnContext,
|
||||
network,
|
||||
underlyingNetworkTemplates,
|
||||
subscriptionGroup,
|
||||
lastSnapshot,
|
||||
carrierConfig,
|
||||
evaluatorCallback,
|
||||
new Dependencies());
|
||||
}
|
||||
|
||||
@VisibleForTesting(visibility = Visibility.PRIVATE)
|
||||
public static class Dependencies {
|
||||
/** Get an IpSecPacketLossDetector instance */
|
||||
public IpSecPacketLossDetector newIpSecPacketLossDetector(
|
||||
@NonNull VcnContext vcnContext,
|
||||
@NonNull Network network,
|
||||
@Nullable PersistableBundleWrapper carrierConfig,
|
||||
@NonNull NetworkMetricMonitor.NetworkMetricMonitorCallback callback)
|
||||
throws IllegalAccessException {
|
||||
return new IpSecPacketLossDetector(vcnContext, network, carrierConfig, callback);
|
||||
}
|
||||
}
|
||||
|
||||
/** Callback to notify caller to reevaluate network selection */
|
||||
public interface NetworkEvaluatorCallback {
|
||||
/**
|
||||
* Called when mIsPenalized changed
|
||||
*
|
||||
* <p>When receiving this call, UnderlyingNetworkController should reevaluate all network
|
||||
* candidates for VCN underlying network selection
|
||||
*/
|
||||
void onEvaluationResultChanged();
|
||||
}
|
||||
|
||||
private class MetricMonitorCallbackImpl
|
||||
implements NetworkMetricMonitor.NetworkMetricMonitorCallback {
|
||||
public void onValidationResultReceived() {
|
||||
mVcnContext.ensureRunningOnLooperThread();
|
||||
|
||||
handleValidationResult();
|
||||
}
|
||||
}
|
||||
|
||||
private void updatePriorityClass(
|
||||
|
|
@ -91,8 +188,25 @@ public class UnderlyingNetworkEvaluator {
|
|||
}
|
||||
}
|
||||
|
||||
public static Comparator<UnderlyingNetworkEvaluator> getComparator() {
|
||||
private boolean isIpSecPacketLossDetectorEnabled() {
|
||||
return isIpSecPacketLossDetectorEnabled(mVcnContext);
|
||||
}
|
||||
|
||||
private static boolean isIpSecPacketLossDetectorEnabled(VcnContext vcnContext) {
|
||||
return vcnContext.isFlagIpSecTransformStateEnabled()
|
||||
&& vcnContext.isFlagNetworkMetricMonitorEnabled();
|
||||
}
|
||||
|
||||
/** Get the comparator for UnderlyingNetworkEvaluator */
|
||||
public static Comparator<UnderlyingNetworkEvaluator> getComparator(VcnContext vcnContext) {
|
||||
return (left, right) -> {
|
||||
if (isIpSecPacketLossDetectorEnabled(vcnContext)) {
|
||||
if (left.mIsPenalized != right.mIsPenalized) {
|
||||
// A penalized network should have lower priority which means a larger index
|
||||
return left.mIsPenalized ? 1 : -1;
|
||||
}
|
||||
}
|
||||
|
||||
final int leftIndex = left.mPriorityClass;
|
||||
final int rightIndex = right.mPriorityClass;
|
||||
|
||||
|
|
@ -112,6 +226,64 @@ public class UnderlyingNetworkEvaluator {
|
|||
};
|
||||
}
|
||||
|
||||
private static long getPenaltyTimeoutMs(@Nullable PersistableBundleWrapper carrierConfig) {
|
||||
final int[] timeoutMinuteList;
|
||||
|
||||
if (carrierConfig != null) {
|
||||
timeoutMinuteList =
|
||||
carrierConfig.getIntArray(
|
||||
VcnManager.VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY,
|
||||
PENALTY_TIMEOUT_MINUTES_DEFAULT);
|
||||
} else {
|
||||
timeoutMinuteList = PENALTY_TIMEOUT_MINUTES_DEFAULT;
|
||||
}
|
||||
|
||||
// TODO: Add the support of back-off timeouts and return the full list
|
||||
return TimeUnit.MINUTES.toMillis(timeoutMinuteList[0]);
|
||||
}
|
||||
|
||||
private void handleValidationResult() {
|
||||
final boolean wasPenalized = mIsPenalized;
|
||||
mIsPenalized = false;
|
||||
for (NetworkMetricMonitor monitor : mMetricMonitors) {
|
||||
mIsPenalized |= monitor.isValidationFailed();
|
||||
}
|
||||
|
||||
if (wasPenalized == mIsPenalized) {
|
||||
return;
|
||||
}
|
||||
|
||||
logInfo(
|
||||
"#handleValidationResult: wasPenalized "
|
||||
+ wasPenalized
|
||||
+ " mIsPenalized "
|
||||
+ mIsPenalized);
|
||||
|
||||
if (mIsPenalized) {
|
||||
mHandler.postDelayed(
|
||||
new ExitPenaltyBoxRunnable(), mCancellationToken, mPenalizedTimeoutMs);
|
||||
} else {
|
||||
// Exit the penalty box
|
||||
mHandler.removeCallbacksAndEqualMessages(mCancellationToken);
|
||||
}
|
||||
mEvaluatorCallback.onEvaluationResultChanged();
|
||||
}
|
||||
|
||||
public class ExitPenaltyBoxRunnable implements Runnable {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!mIsPenalized) {
|
||||
logWtf("Evaluator not being penalized but ExitPenaltyBoxRunnable was scheduled");
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO: There might be a future metric monitor (e.g. ping) that will require the
|
||||
// validation to pass before exiting the penalty box.
|
||||
mIsPenalized = false;
|
||||
mEvaluatorCallback.onEvaluationResultChanged();
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the NetworkCapabilities */
|
||||
public void setNetworkCapabilities(
|
||||
@NonNull NetworkCapabilities nc,
|
||||
|
|
@ -162,6 +334,10 @@ public class UnderlyingNetworkEvaluator {
|
|||
|
||||
updatePriorityClass(
|
||||
underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
|
||||
|
||||
for (NetworkMetricMonitor monitor : mMetricMonitors) {
|
||||
monitor.setIsSelectedUnderlyingNetwork(isSelected);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -174,6 +350,35 @@ public class UnderlyingNetworkEvaluator {
|
|||
@Nullable PersistableBundleWrapper carrierConfig) {
|
||||
updatePriorityClass(
|
||||
underlyingNetworkTemplates, subscriptionGroup, lastSnapshot, carrierConfig);
|
||||
|
||||
// The already scheduled event will not be affected. The followup events will be scheduled
|
||||
// with the new timeout
|
||||
mPenalizedTimeoutMs = getPenaltyTimeoutMs(carrierConfig);
|
||||
|
||||
for (NetworkMetricMonitor monitor : mMetricMonitors) {
|
||||
monitor.setCarrierConfig(carrierConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/** Update the inbound IpSecTransform applied to the network */
|
||||
public void setInboundTransform(@NonNull IpSecTransform transform) {
|
||||
if (!mIsSelected) {
|
||||
logWtf("setInboundTransform on an unselected evaluator");
|
||||
return;
|
||||
}
|
||||
|
||||
for (NetworkMetricMonitor monitor : mMetricMonitors) {
|
||||
monitor.setInboundTransform(transform);
|
||||
}
|
||||
}
|
||||
|
||||
/** Close the evaluator and stop all the underlying network metric monitors */
|
||||
public void close() {
|
||||
mHandler.removeCallbacksAndEqualMessages(mCancellationToken);
|
||||
|
||||
for (NetworkMetricMonitor monitor : mMetricMonitors) {
|
||||
monitor.close();
|
||||
}
|
||||
}
|
||||
|
||||
/** Return whether this network evaluator is valid */
|
||||
|
|
@ -196,6 +401,11 @@ public class UnderlyingNetworkEvaluator {
|
|||
return mPriorityClass;
|
||||
}
|
||||
|
||||
/** Return whether the network is being penalized */
|
||||
public boolean isPenalized() {
|
||||
return mIsPenalized;
|
||||
}
|
||||
|
||||
/** Dump the information of this instance */
|
||||
public void dump(IndentingPrintWriter pw) {
|
||||
pw.println("UnderlyingNetworkEvaluator:");
|
||||
|
|
@ -211,7 +421,22 @@ public class UnderlyingNetworkEvaluator {
|
|||
|
||||
pw.println("mIsSelected: " + mIsSelected);
|
||||
pw.println("mPriorityClass: " + mPriorityClass);
|
||||
pw.println("mIsPenalized: " + mIsPenalized);
|
||||
|
||||
pw.decreaseIndent();
|
||||
}
|
||||
|
||||
private String getLogPrefix() {
|
||||
return "[Network " + mNetworkRecordBuilder.getNetwork() + "] ";
|
||||
}
|
||||
|
||||
private void logInfo(String msg) {
|
||||
Slog.i(TAG, getLogPrefix() + msg);
|
||||
LOCAL_LOG.log("[INFO ] " + TAG + getLogPrefix() + msg);
|
||||
}
|
||||
|
||||
private void logWtf(String msg) {
|
||||
Slog.wtf(TAG, getLogPrefix() + msg);
|
||||
LOCAL_LOG.log("[WTF ] " + TAG + getLogPrefix() + msg);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -269,6 +269,7 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||
@Test
|
||||
public void testCreatedTransformsAreApplied() throws Exception {
|
||||
verifyVcnTransformsApplied(mGatewayConnection, false /* expectForwardTransform */);
|
||||
verify(mUnderlyingNetworkController).updateInboundTransform(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -327,6 +328,8 @@ public class VcnGatewayConnectionConnectedStateTest extends VcnGatewayConnection
|
|||
eq(TEST_IPSEC_TUNNEL_RESOURCE_ID), eq(direction), anyInt(), any());
|
||||
}
|
||||
|
||||
verify(mUnderlyingNetworkController).updateInboundTransform(any(), any());
|
||||
|
||||
assertEquals(mGatewayConnection.mConnectedState, mGatewayConnection.getCurrentState());
|
||||
|
||||
final List<ChildSaProposal> saProposals =
|
||||
|
|
|
|||
|
|
@ -223,6 +223,8 @@ public class VcnGatewayConnectionTestBase {
|
|||
doReturn(mVcnNetworkProvider).when(mVcnContext).getVcnNetworkProvider();
|
||||
doReturn(mFeatureFlags).when(mVcnContext).getFeatureFlags();
|
||||
doReturn(true).when(mVcnContext).isFlagSafeModeTimeoutConfigEnabled();
|
||||
doReturn(true).when(mVcnContext).isFlagIpSecTransformStateEnabled();
|
||||
doReturn(true).when(mVcnContext).isFlagNetworkMetricMonitorEnabled();
|
||||
|
||||
doReturn(mUnderlyingNetworkController)
|
||||
.when(mDeps)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ import static org.mockito.Mockito.spy;
|
|||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.IpSecConfig;
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
|
|
@ -141,4 +143,8 @@ public abstract class NetworkEvaluationTestBase {
|
|||
mock(Handler.class));
|
||||
setupSystemService(mContext, mPowerManager, Context.POWER_SERVICE, PowerManager.class);
|
||||
}
|
||||
|
||||
protected IpSecTransform makeDummyIpSecTransform() throws Exception {
|
||||
return new IpSecTransform(mContext, new IpSecConfig());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,8 @@ import static org.mockito.Mockito.when;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.ConnectivityManager;
|
||||
import android.net.IpSecConfig;
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.LinkProperties;
|
||||
import android.net.Network;
|
||||
import android.net.NetworkCapabilities;
|
||||
|
|
@ -70,6 +72,7 @@ import com.android.server.vcn.routeselection.UnderlyingNetworkController.Depende
|
|||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.NetworkBringupCallback;
|
||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkControllerCallback;
|
||||
import com.android.server.vcn.routeselection.UnderlyingNetworkController.UnderlyingNetworkListener;
|
||||
import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
|
@ -153,11 +156,13 @@ public class UnderlyingNetworkControllerTest {
|
|||
@Mock private CarrierConfigManager mCarrierConfigManager;
|
||||
@Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
|
||||
@Mock private UnderlyingNetworkControllerCallback mNetworkControllerCb;
|
||||
@Mock private NetworkEvaluatorCallback mEvaluatorCallback;
|
||||
@Mock private Network mNetwork;
|
||||
|
||||
@Spy private Dependencies mDependencies = new Dependencies();
|
||||
|
||||
@Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor;
|
||||
@Captor private ArgumentCaptor<NetworkEvaluatorCallback> mEvaluatorCallbackCaptor;
|
||||
|
||||
private TestLooper mTestLooper;
|
||||
private VcnContext mVcnContext;
|
||||
|
|
@ -176,7 +181,7 @@ public class UnderlyingNetworkControllerTest {
|
|||
mTestLooper.getLooper(),
|
||||
mVcnNetworkProvider,
|
||||
false /* isInTestMode */));
|
||||
resetVcnContext();
|
||||
resetVcnContext(mVcnContext);
|
||||
|
||||
setupSystemService(
|
||||
mContext,
|
||||
|
|
@ -202,10 +207,11 @@ public class UnderlyingNetworkControllerTest {
|
|||
.getVcnUnderlyingNetworkPriorities(),
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
null));
|
||||
null,
|
||||
mEvaluatorCallback));
|
||||
doReturn(mNetworkEvaluator)
|
||||
.when(mDependencies)
|
||||
.newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any());
|
||||
.newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any());
|
||||
|
||||
mUnderlyingNetworkController =
|
||||
new UnderlyingNetworkController(
|
||||
|
|
@ -217,9 +223,11 @@ public class UnderlyingNetworkControllerTest {
|
|||
mDependencies);
|
||||
}
|
||||
|
||||
private void resetVcnContext() {
|
||||
reset(mVcnContext);
|
||||
doNothing().when(mVcnContext).ensureRunningOnLooperThread();
|
||||
private void resetVcnContext(VcnContext vcnContext) {
|
||||
reset(vcnContext);
|
||||
doNothing().when(vcnContext).ensureRunningOnLooperThread();
|
||||
doReturn(true).when(vcnContext).isFlagNetworkMetricMonitorEnabled();
|
||||
doReturn(true).when(vcnContext).isFlagIpSecTransformStateEnabled();
|
||||
}
|
||||
|
||||
// Package private for use in NetworkPriorityClassifierTest
|
||||
|
|
@ -245,11 +253,13 @@ public class UnderlyingNetworkControllerTest {
|
|||
final ConnectivityManager cm = mock(ConnectivityManager.class);
|
||||
setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
|
||||
final VcnContext vcnContext =
|
||||
new VcnContext(
|
||||
mContext,
|
||||
mTestLooper.getLooper(),
|
||||
mVcnNetworkProvider,
|
||||
true /* isInTestMode */);
|
||||
spy(
|
||||
new VcnContext(
|
||||
mContext,
|
||||
mTestLooper.getLooper(),
|
||||
mVcnNetworkProvider,
|
||||
true /* isInTestMode */));
|
||||
resetVcnContext(vcnContext);
|
||||
|
||||
new UnderlyingNetworkController(
|
||||
vcnContext,
|
||||
|
|
@ -554,6 +564,45 @@ public class UnderlyingNetworkControllerTest {
|
|||
verify(mNetworkEvaluator).reevaluate(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateIpSecTransform() {
|
||||
verifyRegistrationOnAvailableAndGetCallback();
|
||||
|
||||
final UnderlyingNetworkRecord expectedRecord =
|
||||
getTestNetworkRecord(
|
||||
mNetwork,
|
||||
INITIAL_NETWORK_CAPABILITIES,
|
||||
INITIAL_LINK_PROPERTIES,
|
||||
false /* isBlocked */);
|
||||
final IpSecTransform expectedTransform = new IpSecTransform(mContext, new IpSecConfig());
|
||||
|
||||
mUnderlyingNetworkController.updateInboundTransform(expectedRecord, expectedTransform);
|
||||
verify(mNetworkEvaluator).setInboundTransform(expectedTransform);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnEvaluationResultChanged() {
|
||||
verifyRegistrationOnAvailableAndGetCallback();
|
||||
|
||||
// Verify #reevaluateNetworks is called by checking #getNetworkRecord
|
||||
verify(mNetworkEvaluator).getNetworkRecord();
|
||||
|
||||
// Trigger the callback
|
||||
verify(mDependencies)
|
||||
.newUnderlyingNetworkEvaluator(
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
any(),
|
||||
mEvaluatorCallbackCaptor.capture());
|
||||
mEvaluatorCallbackCaptor.getValue().onEvaluationResultChanged();
|
||||
|
||||
// Verify #reevaluateNetworks is called again
|
||||
verify(mNetworkEvaluator, times(2)).getNetworkRecord();
|
||||
}
|
||||
|
||||
private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() {
|
||||
return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES);
|
||||
}
|
||||
|
|
@ -682,7 +731,7 @@ public class UnderlyingNetworkControllerTest {
|
|||
|
||||
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
|
||||
|
||||
verifyOnSelectedUnderlyingNetworkChanged(null);
|
||||
verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -690,6 +739,7 @@ public class UnderlyingNetworkControllerTest {
|
|||
UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
|
||||
|
||||
cb.onLost(mNetwork);
|
||||
verify(mNetworkEvaluator).close();
|
||||
|
||||
verify(mNetworkControllerCb).onSelectedUnderlyingNetworkChanged(null);
|
||||
}
|
||||
|
|
@ -755,10 +805,11 @@ public class UnderlyingNetworkControllerTest {
|
|||
underlyingNetworkTemplates,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
null));
|
||||
null,
|
||||
mEvaluatorCallback));
|
||||
doReturn(evaluator)
|
||||
.when(mDependencies)
|
||||
.newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any());
|
||||
.newUnderlyingNetworkEvaluator(any(), any(), any(), any(), any(), any(), any());
|
||||
|
||||
cb.onAvailable(network);
|
||||
cb.onCapabilitiesChanged(network, responseNetworkCaps);
|
||||
|
|
|
|||
|
|
@ -16,27 +16,65 @@
|
|||
|
||||
package com.android.server.vcn.routeselection;
|
||||
|
||||
import static android.net.vcn.VcnManager.VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY;
|
||||
|
||||
import static com.android.server.vcn.routeselection.NetworkPriorityClassifier.PRIORITY_INVALID;
|
||||
import static com.android.server.vcn.util.PersistableBundleUtils.PersistableBundleWrapper;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyObject;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import android.net.IpSecTransform;
|
||||
import android.net.vcn.VcnGatewayConnectionConfig;
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
import com.android.server.vcn.routeselection.NetworkMetricMonitor.NetworkMetricMonitorCallback;
|
||||
import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.Dependencies;
|
||||
import com.android.server.vcn.routeselection.UnderlyingNetworkEvaluator.NetworkEvaluatorCallback;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase {
|
||||
private PersistableBundleWrapper mCarrierConfig;
|
||||
private static final int PENALTY_TIMEOUT_MIN = 10;
|
||||
private static final long PENALTY_TIMEOUT_MS = TimeUnit.MINUTES.toMillis(PENALTY_TIMEOUT_MIN);
|
||||
|
||||
@Mock private PersistableBundleWrapper mCarrierConfig;
|
||||
@Mock private IpSecPacketLossDetector mIpSecPacketLossDetector;
|
||||
@Mock private Dependencies mDependencies;
|
||||
@Mock private NetworkEvaluatorCallback mEvaluatorCallback;
|
||||
|
||||
@Captor private ArgumentCaptor<NetworkMetricMonitorCallback> mMetricMonitorCbCaptor;
|
||||
|
||||
private UnderlyingNetworkEvaluator mNetworkEvaluator;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
super.setUp();
|
||||
mCarrierConfig = new PersistableBundleWrapper(new PersistableBundle());
|
||||
|
||||
when(mDependencies.newIpSecPacketLossDetector(any(), any(), any(), any()))
|
||||
.thenReturn(mIpSecPacketLossDetector);
|
||||
|
||||
when(mCarrierConfig.getIntArray(
|
||||
eq(VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY), anyObject()))
|
||||
.thenReturn(new int[] {PENALTY_TIMEOUT_MIN});
|
||||
|
||||
mNetworkEvaluator = newValidUnderlyingNetworkEvaluator();
|
||||
}
|
||||
|
||||
private UnderlyingNetworkEvaluator newUnderlyingNetworkEvaluator() {
|
||||
|
|
@ -46,7 +84,34 @@ public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase {
|
|||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig,
|
||||
mEvaluatorCallback,
|
||||
mDependencies);
|
||||
}
|
||||
|
||||
private UnderlyingNetworkEvaluator newValidUnderlyingNetworkEvaluator() {
|
||||
final UnderlyingNetworkEvaluator evaluator = newUnderlyingNetworkEvaluator();
|
||||
|
||||
evaluator.setNetworkCapabilities(
|
||||
CELL_NETWORK_CAPABILITIES,
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
evaluator.setLinkProperties(
|
||||
LINK_PROPERTIES,
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
evaluator.setIsBlocked(
|
||||
false /* isBlocked */,
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
|
||||
return evaluator;
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
@ -98,4 +163,174 @@ public class UnderlyingNetworkEvaluatorTest extends NetworkEvaluationTestBase {
|
|||
assertEquals(2, evaluator.getPriorityClass());
|
||||
assertEquals(expectedRecord, evaluator.getNetworkRecord());
|
||||
}
|
||||
|
||||
private void checkSetSelectedNetwork(boolean isSelected) {
|
||||
mNetworkEvaluator.setIsSelected(
|
||||
isSelected,
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
verify(mIpSecPacketLossDetector).setIsSelectedUnderlyingNetwork(isSelected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetIsSelected_selected() throws Exception {
|
||||
checkSetSelectedNetwork(true /* isSelectedExpected */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetIsSelected_unselected() throws Exception {
|
||||
checkSetSelectedNetwork(false /* isSelectedExpected */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetIpSecTransform_onSelectedNetwork() throws Exception {
|
||||
final IpSecTransform transform = makeDummyIpSecTransform();
|
||||
|
||||
// Make the network selected
|
||||
mNetworkEvaluator.setIsSelected(
|
||||
true,
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
mNetworkEvaluator.setInboundTransform(transform);
|
||||
|
||||
verify(mIpSecPacketLossDetector).setInboundTransform(transform);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetIpSecTransform_onUnSelectedNetwork() throws Exception {
|
||||
mNetworkEvaluator.setIsSelected(
|
||||
false,
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
mNetworkEvaluator.setInboundTransform(makeDummyIpSecTransform());
|
||||
|
||||
verify(mIpSecPacketLossDetector, never()).setInboundTransform(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void close() throws Exception {
|
||||
mNetworkEvaluator.close();
|
||||
|
||||
verify(mIpSecPacketLossDetector).close();
|
||||
mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
|
||||
assertNull(mTestLooper.nextMessage());
|
||||
}
|
||||
|
||||
private NetworkMetricMonitorCallback getMetricMonitorCbCaptor() throws Exception {
|
||||
verify(mDependencies)
|
||||
.newIpSecPacketLossDetector(any(), any(), any(), mMetricMonitorCbCaptor.capture());
|
||||
|
||||
return mMetricMonitorCbCaptor.getValue();
|
||||
}
|
||||
|
||||
private void checkPenalizeNetwork() throws Exception {
|
||||
assertFalse(mNetworkEvaluator.isPenalized());
|
||||
|
||||
// Validation failed
|
||||
when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(true);
|
||||
getMetricMonitorCbCaptor().onValidationResultReceived();
|
||||
|
||||
// Verify the evaluator is penalized
|
||||
assertTrue(mNetworkEvaluator.isPenalized());
|
||||
verify(mEvaluatorCallback).onEvaluationResultChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRcvValidationResult_penalizeNetwork_penaltyTimeout() throws Exception {
|
||||
checkPenalizeNetwork();
|
||||
|
||||
// Penalty timeout
|
||||
mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
// Verify the evaluator is not penalized
|
||||
assertFalse(mNetworkEvaluator.isPenalized());
|
||||
verify(mEvaluatorCallback, times(2)).onEvaluationResultChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRcvValidationResult_penalizeNetwork_passValidation() throws Exception {
|
||||
checkPenalizeNetwork();
|
||||
|
||||
// Validation passed
|
||||
when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(false);
|
||||
getMetricMonitorCbCaptor().onValidationResultReceived();
|
||||
|
||||
// Verify the evaluator is not penalized and penalty timeout is canceled
|
||||
assertFalse(mNetworkEvaluator.isPenalized());
|
||||
verify(mEvaluatorCallback, times(2)).onEvaluationResultChanged();
|
||||
mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
|
||||
assertNull(mTestLooper.nextMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRcvValidationResult_penalizeNetwork_closeEvaluator() throws Exception {
|
||||
checkPenalizeNetwork();
|
||||
|
||||
mNetworkEvaluator.close();
|
||||
|
||||
// Verify penalty timeout is canceled
|
||||
mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
|
||||
assertNull(mTestLooper.nextMessage());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRcvValidationResult_PenaltyStateUnchanged() throws Exception {
|
||||
assertFalse(mNetworkEvaluator.isPenalized());
|
||||
|
||||
// Validation passed
|
||||
when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(false);
|
||||
getMetricMonitorCbCaptor().onValidationResultReceived();
|
||||
|
||||
// Verifications
|
||||
assertFalse(mNetworkEvaluator.isPenalized());
|
||||
verify(mEvaluatorCallback, never()).onEvaluationResultChanged();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetCarrierConfig() throws Exception {
|
||||
final int additionalTimeoutMin = 10;
|
||||
when(mCarrierConfig.getIntArray(
|
||||
eq(VCN_NETWORK_SELECTION_PENALTY_TIMEOUT_MINUTES_LIST_KEY), anyObject()))
|
||||
.thenReturn(new int[] {PENALTY_TIMEOUT_MIN + additionalTimeoutMin});
|
||||
|
||||
// Update evaluator and penalize the network
|
||||
mNetworkEvaluator.reevaluate(
|
||||
VcnGatewayConnectionConfig.DEFAULT_UNDERLYING_NETWORK_TEMPLATES,
|
||||
SUB_GROUP,
|
||||
mSubscriptionSnapshot,
|
||||
mCarrierConfig);
|
||||
checkPenalizeNetwork();
|
||||
|
||||
// Verify penalty timeout is changed
|
||||
mTestLooper.moveTimeForward(PENALTY_TIMEOUT_MS);
|
||||
assertNull(mTestLooper.nextMessage());
|
||||
mTestLooper.moveTimeForward(TimeUnit.MINUTES.toMillis(additionalTimeoutMin));
|
||||
assertNotNull(mTestLooper.nextMessage());
|
||||
|
||||
// Verify NetworkMetricMonitor is notified
|
||||
verify(mIpSecPacketLossDetector).setCarrierConfig(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompare() throws Exception {
|
||||
when(mIpSecPacketLossDetector.isValidationFailed()).thenReturn(true);
|
||||
getMetricMonitorCbCaptor().onValidationResultReceived();
|
||||
|
||||
final UnderlyingNetworkEvaluator penalized = mNetworkEvaluator;
|
||||
final UnderlyingNetworkEvaluator notPenalized = newValidUnderlyingNetworkEvaluator();
|
||||
|
||||
assertEquals(penalized.getPriorityClass(), notPenalized.getPriorityClass());
|
||||
|
||||
final int result =
|
||||
UnderlyingNetworkEvaluator.getComparator(mVcnContext)
|
||||
.compare(penalized, notPenalized);
|
||||
assertEquals(1, result);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue