Loading src/java/com/android/internal/telephony/data/DataNetwork.java +29 −4 Original line number Diff line number Diff line Loading @@ -210,6 +210,12 @@ public class DataNetwork extends StateMachine { */ private static final int EVENT_STUCK_IN_TRANSIENT_STATE = 20; /** * Event for waiting for tearing down condition met. This will cause data network entering * disconnecting state. */ private static final int EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET = 21; /** The default MTU for IPv4 network. */ private static final int DEFAULT_MTU_V4 = 1280; Loading Loading @@ -985,7 +991,9 @@ public class DataNetwork extends StateMachine { case EVENT_PCO_DATA_RECEIVED: case EVENT_STUCK_IN_TRANSIENT_STATE: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: // Ignore the events when not in the correct state. log("Ignored " + eventToString(msg.what)); break; case EVENT_START_HANDOVER: log("Ignore the handover to " + AccessNetworkConstants Loading Loading @@ -1058,6 +1066,7 @@ public class DataNetwork extends StateMachine { case EVENT_START_HANDOVER: case EVENT_TEAR_DOWN_NETWORK: case EVENT_PCO_DATA_RECEIVED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: // Defer the request until connected or disconnected. deferMessage(msg); break; Loading Loading @@ -1177,6 +1186,10 @@ public class DataNetwork extends StateMachine { int resultCode = msg.arg1; onDeactivateResponse(resultCode); break; case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: transitionTo(mDisconnectingState); sendMessageDelayed(EVENT_TEAR_DOWN_NETWORK, msg.arg1, msg.arg2); break; default: return NOT_HANDLED; } Loading Loading @@ -1214,6 +1227,7 @@ public class DataNetwork extends StateMachine { deferMessage(msg); } break; case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_TEAR_DOWN_NETWORK: // Defer the request until handover succeeds or fails. Loading Loading @@ -1315,6 +1329,15 @@ public class DataNetwork extends StateMachine { public boolean processMessage(Message msg) { logv("event=" + eventToString(msg.what)); switch (msg.what) { case EVENT_TEAR_DOWN_NETWORK: if (mInvokedDataDeactivation) { log("Ignore tear down request because network is being torn down."); break; } removeMessages(EVENT_TEAR_DOWN_NETWORK); removeDeferredMessages(EVENT_TEAR_DOWN_NETWORK); onTearDown(msg.arg1); break; case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE: int resultCode = msg.arg1; onDeactivateResponse(resultCode); Loading Loading @@ -2159,15 +2182,15 @@ public class DataNetwork extends StateMachine { * will be performed. {@code null} if the data network is already disconnected or being * disconnected. */ public @Nullable Runnable tearDownWithCondition(@TearDownReason int reason, public @Nullable Runnable tearDownWhenConditionMet(@TearDownReason int reason, long timeoutMillis) { if (getCurrentState() == null || isDisconnected() || isDisconnecting()) { loge("tearDownGracefully: Not in the right state. State=" + getCurrentState()); loge("tearDownWhenConditionMet: Not in the right state. State=" + getCurrentState()); return null; } logl("tearDownWithCondition: reason=" + tearDownReasonToString(reason) + ", timeout=" logl("tearDownWhenConditionMet: reason=" + tearDownReasonToString(reason) + ", timeout=" + timeoutMillis + "ms."); sendMessageDelayed(EVENT_TEAR_DOWN_NETWORK, reason, timeoutMillis); sendMessage(EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET, reason, (int) timeoutMillis); return () -> this.tearDown(reason); } Loading Loading @@ -2865,6 +2888,8 @@ public class DataNetwork extends StateMachine { return "EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE"; case EVENT_STUCK_IN_TRANSIENT_STATE: return "EVENT_STUCK_IN_TRANSIENT_STATE"; case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: return "EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET"; default: return "Unknown(" + event + ")"; } Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +4 −5 Original line number Diff line number Diff line Loading @@ -867,9 +867,8 @@ public class DataNetworkController extends Handler { } }); mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged( AccessNetworkConstants.TRANSPORT_TYPE_WWAN, this, EVENT_SERVICE_STATE_CHANGED, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); mPhone.getServiceStateTracker().registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED); mDataConfigManager.registerForConfigUpdate(this, EVENT_DATA_CONFIG_UPDATED); mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null); Loading Loading @@ -1899,7 +1898,7 @@ public class DataNetworkController extends Handler { } /** * Unregister IMS faeture state callbacks. * Unregister IMS feature state callbacks. * * @param subId Subscription index. */ Loading Loading @@ -2983,7 +2982,7 @@ public class DataNetworkController extends Handler { ? "registered" : "not registered") ); mPendingImsDeregDataNetworks.put(dataNetwork, dataNetwork.tearDownWithCondition(reason, deregDelay)); dataNetwork.tearDownWhenConditionMet(reason, deregDelay)); } else { // Graceful tear down is not turned on. Tear down the network immediately. log("tearDownGracefully: Safe to tear down " + dataNetwork); Loading tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +149 −6 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.telephony.DataSpecificRegistrationInfo; import android.telephony.LteVopsSupportInfo; import android.telephony.NetworkRegistrationInfo; import android.telephony.NetworkRegistrationInfo.RegistrationState; import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; Loading @@ -77,6 +78,15 @@ import android.telephony.data.DataCallResponse.LinkStatus; import android.telephony.data.DataProfile; import android.telephony.data.DataServiceCallback; import android.telephony.data.ThrottleStatus; import android.telephony.ims.ImsManager; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.ImsRcsManager; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.ImsStateCallback; import android.telephony.ims.RegistrationManager.RegistrationCallback; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.ArraySet; Loading @@ -89,6 +99,7 @@ import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataNetworkController.HandoverRule; import com.android.internal.telephony.data.DataRetryManager.DataRetryManagerCallback; import com.android.internal.telephony.ims.ImsResolver; import org.junit.After; import org.junit.Before; Loading @@ -114,11 +125,23 @@ public class DataNetworkControllerTest extends TelephonyTest { private static final String IPV4_ADDRESS = "10.0.2.15"; private static final String IPV6_ADDRESS = "2607:fb90:a620:651d:eabe:f8da:c107:44be"; private static final String FAKE_MMTEL_PACKAGE = "fake.mmtel.package"; private static final String FAKE_RCS_PACKAGE = "fake.rcs.package"; // Mocked classes private PhoneSwitcher mMockedPhoneSwitcher; protected ISub mIsub; protected ISub mMockedIsub; private DataNetworkControllerCallback mMockedDataNetworkControllerCallback; private DataRetryManagerCallback mMockedDataRetryManagerCallback; private ImsResolver mMockedImsResolver; private ImsManager mMockedImsManager; private ImsMmTelManager mMockedImsMmTelManager; private ImsRcsManager mMockedImsRcsManager; private ImsStateCallback mMmtelStateCallback; private ImsStateCallback mRcsStateCallback; private RegistrationCallback mMmtelRegCallback; private RegistrationCallback mRcsRegCallback; private int mNetworkRequestId = 0; Loading Loading @@ -333,6 +356,36 @@ public class DataNetworkControllerTest extends TelephonyTest { processAllMessages(); } private void setImsRegistered(boolean registered) { if (registered) { final ArraySet<String> features = new ArraySet<>(); features.add("feature1"); features.add("feature2"); ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder( ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build(); mMmtelRegCallback.onRegistered(attr); } else { ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, ""); mMmtelRegCallback.onUnregistered(info); } } private void setRcsRegistered(boolean registered) { if (registered) { final ArraySet<String> features = new ArraySet<>(); features.add("feature1"); features.add("feature2"); ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder( ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build(); mRcsRegCallback.onRegistered(attr); } else { ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, ""); mRcsRegCallback.onUnregistered(info); } } private void serviceStateChanged(@NetworkType int networkType, @RegistrationState int regState) { serviceStateChanged(networkType, regState, null); Loading Loading @@ -425,6 +478,9 @@ public class DataNetworkControllerTest extends TelephonyTest { mContextFixture.putResource(com.android.internal.R.string.config_bandwidthEstimateSource, "bandwidth_estimator"); mContextFixture.putIntResource(com.android.internal.R.integer .config_delay_for_ims_dereg_millis, 3000); } @Before Loading @@ -432,12 +488,18 @@ public class DataNetworkControllerTest extends TelephonyTest { logd("DataNetworkControllerTest +Setup!"); super.setUp(getClass().getSimpleName()); mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class); mIsub = Mockito.mock(ISub.class); mMockedIsub = Mockito.mock(ISub.class); mMockedImsManager = mContext.getSystemService(ImsManager.class); mMockedImsMmTelManager = Mockito.mock(ImsMmTelManager.class); mMockedImsRcsManager = Mockito.mock(ImsRcsManager.class); mMockedImsResolver = Mockito.mock(ImsResolver.class); mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class); mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class); when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class), any(DataNetworkController.class), any(Looper.class), any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod(); doReturn(mMockedImsMmTelManager).when(mMockedImsManager).getImsMmTelManager(anyInt()); doReturn(mMockedImsRcsManager).when(mMockedImsManager).getImsRcsManager(anyInt()); initializeConfig(); mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, Loading @@ -446,8 +508,8 @@ public class DataNetworkControllerTest extends TelephonyTest { mMockedWlanDataServiceManager); replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher); doReturn(1).when(mIsub).getDefaultDataSubId(); doReturn(mIsub).when(mIBinder).queryLocalInterface(anyString()); doReturn(1).when(mMockedIsub).getDefaultDataSubId(); doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString()); doReturn(mPhone).when(mPhone).getImsPhone(); mServiceManagerMockedServices.put("isub", mIBinder); doReturn(new SubscriptionPlan[]{}).when(mNetworkPolicyManager) Loading Loading @@ -481,6 +543,8 @@ public class DataNetworkControllerTest extends TelephonyTest { Handler.class), anyInt()); } doReturn(-1).when(mPhone).getSubId(); // Note that creating a "real" data network controller will also result in creating // real DataRetryManager, DataConfigManager, etc...Normally in unit test we should isolate // other modules and make them mocked, but only focusing on testing the unit we would like Loading @@ -489,6 +553,10 @@ public class DataNetworkControllerTest extends TelephonyTest { // as well, except some modules below we replaced with mocks. mDataNetworkControllerUT = new DataNetworkController(mPhone, Looper.myLooper()); doReturn(mDataNetworkControllerUT).when(mPhone).getDataNetworkController(); doReturn(1).when(mPhone).getSubId(); mDataNetworkControllerUT.obtainMessage(15/*EVENT_SUBSCRIPTION_CHANGED*/).sendToTarget(); processAllMessages(); // Clear the callbacks created by the real sub-modules created by DataNetworkController. clearCallbacks(); Loading @@ -503,6 +571,7 @@ public class DataNetworkControllerTest extends TelephonyTest { mDataNetworkControllerUT, mDataProfileManager); replaceInstance(DataNetworkController.class, "mAccessNetworksManager", mDataNetworkControllerUT, mAccessNetworksManager); replaceInstance(ImsResolver.class, "sInstance", null, mMockedImsResolver); ArgumentCaptor<AccessNetworksManagerCallback> callbackCaptor = ArgumentCaptor.forClass(AccessNetworksManagerCallback.class); Loading Loading @@ -555,11 +624,41 @@ public class DataNetworkControllerTest extends TelephonyTest { new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, true, null)) .sendToTarget(); ArgumentCaptor<ImsStateCallback> imsCallbackCaptor = ArgumentCaptor.forClass(ImsStateCallback.class); verify(mMockedImsMmTelManager).registerImsStateCallback(any(Executor.class), imsCallbackCaptor.capture()); mMmtelStateCallback = imsCallbackCaptor.getValue(); verify(mMockedImsRcsManager).registerImsStateCallback(any(Executor.class), imsCallbackCaptor.capture()); mRcsStateCallback = imsCallbackCaptor.getValue(); carrierConfigChanged(); serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE, NetworkRegistrationInfo.REGISTRATION_STATE_HOME); // IMS registration doReturn(FAKE_MMTEL_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName( anyInt(), eq(ImsFeature.FEATURE_MMTEL)); doReturn(FAKE_RCS_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName( anyInt(), eq(ImsFeature.FEATURE_RCS)); mMmtelStateCallback.onAvailable(); mRcsStateCallback.onAvailable(); ArgumentCaptor<RegistrationCallback> regCallbackCaptor = ArgumentCaptor.forClass(RegistrationCallback.class); verify(mMockedImsMmTelManager).registerImsRegistrationCallback(any(Executor.class), regCallbackCaptor.capture()); mMmtelRegCallback = regCallbackCaptor.getValue(); verify(mMockedImsRcsManager).registerImsRegistrationCallback(any(Executor.class), regCallbackCaptor.capture()); mRcsRegCallback = regCallbackCaptor.getValue(); processAllMessages(); logd("DataNetworkControllerTest -Setup!"); Loading Loading @@ -739,7 +838,6 @@ public class DataNetworkControllerTest extends TelephonyTest { verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS); verifyConnectedNetworkHasDataProfile(mImsDataProfile); List<DataNetwork> dataNetworkList = getDataNetworks(); DataNetwork dataNetwork = dataNetworkList.get(0); assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly( InetAddresses.parseNumericAddress(IPV4_ADDRESS), InetAddresses.parseNumericAddress(IPV6_ADDRESS)); Loading Loading @@ -1918,4 +2016,49 @@ public class DataNetworkControllerTest extends TelephonyTest { verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN); verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA); } @Test public void testImsGracefulTearDown() throws Exception { setImsRegistered(true); setRcsRegistered(true); NetworkCapabilities netCaps = new NetworkCapabilities(); netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE); NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST); TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest( nativeNetworkRequest, mPhone); mDataNetworkControllerUT.addNetworkRequest(networkRequest); processAllMessages(); Mockito.clearInvocations(mPhone); // SIM removal mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/, TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget(); processAllMessages(); // Make sure data network enters disconnecting state ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = ArgumentCaptor.forClass(PreciseDataConnectionState.class); verify(mPhone).notifyDataConnection(pdcsCaptor.capture()); PreciseDataConnectionState pdcs = pdcsCaptor.getValue(); assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING); // IMS de-registered. Now data network is safe to be torn down. Mockito.clearInvocations(mPhone); setImsRegistered(false); setRcsRegistered(false); processAllMessages(); // All data should be disconnected. verifyAllDataDisconnected(); verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS); verify(mPhone).notifyDataConnection(pdcsCaptor.capture()); pdcs = pdcsCaptor.getValue(); assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED); } } Loading
src/java/com/android/internal/telephony/data/DataNetwork.java +29 −4 Original line number Diff line number Diff line Loading @@ -210,6 +210,12 @@ public class DataNetwork extends StateMachine { */ private static final int EVENT_STUCK_IN_TRANSIENT_STATE = 20; /** * Event for waiting for tearing down condition met. This will cause data network entering * disconnecting state. */ private static final int EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET = 21; /** The default MTU for IPv4 network. */ private static final int DEFAULT_MTU_V4 = 1280; Loading Loading @@ -985,7 +991,9 @@ public class DataNetwork extends StateMachine { case EVENT_PCO_DATA_RECEIVED: case EVENT_STUCK_IN_TRANSIENT_STATE: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: // Ignore the events when not in the correct state. log("Ignored " + eventToString(msg.what)); break; case EVENT_START_HANDOVER: log("Ignore the handover to " + AccessNetworkConstants Loading Loading @@ -1058,6 +1066,7 @@ public class DataNetwork extends StateMachine { case EVENT_START_HANDOVER: case EVENT_TEAR_DOWN_NETWORK: case EVENT_PCO_DATA_RECEIVED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: // Defer the request until connected or disconnected. deferMessage(msg); break; Loading Loading @@ -1177,6 +1186,10 @@ public class DataNetwork extends StateMachine { int resultCode = msg.arg1; onDeactivateResponse(resultCode); break; case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: transitionTo(mDisconnectingState); sendMessageDelayed(EVENT_TEAR_DOWN_NETWORK, msg.arg1, msg.arg2); break; default: return NOT_HANDLED; } Loading Loading @@ -1214,6 +1227,7 @@ public class DataNetwork extends StateMachine { deferMessage(msg); } break; case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_TEAR_DOWN_NETWORK: // Defer the request until handover succeeds or fails. Loading Loading @@ -1315,6 +1329,15 @@ public class DataNetwork extends StateMachine { public boolean processMessage(Message msg) { logv("event=" + eventToString(msg.what)); switch (msg.what) { case EVENT_TEAR_DOWN_NETWORK: if (mInvokedDataDeactivation) { log("Ignore tear down request because network is being torn down."); break; } removeMessages(EVENT_TEAR_DOWN_NETWORK); removeDeferredMessages(EVENT_TEAR_DOWN_NETWORK); onTearDown(msg.arg1); break; case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE: int resultCode = msg.arg1; onDeactivateResponse(resultCode); Loading Loading @@ -2159,15 +2182,15 @@ public class DataNetwork extends StateMachine { * will be performed. {@code null} if the data network is already disconnected or being * disconnected. */ public @Nullable Runnable tearDownWithCondition(@TearDownReason int reason, public @Nullable Runnable tearDownWhenConditionMet(@TearDownReason int reason, long timeoutMillis) { if (getCurrentState() == null || isDisconnected() || isDisconnecting()) { loge("tearDownGracefully: Not in the right state. State=" + getCurrentState()); loge("tearDownWhenConditionMet: Not in the right state. State=" + getCurrentState()); return null; } logl("tearDownWithCondition: reason=" + tearDownReasonToString(reason) + ", timeout=" logl("tearDownWhenConditionMet: reason=" + tearDownReasonToString(reason) + ", timeout=" + timeoutMillis + "ms."); sendMessageDelayed(EVENT_TEAR_DOWN_NETWORK, reason, timeoutMillis); sendMessage(EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET, reason, (int) timeoutMillis); return () -> this.tearDown(reason); } Loading Loading @@ -2865,6 +2888,8 @@ public class DataNetwork extends StateMachine { return "EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE"; case EVENT_STUCK_IN_TRANSIENT_STATE: return "EVENT_STUCK_IN_TRANSIENT_STATE"; case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: return "EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET"; default: return "Unknown(" + event + ")"; } Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +4 −5 Original line number Diff line number Diff line Loading @@ -867,9 +867,8 @@ public class DataNetworkController extends Handler { } }); mPhone.getServiceStateTracker().registerForDataRegStateOrRatChanged( AccessNetworkConstants.TRANSPORT_TYPE_WWAN, this, EVENT_SERVICE_STATE_CHANGED, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); mPhone.getServiceStateTracker().registerForServiceStateChanged(this, EVENT_SERVICE_STATE_CHANGED); mDataConfigManager.registerForConfigUpdate(this, EVENT_DATA_CONFIG_UPDATED); mPhone.getServiceStateTracker().registerForPsRestrictedEnabled(this, EVENT_PS_RESTRICT_ENABLED, null); Loading Loading @@ -1899,7 +1898,7 @@ public class DataNetworkController extends Handler { } /** * Unregister IMS faeture state callbacks. * Unregister IMS feature state callbacks. * * @param subId Subscription index. */ Loading Loading @@ -2983,7 +2982,7 @@ public class DataNetworkController extends Handler { ? "registered" : "not registered") ); mPendingImsDeregDataNetworks.put(dataNetwork, dataNetwork.tearDownWithCondition(reason, deregDelay)); dataNetwork.tearDownWhenConditionMet(reason, deregDelay)); } else { // Graceful tear down is not turned on. Tear down the network immediately. log("tearDownGracefully: Safe to tear down " + dataNetwork); Loading
tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +149 −6 Original line number Diff line number Diff line Loading @@ -68,6 +68,7 @@ import android.telephony.DataSpecificRegistrationInfo; import android.telephony.LteVopsSupportInfo; import android.telephony.NetworkRegistrationInfo; import android.telephony.NetworkRegistrationInfo.RegistrationState; import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyManager; Loading @@ -77,6 +78,15 @@ import android.telephony.data.DataCallResponse.LinkStatus; import android.telephony.data.DataProfile; import android.telephony.data.DataServiceCallback; import android.telephony.data.ThrottleStatus; import android.telephony.ims.ImsManager; import android.telephony.ims.ImsMmTelManager; import android.telephony.ims.ImsRcsManager; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.ImsStateCallback; import android.telephony.ims.RegistrationManager.RegistrationCallback; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.util.ArraySet; Loading @@ -89,6 +99,7 @@ import com.android.internal.telephony.TelephonyTest; import com.android.internal.telephony.data.AccessNetworksManager.AccessNetworksManagerCallback; import com.android.internal.telephony.data.DataNetworkController.HandoverRule; import com.android.internal.telephony.data.DataRetryManager.DataRetryManagerCallback; import com.android.internal.telephony.ims.ImsResolver; import org.junit.After; import org.junit.Before; Loading @@ -114,11 +125,23 @@ public class DataNetworkControllerTest extends TelephonyTest { private static final String IPV4_ADDRESS = "10.0.2.15"; private static final String IPV6_ADDRESS = "2607:fb90:a620:651d:eabe:f8da:c107:44be"; private static final String FAKE_MMTEL_PACKAGE = "fake.mmtel.package"; private static final String FAKE_RCS_PACKAGE = "fake.rcs.package"; // Mocked classes private PhoneSwitcher mMockedPhoneSwitcher; protected ISub mIsub; protected ISub mMockedIsub; private DataNetworkControllerCallback mMockedDataNetworkControllerCallback; private DataRetryManagerCallback mMockedDataRetryManagerCallback; private ImsResolver mMockedImsResolver; private ImsManager mMockedImsManager; private ImsMmTelManager mMockedImsMmTelManager; private ImsRcsManager mMockedImsRcsManager; private ImsStateCallback mMmtelStateCallback; private ImsStateCallback mRcsStateCallback; private RegistrationCallback mMmtelRegCallback; private RegistrationCallback mRcsRegCallback; private int mNetworkRequestId = 0; Loading Loading @@ -333,6 +356,36 @@ public class DataNetworkControllerTest extends TelephonyTest { processAllMessages(); } private void setImsRegistered(boolean registered) { if (registered) { final ArraySet<String> features = new ArraySet<>(); features.add("feature1"); features.add("feature2"); ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder( ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build(); mMmtelRegCallback.onRegistered(attr); } else { ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, ""); mMmtelRegCallback.onUnregistered(info); } } private void setRcsRegistered(boolean registered) { if (registered) { final ArraySet<String> features = new ArraySet<>(); features.add("feature1"); features.add("feature2"); ImsRegistrationAttributes attr = new ImsRegistrationAttributes.Builder( ImsRegistrationImplBase.REGISTRATION_TECH_LTE).setFeatureTags(features).build(); mRcsRegCallback.onRegistered(attr); } else { ImsReasonInfo info = new ImsReasonInfo(ImsReasonInfo.CODE_LOCAL_ILLEGAL_STATE, -1, ""); mRcsRegCallback.onUnregistered(info); } } private void serviceStateChanged(@NetworkType int networkType, @RegistrationState int regState) { serviceStateChanged(networkType, regState, null); Loading Loading @@ -425,6 +478,9 @@ public class DataNetworkControllerTest extends TelephonyTest { mContextFixture.putResource(com.android.internal.R.string.config_bandwidthEstimateSource, "bandwidth_estimator"); mContextFixture.putIntResource(com.android.internal.R.integer .config_delay_for_ims_dereg_millis, 3000); } @Before Loading @@ -432,12 +488,18 @@ public class DataNetworkControllerTest extends TelephonyTest { logd("DataNetworkControllerTest +Setup!"); super.setUp(getClass().getSimpleName()); mMockedPhoneSwitcher = Mockito.mock(PhoneSwitcher.class); mIsub = Mockito.mock(ISub.class); mMockedIsub = Mockito.mock(ISub.class); mMockedImsManager = mContext.getSystemService(ImsManager.class); mMockedImsMmTelManager = Mockito.mock(ImsMmTelManager.class); mMockedImsRcsManager = Mockito.mock(ImsRcsManager.class); mMockedImsResolver = Mockito.mock(ImsResolver.class); mMockedDataNetworkControllerCallback = Mockito.mock(DataNetworkControllerCallback.class); mMockedDataRetryManagerCallback = Mockito.mock(DataRetryManagerCallback.class); when(mTelephonyComponentFactory.makeDataSettingsManager(any(Phone.class), any(DataNetworkController.class), any(Looper.class), any(DataSettingsManager.DataSettingsManagerCallback.class))).thenCallRealMethod(); doReturn(mMockedImsMmTelManager).when(mMockedImsManager).getImsMmTelManager(anyInt()); doReturn(mMockedImsRcsManager).when(mMockedImsManager).getImsRcsManager(anyInt()); initializeConfig(); mMockedDataServiceManagers.put(AccessNetworkConstants.TRANSPORT_TYPE_WWAN, Loading @@ -446,8 +508,8 @@ public class DataNetworkControllerTest extends TelephonyTest { mMockedWlanDataServiceManager); replaceInstance(PhoneSwitcher.class, "sPhoneSwitcher", null, mMockedPhoneSwitcher); doReturn(1).when(mIsub).getDefaultDataSubId(); doReturn(mIsub).when(mIBinder).queryLocalInterface(anyString()); doReturn(1).when(mMockedIsub).getDefaultDataSubId(); doReturn(mMockedIsub).when(mIBinder).queryLocalInterface(anyString()); doReturn(mPhone).when(mPhone).getImsPhone(); mServiceManagerMockedServices.put("isub", mIBinder); doReturn(new SubscriptionPlan[]{}).when(mNetworkPolicyManager) Loading Loading @@ -481,6 +543,8 @@ public class DataNetworkControllerTest extends TelephonyTest { Handler.class), anyInt()); } doReturn(-1).when(mPhone).getSubId(); // Note that creating a "real" data network controller will also result in creating // real DataRetryManager, DataConfigManager, etc...Normally in unit test we should isolate // other modules and make them mocked, but only focusing on testing the unit we would like Loading @@ -489,6 +553,10 @@ public class DataNetworkControllerTest extends TelephonyTest { // as well, except some modules below we replaced with mocks. mDataNetworkControllerUT = new DataNetworkController(mPhone, Looper.myLooper()); doReturn(mDataNetworkControllerUT).when(mPhone).getDataNetworkController(); doReturn(1).when(mPhone).getSubId(); mDataNetworkControllerUT.obtainMessage(15/*EVENT_SUBSCRIPTION_CHANGED*/).sendToTarget(); processAllMessages(); // Clear the callbacks created by the real sub-modules created by DataNetworkController. clearCallbacks(); Loading @@ -503,6 +571,7 @@ public class DataNetworkControllerTest extends TelephonyTest { mDataNetworkControllerUT, mDataProfileManager); replaceInstance(DataNetworkController.class, "mAccessNetworksManager", mDataNetworkControllerUT, mAccessNetworksManager); replaceInstance(ImsResolver.class, "sInstance", null, mMockedImsResolver); ArgumentCaptor<AccessNetworksManagerCallback> callbackCaptor = ArgumentCaptor.forClass(AccessNetworksManagerCallback.class); Loading Loading @@ -555,11 +624,41 @@ public class DataNetworkControllerTest extends TelephonyTest { new AsyncResult(AccessNetworkConstants.TRANSPORT_TYPE_WLAN, true, null)) .sendToTarget(); ArgumentCaptor<ImsStateCallback> imsCallbackCaptor = ArgumentCaptor.forClass(ImsStateCallback.class); verify(mMockedImsMmTelManager).registerImsStateCallback(any(Executor.class), imsCallbackCaptor.capture()); mMmtelStateCallback = imsCallbackCaptor.getValue(); verify(mMockedImsRcsManager).registerImsStateCallback(any(Executor.class), imsCallbackCaptor.capture()); mRcsStateCallback = imsCallbackCaptor.getValue(); carrierConfigChanged(); serviceStateChanged(TelephonyManager.NETWORK_TYPE_LTE, NetworkRegistrationInfo.REGISTRATION_STATE_HOME); // IMS registration doReturn(FAKE_MMTEL_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName( anyInt(), eq(ImsFeature.FEATURE_MMTEL)); doReturn(FAKE_RCS_PACKAGE).when(mMockedImsResolver).getConfiguredImsServicePackageName( anyInt(), eq(ImsFeature.FEATURE_RCS)); mMmtelStateCallback.onAvailable(); mRcsStateCallback.onAvailable(); ArgumentCaptor<RegistrationCallback> regCallbackCaptor = ArgumentCaptor.forClass(RegistrationCallback.class); verify(mMockedImsMmTelManager).registerImsRegistrationCallback(any(Executor.class), regCallbackCaptor.capture()); mMmtelRegCallback = regCallbackCaptor.getValue(); verify(mMockedImsRcsManager).registerImsRegistrationCallback(any(Executor.class), regCallbackCaptor.capture()); mRcsRegCallback = regCallbackCaptor.getValue(); processAllMessages(); logd("DataNetworkControllerTest -Setup!"); Loading Loading @@ -739,7 +838,6 @@ public class DataNetworkControllerTest extends TelephonyTest { verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_IMS); verifyConnectedNetworkHasDataProfile(mImsDataProfile); List<DataNetwork> dataNetworkList = getDataNetworks(); DataNetwork dataNetwork = dataNetworkList.get(0); assertThat(dataNetworkList.get(0).getLinkProperties().getAddresses()).containsExactly( InetAddresses.parseNumericAddress(IPV4_ADDRESS), InetAddresses.parseNumericAddress(IPV6_ADDRESS)); Loading Loading @@ -1918,4 +2016,49 @@ public class DataNetworkControllerTest extends TelephonyTest { verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_DUN); verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_FOTA); } @Test public void testImsGracefulTearDown() throws Exception { setImsRegistered(true); setRcsRegistered(true); NetworkCapabilities netCaps = new NetworkCapabilities(); netCaps.addCapability(NetworkCapabilities.NET_CAPABILITY_IMS); netCaps.setRequestorPackageName(FAKE_MMTEL_PACKAGE); NetworkRequest nativeNetworkRequest = new NetworkRequest(netCaps, ConnectivityManager.TYPE_MOBILE, ++mNetworkRequestId, NetworkRequest.Type.REQUEST); TelephonyNetworkRequest networkRequest = new TelephonyNetworkRequest( nativeNetworkRequest, mPhone); mDataNetworkControllerUT.addNetworkRequest(networkRequest); processAllMessages(); Mockito.clearInvocations(mPhone); // SIM removal mDataNetworkControllerUT.obtainMessage(9/*EVENT_SIM_STATE_CHANGED*/, TelephonyManager.SIM_STATE_ABSENT, 0).sendToTarget(); processAllMessages(); // Make sure data network enters disconnecting state ArgumentCaptor<PreciseDataConnectionState> pdcsCaptor = ArgumentCaptor.forClass(PreciseDataConnectionState.class); verify(mPhone).notifyDataConnection(pdcsCaptor.capture()); PreciseDataConnectionState pdcs = pdcsCaptor.getValue(); assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTING); // IMS de-registered. Now data network is safe to be torn down. Mockito.clearInvocations(mPhone); setImsRegistered(false); setRcsRegistered(false); processAllMessages(); // All data should be disconnected. verifyAllDataDisconnected(); verifyNoConnectedNetworkHasCapability(NetworkCapabilities.NET_CAPABILITY_IMS); verify(mPhone).notifyDataConnection(pdcsCaptor.capture()); pdcs = pdcsCaptor.getValue(); assertThat(pdcs.getState()).isEqualTo(TelephonyManager.DATA_DISCONNECTED); } }