Use NetworkCallback to determine active data sub
- SubscriptionManager#getActiveDataSubscriptionId() does not return
the current active data subscription immediately; it takes about 30s
to update its cache.
- Moreover when internet is on WiFi, this API returns the default
data subscription, instead of INVALID_SUB_ID.
- IWLAN aligns with QNS on using the ConnectivityManager.NetworkCallback
to determine the actie data sub from NetworkCapabilities.
Bug: 249609998
Test: Live test in P10. Updated IwlanDataServiceTest and
IwlanNetworkServiceTest. New UTs:
IwlanDataServiceTest#testNetworkNotConnectedWithCellularAndCrossSimDisabled
IwlanDataServiceTest#testCrossSimNetworkConnectedWithTelephonyNetwork
IwlanDataServiceTest#testCrossSimNetworkConnectedWithVcn
IwlanNetworkServiceTest#
testNetworkRegistrationInfoHomeForCellularVcnOnDifferentSubAndCstEnabled
Change-Id: I25803aba4182ac123b3df7b84b4a299649f252b8
diff --git a/src/com/google/android/iwlan/IwlanDataService.java b/src/com/google/android/iwlan/IwlanDataService.java
index 9ae95f2..0131ed0 100644
--- a/src/com/google/android/iwlan/IwlanDataService.java
+++ b/src/com/google/android/iwlan/IwlanDataService.java
@@ -26,6 +26,10 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.NetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.TransportInfo;
+import android.net.vcn.VcnTransportInfo;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
@@ -81,6 +85,11 @@
private HandlerThread mIwlanDataServiceHandlerThread;
private static final Map<Integer, IwlanDataServiceProvider> sIwlanDataServiceProviders =
new ConcurrentHashMap<>();
+ private static final int INVALID_SUB_ID = -1;
+
+ // The current subscription with the active internet PDN. Need not be the default data sub.
+ // If internet is over WiFi, this value will be INVALID_SUB_ID.
+ private static int mConnectedDataSub = INVALID_SUB_ID;
private static final int EVENT_BASE = IwlanEventListener.DATA_SERVICE_INTERNAL_EVENT_BASE;
private static final int EVENT_TUNNEL_OPENED = EVENT_BASE;
@@ -140,6 +149,7 @@
@Override
public void onLost(Network network) {
Log.d(TAG, "onLost: " + network);
+ IwlanDataService.setConnectedDataSub(INVALID_SUB_ID);
IwlanDataService.setNetworkConnected(false, network, Transport.UNSPECIFIED_NETWORK);
}
@@ -170,9 +180,11 @@
if (networkCapabilities != null) {
if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
Log.d(TAG, "Network " + network + " connected using transport MOBILE");
+ IwlanDataService.setConnectedDataSub(getConnectedDataSub(networkCapabilities));
IwlanDataService.setNetworkConnected(true, network, Transport.MOBILE);
} else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
Log.d(TAG, "Network " + network + " connected using transport WIFI");
+ IwlanDataService.setConnectedDataSub(INVALID_SUB_ID);
IwlanDataService.setNetworkConnected(true, network, Transport.WIFI);
} else {
Log.w(TAG, "Network does not have cellular or wifi capability");
@@ -839,7 +851,7 @@
getTunnelManager().closeTunnel(entry.getKey(), true);
} else {
if (mIwlanDataService.isNetworkConnected(
- IwlanHelper.isActiveDataOnOtherSlot(mContext, getSlotIndex()),
+ isActiveDataOnOtherSub(getSlotIndex()),
IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()))) {
getTunnelManager().updateNetwork(network, entry.getKey());
}
@@ -866,7 +878,7 @@
private void dnsPrefetchCheck() {
boolean networkConnected =
mIwlanDataService.isNetworkConnected(
- IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex()),
+ isActiveDataOnOtherSub(getSlotIndex()),
IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex()));
/* Check if we need to do prefecting */
if (networkConnected == true
@@ -909,19 +921,20 @@
public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
pw.println("---- IwlanDataServiceProvider[" + getSlotIndex() + "] ----");
boolean isDDS = IwlanHelper.isDefaultDataSlot(mContext, getSlotIndex());
- boolean isActiveDataOnOtherSlot =
- IwlanHelper.isActiveDataOnOtherSlot(mContext, getSlotIndex());
boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, getSlotIndex());
pw.println(
"isDefaultDataSlot: "
+ isDDS
- + " isActiveDataOnOtherSlot: "
- + isActiveDataOnOtherSlot
+ + "subID: "
+ + IwlanHelper.getSubId(mContext, getSlotIndex())
+ + " mConnectedDataSub: "
+ + mConnectedDataSub
+ " isCrossSimEnabled: "
+ isCSTEnabled);
pw.println(
"isNetworkConnected: "
- + isNetworkConnected(isActiveDataOnOtherSlot, isCSTEnabled)
+ + isNetworkConnected(
+ isActiveDataOnOtherSub(getSlotIndex()), isCSTEnabled)
+ " Wfc enabled: "
+ mWfcEnabled);
for (Map.Entry<String, TunnelState> entry : mTunnelStateForApn.entrySet()) {
@@ -1137,18 +1150,15 @@
}
slotId = iwlanDataServiceProvider.getSlotIndex();
- boolean isActiveDataOnOtherSlot =
- IwlanHelper.isActiveDataOnOtherSlot(mContext, slotId);
boolean isCSTEnabled = IwlanHelper.isCrossSimCallingEnabled(mContext, slotId);
boolean networkConnected =
- isNetworkConnected(isActiveDataOnOtherSlot, isCSTEnabled);
+ isNetworkConnected(isActiveDataOnOtherSub(slotId), isCSTEnabled);
Log.d(
TAG + "[" + slotId + "]",
"isDds: "
- + IwlanHelper.isDefaultDataSlot(
- mContext, slotId)
- + ", isActiveDataOnOtherSlot: "
- + isActiveDataOnOtherSlot
+ + IwlanHelper.isDefaultDataSlot(mContext, slotId)
+ + ", isActiveDataOnOtherSub: "
+ + isActiveDataOnOtherSub(slotId)
+ ", isCstEnabled: "
+ isCSTEnabled
+ ", transport: "
@@ -1273,7 +1283,7 @@
slotId = iwlanDataServiceProvider.getSlotIndex();
boolean isNetworkLost =
!isNetworkConnected(
- IwlanHelper.isActiveDataOnOtherSlot(mContext, slotId),
+ isActiveDataOnOtherSub(slotId),
IwlanHelper.isCrossSimCallingEnabled(mContext, slotId));
boolean isHandOutSuccessful = (reason == REQUEST_REASON_HANDOVER);
@@ -1457,11 +1467,34 @@
}
}
+ static int getConnectedDataSub(NetworkCapabilities networkCapabilities) {
+ int connectedDataSub = INVALID_SUB_ID;
+ NetworkSpecifier specifier = networkCapabilities.getNetworkSpecifier();
+ TransportInfo transportInfo = networkCapabilities.getTransportInfo();
+
+ if (specifier != null && specifier instanceof TelephonyNetworkSpecifier) {
+ connectedDataSub = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
+ } else if (transportInfo != null && transportInfo instanceof VcnTransportInfo) {
+ connectedDataSub = ((VcnTransportInfo) transportInfo).getSubId();
+ }
+ return connectedDataSub;
+ }
+
+ static void setConnectedDataSub(int subId) {
+ mConnectedDataSub = subId;
+ }
+
@VisibleForTesting
- static boolean isNetworkConnected(boolean isActiveDataOnOtherSlot, boolean isCstEnabled) {
- if (isActiveDataOnOtherSlot && isCstEnabled) {
+ static boolean isActiveDataOnOtherSub(int slotId) {
+ int subId = IwlanHelper.getSubId(mContext, slotId);
+ return mConnectedDataSub != INVALID_SUB_ID && subId != mConnectedDataSub;
+ }
+
+ @VisibleForTesting
+ static boolean isNetworkConnected(boolean isActiveDataOnOtherSub, boolean isCstEnabled) {
+ if (isActiveDataOnOtherSub && isCstEnabled) {
// For cross-SIM IWLAN (Transport.MOBILE), an active data PDN must be maintained on the
- // other slot.
+ // other subscription.
if (sNetworkConnected && (sDefaultDataTransport != Transport.MOBILE)) {
Log.e(TAG, "Internet is on other slot, but default transport is not MOBILE!");
}
diff --git a/src/com/google/android/iwlan/IwlanHelper.java b/src/com/google/android/iwlan/IwlanHelper.java
index 34adddd..efda5b7 100644
--- a/src/com/google/android/iwlan/IwlanHelper.java
+++ b/src/com/google/android/iwlan/IwlanHelper.java
@@ -237,37 +237,6 @@
return false;
}
- /**
- * Gets the slot index associated with the current active data subscription.
- *
- * <p>The currently active data slot may be different from the default data slot. For instance,
- * when the DDS is OOS or the nDDS is in a voice call, the data PDN may move to the nDDS.
- *
- * @param context application context
- * @return slot index associated with the active data subscription, or
- * SubscriptionManager#INVALID_SIM_SLOT_INDEX if no active data PDN.
- */
- private static int getActiveDataSlot(Context context) {
- SubscriptionManager sm = context.getSystemService(SubscriptionManager.class);
- return sm.getSlotIndex(sm.getActiveDataSubscriptionId());
- }
-
- /**
- * For dual-SIM UEs, determines if the active data PDN is on the other slot to the one provided.
- *
- * @param context application context
- * @param slotIndex slot index associated with current subscription
- * @return whether the other subscription has active data PDN.
- */
- public static boolean isActiveDataOnOtherSlot(Context context, int slotIndex) {
- int activeDataSlot = getActiveDataSlot(context);
- Log.d("apsankar:", slotIndex + " " + activeDataSlot);
- if (activeDataSlot != SubscriptionManager.INVALID_SIM_SLOT_INDEX) {
- return activeDataSlot != slotIndex;
- }
- return false;
- }
-
public static boolean isCrossSimCallingEnabled(Context context, int slotId) {
boolean isCstEnabled = false;
int subid = getSubId(context, slotId);
diff --git a/src/com/google/android/iwlan/IwlanNetworkService.java b/src/com/google/android/iwlan/IwlanNetworkService.java
index 5e87710..8c5820e 100644
--- a/src/com/google/android/iwlan/IwlanNetworkService.java
+++ b/src/com/google/android/iwlan/IwlanNetworkService.java
@@ -25,6 +25,10 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.NetworkSpecifier;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.TransportInfo;
+import android.net.vcn.VcnTransportInfo;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
@@ -49,7 +53,7 @@
public class IwlanNetworkService extends NetworkService {
private static final String TAG = IwlanNetworkService.class.getSimpleName();
- private Context mContext;
+ private static Context mContext;
private IwlanNetworkMonitorCallback mNetworkMonitorCallback;
private IwlanOnSubscriptionsChangedListener mSubsChangeListener;
private Handler mIwlanNetworkServiceHandler;
@@ -57,6 +61,11 @@
private static boolean sNetworkConnected;
private static final Map<Integer, IwlanNetworkServiceProvider> sIwlanNetworkServiceProviders =
new ConcurrentHashMap<>();
+ private static final int INVALID_SUB_ID = -1;
+
+ // The current subscription with the active internet PDN. Need not be the default data sub.
+ // If internet is over WiFi, this value will be INVALID_SUB_ID.
+ private static int mConnectedDataSub = INVALID_SUB_ID;
private static final int EVENT_BASE = IwlanEventListener.NETWORK_SERVICE_INTERNAL_EVENT_BASE;
private static final int EVENT_NETWORK_REGISTRATION_INFO_REQUEST = EVENT_BASE;
@@ -99,6 +108,7 @@
@Override
public void onLost(Network network) {
Log.d(TAG, "onLost: " + network);
+ IwlanNetworkService.setConnectedDataSub(INVALID_SUB_ID);
IwlanNetworkService.setNetworkConnected(false, Transport.UNSPECIFIED_NETWORK);
}
@@ -123,9 +133,12 @@
Log.d(TAG, "onCapabilitiesChanged: " + network);
if (networkCapabilities != null) {
if (networkCapabilities.hasTransport(TRANSPORT_CELLULAR)) {
+ IwlanNetworkService.setConnectedDataSub(
+ getConnectedDataSub(networkCapabilities));
IwlanNetworkService.setNetworkConnected(
true, IwlanNetworkService.Transport.MOBILE);
} else if (networkCapabilities.hasTransport(TRANSPORT_WIFI)) {
+ IwlanNetworkService.setConnectedDataSub(INVALID_SUB_ID);
IwlanNetworkService.setNetworkConnected(
true, IwlanNetworkService.Transport.WIFI);
} else {
@@ -264,7 +277,7 @@
slotId = iwlanNetworkServiceProvider.getSlotIndex();
if (!IwlanNetworkService.isNetworkConnected(
- IwlanHelper.isActiveDataOnOtherSlot(mContext, slotId),
+ isActiveDataOnOtherSub(slotId),
IwlanHelper.isCrossSimCallingEnabled(mContext, slotId))) {
nriBuilder
.setRegistrationState(
@@ -360,11 +373,32 @@
return np;
}
- public static boolean isNetworkConnected(
- boolean isActiveDataOnOtherSlot, boolean isCstEnabled) {
- if (isActiveDataOnOtherSlot && isCstEnabled) {
+ static void setConnectedDataSub(int subId) {
+ mConnectedDataSub = subId;
+ }
+
+ static int getConnectedDataSub(NetworkCapabilities networkCapabilities) {
+ int connectedDataSub = INVALID_SUB_ID;
+ NetworkSpecifier specifier = networkCapabilities.getNetworkSpecifier();
+ TransportInfo transportInfo = networkCapabilities.getTransportInfo();
+
+ if (specifier != null && specifier instanceof TelephonyNetworkSpecifier) {
+ connectedDataSub = ((TelephonyNetworkSpecifier) specifier).getSubscriptionId();
+ } else if (transportInfo != null && transportInfo instanceof VcnTransportInfo) {
+ connectedDataSub = ((VcnTransportInfo) transportInfo).getSubId();
+ }
+ return connectedDataSub;
+ }
+
+ static boolean isActiveDataOnOtherSub(int slotId) {
+ int subId = IwlanHelper.getSubId(mContext, slotId);
+ return mConnectedDataSub != INVALID_SUB_ID && subId != mConnectedDataSub;
+ }
+
+ public static boolean isNetworkConnected(boolean isActiveDataOnOtherSub, boolean isCstEnabled) {
+ if (isActiveDataOnOtherSub && isCstEnabled) {
// For cross-SIM IWLAN (Transport.MOBILE), an active data PDN must be maintained on the
- // other slot.
+ // other susbcription.
if (sNetworkConnected && (sDefaultDataTransport != Transport.MOBILE)) {
Log.e(TAG, "Internet is on other slot, but default transport is not MOBILE!");
}
@@ -457,6 +491,11 @@
}
@VisibleForTesting
+ IwlanNetworkMonitorCallback getNetworkMonitorCallback() {
+ return mNetworkMonitorCallback;
+ }
+
+ @VisibleForTesting
void initHandler() {
mIwlanNetworkServiceHandler = new IwlanNetworkServiceHandler(getLooper());
}
diff --git a/test/com/google/android/iwlan/IwlanDataServiceTest.java b/test/com/google/android/iwlan/IwlanDataServiceTest.java
index f058b2c..5165d31 100644
--- a/test/com/google/android/iwlan/IwlanDataServiceTest.java
+++ b/test/com/google/android/iwlan/IwlanDataServiceTest.java
@@ -17,6 +17,7 @@
package com.google.android.iwlan;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
+import static android.net.NetworkCapabilities.TRANSPORT_CELLULAR;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
@@ -31,6 +32,8 @@
import android.net.LinkProperties;
import android.net.Network;
import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnTransportInfo;
import android.os.test.TestLooper;
import android.telephony.AccessNetworkConstants.AccessNetworkType;
import android.telephony.DataFailCause;
@@ -258,7 +261,7 @@
verifyNetworkConnected(TRANSPORT_WIFI);
assertTrue(
mIwlanDataService.isNetworkConnected(
- false /* isActiveDataOnOtherSlot */, false /* isCstEnabled */));
+ false /* isActiveDataOnOtherSub */, false /* isCstEnabled */));
}
@Test
@@ -269,13 +272,62 @@
verifyNetworkLost();
assertFalse(
mIwlanDataService.isNetworkConnected(
- false /* isActiveDataOnOtherSlot */, false /* isCstEnabled */));
+ false /* isActiveDataOnOtherSub */, false /* isCstEnabled */));
verify(mMockIwlanDataServiceProvider).forceCloseTunnelsInDeactivatingState();
mIwlanDataService.removeDataServiceProvider(mMockIwlanDataServiceProvider);
mTestLooper.dispatchAll();
}
@Test
+ public void testNetworkNotConnectedWithCellularAndCrossSimDisabled()
+ throws InterruptedException {
+ NetworkCapabilities nc =
+ prepareNetworkCapabilitiesForTest(
+ TRANSPORT_CELLULAR, DEFAULT_SUB_INDEX, false /* isVcn */);
+ mIwlanDataService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
+
+ boolean isActiveDataOnOtherSub =
+ mIwlanDataService.isActiveDataOnOtherSub(DEFAULT_SLOT_INDEX);
+
+ assertFalse(isActiveDataOnOtherSub);
+ assertFalse(
+ mIwlanDataService.isNetworkConnected(
+ isActiveDataOnOtherSub, true /* isCstEnabled */));
+ }
+
+ @Test
+ public void testCrossSimNetworkConnectedWithTelephonyNetwork() throws InterruptedException {
+ NetworkCapabilities nc =
+ prepareNetworkCapabilitiesForTest(
+ TRANSPORT_CELLULAR, DEFAULT_SUB_INDEX + 1, false /* isVcn */);
+ mIwlanDataService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
+
+ boolean isActiveDataOnOtherSub =
+ mIwlanDataService.isActiveDataOnOtherSub(DEFAULT_SLOT_INDEX);
+
+ assertTrue(isActiveDataOnOtherSub);
+ assertTrue(
+ mIwlanDataService.isNetworkConnected(
+ isActiveDataOnOtherSub, true /* isCstEnabled */));
+ }
+
+ @Test
+ public void testCrossSimNetworkConnectedWithVcn() throws InterruptedException {
+ NetworkCapabilities nc =
+ prepareNetworkCapabilitiesForTest(
+ TRANSPORT_CELLULAR, DEFAULT_SUB_INDEX + 1, true /* isVcn */);
+ mIwlanDataService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
+
+ boolean isActiveDataOnOtherSub =
+ mIwlanDataService.isActiveDataOnOtherSub(DEFAULT_SLOT_INDEX);
+
+ assertTrue(isActiveDataOnOtherSub);
+ assertTrue(
+ mIwlanDataService.isNetworkConnected(
+ isActiveDataOnOtherSub, true /* isCstEnabled */));
+ }
+
+ @Test
public void testAddDuplicateDataServiceProviderThrows() throws Exception {
when(mMockIwlanDataServiceProvider.getSlotIndex()).thenReturn(DEFAULT_SLOT_INDEX);
assertThrows(
@@ -727,17 +779,28 @@
return dp;
}
+ private NetworkCapabilities prepareNetworkCapabilitiesForTest(
+ int transportType, int subId, boolean isVcn) {
+ NetworkCapabilities.Builder builder =
+ new NetworkCapabilities.Builder().addTransportType(transportType);
+ if (isVcn) {
+ builder.setTransportInfo(new VcnTransportInfo(subId));
+ } else {
+ builder.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+ }
+ return builder.build();
+ }
+
@Test
public void testIwlanSetupDataCallFailsWithCellularAndCstDisabled() throws Exception {
DataProfile dp = buildDataProfile();
-
- /* Internet is connected through Mobile */
- mIwlanDataService.setNetworkConnected(
- true, mMockNetwork, IwlanDataService.Transport.MOBILE);
-
/* CST is disabled, and data is on the same sub as the data service provider */
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(false);
- when(mMockSubscriptionManager.getActiveDataSubscriptionId()).thenReturn(DEFAULT_SUB_INDEX);
+
+ NetworkCapabilities nc =
+ prepareNetworkCapabilitiesForTest(
+ TRANSPORT_CELLULAR, DEFAULT_SUB_INDEX, false /* isVcn */);
+ mIwlanDataService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
mIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
@@ -763,13 +826,13 @@
public void testIwlanSetupDataCallFailsWithCellularOnSameSubAndCstEnabled() throws Exception {
DataProfile dp = buildDataProfile();
- /* Internet is connected through Mobile */
- mIwlanDataService.setNetworkConnected(
- true, mMockNetwork, IwlanDataService.Transport.MOBILE);
-
/* CST is enabled, but data is on the same sub as the DataServiceProvider */
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(true);
- when(mMockSubscriptionManager.getActiveDataSubscriptionId()).thenReturn(DEFAULT_SUB_INDEX);
+
+ NetworkCapabilities nc =
+ prepareNetworkCapabilitiesForTest(
+ TRANSPORT_CELLULAR, DEFAULT_SUB_INDEX, false /* isVcn */);
+ mIwlanDataService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
mSpyIwlanDataServiceProvider.setupDataCall(
AccessNetworkType.IWLAN, /* AccessNetworkType */
@@ -796,14 +859,13 @@
throws Exception {
DataProfile dp = buildDataProfile();
- /* Internet is connected through Mobile */
- mIwlanDataService.setNetworkConnected(
- true, mMockNetwork, IwlanDataService.Transport.MOBILE);
-
- /* CST is enabled, and data is on a different sub than the DataServiceProvider */
+ /* CST is enabled, but data is on the same sub as the DataServiceProvider */
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(true);
- when(mMockSubscriptionManager.getActiveDataSubscriptionId())
- .thenReturn(DEFAULT_SUB_INDEX + 1);
+
+ NetworkCapabilities nc =
+ prepareNetworkCapabilitiesForTest(
+ TRANSPORT_CELLULAR, DEFAULT_SUB_INDEX + 1, false /* isVcn */);
+ mIwlanDataService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
doReturn(mMockEpdgTunnelManager).when(mSpyIwlanDataServiceProvider).getTunnelManager();
diff --git a/test/com/google/android/iwlan/IwlanNetworkServiceTest.java b/test/com/google/android/iwlan/IwlanNetworkServiceTest.java
index 3164bf2..0633900 100644
--- a/test/com/google/android/iwlan/IwlanNetworkServiceTest.java
+++ b/test/com/google/android/iwlan/IwlanNetworkServiceTest.java
@@ -24,6 +24,10 @@
import android.annotation.Nullable;
import android.content.Context;
import android.net.ConnectivityManager;
+import android.net.Network;
+import android.net.NetworkCapabilities;
+import android.net.TelephonyNetworkSpecifier;
+import android.net.vcn.VcnTransportInfo;
import android.telephony.AccessNetworkConstants;
import android.telephony.INetworkService;
import android.telephony.INetworkServiceCallback;
@@ -59,6 +63,7 @@
@Mock private ImsManager mMockImsManager;
@Mock private ImsMmTelManager mMockImsMmTelManager;
@Mock private INetworkServiceCallback mCallback;
+ @Mock private Network mMockNetwork;
MockitoSession mStaticMockSession;
IwlanNetworkService mIwlanNetworkService;
@@ -153,6 +158,25 @@
eq(expectedStateBuilder.build()));
}
+ private NetworkCapabilities prepareCellularNetworkCapabilitiesForTest(
+ int subId, boolean isVcn) {
+ NetworkCapabilities.Builder builder =
+ new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR);
+ if (isVcn) {
+ builder.setTransportInfo(new VcnTransportInfo(subId));
+ } else {
+ builder.setNetworkSpecifier(new TelephonyNetworkSpecifier(subId));
+ }
+ return builder.build();
+ }
+
+ private NetworkCapabilities prepareWifiNetworkCapabilitiesForTest() {
+ return new NetworkCapabilities.Builder()
+ .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
+ .build();
+ }
+
@Test
public void testNetworkRegistrationInfoSearchingForCellularAndCstDisabled() throws Exception {
mIwlanNetworkServiceProvider = initNSP();
@@ -160,7 +184,9 @@
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(false);
- mIwlanNetworkService.setNetworkConnected(true, IwlanNetworkService.Transport.MOBILE);
+ NetworkCapabilities nc =
+ prepareCellularNetworkCapabilitiesForTest(DEFAULT_SUB_INDEX, false /* is Vcn */);
+ mIwlanNetworkService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
mIwlanNetworkServiceProvider.subscriptionChanged();
// Create expected NetworkRegistrationInfo
@@ -186,7 +212,9 @@
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(true);
- mIwlanNetworkService.setNetworkConnected(true, IwlanNetworkService.Transport.MOBILE);
+ NetworkCapabilities nc =
+ prepareCellularNetworkCapabilitiesForTest(DEFAULT_SUB_INDEX, false /* is Vcn */);
+ mIwlanNetworkService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
mIwlanNetworkServiceProvider.subscriptionChanged();
// Create expected NetworkRegistrationInfo
@@ -211,10 +239,41 @@
assertTrue(mIwlanNetworkServiceProvider != null);
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(true);
- when(mMockSubscriptionManager.getActiveDataSubscriptionId())
- .thenReturn(DEFAULT_SUB_INDEX + 1);
- mIwlanNetworkService.setNetworkConnected(true, IwlanNetworkService.Transport.MOBILE);
+ // Cellular data is on the other sub
+ NetworkCapabilities nc =
+ prepareCellularNetworkCapabilitiesForTest(
+ DEFAULT_SUB_INDEX + 1, false /* is Vcn */);
+ mIwlanNetworkService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
+ mIwlanNetworkServiceProvider.subscriptionChanged();
+
+ // Create expected NetworkRegistrationInfo
+ NetworkRegistrationInfo.Builder expectedStateBuilder =
+ generateStateBuilder(
+ NetworkRegistrationInfo.DOMAIN_PS,
+ true /* isSubActive */,
+ NetworkRegistrationInfo.REGISTRATION_STATE_HOME);
+
+ mBinder.requestNetworkRegistrationInfo(0, NetworkRegistrationInfo.DOMAIN_PS, mCallback);
+
+ verify(mCallback, timeout(1000).times(1))
+ .onRequestNetworkRegistrationInfoComplete(
+ eq(NetworkServiceCallback.RESULT_SUCCESS),
+ eq(expectedStateBuilder.build()));
+ }
+
+ @Test
+ public void testNetworkRegistrationInfoHomeForCellularVcnOnDifferentSubAndCstEnabled()
+ throws Exception {
+ mIwlanNetworkServiceProvider = initNSP();
+ assertTrue(mIwlanNetworkServiceProvider != null);
+
+ when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(true);
+
+ // Cellular data as a VCN network is on the other sub
+ NetworkCapabilities nc =
+ prepareCellularNetworkCapabilitiesForTest(DEFAULT_SUB_INDEX + 1, true /* is Vcn */);
+ mIwlanNetworkService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
mIwlanNetworkServiceProvider.subscriptionChanged();
// Create expected NetworkRegistrationInfo
@@ -239,7 +298,8 @@
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(true);
- mIwlanNetworkService.setNetworkConnected(true, IwlanNetworkService.Transport.WIFI);
+ NetworkCapabilities nc = prepareWifiNetworkCapabilitiesForTest();
+ mIwlanNetworkService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
mIwlanNetworkServiceProvider.subscriptionChanged();
// Create expected NetworkRegistrationInfo
@@ -264,7 +324,9 @@
when(mMockImsMmTelManager.isCrossSimCallingEnabled()).thenReturn(false);
- mIwlanNetworkService.setNetworkConnected(true, IwlanNetworkService.Transport.WIFI);
+ NetworkCapabilities nc = prepareWifiNetworkCapabilitiesForTest();
+ mIwlanNetworkService.getNetworkMonitorCallback().onCapabilitiesChanged(mMockNetwork, nc);
+
mIwlanNetworkServiceProvider.subscriptionChanged();
// Create expected NetworkRegistrationInfo