Loading services/core/java/com/android/server/vcn/Vcn.java +65 −4 Original line number Original line Diff line number Diff line Loading @@ -39,10 +39,13 @@ import android.net.vcn.VcnConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnManager.VcnErrorCode; import android.net.vcn.VcnManager.VcnErrorCode; import android.os.Handler; import android.os.Handler; import android.os.HandlerExecutor; import android.os.Message; import android.os.Message; import android.os.ParcelUuid; import android.os.ParcelUuid; import android.provider.Settings; import android.provider.Settings; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.ArraySet; import android.util.ArraySet; import android.util.Slog; import android.util.Slog; Loading @@ -57,6 +60,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Map.Entry; import java.util.Map.Entry; Loading Loading @@ -148,6 +152,10 @@ public class Vcn extends Handler { @NonNull private final VcnContentResolver mContentResolver; @NonNull private final VcnContentResolver mContentResolver; @NonNull private final ContentObserver mMobileDataSettingsObserver; @NonNull private final ContentObserver mMobileDataSettingsObserver; @NonNull private final Map<Integer, VcnUserMobileDataStateListener> mMobileDataStateListeners = new ArrayMap<>(); /** /** * Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs. * Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs. * * Loading Loading @@ -221,6 +229,9 @@ public class Vcn extends Handler { // Update mIsMobileDataEnabled before starting handling of NetworkRequests. // Update mIsMobileDataEnabled before starting handling of NetworkRequests. mIsMobileDataEnabled = getMobileDataStatus(); mIsMobileDataEnabled = getMobileDataStatus(); // Register mobile data state listeners. updateMobileDataStateListeners(); // Register to receive cached and future NetworkRequests // Register to receive cached and future NetworkRequests mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener); mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener); } } Loading Loading @@ -348,6 +359,12 @@ public class Vcn extends Handler { gatewayConnection.teardownAsynchronously(); gatewayConnection.teardownAsynchronously(); } } // Unregister MobileDataStateListeners for (VcnUserMobileDataStateListener listener : mMobileDataStateListeners.values()) { getTelephonyManager().unregisterTelephonyCallback(listener); } mMobileDataStateListeners.clear(); mCurrentStatus = VCN_STATUS_CODE_INACTIVE; mCurrentStatus = VCN_STATUS_CODE_INACTIVE; } } Loading Loading @@ -454,11 +471,40 @@ public class Vcn extends Handler { gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot); gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot); } } updateMobileDataStateListeners(); // Update the mobile data state after updating the subscription snapshot as a change in // Update the mobile data state after updating the subscription snapshot as a change in // subIds for a subGroup may affect the mobile data state. // subIds for a subGroup may affect the mobile data state. handleMobileDataToggled(); handleMobileDataToggled(); } } private void updateMobileDataStateListeners() { final Set<Integer> subIdsInGroup = mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup); final HandlerExecutor executor = new HandlerExecutor(this); // Register new callbacks for (int subId : subIdsInGroup) { if (!mMobileDataStateListeners.containsKey(subId)) { final VcnUserMobileDataStateListener listener = new VcnUserMobileDataStateListener(); getTelephonyManagerForSubid(subId).registerTelephonyCallback(executor, listener); mMobileDataStateListeners.put(subId, listener); } } // Unregister old callbacks Iterator<Entry<Integer, VcnUserMobileDataStateListener>> iterator = mMobileDataStateListeners.entrySet().iterator(); while (iterator.hasNext()) { final Entry<Integer, VcnUserMobileDataStateListener> entry = iterator.next(); if (!subIdsInGroup.contains(entry.getKey())) { getTelephonyManager().unregisterTelephonyCallback(entry.getValue()); iterator.remove(); } } } private void handleMobileDataToggled() { private void handleMobileDataToggled() { final boolean oldMobileDataEnabledStatus = mIsMobileDataEnabled; final boolean oldMobileDataEnabledStatus = mIsMobileDataEnabled; mIsMobileDataEnabled = getMobileDataStatus(); mIsMobileDataEnabled = getMobileDataStatus(); Loading Loading @@ -493,11 +539,8 @@ public class Vcn extends Handler { } } private boolean getMobileDataStatus() { private boolean getMobileDataStatus() { final TelephonyManager genericTelMan = mVcnContext.getContext().getSystemService(TelephonyManager.class); for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) { for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) { if (genericTelMan.createForSubscriptionId(subId).isDataEnabled()) { if (getTelephonyManagerForSubid(subId).isDataEnabled()) { return true; return true; } } } } Loading @@ -517,6 +560,14 @@ public class Vcn extends Handler { return request.canBeSatisfiedBy(builder.build()); return request.canBeSatisfiedBy(builder.build()); } } private TelephonyManager getTelephonyManager() { return mVcnContext.getContext().getSystemService(TelephonyManager.class); } private TelephonyManager getTelephonyManagerForSubid(int subid) { return getTelephonyManager().createForSubscriptionId(subid); } private String getLogPrefix() { private String getLogPrefix() { return "[" return "[" + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) Loading Loading @@ -670,6 +721,16 @@ public class Vcn extends Handler { } } } } @VisibleForTesting(visibility = Visibility.PRIVATE) class VcnUserMobileDataStateListener extends TelephonyCallback implements TelephonyCallback.UserMobileDataStateListener { @Override public void onUserMobileDataStateChanged(boolean enabled) { sendMessage(obtainMessage(MSG_EVENT_MOBILE_DATA_TOGGLED)); } } /** External dependencies used by Vcn, for injection in tests */ /** External dependencies used by Vcn, for injection in tests */ @VisibleForTesting(visibility = Visibility.PRIVATE) @VisibleForTesting(visibility = Visibility.PRIVATE) public static class Dependencies { public static class Dependencies { Loading tests/vcn/java/com/android/server/vcn/VcnTest.java +109 −21 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.util.ArraySet; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.Vcn.VcnUserMobileDataStateListener; import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener; import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener; import org.junit.Before; import org.junit.Before; Loading Loading @@ -207,6 +208,13 @@ public class VcnTest { .registerContentObserver(eq(uri), eq(true), any(ContentObserver.class)); .registerContentObserver(eq(uri), eq(true), any(ContentObserver.class)); } } @Test public void testMobileDataStateListenersRegistered() { // Validate state from setUp() verify(mTelephonyManager, times(3)) .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class)); } @Test @Test public void testMobileDataStateCheckedOnInitialization_enabled() { public void testMobileDataStateCheckedOnInitialization_enabled() { // Validate state from setUp() // Validate state from setUp() Loading Loading @@ -263,6 +271,24 @@ public class VcnTest { assertFalse(mVcn.isMobileDataEnabled()); assertFalse(mVcn.isMobileDataEnabled()); } } @Test public void testSubscriptionSnapshotUpdatesMobileDataStateListeners() { final TelephonySubscriptionSnapshot updatedSnapshot = mock(TelephonySubscriptionSnapshot.class); doReturn(new ArraySet<>(Arrays.asList(2, 4))) .when(updatedSnapshot) .getAllSubIdsInGroup(any()); mVcn.updateSubscriptionSnapshot(updatedSnapshot); mTestLooper.dispatchAll(); verify(mTelephonyManager, times(4)) .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class)); verify(mTelephonyManager, times(2)) .unregisterTelephonyCallback(any(VcnUserMobileDataStateListener.class)); } private void triggerVcnRequestListeners(NetworkRequestListener requestListener) { private void triggerVcnRequestListeners(NetworkRequestListener requestListener) { for (final int[] caps : TEST_CAPS) { for (final int[] caps : TEST_CAPS) { startVcnGatewayWithCapabilities(requestListener, caps); startVcnGatewayWithCapabilities(requestListener, caps); Loading Loading @@ -402,24 +428,17 @@ public class VcnTest { verify(mVcnNetworkProvider).resendAllRequests(requestListener); verify(mVcnNetworkProvider).resendAllRequests(requestListener); } } private void verifyMobileDataToggled(boolean startingToggleState, boolean endingToggleState) { private void setupForMobileDataTest(boolean startingToggleState) { final ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(ContentObserver.class); verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture()); final ContentObserver contentObserver = captor.getValue(); // Start VcnGatewayConnections // Start VcnGatewayConnections final NetworkRequestListener requestListener = verifyAndGetRequestListener(); final NetworkRequestListener requestListener = verifyAndGetRequestListener(); mVcn.setMobileDataEnabled(startingToggleState); mVcn.setMobileDataEnabled(startingToggleState); triggerVcnRequestListeners(requestListener); triggerVcnRequestListeners(requestListener); final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways = } mVcn.getVcnGatewayConnectionConfigMap(); // Trigger data toggle change. doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled(); contentObserver.onChange(false /* selfChange, ignored */); mTestLooper.dispatchAll(); private void verifyMobileDataToggledUpdatesGatewayConnections( boolean startingToggleState, boolean endingToggleState, Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways) { // Verify that data toggle changes restart ONLY INTERNET or DUN networks, and only if the // Verify that data toggle changes restart ONLY INTERNET or DUN networks, and only if the // toggle state changed. // toggle state changed. for (Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry : gateways.entrySet()) { for (Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry : gateways.entrySet()) { Loading @@ -433,29 +452,98 @@ public class VcnTest { } } } } final NetworkRequestListener requestListener = verifyAndGetRequestListener(); if (startingToggleState != endingToggleState) { if (startingToggleState != endingToggleState) { verify(mVcnNetworkProvider).resendAllRequests(requestListener); verify(mVcnNetworkProvider).resendAllRequests(requestListener); } } assertEquals(endingToggleState, mVcn.isMobileDataEnabled()); assertEquals(endingToggleState, mVcn.isMobileDataEnabled()); } } private void verifyGlobalMobileDataToggled( boolean startingToggleState, boolean endingToggleState) { setupForMobileDataTest(startingToggleState); final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways = mVcn.getVcnGatewayConnectionConfigMap(); // Trigger data toggle change final ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(ContentObserver.class); verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture()); final ContentObserver contentObserver = captor.getValue(); doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled(); contentObserver.onChange(false /* selfChange, ignored */); mTestLooper.dispatchAll(); // Verify resultant behavior verifyMobileDataToggledUpdatesGatewayConnections( startingToggleState, endingToggleState, gateways); } @Test public void testGlobalMobileDataEnabled() { verifyGlobalMobileDataToggled( false /* startingToggleState */, true /* endingToggleState */); } @Test public void testGlobalMobileDataDisabled() { verifyGlobalMobileDataToggled( true /* startingToggleState */, false /* endingToggleState */); } @Test public void testGlobalMobileDataObserverFiredWithoutChanges_dataEnabled() { verifyGlobalMobileDataToggled( false /* startingToggleState */, false /* endingToggleState */); } @Test public void testGlobalMobileDataObserverFiredWithoutChanges_dataDisabled() { verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */); } private void verifySubscriptionMobileDataToggled( boolean startingToggleState, boolean endingToggleState) { setupForMobileDataTest(startingToggleState); final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways = mVcn.getVcnGatewayConnectionConfigMap(); // Trigger data toggle change. final ArgumentCaptor<VcnUserMobileDataStateListener> captor = ArgumentCaptor.forClass(VcnUserMobileDataStateListener.class); verify(mTelephonyManager, times(3)).registerTelephonyCallback(any(), captor.capture()); final VcnUserMobileDataStateListener listener = captor.getValue(); doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled(); listener.onUserMobileDataStateChanged(false /* enabled, ignored */); mTestLooper.dispatchAll(); // Verify resultant behavior verifyMobileDataToggledUpdatesGatewayConnections( startingToggleState, endingToggleState, gateways); } @Test @Test public void testMobileDataEnabled() { public void testSubscriptionMobileDataEnabled() { verifyMobileDataToggled(false /* startingToggleState */, true /* endingToggleState */); verifyGlobalMobileDataToggled( false /* startingToggleState */, true /* endingToggleState */); } } @Test @Test public void testMobileDataDisabled() { public void testSubscriptionMobileDataDisabled() { verifyMobileDataToggled(true /* startingToggleState */, false /* endingToggleState */); verifyGlobalMobileDataToggled( true /* startingToggleState */, false /* endingToggleState */); } } @Test @Test public void testMobileDataObserverFiredWithoutChanges_dataEnabled() { public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataEnabled() { verifyMobileDataToggled(false /* startingToggleState */, false /* endingToggleState */); verifyGlobalMobileDataToggled( false /* startingToggleState */, false /* endingToggleState */); } } @Test @Test public void testMobileDataObserverFiredWithoutChanges_dataDisabled() { public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataDisabled() { verifyMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */); verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */); } } } } Loading
services/core/java/com/android/server/vcn/Vcn.java +65 −4 Original line number Original line Diff line number Diff line Loading @@ -39,10 +39,13 @@ import android.net.vcn.VcnConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnGatewayConnectionConfig; import android.net.vcn.VcnManager.VcnErrorCode; import android.net.vcn.VcnManager.VcnErrorCode; import android.os.Handler; import android.os.Handler; import android.os.HandlerExecutor; import android.os.Message; import android.os.Message; import android.os.ParcelUuid; import android.os.ParcelUuid; import android.provider.Settings; import android.provider.Settings; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager; import android.util.ArrayMap; import android.util.ArraySet; import android.util.ArraySet; import android.util.Slog; import android.util.Slog; Loading @@ -57,6 +60,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Collections; import java.util.HashMap; import java.util.HashMap; import java.util.HashSet; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.List; import java.util.Map; import java.util.Map; import java.util.Map.Entry; import java.util.Map.Entry; Loading Loading @@ -148,6 +152,10 @@ public class Vcn extends Handler { @NonNull private final VcnContentResolver mContentResolver; @NonNull private final VcnContentResolver mContentResolver; @NonNull private final ContentObserver mMobileDataSettingsObserver; @NonNull private final ContentObserver mMobileDataSettingsObserver; @NonNull private final Map<Integer, VcnUserMobileDataStateListener> mMobileDataStateListeners = new ArrayMap<>(); /** /** * Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs. * Map containing all VcnGatewayConnections and their VcnGatewayConnectionConfigs. * * Loading Loading @@ -221,6 +229,9 @@ public class Vcn extends Handler { // Update mIsMobileDataEnabled before starting handling of NetworkRequests. // Update mIsMobileDataEnabled before starting handling of NetworkRequests. mIsMobileDataEnabled = getMobileDataStatus(); mIsMobileDataEnabled = getMobileDataStatus(); // Register mobile data state listeners. updateMobileDataStateListeners(); // Register to receive cached and future NetworkRequests // Register to receive cached and future NetworkRequests mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener); mVcnContext.getVcnNetworkProvider().registerListener(mRequestListener); } } Loading Loading @@ -348,6 +359,12 @@ public class Vcn extends Handler { gatewayConnection.teardownAsynchronously(); gatewayConnection.teardownAsynchronously(); } } // Unregister MobileDataStateListeners for (VcnUserMobileDataStateListener listener : mMobileDataStateListeners.values()) { getTelephonyManager().unregisterTelephonyCallback(listener); } mMobileDataStateListeners.clear(); mCurrentStatus = VCN_STATUS_CODE_INACTIVE; mCurrentStatus = VCN_STATUS_CODE_INACTIVE; } } Loading Loading @@ -454,11 +471,40 @@ public class Vcn extends Handler { gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot); gatewayConnection.updateSubscriptionSnapshot(mLastSnapshot); } } updateMobileDataStateListeners(); // Update the mobile data state after updating the subscription snapshot as a change in // Update the mobile data state after updating the subscription snapshot as a change in // subIds for a subGroup may affect the mobile data state. // subIds for a subGroup may affect the mobile data state. handleMobileDataToggled(); handleMobileDataToggled(); } } private void updateMobileDataStateListeners() { final Set<Integer> subIdsInGroup = mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup); final HandlerExecutor executor = new HandlerExecutor(this); // Register new callbacks for (int subId : subIdsInGroup) { if (!mMobileDataStateListeners.containsKey(subId)) { final VcnUserMobileDataStateListener listener = new VcnUserMobileDataStateListener(); getTelephonyManagerForSubid(subId).registerTelephonyCallback(executor, listener); mMobileDataStateListeners.put(subId, listener); } } // Unregister old callbacks Iterator<Entry<Integer, VcnUserMobileDataStateListener>> iterator = mMobileDataStateListeners.entrySet().iterator(); while (iterator.hasNext()) { final Entry<Integer, VcnUserMobileDataStateListener> entry = iterator.next(); if (!subIdsInGroup.contains(entry.getKey())) { getTelephonyManager().unregisterTelephonyCallback(entry.getValue()); iterator.remove(); } } } private void handleMobileDataToggled() { private void handleMobileDataToggled() { final boolean oldMobileDataEnabledStatus = mIsMobileDataEnabled; final boolean oldMobileDataEnabledStatus = mIsMobileDataEnabled; mIsMobileDataEnabled = getMobileDataStatus(); mIsMobileDataEnabled = getMobileDataStatus(); Loading Loading @@ -493,11 +539,8 @@ public class Vcn extends Handler { } } private boolean getMobileDataStatus() { private boolean getMobileDataStatus() { final TelephonyManager genericTelMan = mVcnContext.getContext().getSystemService(TelephonyManager.class); for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) { for (int subId : mLastSnapshot.getAllSubIdsInGroup(mSubscriptionGroup)) { if (genericTelMan.createForSubscriptionId(subId).isDataEnabled()) { if (getTelephonyManagerForSubid(subId).isDataEnabled()) { return true; return true; } } } } Loading @@ -517,6 +560,14 @@ public class Vcn extends Handler { return request.canBeSatisfiedBy(builder.build()); return request.canBeSatisfiedBy(builder.build()); } } private TelephonyManager getTelephonyManager() { return mVcnContext.getContext().getSystemService(TelephonyManager.class); } private TelephonyManager getTelephonyManagerForSubid(int subid) { return getTelephonyManager().createForSubscriptionId(subid); } private String getLogPrefix() { private String getLogPrefix() { return "[" return "[" + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) + LogUtils.getHashedSubscriptionGroup(mSubscriptionGroup) Loading Loading @@ -670,6 +721,16 @@ public class Vcn extends Handler { } } } } @VisibleForTesting(visibility = Visibility.PRIVATE) class VcnUserMobileDataStateListener extends TelephonyCallback implements TelephonyCallback.UserMobileDataStateListener { @Override public void onUserMobileDataStateChanged(boolean enabled) { sendMessage(obtainMessage(MSG_EVENT_MOBILE_DATA_TOGGLED)); } } /** External dependencies used by Vcn, for injection in tests */ /** External dependencies used by Vcn, for injection in tests */ @VisibleForTesting(visibility = Visibility.PRIVATE) @VisibleForTesting(visibility = Visibility.PRIVATE) public static class Dependencies { public static class Dependencies { Loading
tests/vcn/java/com/android/server/vcn/VcnTest.java +109 −21 Original line number Original line Diff line number Diff line Loading @@ -58,6 +58,7 @@ import android.util.ArraySet; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.VcnManagementService.VcnCallback; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.TelephonySubscriptionTracker.TelephonySubscriptionSnapshot; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.Vcn.VcnGatewayStatusCallback; import com.android.server.vcn.Vcn.VcnUserMobileDataStateListener; import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener; import com.android.server.vcn.VcnNetworkProvider.NetworkRequestListener; import org.junit.Before; import org.junit.Before; Loading Loading @@ -207,6 +208,13 @@ public class VcnTest { .registerContentObserver(eq(uri), eq(true), any(ContentObserver.class)); .registerContentObserver(eq(uri), eq(true), any(ContentObserver.class)); } } @Test public void testMobileDataStateListenersRegistered() { // Validate state from setUp() verify(mTelephonyManager, times(3)) .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class)); } @Test @Test public void testMobileDataStateCheckedOnInitialization_enabled() { public void testMobileDataStateCheckedOnInitialization_enabled() { // Validate state from setUp() // Validate state from setUp() Loading Loading @@ -263,6 +271,24 @@ public class VcnTest { assertFalse(mVcn.isMobileDataEnabled()); assertFalse(mVcn.isMobileDataEnabled()); } } @Test public void testSubscriptionSnapshotUpdatesMobileDataStateListeners() { final TelephonySubscriptionSnapshot updatedSnapshot = mock(TelephonySubscriptionSnapshot.class); doReturn(new ArraySet<>(Arrays.asList(2, 4))) .when(updatedSnapshot) .getAllSubIdsInGroup(any()); mVcn.updateSubscriptionSnapshot(updatedSnapshot); mTestLooper.dispatchAll(); verify(mTelephonyManager, times(4)) .registerTelephonyCallback(any(), any(VcnUserMobileDataStateListener.class)); verify(mTelephonyManager, times(2)) .unregisterTelephonyCallback(any(VcnUserMobileDataStateListener.class)); } private void triggerVcnRequestListeners(NetworkRequestListener requestListener) { private void triggerVcnRequestListeners(NetworkRequestListener requestListener) { for (final int[] caps : TEST_CAPS) { for (final int[] caps : TEST_CAPS) { startVcnGatewayWithCapabilities(requestListener, caps); startVcnGatewayWithCapabilities(requestListener, caps); Loading Loading @@ -402,24 +428,17 @@ public class VcnTest { verify(mVcnNetworkProvider).resendAllRequests(requestListener); verify(mVcnNetworkProvider).resendAllRequests(requestListener); } } private void verifyMobileDataToggled(boolean startingToggleState, boolean endingToggleState) { private void setupForMobileDataTest(boolean startingToggleState) { final ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(ContentObserver.class); verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture()); final ContentObserver contentObserver = captor.getValue(); // Start VcnGatewayConnections // Start VcnGatewayConnections final NetworkRequestListener requestListener = verifyAndGetRequestListener(); final NetworkRequestListener requestListener = verifyAndGetRequestListener(); mVcn.setMobileDataEnabled(startingToggleState); mVcn.setMobileDataEnabled(startingToggleState); triggerVcnRequestListeners(requestListener); triggerVcnRequestListeners(requestListener); final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways = } mVcn.getVcnGatewayConnectionConfigMap(); // Trigger data toggle change. doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled(); contentObserver.onChange(false /* selfChange, ignored */); mTestLooper.dispatchAll(); private void verifyMobileDataToggledUpdatesGatewayConnections( boolean startingToggleState, boolean endingToggleState, Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways) { // Verify that data toggle changes restart ONLY INTERNET or DUN networks, and only if the // Verify that data toggle changes restart ONLY INTERNET or DUN networks, and only if the // toggle state changed. // toggle state changed. for (Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry : gateways.entrySet()) { for (Entry<VcnGatewayConnectionConfig, VcnGatewayConnection> entry : gateways.entrySet()) { Loading @@ -433,29 +452,98 @@ public class VcnTest { } } } } final NetworkRequestListener requestListener = verifyAndGetRequestListener(); if (startingToggleState != endingToggleState) { if (startingToggleState != endingToggleState) { verify(mVcnNetworkProvider).resendAllRequests(requestListener); verify(mVcnNetworkProvider).resendAllRequests(requestListener); } } assertEquals(endingToggleState, mVcn.isMobileDataEnabled()); assertEquals(endingToggleState, mVcn.isMobileDataEnabled()); } } private void verifyGlobalMobileDataToggled( boolean startingToggleState, boolean endingToggleState) { setupForMobileDataTest(startingToggleState); final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways = mVcn.getVcnGatewayConnectionConfigMap(); // Trigger data toggle change final ArgumentCaptor<ContentObserver> captor = ArgumentCaptor.forClass(ContentObserver.class); verify(mContentResolver).registerContentObserver(any(), anyBoolean(), captor.capture()); final ContentObserver contentObserver = captor.getValue(); doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled(); contentObserver.onChange(false /* selfChange, ignored */); mTestLooper.dispatchAll(); // Verify resultant behavior verifyMobileDataToggledUpdatesGatewayConnections( startingToggleState, endingToggleState, gateways); } @Test public void testGlobalMobileDataEnabled() { verifyGlobalMobileDataToggled( false /* startingToggleState */, true /* endingToggleState */); } @Test public void testGlobalMobileDataDisabled() { verifyGlobalMobileDataToggled( true /* startingToggleState */, false /* endingToggleState */); } @Test public void testGlobalMobileDataObserverFiredWithoutChanges_dataEnabled() { verifyGlobalMobileDataToggled( false /* startingToggleState */, false /* endingToggleState */); } @Test public void testGlobalMobileDataObserverFiredWithoutChanges_dataDisabled() { verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */); } private void verifySubscriptionMobileDataToggled( boolean startingToggleState, boolean endingToggleState) { setupForMobileDataTest(startingToggleState); final Map<VcnGatewayConnectionConfig, VcnGatewayConnection> gateways = mVcn.getVcnGatewayConnectionConfigMap(); // Trigger data toggle change. final ArgumentCaptor<VcnUserMobileDataStateListener> captor = ArgumentCaptor.forClass(VcnUserMobileDataStateListener.class); verify(mTelephonyManager, times(3)).registerTelephonyCallback(any(), captor.capture()); final VcnUserMobileDataStateListener listener = captor.getValue(); doReturn(endingToggleState).when(mTelephonyManager).isDataEnabled(); listener.onUserMobileDataStateChanged(false /* enabled, ignored */); mTestLooper.dispatchAll(); // Verify resultant behavior verifyMobileDataToggledUpdatesGatewayConnections( startingToggleState, endingToggleState, gateways); } @Test @Test public void testMobileDataEnabled() { public void testSubscriptionMobileDataEnabled() { verifyMobileDataToggled(false /* startingToggleState */, true /* endingToggleState */); verifyGlobalMobileDataToggled( false /* startingToggleState */, true /* endingToggleState */); } } @Test @Test public void testMobileDataDisabled() { public void testSubscriptionMobileDataDisabled() { verifyMobileDataToggled(true /* startingToggleState */, false /* endingToggleState */); verifyGlobalMobileDataToggled( true /* startingToggleState */, false /* endingToggleState */); } } @Test @Test public void testMobileDataObserverFiredWithoutChanges_dataEnabled() { public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataEnabled() { verifyMobileDataToggled(false /* startingToggleState */, false /* endingToggleState */); verifyGlobalMobileDataToggled( false /* startingToggleState */, false /* endingToggleState */); } } @Test @Test public void testMobileDataObserverFiredWithoutChanges_dataDisabled() { public void testSubscriptionMobileDataListenerFiredWithoutChanges_dataDisabled() { verifyMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */); verifyGlobalMobileDataToggled(true /* startingToggleState */, true /* endingToggleState */); } } } }