Loading core/java/android/net/vcn/VcnManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -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<>(); Loading services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +24 −14 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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: Loading @@ -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)) { Loading Loading @@ -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 = Loading @@ -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()) { Loading @@ -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; } /** Loading @@ -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()); } } Loading @@ -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 Loading @@ -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); } Loading @@ -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(); Loading @@ -335,7 +345,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @Override public String toString() { return "TelephonySubscriptionSnapshot{ " + "mSubIdToGroupMap=" + mSubIdToGroupMap + "mSubIdToInfoMap=" + mSubIdToInfoMap + ", mPrivilegedPackages=" + mPrivilegedPackages + " }"; } Loading services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +361 −84 File changed.Preview size limit exceeded, changes collapsed. Show changes tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +10 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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)); Loading @@ -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)), Loading tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +88 −41 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -163,15 +174,15 @@ 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 */)); true /* isInTestMode */); mUnderlyingNetworkTracker = new UnderlyingNetworkTracker( vcnContext, SUB_GROUP, Loading @@ -179,10 +190,10 @@ public class UnderlyingNetworkTrackerTest { Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET), mNetworkTrackerCb); verify(mConnectivityManager) .requestBackgroundNetwork( verify(cm) .registerNetworkCallback( eq(getTestNetworkRequest(INITIAL_SUB_IDS)), any(RouteSelectionCallback.class), any(UnderlyingNetworkListener.class), any()); } Loading @@ -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()); } Loading @@ -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); } Loading @@ -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) Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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); Loading @@ -332,7 +377,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES); Loading @@ -347,7 +392,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES); Loading @@ -362,7 +407,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkSuspended() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES); Loading @@ -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); Loading @@ -401,7 +446,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForBlocked() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */); Loading @@ -416,7 +461,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkLoss() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLost(mNetwork); Loading @@ -425,7 +470,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackIgnoresDuplicateRecord() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); Loading @@ -433,4 +478,6 @@ public class UnderlyingNetworkTrackerTest { // UnderlyingNetworkRecord does not actually change verifyNoMoreInteractions(mNetworkTrackerCb); } // TODO (b/187991063): Add tests for network prioritization } Loading
core/java/android/net/vcn/VcnManager.java +30 −0 Original line number Diff line number Diff line Loading @@ -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<>(); Loading
services/core/java/com/android/server/vcn/TelephonySubscriptionTracker.java +24 −14 Original line number Diff line number Diff line Loading @@ -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) { Loading @@ -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: Loading @@ -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)) { Loading Loading @@ -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 = Loading @@ -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()) { Loading @@ -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; } /** Loading @@ -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()); } } Loading @@ -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 Loading @@ -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); } Loading @@ -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(); Loading @@ -335,7 +345,7 @@ public class TelephonySubscriptionTracker extends BroadcastReceiver { @Override public String toString() { return "TelephonySubscriptionSnapshot{ " + "mSubIdToGroupMap=" + mSubIdToGroupMap + "mSubIdToInfoMap=" + mSubIdToInfoMap + ", mPrivilegedPackages=" + mPrivilegedPackages + " }"; } Loading
services/core/java/com/android/server/vcn/UnderlyingNetworkTracker.java +361 −84 File changed.Preview size limit exceeded, changes collapsed. Show changes
tests/vcn/java/com/android/server/vcn/TelephonySubscriptionTrackerTest.java +10 −10 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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() { Loading Loading @@ -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)); Loading @@ -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)), Loading
tests/vcn/java/com/android/server/vcn/UnderlyingNetworkTrackerTest.java +88 −41 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); Loading Loading @@ -163,15 +174,15 @@ 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 */)); true /* isInTestMode */); mUnderlyingNetworkTracker = new UnderlyingNetworkTracker( vcnContext, SUB_GROUP, Loading @@ -179,10 +190,10 @@ public class UnderlyingNetworkTrackerTest { Collections.singleton(NetworkCapabilities.NET_CAPABILITY_INTERNET), mNetworkTrackerCb); verify(mConnectivityManager) .requestBackgroundNetwork( verify(cm) .registerNetworkCallback( eq(getTestNetworkRequest(INITIAL_SUB_IDS)), any(RouteSelectionCallback.class), any(UnderlyingNetworkListener.class), any()); } Loading @@ -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()); } Loading @@ -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); } Loading @@ -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) Loading @@ -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) { Loading @@ -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 Loading Loading @@ -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); Loading @@ -332,7 +377,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkCapabilitiesChange() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, UPDATED_NETWORK_CAPABILITIES); Loading @@ -347,7 +392,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForLinkPropertiesChange() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLinkPropertiesChanged(mNetwork, UPDATED_LINK_PROPERTIES); Loading @@ -362,7 +407,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkSuspended() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, SUSPENDED_NETWORK_CAPABILITIES); Loading @@ -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); Loading @@ -401,7 +446,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForBlocked() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onBlockedStatusChanged(mNetwork, true /* isBlocked */); Loading @@ -416,7 +461,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackNotifiedForNetworkLoss() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onLost(mNetwork); Loading @@ -425,7 +470,7 @@ public class UnderlyingNetworkTrackerTest { @Test public void testRecordTrackerCallbackIgnoresDuplicateRecord() { RouteSelectionCallback cb = verifyRegistrationOnAvailableAndGetCallback(); UnderlyingNetworkListener cb = verifyRegistrationOnAvailableAndGetCallback(); cb.onCapabilitiesChanged(mNetwork, INITIAL_NETWORK_CAPABILITIES); Loading @@ -433,4 +478,6 @@ public class UnderlyingNetworkTrackerTest { // UnderlyingNetworkRecord does not actually change verifyNoMoreInteractions(mNetworkTrackerCb); } // TODO (b/187991063): Add tests for network prioritization }