summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Benedict Wong <benedictwong@google.com> 2021-05-10 10:15:15 -0700
committer Benedict Wong <benedictwong@google.com> 2021-05-13 18:57:05 -0700
commit9028cac4fe39206ce6162ea3662a66b329563961 (patch)
treea51e0ddb43cb23860013ed37f1568639fbfa01c3
parent3b2decbb34e30736a9d6fa9d8d43a37a1db165d0 (diff)
Custom network selection
This change adds a basic prioritization framework in the VCN, and signal strength thresholds for WiFi. Bug: 188104094 Test: atest FrameworksVcnTests Change-Id: Iee4e3dbecf1102ddc127a8c8daf08a00b6fccbbd
-rw-r--r--core/java/android/net/vcn/VcnManager.java30
-rw-r--r--services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java38
-rw-r--r--services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java445
-rw-r--r--tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java20
-rw-r--r--tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java129
-rw-r--r--tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java9
6 files changed, 521 insertions, 150 deletions
diff --git a/core/java/android/net/vcn/VcnManager.java b/core/java/android/net/vcn/VcnManager.java
index 9d1c1ff898e7..390c3b9453c2 100644
--- a/core/java/android/net/vcn/VcnManager.java
+++ b/core/java/android/net/vcn/VcnManager.java
@@ -74,6 +74,36 @@ import java.util.concurrent.Executor;
public class VcnManager {
@NonNull private static final String TAG = VcnManager.class.getSimpleName();
+ /**
+ * Key for WiFi entry RSSI thresholds
+ *
+ * <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
+ public static final String VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY =
+ "vcn_network_selection_wifi_entry_rssi_threshold";
+
+ /**
+ * Key for WiFi entry RSSI thresholds
+ *
+ * <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
+ public static final String VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY =
+ "vcn_network_selection_wifi_exit_rssi_threshold";
+
+ // TODO: Add separate signal strength thresholds for 2.4 GHz and 5GHz
+
private static final Map<
VcnNetworkPolicyChangeListener, VcnUnderlyingNetworkPolicyListenerBinder>
REGISTERED_POLICY_LISTENERS = new ConcurrentHashMap<>();
diff --git a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
index 19fbdbd86099..5565ccb6cf7c 100644
--- a/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
+++ b/services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java
@@ -145,7 +145,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
*/
public void handleSubscriptionsChanged() {
final Map<ParcelUuid, Set<String>> privilegedPackages = new HashMap<>();
- final Map<Integer, ParcelUuid> newSubIdToGroupMap = new HashMap<>();
+ final Map<Integer, SubscriptionInfo> newSubIdToInfoMap = new HashMap<>();
final List<SubscriptionInfo> allSubs = mSubscriptionManager.getAllSubscriptionInfoList();
if (allSubs == null) {
@@ -160,7 +160,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
}
// Build subId -> subGrp cache
- newSubIdToGroupMap.put(subInfo.getSubscriptionId(), subInfo.getGroupUuid());
+ newSubIdToInfoMap.put(subInfo.getSubscriptionId(), subInfo);
// Update subscription groups that are both ready, and active. For a group to be
// considered active, both of the following must be true:
@@ -186,7 +186,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
}
final TelephonySubscriptionSnapshot newSnapshot =
- new TelephonySubscriptionSnapshot(newSubIdToGroupMap, privilegedPackages);
+ new TelephonySubscriptionSnapshot(newSubIdToInfoMap, privilegedPackages);
// If snapshot was meaningfully updated, fire the callback
if (!newSnapshot.equals(mCurrentSnapshot)) {
@@ -245,7 +245,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
/** TelephonySubscriptionSnapshot is a class containing info about active subscriptions */
public static class TelephonySubscriptionSnapshot {
- private final Map<Integer, ParcelUuid> mSubIdToGroupMap;
+ private final Map<Integer, SubscriptionInfo> mSubIdToInfoMap;
private final Map<ParcelUuid, Set<String>> mPrivilegedPackages;
public static final TelephonySubscriptionSnapshot EMPTY_SNAPSHOT =
@@ -253,12 +253,12 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
@VisibleForTesting(visibility = Visibility.PRIVATE)
TelephonySubscriptionSnapshot(
- @NonNull Map<Integer, ParcelUuid> subIdToGroupMap,
+ @NonNull Map<Integer, SubscriptionInfo> subIdToInfoMap,
@NonNull Map<ParcelUuid, Set<String>> privilegedPackages) {
- Objects.requireNonNull(subIdToGroupMap, "subIdToGroupMap was null");
+ Objects.requireNonNull(subIdToInfoMap, "subIdToInfoMap was null");
Objects.requireNonNull(privilegedPackages, "privilegedPackages was null");
- mSubIdToGroupMap = Collections.unmodifiableMap(subIdToGroupMap);
+ mSubIdToInfoMap = Collections.unmodifiableMap(subIdToInfoMap);
final Map<ParcelUuid, Set<String>> unmodifiableInnerSets = new ArrayMap<>();
for (Entry<ParcelUuid, Set<String>> entry : privilegedPackages.entrySet()) {
@@ -285,7 +285,9 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
/** Returns the Subscription Group for a given subId. */
@Nullable
public ParcelUuid getGroupForSubId(int subId) {
- return mSubIdToGroupMap.get(subId);
+ return mSubIdToInfoMap.containsKey(subId)
+ ? mSubIdToInfoMap.get(subId).getGroupUuid()
+ : null;
}
/**
@@ -295,8 +297,8 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
public Set<Integer> getAllSubIdsInGroup(ParcelUuid subGrp) {
final Set<Integer> subIds = new ArraySet<>();
- for (Entry<Integer, ParcelUuid> entry : mSubIdToGroupMap.entrySet()) {
- if (subGrp.equals(entry.getValue())) {
+ for (Entry<Integer, SubscriptionInfo> entry : mSubIdToInfoMap.entrySet()) {
+ if (subGrp.equals(entry.getValue().getGroupUuid())) {
subIds.add(entry.getKey());
}
}
@@ -304,9 +306,17 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
return subIds;
}
+ /** Checks if the requested subscription is opportunistic */
+ @NonNull
+ public boolean isOpportunistic(int subId) {
+ return mSubIdToInfoMap.containsKey(subId)
+ ? mSubIdToInfoMap.get(subId).isOpportunistic()
+ : false;
+ }
+
@Override
public int hashCode() {
- return Objects.hash(mSubIdToGroupMap, mPrivilegedPackages);
+ return Objects.hash(mSubIdToInfoMap, mPrivilegedPackages);
}
@Override
@@ -317,7 +327,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
final TelephonySubscriptionSnapshot other = (TelephonySubscriptionSnapshot) obj;
- return mSubIdToGroupMap.equals(other.mSubIdToGroupMap)
+ return mSubIdToInfoMap.equals(other.mSubIdToInfoMap)
&& mPrivilegedPackages.equals(other.mPrivilegedPackages);
}
@@ -326,7 +336,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
pw.println("TelephonySubscriptionSnapshot:");
pw.increaseIndent();
- pw.println("mSubIdToGroupMap: " + mSubIdToGroupMap);
+ pw.println("mSubIdToInfoMap: " + mSubIdToInfoMap);
pw.println("mPrivilegedPackages: " + mPrivilegedPackages);
pw.decreaseIndent();
@@ -335,7 +345,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver {
@Override
public String toString() {
return "TelephonySubscriptionSnapshot{ "
- + "mSubIdToGroupMap=" + mSubIdToGroupMap
+ + "mSubIdToInfoMap=" + mSubIdToInfoMap
+ ", mPrivilegedPackages=" + mPrivilegedPackages
+ " }";
}
diff --git a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
index 3bdeec0c1d8e..fb4c6236a9a0 100644
--- a/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
+++ b/services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java
@@ -16,6 +16,10 @@
package com.android.server.vcn;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
+import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.telephony.TelephonyCallback.ActiveDataSubscriptionIdListener;
+
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.ConnectivityManager;
@@ -25,8 +29,16 @@ import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnManager;
import android.os.Handler;
+import android.os.HandlerExecutor;
import android.os.ParcelUuid;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
+import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyCallback;
+import android.telephony.TelephonyManager;
+import android.util.ArrayMap;
import android.util.Slog;
import com.android.internal.annotations.VisibleForTesting;
@@ -35,9 +47,13 @@ import com.android.internal.util.IndentingPrintWriter;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
+import java.util.Map;
import java.util.Objects;
import java.util.Set;
+import java.util.TreeSet;
/**
* Tracks a set of Networks underpinning a VcnGatewayConnection.
@@ -51,6 +67,45 @@ import java.util.Set;
public class UnderlyingNetworkTracker {
@NonNull private static final String TAG = UnderlyingNetworkTracker.class.getSimpleName();
+ /**
+ * Minimum signal strength for a WiFi network to be eligible for switching to
+ *
+ * <p>A network that satisfies this is eligible to become the selected underlying network with
+ * no additional conditions
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT = -70;
+
+ /**
+ * Minimum signal strength to continue using a WiFi network
+ *
+ * <p>A network that satisfies the conditions may ONLY continue to be used if it is already
+ * selected as the underlying network. A WiFi network satisfying this condition, but NOT the
+ * prospective-network RSSI threshold CANNOT be switched to.
+ */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int WIFI_EXIT_RSSI_THRESHOLD_DEFAULT = -74;
+
+ /** Priority for any cellular network for which the subscription is listed as opportunistic */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_OPPORTUNISTIC_CELLULAR = 0;
+
+ /** Priority for any WiFi network which is in use, and satisfies the in-use RSSI threshold */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_WIFI_IN_USE = 1;
+
+ /** Priority for any WiFi network which satisfies the prospective-network RSSI threshold */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_WIFI_PROSPECTIVE = 2;
+
+ /** Priority for any standard macro cellular network */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_MACRO_CELLULAR = 3;
+
+ /** Priority for any other networks (including unvalidated, etc) */
+ @VisibleForTesting(visibility = Visibility.PRIVATE)
+ static final int PRIORITY_ANY = Integer.MAX_VALUE;
+
@NonNull private final VcnContext mVcnContext;
@NonNull private final ParcelUuid mSubscriptionGroup;
@NonNull private final Set<Integer> mRequiredUnderlyingNetworkCapabilities;
@@ -58,12 +113,17 @@ public class UnderlyingNetworkTracker {
@NonNull private final Dependencies mDeps;
@NonNull private final Handler mHandler;
@NonNull private final ConnectivityManager mConnectivityManager;
+ @NonNull private final TelephonyCallback mActiveDataSubIdListener =
+ new VcnActiveDataSubscriptionIdListener();
@NonNull private final List<NetworkCallback> mCellBringupCallbacks = new ArrayList<>();
@Nullable private NetworkCallback mWifiBringupCallback;
- @Nullable private NetworkCallback mRouteSelectionCallback;
+ @Nullable private NetworkCallback mWifiEntryRssiThresholdCallback;
+ @Nullable private NetworkCallback mWifiExitRssiThresholdCallback;
+ @Nullable private UnderlyingNetworkListener mRouteSelectionCallback;
@NonNull private TelephonySubscriptionSnapshot mLastSnapshot;
+ @Nullable private PersistableBundle mCarrierConfig;
private boolean mIsQuitting = false;
@Nullable private UnderlyingNetworkRecord mCurrentRecord;
@@ -104,6 +164,30 @@ public class UnderlyingNetworkTracker {
mHandler = new Handler(mVcnContext.getLooper());
mConnectivityManager = mVcnContext.getContext().getSystemService(ConnectivityManager.class);
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .registerTelephonyCallback(new HandlerExecutor(mHandler), mActiveDataSubIdListener);
+
+ // TODO: Listen for changes in carrier config that affect this.
+ for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) {
+ PersistableBundle config =
+ mVcnContext
+ .getContext()
+ .getSystemService(CarrierConfigManager.class)
+ .getConfigForSubId(subId);
+
+ if (config != null) {
+ mCarrierConfig = config;
+
+ // Attempt to use (any) non-opportunistic subscription. If this subscription is
+ // opportunistic, continue and try to find a non-opportunistic subscription, using
+ // the opportunistic ones as a last resort.
+ if (!isOpportunistic(mLastSnapshot, Collections.singleton(subId))) {
+ break;
+ }
+ }
+ }
registerOrUpdateNetworkRequests();
}
@@ -111,16 +195,30 @@ public class UnderlyingNetworkTracker {
private void registerOrUpdateNetworkRequests() {
NetworkCallback oldRouteSelectionCallback = mRouteSelectionCallback;
NetworkCallback oldWifiCallback = mWifiBringupCallback;
+ NetworkCallback oldWifiEntryRssiThresholdCallback = mWifiEntryRssiThresholdCallback;
+ NetworkCallback oldWifiExitRssiThresholdCallback = mWifiExitRssiThresholdCallback;
List<NetworkCallback> oldCellCallbacks = new ArrayList<>(mCellBringupCallbacks);
mCellBringupCallbacks.clear();
// Register new callbacks. Make-before-break; always register new callbacks before removal
// of old callbacks
if (!mIsQuitting) {
- mRouteSelectionCallback = new RouteSelectionCallback();
- mConnectivityManager.requestBackgroundNetwork(
+ mRouteSelectionCallback = new UnderlyingNetworkListener();
+ mConnectivityManager.registerNetworkCallback(
getRouteSelectionRequest(), mRouteSelectionCallback, mHandler);
+ mWifiEntryRssiThresholdCallback = new NetworkBringupCallback();
+ mConnectivityManager.registerNetworkCallback(
+ getWifiEntryRssiThresholdNetworkRequest(),
+ mWifiEntryRssiThresholdCallback,
+ mHandler);
+
+ mWifiExitRssiThresholdCallback = new NetworkBringupCallback();
+ mConnectivityManager.registerNetworkCallback(
+ getWifiExitRssiThresholdNetworkRequest(),
+ mWifiExitRssiThresholdCallback,
+ mHandler);
+
mWifiBringupCallback = new NetworkBringupCallback();
mConnectivityManager.requestBackgroundNetwork(
getWifiNetworkRequest(), mWifiBringupCallback, mHandler);
@@ -135,6 +233,8 @@ public class UnderlyingNetworkTracker {
} else {
mRouteSelectionCallback = null;
mWifiBringupCallback = null;
+ mWifiEntryRssiThresholdCallback = null;
+ mWifiExitRssiThresholdCallback = null;
// mCellBringupCallbacks already cleared above.
}
@@ -145,6 +245,12 @@ public class UnderlyingNetworkTracker {
if (oldWifiCallback != null) {
mConnectivityManager.unregisterNetworkCallback(oldWifiCallback);
}
+ if (oldWifiEntryRssiThresholdCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(oldWifiEntryRssiThresholdCallback);
+ }
+ if (oldWifiExitRssiThresholdCallback != null) {
+ mConnectivityManager.unregisterNetworkCallback(oldWifiExitRssiThresholdCallback);
+ }
for (NetworkCallback cellBringupCallback : oldCellCallbacks) {
mConnectivityManager.unregisterNetworkCallback(cellBringupCallback);
}
@@ -168,6 +274,8 @@ public class UnderlyingNetworkTracker {
}
return getBaseNetworkRequestBuilder()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
.setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
.build();
}
@@ -189,6 +297,38 @@ public class UnderlyingNetworkTracker {
}
/**
+ * Builds the WiFi entry threshold signal strength request
+ *
+ * <p>This request ensures that WiFi reports the crossing of the wifi entry RSSI threshold.
+ * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a
+ * pace to effectively select a short-lived WiFi offload network.
+ */
+ private NetworkRequest getWifiEntryRssiThresholdNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ // Ensure wifi updates signal strengths when crossing this threshold.
+ .setSignalStrength(getWifiEntryRssiThreshold(mCarrierConfig))
+ .build();
+ }
+
+ /**
+ * Builds the WiFi exit threshold signal strength request
+ *
+ * <p>This request ensures that WiFi reports the crossing of the wifi exit RSSI threshold.
+ * Without this request, WiFi rate-limits, and reports signal strength changes at too slow a
+ * pace to effectively select away from a failing WiFi network.
+ */
+ private NetworkRequest getWifiExitRssiThresholdNetworkRequest() {
+ return getBaseNetworkRequestBuilder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))
+ // Ensure wifi updates signal strengths when crossing this threshold.
+ .setSignalStrength(getWifiExitRssiThreshold(mCarrierConfig))
+ .build();
+ }
+
+ /**
* Builds a Cellular bringup request for a given subId
*
* <p>This request is filed in order to ensure that the Telephony stack always has a
@@ -233,10 +373,18 @@ public class UnderlyingNetworkTracker {
* reevaluate its NetworkBringupCallbacks. This may result in NetworkRequests being registered
* or unregistered if the subIds mapped to the this Tracker's SubscriptionGroup change.
*/
- public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot snapshot) {
- Objects.requireNonNull(snapshot, "Missing snapshot");
+ public void updateSubscriptionSnapshot(@NonNull TelephonySubscriptionSnapshot newSnapshot) {
+ Objects.requireNonNull(newSnapshot, "Missing newSnapshot");
+
+ final TelephonySubscriptionSnapshot oldSnapshot = mLastSnapshot;
+ mLastSnapshot = newSnapshot;
- mLastSnapshot = snapshot;
+ // Only trigger re-registration if subIds in this group have changed
+ if (oldSnapshot
+ .getAllSubIdsInGroup(mSubscriptionGroup)
+ .equals(newSnapshot.getAllSubIdsInGroup(mSubscriptionGroup))) {
+ return;
+ }
registerOrUpdateNetworkRequests();
}
@@ -247,88 +395,43 @@ public class UnderlyingNetworkTracker {
// Will unregister all existing callbacks, but not register new ones due to quitting flag.
registerOrUpdateNetworkRequests();
- }
- /** Returns whether the currently selected Network matches the given network. */
- private static boolean isSameNetwork(
- @Nullable UnderlyingNetworkRecord.Builder recordInProgress, @NonNull Network network) {
- return recordInProgress != null && recordInProgress.getNetwork().equals(network);
+ mVcnContext
+ .getContext()
+ .getSystemService(TelephonyManager.class)
+ .unregisterTelephonyCallback(mActiveDataSubIdListener);
}
- /** Notify the Callback if a full UnderlyingNetworkRecord exists. */
- private void maybeNotifyCallback() {
- // Only forward this update if a complete record has been received
- if (!mRecordInProgress.isValid()) {
- return;
- }
+ private void reevaluateNetworks() {
+ TreeSet<UnderlyingNetworkRecord> sorted =
+ new TreeSet<>(
+ UnderlyingNetworkRecord.getComparator(
+ mSubscriptionGroup, mLastSnapshot, mCurrentRecord, mCarrierConfig));
+ sorted.addAll(mRouteSelectionCallback.getUnderlyingNetworks());
- // Only forward this update if the updated record differs form the current record
- UnderlyingNetworkRecord updatedRecord = mRecordInProgress.build();
- if (!updatedRecord.equals(mCurrentRecord)) {
- mCurrentRecord = updatedRecord;
-
- mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
- }
- }
-
- private void handleNetworkAvailable(@NonNull Network network) {
- mVcnContext.ensureRunningOnLooperThread();
-
- mRecordInProgress = new UnderlyingNetworkRecord.Builder(network);
- }
-
- private void handleNetworkLost(@NonNull Network network) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Non-underlying Network lost");
+ UnderlyingNetworkRecord candidate = sorted.isEmpty() ? null : sorted.first();
+ if (Objects.equals(mCurrentRecord, candidate)) {
return;
}
- mRecordInProgress = null;
- mCurrentRecord = null;
- mCb.onSelectedUnderlyingNetworkChanged(null /* underlyingNetworkRecord */);
+ mCurrentRecord = candidate;
+ mCb.onSelectedUnderlyingNetworkChanged(mCurrentRecord);
}
- private void handleCapabilitiesChanged(
- @NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to NetworkCapabilities");
- return;
+ private static boolean isOpportunistic(
+ @NonNull TelephonySubscriptionSnapshot snapshot, Set<Integer> subIds) {
+ if (snapshot == null) {
+ Slog.wtf(TAG, "Got null snapshot");
+ return false;
}
- mRecordInProgress.setNetworkCapabilities(networkCapabilities);
-
- maybeNotifyCallback();
- }
-
- private void handlePropertiesChanged(
- @NonNull Network network, @NonNull LinkProperties linkProperties) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to LinkProperties");
- return;
- }
-
- mRecordInProgress.setLinkProperties(linkProperties);
-
- maybeNotifyCallback();
- }
-
- private void handleNetworkBlocked(@NonNull Network network, boolean isBlocked) {
- mVcnContext.ensureRunningOnLooperThread();
-
- if (!isSameNetwork(mRecordInProgress, network)) {
- Slog.wtf(TAG, "Invalid update to isBlocked");
- return;
+ for (int subId : subIds) {
+ if (snapshot.isOpportunistic(subId)) {
+ return true;
+ }
}
- mRecordInProgress.setIsBlocked(isBlocked);
-
- maybeNotifyCallback();
+ return false;
}
/**
@@ -347,36 +450,104 @@ public class UnderlyingNetworkTracker {
* truth.
*/
@VisibleForTesting
- class RouteSelectionCallback extends NetworkCallback {
+ class UnderlyingNetworkListener extends NetworkCallback {
+ private final Map<Network, UnderlyingNetworkRecord.Builder>
+ mUnderlyingNetworkRecordBuilders = new ArrayMap<>();
+
+ private List<UnderlyingNetworkRecord> getUnderlyingNetworks() {
+ final List<UnderlyingNetworkRecord> records = new ArrayList<>();
+
+ for (UnderlyingNetworkRecord.Builder builder :
+ mUnderlyingNetworkRecordBuilders.values()) {
+ if (builder.isValid()) {
+ records.add(builder.build());
+ }
+ }
+
+ return records;
+ }
+
@Override
public void onAvailable(@NonNull Network network) {
- handleNetworkAvailable(network);
+ mUnderlyingNetworkRecordBuilders.put(
+ network, new UnderlyingNetworkRecord.Builder(network));
}
@Override
public void onLost(@NonNull Network network) {
- handleNetworkLost(network);
+ mUnderlyingNetworkRecordBuilders.remove(network);
+
+ reevaluateNetworks();
}
@Override
public void onCapabilitiesChanged(
@NonNull Network network, @NonNull NetworkCapabilities networkCapabilities) {
- if (networkCapabilities.equals(mRecordInProgress.getNetworkCapabilities())) return;
- handleCapabilitiesChanged(network, networkCapabilities);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got capabilities change for unknown key: " + network);
+ return;
+ }
+
+ builder.setNetworkCapabilities(networkCapabilities);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
@Override
public void onLinkPropertiesChanged(
@NonNull Network network, @NonNull LinkProperties linkProperties) {
- handlePropertiesChanged(network, linkProperties);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got link properties change for unknown key: " + network);
+ return;
+ }
+
+ builder.setLinkProperties(linkProperties);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
@Override
public void onBlockedStatusChanged(@NonNull Network network, boolean isBlocked) {
- handleNetworkBlocked(network, isBlocked);
+ final UnderlyingNetworkRecord.Builder builder =
+ mUnderlyingNetworkRecordBuilders.get(network);
+ if (builder == null) {
+ Slog.wtf(TAG, "Got blocked status change for unknown key: " + network);
+ return;
+ }
+
+ builder.setIsBlocked(isBlocked);
+ if (builder.isValid()) {
+ reevaluateNetworks();
+ }
}
}
+ private static int getWifiEntryRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_WIFI_ENTRY_RSSI_THRESHOLD_KEY,
+ WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT);
+ }
+
+ return WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT;
+ }
+
+ private static int getWifiExitRssiThreshold(@Nullable PersistableBundle carrierConfig) {
+ if (carrierConfig != null) {
+ return carrierConfig.getInt(
+ VcnManager.VCN_NETWORK_SELECTION_WIFI_EXIT_RSSI_THRESHOLD_KEY,
+ WIFI_EXIT_RSSI_THRESHOLD_DEFAULT);
+ }
+
+ return WIFI_EXIT_RSSI_THRESHOLD_DEFAULT;
+ }
+
/** A record of a single underlying network, caching relevant fields. */
public static class UnderlyingNetworkRecord {
@NonNull public final Network network;
@@ -413,6 +584,89 @@ public class UnderlyingNetworkTracker {
return Objects.hash(network, networkCapabilities, linkProperties, isBlocked);
}
+ /**
+ * Gives networks a priority class, based on the following priorities:
+ *
+ * <ol>
+ * <li>Opportunistic cellular
+ * <li>Carrier WiFi, signal strength >= WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT
+ * <li>Carrier WiFi, active network + signal strength >= WIFI_EXIT_RSSI_THRESHOLD_DEFAULT
+ * <li>Macro cellular
+ * <li>Any others
+ * </ol>
+ */
+ private int calculatePriorityClass(
+ ParcelUuid subscriptionGroup,
+ TelephonySubscriptionSnapshot snapshot,
+ UnderlyingNetworkRecord currentlySelected,
+ PersistableBundle carrierConfig) {
+ final NetworkCapabilities caps = networkCapabilities;
+
+ // mRouteSelectionNetworkRequest requires a network be both VALIDATED and NOT_SUSPENDED
+
+ if (isBlocked) {
+ Slog.wtf(TAG, "Network blocked for System Server: " + network);
+ return PRIORITY_ANY;
+ }
+
+ if (caps.hasTransport(TRANSPORT_CELLULAR)
+ && isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ // If this carrier is the active data provider, ensure that opportunistic is only
+ // ever prioritized if it is also the active data subscription. This ensures that
+ // if an opportunistic subscription is still in the process of being switched to,
+ // or switched away from, the VCN does not attempt to continue using it against the
+ // decision made at the telephony layer. Failure to do so may result in the modem
+ // switching back and forth.
+ //
+ // Allow the following two cases:
+ // 1. Active subId is NOT in the group that this VCN is supporting
+ // 2. This opportunistic subscription is for the active subId
+ if (!snapshot.getAllSubIdsInGroup(subscriptionGroup)
+ .contains(SubscriptionManager.getActiveDataSubscriptionId())
+ || caps.getSubscriptionIds()
+ .contains(SubscriptionManager.getActiveDataSubscriptionId())) {
+ return PRIORITY_OPPORTUNISTIC_CELLULAR;
+ }
+ }
+
+ if (caps.hasTransport(TRANSPORT_WIFI)) {
+ if (caps.getSignalStrength() >= getWifiExitRssiThreshold(carrierConfig)
+ && currentlySelected != null
+ && network.equals(currentlySelected.network)) {
+ return PRIORITY_WIFI_IN_USE;
+ }
+
+ if (caps.getSignalStrength() >= getWifiEntryRssiThreshold(carrierConfig)) {
+ return PRIORITY_WIFI_PROSPECTIVE;
+ }
+ }
+
+ // Disallow opportunistic subscriptions from matching PRIORITY_MACRO_CELLULAR, as might
+ // be the case when Default Data SubId (CBRS) != Active Data SubId (MACRO), as might be
+ // the case if the Default Data SubId does not support certain services (eg voice
+ // calling)
+ if (caps.hasTransport(TRANSPORT_CELLULAR)
+ && !isOpportunistic(snapshot, caps.getSubscriptionIds())) {
+ return PRIORITY_MACRO_CELLULAR;
+ }
+
+ return PRIORITY_ANY;
+ }
+
+ private static Comparator<UnderlyingNetworkRecord> getComparator(
+ ParcelUuid subscriptionGroup,
+ TelephonySubscriptionSnapshot snapshot,
+ UnderlyingNetworkRecord currentlySelected,
+ PersistableBundle carrierConfig) {
+ return (left, right) -> {
+ return Integer.compare(
+ left.calculatePriorityClass(
+ subscriptionGroup, snapshot, currentlySelected, carrierConfig),
+ right.calculatePriorityClass(
+ subscriptionGroup, snapshot, currentlySelected, carrierConfig));
+ };
+ }
+
/** Dumps the state of this record for logging and debugging purposes. */
public void dump(IndentingPrintWriter pw) {
pw.println("UnderlyingNetworkRecord:");
@@ -434,6 +688,8 @@ public class UnderlyingNetworkTracker {
boolean mIsBlocked;
boolean mWasIsBlockedSet;
+ @Nullable private UnderlyingNetworkRecord mCached;
+
private Builder(@NonNull Network network) {
mNetwork = network;
}
@@ -445,6 +701,7 @@ public class UnderlyingNetworkTracker {
private void setNetworkCapabilities(@NonNull NetworkCapabilities networkCapabilities) {
mNetworkCapabilities = networkCapabilities;
+ mCached = null;
}
@Nullable
@@ -454,11 +711,13 @@ public class UnderlyingNetworkTracker {
private void setLinkProperties(@NonNull LinkProperties linkProperties) {
mLinkProperties = linkProperties;
+ mCached = null;
}
private void setIsBlocked(boolean isBlocked) {
mIsBlocked = isBlocked;
mWasIsBlockedSet = true;
+ mCached = null;
}
private boolean isValid() {
@@ -466,12 +725,30 @@ public class UnderlyingNetworkTracker {
}
private UnderlyingNetworkRecord build() {
- return new UnderlyingNetworkRecord(
- mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+ if (!isValid()) {
+ throw new IllegalArgumentException(
+ "Called build before UnderlyingNetworkRecord was valid");
+ }
+
+ if (mCached == null) {
+ mCached =
+ new UnderlyingNetworkRecord(
+ mNetwork, mNetworkCapabilities, mLinkProperties, mIsBlocked);
+ }
+
+ return mCached;
}
}
}
+ private class VcnActiveDataSubscriptionIdListener extends TelephonyCallback
+ implements ActiveDataSubscriptionIdListener {
+ @Override
+ public void onActiveDataSubscriptionIdChanged(int subId) {
+ reevaluateNetworks();
+ }
+ }
+
/** Callbacks for being notified of the changes in, or to the selected underlying network. */
public interface UnderlyingNetworkTrackerCallback {
/**
diff --git a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
index 528f240b9912..ca7463884d3a 100644
--- a/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java
@@ -88,13 +88,13 @@ public class TelephonySubscriptionTrackerTest {
private static final SubscriptionInfo TEST_SUBINFO_2 = mock(SubscriptionInfo.class);
private static final Map<ParcelUuid, Set<String>> TEST_PRIVILEGED_PACKAGES =
Collections.singletonMap(TEST_PARCEL_UUID, Collections.singleton(PACKAGE_NAME));
- private static final Map<Integer, ParcelUuid> TEST_SUBID_TO_GROUP_MAP;
+ private static final Map<Integer, SubscriptionInfo> TEST_SUBID_TO_INFO_MAP;
static {
- final Map<Integer, ParcelUuid> subIdToGroupMap = new HashMap<>();
- subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_PARCEL_UUID);
- subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_PARCEL_UUID);
- TEST_SUBID_TO_GROUP_MAP = Collections.unmodifiableMap(subIdToGroupMap);
+ final Map<Integer, SubscriptionInfo> subIdToGroupMap = new HashMap<>();
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_1, TEST_SUBINFO_1);
+ subIdToGroupMap.put(TEST_SUBSCRIPTION_ID_2, TEST_SUBINFO_2);
+ TEST_SUBID_TO_INFO_MAP = Collections.unmodifiableMap(subIdToGroupMap);
}
@NonNull private final Context mContext;
@@ -190,13 +190,13 @@ public class TelephonySubscriptionTrackerTest {
private TelephonySubscriptionSnapshot buildExpectedSnapshot(
Map<ParcelUuid, Set<String>> privilegedPackages) {
- return buildExpectedSnapshot(TEST_SUBID_TO_GROUP_MAP, privilegedPackages);
+ return buildExpectedSnapshot(TEST_SUBID_TO_INFO_MAP, privilegedPackages);
}
private TelephonySubscriptionSnapshot buildExpectedSnapshot(
- Map<Integer, ParcelUuid> subIdToGroupMap,
+ Map<Integer, SubscriptionInfo> subIdToInfoMap,
Map<ParcelUuid, Set<String>> privilegedPackages) {
- return new TelephonySubscriptionSnapshot(subIdToGroupMap, privilegedPackages);
+ return new TelephonySubscriptionSnapshot(subIdToInfoMap, privilegedPackages);
}
private void verifyNoActiveSubscriptions() {
@@ -371,7 +371,7 @@ public class TelephonySubscriptionTrackerTest {
@Test
public void testTelephonySubscriptionSnapshotGetGroupForSubId() throws Exception {
final TelephonySubscriptionSnapshot snapshot =
- new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap());
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap());
assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_1));
assertEquals(TEST_PARCEL_UUID, snapshot.getGroupForSubId(TEST_SUBSCRIPTION_ID_2));
@@ -380,7 +380,7 @@ public class TelephonySubscriptionTrackerTest {
@Test
public void testTelephonySubscriptionSnapshotGetAllSubIdsInGroup() throws Exception {
final TelephonySubscriptionSnapshot snapshot =
- new TelephonySubscriptionSnapshot(TEST_SUBID_TO_GROUP_MAP, emptyMap());
+ new TelephonySubscriptionSnapshot(TEST_SUBID_TO_INFO_MAP, emptyMap());
assertEquals(
new ArraySet<>(Arrays.asList(TEST_SUBSCRIPTION_ID_1, TEST_SUBSCRIPTION_ID_2)),
diff --git a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
index 0b72cd93e8b0..a36fd797d11c 100644
--- a/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
+++ b/tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java
@@ -42,12 +42,14 @@ import android.net.NetworkRequest;
import android.net.TelephonyNetworkSpecifier;
import android.os.ParcelUuid;
import android.os.test.TestLooper;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
+import android.telephony.TelephonyManager;
import android.util.ArraySet;
import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot;
import com.android.server.vcn.UnderlyingNetworkTracker.NetworkBringupCallback;
-import com.android.server.vcn.UnderlyingNetworkTracker.RouteSelectionCallback;
+import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkListener;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkRecord;
import com.android.server.vcn.UnderlyingNetworkTracker.UnderlyingNetworkTrackerCallback;
@@ -98,11 +100,13 @@ public class UnderlyingNetworkTrackerTest {
@Mock private Context mContext;
@Mock private VcnNetworkProvider mVcnNetworkProvider;
@Mock private ConnectivityManager mConnectivityManager;
+ @Mock private TelephonyManager mTelephonyManager;
+ @Mock private CarrierConfigManager mCarrierConfigManager;
@Mock private TelephonySubscriptionSnapshot mSubscriptionSnapshot;
@Mock private UnderlyingNetworkTrackerCallback mNetworkTrackerCb;
@Mock private Network mNetwork;
- @Captor private ArgumentCaptor<RouteSelectionCallback> mRouteSelectionCallbackCaptor;
+ @Captor private ArgumentCaptor<UnderlyingNetworkListener> mUnderlyingNetworkListenerCaptor;
private TestLooper mTestLooper;
private VcnContext mVcnContext;
@@ -127,6 +131,13 @@ public class UnderlyingNetworkTrackerTest {
mConnectivityManager,
Context.CONNECTIVITY_SERVICE,
ConnectivityManager.class);
+ setupSystemService(
+ mContext, mTelephonyManager, Context.TELEPHONY_SERVICE, TelephonyManager.class);
+ setupSystemService(
+ mContext,
+ mCarrierConfigManager,
+ Context.CARRIER_CONFIG_SERVICE,
+ CarrierConfigManager.class);
when(mSubscriptionSnapshot.getAllSubIdsInGroup(eq(SUB_GROUP))).thenReturn(INITIAL_SUB_IDS);
@@ -163,26 +174,26 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testNetworkCallbacksRegisteredOnStartupForTestMode() {
+ final ConnectivityManager cm = mock(ConnectivityManager.class);
+ setupSystemService(mContext, cm, Context.CONNECTIVITY_SERVICE, ConnectivityManager.class);
final VcnContext vcnContext =
- spy(
- new VcnContext(
- mContext,
- mTestLooper.getLooper(),
- mVcnNetworkProvider,
- true /* isInTestMode */));
-
- mUnderlyingNetworkTracker =
- new UnderlyingNetworkTracker(
- vcnContext,
- SUB_GROUP,
- mSubscriptionSnapshot,
- Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
- mNetworkTrackerCb);
-
- verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ new VcnContext(
+ mContext,
+ mTestLooper.getLooper(),
+ mVcnNetworkProvider,
+ true /* isInTestMode */);
+
+ new UnderlyingNetworkTracker(
+ vcnContext,
+ SUB_GROUP,
+ mSubscriptionSnapshot,
+ Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET),
+ mNetworkTrackerCb);
+
+ verify(cm)
+ .registerNetworkCallback(
eq(getTestNetworkRequest(INITIAL_SUB_IDS)),
- any(RouteSelectionCallback.class),
+ any(UnderlyingNetworkListener.class),
any());
}
@@ -200,9 +211,19 @@ public class UnderlyingNetworkTrackerTest {
}
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(expectedSubIds)),
- any(RouteSelectionCallback.class),
+ any(UnderlyingNetworkListener.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiEntryRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
+ any());
+ verify(mConnectivityManager)
+ .registerNetworkCallback(
+ eq(getWifiExitRssiThresholdRequest(expectedSubIds)),
+ any(NetworkBringupCallback.class),
any());
}
@@ -218,9 +239,10 @@ public class UnderlyingNetworkTrackerTest {
mUnderlyingNetworkTracker.updateSubscriptionSnapshot(subscriptionUpdate);
// verify that initially-filed bringup requests are unregistered (cell + wifi)
- verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 1))
+ verify(mConnectivityManager, times(INITIAL_SUB_IDS.size() + 3))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
- verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class));
+ verify(mConnectivityManager)
+ .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
verifyNetworkRequestsRegistered(UPDATED_SUB_IDS);
}
@@ -231,6 +253,24 @@ public class UnderlyingNetworkTrackerTest {
.build();
}
+ private NetworkRequest getWifiEntryRssiThresholdRequest(Set<Integer> netCapsSubIds) {
+ // TODO (b/187991063): Add tests for carrier-config based thresholds
+ return getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(netCapsSubIds)
+ .setSignalStrength(UnderlyingNetworkTracker.WIFI_ENTRY_RSSI_THRESHOLD_DEFAULT)
+ .build();
+ }
+
+ private NetworkRequest getWifiExitRssiThresholdRequest(Set<Integer> netCapsSubIds) {
+ // TODO (b/187991063): Add tests for carrier-config based thresholds
+ return getExpectedRequestBase()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .setSubscriptionIds(netCapsSubIds)
+ .setSignalStrength(UnderlyingNetworkTracker.WIFI_EXIT_RSSI_THRESHOLD_DEFAULT)
+ .build();
+ }
+
private NetworkRequest getCellRequestForSubId(int subId) {
return getExpectedRequestBase()
.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
@@ -239,7 +279,11 @@ public class UnderlyingNetworkTrackerTest {
}
private NetworkRequest getRouteSelectionRequest(Set<Integer> netCapsSubIds) {
- return getExpectedRequestBase().setSubscriptionIds(netCapsSubIds).build();
+ return getExpectedRequestBase()
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_VALIDATED)
+ .addCapability(NetworkCapabilities.NET_CAPABILITY_NOT_SUSPENDED)
+ .setSubscriptionIds(netCapsSubIds)
+ .build();
}
private NetworkRequest getTestNetworkRequest(Set<Integer> netCapsSubIds) {
@@ -265,11 +309,12 @@ public class UnderlyingNetworkTrackerTest {
public void testTeardown() {
mUnderlyingNetworkTracker.teardown();
- // Expect 3 NetworkBringupCallbacks to be unregistered: 1 for WiFi and 2 for Cellular (1x
- // for each subId)
- verify(mConnectivityManager, times(3))
+ // Expect 5 NetworkBringupCallbacks to be unregistered: 1 for WiFi, 2 for Cellular (1x for
+ // each subId), and 1 for each of the Wifi signal strength thresholds
+ verify(mConnectivityManager, times(5))
.unregisterNetworkCallback(any(NetworkBringupCallback.class));
- verify(mConnectivityManager).unregisterNetworkCallback(any(RouteSelectionCallback.class));
+ verify(mConnectivityManager)
+ .unregisterNetworkCallback(any(UnderlyingNetworkListener.class));
}
@Test
@@ -302,19 +347,19 @@ public class UnderlyingNetworkTrackerTest {
verifyRegistrationOnAvailableAndGetCallback();
}
- private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback() {
+ private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback() {
return verifyRegistrationOnAvailableAndGetCallback(INITIAL_NETWORK_CAPABILITIES);
}
- private RouteSelectionCallback verifyRegistrationOnAvailableAndGetCallback(
+ private UnderlyingNetworkListener verifyRegistrationOnAvailableAndGetCallback(
NetworkCapabilities networkCapabilities) {
verify(mConnectivityManager)
- .requestBackgroundNetwork(
+ .registerNetworkCallback(
eq(getRouteSelectionRequest(INITIAL_SUB_IDS)),
- mRouteSelectionCallbackCaptor.capture(),
+ mUnderlyingNetworkListenerCaptor.capture(),
any());
- RouteSelectionCallback cb = mRouteSelectionCallbackCaptor.getValue();
+ UnderlyingNetworkListener cb = mUnderlyingNetworkListenerCaptor.getValue();
cb.onAvailable(mNetwork);
cb.onCapabilitiesChanged(mNetwork, networkCapabilities);
cb.onLinkPropertiesChanged(mNetwork, INITIAL_LINK_PROPERTIES);
@@ -332,7 +377,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES);
@@ -347,7 +392,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES);
@@ -362,7 +407,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkSuspended() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES);
@@ -381,7 +426,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkResumed() {
- RouteSelectionCallback cb =
+ UnderlyingNetworkListener cb =
verifyRegistrationOnAvailableAndGetCallback(SUSPENDED_NETWORK_CAPABILITIES);
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -401,7 +446,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForBlocked() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */);
@@ -416,7 +461,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackNotifiedForNetworkLoss() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onLost(mNetwork);
@@ -425,7 +470,7 @@ public class UnderlyingNetworkTrackerTest {
@Test
public void testRecordTrackerCallbackIgnoresDuplicateRecord() {
- RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback();
+ UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback();
cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES);
@@ -433,4 +478,6 @@ public class UnderlyingNetworkTrackerTest {
// UnderlyingNetworkRecord does not actually change
verifyNoMoreInteractions(mNetworkTrackerCb);
}
+
+ // TODO (b/187991063): Add tests for network prioritization
}
diff --git a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
index 1ecb4c9ee298..c747bc096a6f 100644
--- a/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
+++ b/tests/vcn/java/com/android/server/vcn/VcnGatewayConnectionTestBase.java
@@ -54,6 +54,7 @@ import android.net.vcn.VcnGatewayConnectionConfigTest;
import android.os.ParcelUuid;
import android.os.PowerManager;
import android.os.test.TestLooper;
+import android.telephony.SubscriptionInfo;
import com.android.internal.util.State;
import com.android.internal.util.WakeupMessage;
@@ -73,6 +74,12 @@ import java.util.concurrent.TimeUnit;
public class VcnGatewayConnectionTestBase {
protected static final ParcelUuid TEST_SUB_GRP = new ParcelUuid(UUID.randomUUID());
+ protected static final SubscriptionInfo TEST_SUB_INFO = mock(SubscriptionInfo.class);
+
+ static {
+ doReturn(TEST_SUB_GRP).when(TEST_SUB_INFO).getGroupUuid();
+ }
+
protected static final InetAddress TEST_DNS_ADDR =
InetAddresses.parseNumericAddress("2001:DB8:0:1::");
protected static final InetAddress TEST_DNS_ADDR_2 =
@@ -116,7 +123,7 @@ public class VcnGatewayConnectionTestBase {
protected static final TelephonySubscriptionSnapshot TEST_SUBSCRIPTION_SNAPSHOT =
new TelephonySubscriptionSnapshot(
- Collections.singletonMap(TEST_SUB_ID, TEST_SUB_GRP), Collections.EMPTY_MAP);
+ Collections.singletonMap(TEST_SUB_ID, TEST_SUB_INFO), Collections.EMPTY_MAP);
@NonNull protected final Context mContext;
@NonNull protected final TestLooper mTestLooper;