diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-23 10:15:23 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-09-23 10:15:23 +0000 |
commit | fa9c68d243ea7fd140e0740e083c7fba85a0d43c (patch) | |
tree | 8b04364c66ca59abce437de2175c1e2a083edda9 | |
parent | 970dad03df4e0b91048158c9a24fa911d4a80af0 (diff) | |
parent | c5dc59f7a82992193d151c96517277a517a5fcc2 (diff) | |
download | telephony-android13-mainline-scheduling-release.tar.gz |
Snap for 9098257 from c5dc59f7a82992193d151c96517277a517a5fcc2 to mainline-scheduling-releaseaml_sch_331113000aml_sch_331111000android13-mainline-scheduling-release
Change-Id: Ibac857732533f550f00fdbc30f2d114a799398db
3 files changed, 268 insertions, 73 deletions
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java index f85bc13cae..e483d2b0b7 100644 --- a/src/java/com/android/internal/telephony/data/DataNetwork.java +++ b/src/java/com/android/internal/telephony/data/DataNetwork.java @@ -628,10 +628,10 @@ public class DataNetwork extends StateMachine { private @NonNull DataAllowedReason mDataAllowedReason; /** - * PCO (Protocol Configuration Options) data received from the network. Key is the PCO id, value - * is the PCO content. + * PCO (Protocol Configuration Options) data received from the network. The first key is the + * cid of the PCO data, the second key is the PCO id, the value is the PCO data. */ - private final @NonNull Map<Integer, PcoData> mPcoData = new ArrayMap<>(); + private final @NonNull Map<Integer, Map<Integer, PcoData>> mPcoData = new ArrayMap<>(); /** The QOS bearer sessions. */ private final @NonNull List<QosBearerSession> mQosBearerSessions = new ArrayList<>(); @@ -983,6 +983,7 @@ public class DataNetwork extends StateMachine { public void enter() { logv("Registering all events."); mDataConfigManager.registerForConfigUpdate(getHandler(), EVENT_DATA_CONFIG_UPDATED); + mRil.registerForPcoData(getHandler(), EVENT_PCO_DATA_RECEIVED, null); mPhone.getDisplayInfoController().registerForTelephonyDisplayInfoChanged( getHandler(), EVENT_DISPLAY_INFO_CHANGED, null); mPhone.getServiceStateTracker().registerForServiceStateChanged(getHandler(), @@ -1035,6 +1036,7 @@ public class DataNetwork extends StateMachine { mPhone.getDisplayInfoController().unregisterForTelephonyDisplayInfoChanged( getHandler()); mDataConfigManager.unregisterForConfigUpdate(getHandler()); + mRil.unregisterForPcoData(getHandler()); } @Override @@ -1081,9 +1083,13 @@ public class DataNetwork extends StateMachine { updateNetworkCapabilities(); break; } + case EVENT_PCO_DATA_RECEIVED: { + AsyncResult ar = (AsyncResult) msg.obj; + onPcoDataReceived((PcoData) ar.result); + break; + } case EVENT_BANDWIDTH_ESTIMATE_FROM_MODEM_CHANGED: case EVENT_TEAR_DOWN_NETWORK: - case EVENT_PCO_DATA_RECEIVED: case EVENT_STUCK_IN_TRANSIENT_STATE: case EVENT_DISPLAY_INFO_CHANGED: case EVENT_WAITING_FOR_TEARING_DOWN_CONDITION_MET: @@ -1162,7 +1168,6 @@ public class DataNetwork extends StateMachine { break; 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. log("Defer message " + eventToString(msg.what)); @@ -1229,6 +1234,13 @@ public class DataNetwork extends StateMachine { } } + // If we've ever received PCO data before connected, now it's the time to + // process it. + mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap()) + .forEach((pcoId, pcoData) -> { + onPcoDataChanged(pcoData); + }); + notifyPreciseDataConnectionState(); updateSuspendState(); } @@ -1279,10 +1291,6 @@ public class DataNetwork extends StateMachine { case EVENT_SUBSCRIPTION_PLAN_OVERRIDE: updateMeteredAndCongested(); break; - case EVENT_PCO_DATA_RECEIVED: - ar = (AsyncResult) msg.obj; - onPcoDataReceived((PcoData) ar.result); - break; case EVENT_DEACTIVATE_DATA_NETWORK_RESPONSE: int resultCode = msg.arg1; onDeactivateResponse(resultCode); @@ -1353,10 +1361,6 @@ public class DataNetwork extends StateMachine { onHandoverResponse(resultCode, dataCallResponse, (DataHandoverRetryEntry) msg.obj); break; - case EVENT_PCO_DATA_RECEIVED: - AsyncResult ar = (AsyncResult) msg.obj; - onPcoDataReceived((PcoData) ar.result); - break; case EVENT_STUCK_IN_TRANSIENT_STATE: reportAnomaly("Data service did not respond the handover request within " + TimeUnit.MILLISECONDS.toSeconds( @@ -1545,7 +1549,6 @@ public class DataNetwork extends StateMachine { private void registerForWwanEvents() { registerForBandwidthUpdate(); mKeepaliveTracker.registerForKeepaliveStatus(); - mRil.registerForPcoData(this.getHandler(), EVENT_PCO_DATA_RECEIVED, null); } /** @@ -1554,7 +1557,6 @@ public class DataNetwork extends StateMachine { private void unregisterForWwanEvents() { unregisterForBandwidthUpdate(); mKeepaliveTracker.unregisterForKeepaliveStatus(); - mRil.unregisterForPcoData(this.getHandler()); } @Override @@ -3111,8 +3113,6 @@ public class DataNetwork extends StateMachine { mDataProfile = mHandoverDataProfile; updateDataNetwork(response); if (mTransport != AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { - // Handover from WWAN to WLAN - mPcoData.clear(); unregisterForWwanEvents(); } else { // Handover from WLAN to WWAN @@ -3139,36 +3139,55 @@ public class DataNetwork extends StateMachine { } /** + * Called when PCO data changes. + * + * @param pcoData The PCO data. + */ + private void onPcoDataChanged(@NonNull PcoData pcoData) { + log("onPcoDataChanged: " + pcoData); + mDataNetworkCallback.invokeFromExecutor( + () -> mDataNetworkCallback.onPcoDataChanged(DataNetwork.this)); + if (mDataProfile.getApnSetting() != null) { + for (int apnType : mDataProfile.getApnSetting().getApnTypes()) { + Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE); + intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, apnType); + intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, + ApnSetting.getProtocolIntFromString(pcoData.bearerProto)); + intent.putExtra(TelephonyManager.EXTRA_PCO_ID, pcoData.pcoId); + intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, pcoData.contents); + mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent); + } + } + } + + /** * Called when receiving PCO (Protocol Configuration Options) data from the cellular network. * * @param pcoData PCO data. */ private void onPcoDataReceived(@NonNull PcoData pcoData) { - if (pcoData.cid != getId()) return; - PcoData oldData = mPcoData.put(pcoData.pcoId, pcoData); + // Save all the PCO data received, even though it might be unrelated to this data network. + // The network might be still in connecting state. Save all now and use it when entering + // connected state. + log("onPcoDataReceived: " + pcoData); + PcoData oldData = mPcoData.computeIfAbsent(pcoData.cid, m -> new ArrayMap<>()) + .put(pcoData.pcoId, pcoData); + if (getId() == INVALID_CID || pcoData.cid != getId()) return; if (!Objects.equals(oldData, pcoData)) { - log("onPcoDataReceived: " + pcoData); - mDataNetworkCallback.invokeFromExecutor( - () -> mDataNetworkCallback.onPcoDataChanged(DataNetwork.this)); - if (mDataProfile.getApnSetting() != null) { - for (int apnType : mDataProfile.getApnSetting().getApnTypes()) { - Intent intent = new Intent(TelephonyManager.ACTION_CARRIER_SIGNAL_PCO_VALUE); - intent.putExtra(TelephonyManager.EXTRA_APN_TYPE, apnType); - intent.putExtra(TelephonyManager.EXTRA_APN_PROTOCOL, - ApnSetting.getProtocolIntFromString(pcoData.bearerProto)); - intent.putExtra(TelephonyManager.EXTRA_PCO_ID, pcoData.pcoId); - intent.putExtra(TelephonyManager.EXTRA_PCO_VALUE, pcoData.contents); - mPhone.getCarrierSignalAgent().notifyCarrierSignalReceivers(intent); - } - } + onPcoDataChanged(pcoData); } } /** - * @return The PCO data received from the network. + * @return The PCO data map of the network. The key is the PCO id, the value is the PCO data. + * An empty map if PCO data is not available (or when the network is on IWLAN). */ public @NonNull Map<Integer, PcoData> getPcoData() { - return mPcoData; + if (mTransport == AccessNetworkConstants.TRANSPORT_TYPE_WLAN + || mCid.get(mTransport) == INVALID_CID) { + return Collections.emptyMap(); + } + return mPcoData.getOrDefault(mCid.get(mTransport), Collections.emptyMap()); } /** diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java index 7be0a4d8de..4b02428a10 100644 --- a/src/java/com/android/internal/telephony/data/DataNetworkController.java +++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java @@ -1285,21 +1285,37 @@ public class DataNetworkController extends Handler { } /** - * @return {@code true} if checking registration state is needed before setup data network. - * {@code false} indicates regardless in-service or out-of-service, setup data request will - * be sent down to the data service. + * @param ss The service state to be checked + * @param transport The transport is used to determine the data registration state + * + * @return {@code true} if data is in service or if voice is in service on legacy CS + * connections (2G/3G) on the non-DDS. In those cases we attempt to attach PS. We don't try for + * newer RAT because for those PS attach already occurred. */ - private boolean shouldCheckRegistrationState() { - // Always don't check registration state on non-DDS sub. - if (mPhone.getPhoneId() != PhoneSwitcher.getInstance().getPreferredDataPhoneId()) { - return false; - } + private boolean serviceStateAllowsPSAttach(@NonNull ServiceState ss, + @TransportType int transport) { + // Use the data registration state from the modem instead of the current data registration + // state, which can be overridden. + int nriRegState = getDataRegistrationState(ss, transport); + if (nriRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME + || nriRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING) return true; - // TODO: Expand this method to support more scenarios if needed. On Android 12 or older - // Android, auto attach is enabled by default. We dropped that support in Android 13 since - // it's for the old 2G network. If there are other scenarios that we need to support - // auto-attach, can implement the logic in this method. - return true; + // If data is OOS on the non-DDS, + // attempt to attach PS on 2G/3G if CS connection is available. + return ss.getVoiceRegState() == ServiceState.STATE_IN_SERVICE + && mPhone.getPhoneId() != PhoneSwitcher.getInstance().getPreferredDataPhoneId() + && isLegacyCs(ss.getVoiceNetworkType()); + } + + /** + * @param voiceNetworkType The voice network type to be checked. + * @return {@code true} if the network type is on legacy CS connection. + */ + private boolean isLegacyCs(@NetworkType int voiceNetworkType) { + int voiceAccessNetworkType = DataUtils.networkTypeToAccessNetworkType(voiceNetworkType); + return voiceAccessNetworkType == AccessNetworkType.GERAN + || voiceAccessNetworkType == AccessNetworkType.UTRAN + || voiceAccessNetworkType == AccessNetworkType.CDMA2000; } /** @@ -1384,10 +1400,7 @@ public class DataNetworkController extends Handler { return evaluation; } - int regState = getDataRegistrationState(transport); - if (shouldCheckRegistrationState() - && regState != NetworkRegistrationInfo.REGISTRATION_STATE_HOME - && regState != NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING) { + if (!serviceStateAllowsPSAttach(mServiceState, transport)) { evaluation.addDataDisallowedReason(DataDisallowedReason.NOT_IN_SERVICE); } @@ -1548,7 +1561,7 @@ public class DataNetworkController extends Handler { + TelephonyManager.getNetworkTypeName(getDataNetworkType(transport)) + ", reg state=" + NetworkRegistrationInfo.registrationStateToString( - getDataRegistrationState(transport)) + getDataRegistrationState(mServiceState, transport)) + ", " + networkRequest); } return evaluation; @@ -2992,7 +3005,7 @@ public class DataNetworkController extends Handler { } if (nrAdvancedCapableByPco != mNrAdvancedCapableByPco) { - log("onPcoDataChanged: mNrAdvancedCapableByPco = " + mNrAdvancedCapableByPco); + log("onPcoDataChanged: mNrAdvancedCapableByPco = " + nrAdvancedCapableByPco); mNrAdvancedCapableByPco = nrAdvancedCapableByPco; mDataNetworkControllerCallbacks.forEach(callback -> callback.invokeFromExecutor( () -> callback.onNrAdvancedCapableByPcoChanged(mNrAdvancedCapableByPco))); @@ -3064,27 +3077,39 @@ public class DataNetworkController extends Handler { /** * Check if needed to re-evaluate the unsatisfied network requests. * - * @param oldNri Previous network registration info. - * @param newNri Current network registration info. + * @param oldSS Previous raw service state. + * @param newSS Current raw service state. + * @param transport The network transport to be checked. * @return {@code true} if needed to re-evaluate the unsatisfied network requests. */ - private boolean shouldReevaluateNetworkRequests(@Nullable NetworkRegistrationInfo oldNri, - @Nullable NetworkRegistrationInfo newNri) { - if (newNri == null) return false; - if (newNri.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_UNKNOWN) { + private boolean shouldReevaluateNetworkRequests(@NonNull ServiceState oldSS, + @NonNull ServiceState newSS, @TransportType int transport) { + NetworkRegistrationInfo oldPsNri = oldSS.getNetworkRegistrationInfo( + NetworkRegistrationInfo.DOMAIN_PS, transport); + NetworkRegistrationInfo newPsNri = newSS.getNetworkRegistrationInfo( + NetworkRegistrationInfo.DOMAIN_PS, transport); + + if (newPsNri == null) return false; + if (newPsNri.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_UNKNOWN) { // Sometimes devices temporarily lose signal and RAT becomes unknown. We don't setup // data in this case. return false; } - if (oldNri == null - || oldNri.getAccessNetworkTechnology() != newNri.getAccessNetworkTechnology() - || (!oldNri.isInService() && newNri.isInService())) { + if (oldPsNri == null + || oldPsNri.getAccessNetworkTechnology() != newPsNri.getAccessNetworkTechnology() + || (!oldPsNri.isInService() && newPsNri.isInService())) { return true; } - DataSpecificRegistrationInfo oldDsri = oldNri.getDataSpecificInfo(); - DataSpecificRegistrationInfo newDsri = newNri.getDataSpecificInfo(); + // If CS connection is back to service on non-DDS, reevaluate for potential PS + if (!serviceStateAllowsPSAttach(oldSS, transport) + && serviceStateAllowsPSAttach(newSS, transport)) { + return true; + } + + DataSpecificRegistrationInfo oldDsri = oldPsNri.getDataSpecificInfo(); + DataSpecificRegistrationInfo newDsri = newPsNri.getDataSpecificInfo(); if (oldDsri == null) return false; if ((newDsri == null || newDsri.getVopsSupportInfo() == null @@ -3139,7 +3164,7 @@ public class DataNetworkController extends Handler { evaluateDataNetworks = true; } } - if (shouldReevaluateNetworkRequests(oldNri, newNri)) { + if (shouldReevaluateNetworkRequests(mServiceState, newServiceState, transport)) { if (!hasMessages(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS)) { sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS, DataEvaluationReason.DATA_SERVICE_STATE_CHANGED)); @@ -3276,11 +3301,13 @@ public class DataNetworkController extends Handler { /** * Get data registration state based on transport. * + * @param ss The service state from which to extract the data registration state. * @param transport The transport. * @return The registration state. */ - private @RegistrationState int getDataRegistrationState(@TransportType int transport) { - NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo( + private @RegistrationState int getDataRegistrationState(@NonNull ServiceState ss, + @TransportType int transport) { + NetworkRegistrationInfo nri = ss.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, transport); if (nri != null) { return nri.getRegistrationState(); diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java index 52b487af00..0078277aa7 100644 --- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java +++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkControllerTest.java @@ -75,6 +75,7 @@ import android.telephony.SubscriptionInfo; import android.telephony.SubscriptionPlan; import android.telephony.TelephonyDisplayInfo; import android.telephony.TelephonyManager; +import android.telephony.TelephonyProtoEnums; import android.telephony.data.ApnSetting; import android.telephony.data.DataCallResponse; import android.telephony.data.DataCallResponse.LinkStatus; @@ -478,17 +479,31 @@ public class DataNetworkControllerTest extends TelephonyTest { new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED, LteVopsSupportInfo.LTE_STATUS_SUPPORTED)); - serviceStateChanged(networkType, regState, dsri); + serviceStateChanged(networkType, regState, regState, + NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri); } private void serviceStateChanged(@NetworkType int networkType, @RegistrationState int regState, DataSpecificRegistrationInfo dsri) { + serviceStateChanged(networkType, regState, regState, + NetworkRegistrationInfo.REGISTRATION_STATE_HOME, dsri); + } + + private void serviceStateChanged(@NetworkType int networkType, + @RegistrationState int dataRegState, @RegistrationState int voiceRegState, + @RegistrationState int iwlanRegState, DataSpecificRegistrationInfo dsri) { + if (dsri == null) { + dsri = new DataSpecificRegistrationInfo(8, false, true, true, + new LteVopsSupportInfo(LteVopsSupportInfo.LTE_STATUS_SUPPORTED, + LteVopsSupportInfo.LTE_STATUS_SUPPORTED)); + } + ServiceState ss = new ServiceState(); ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder() .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setAccessNetworkTechnology(networkType) - .setRegistrationState(regState) + .setRegistrationState(dataRegState) .setDomain(NetworkRegistrationInfo.DOMAIN_PS) .setDataSpecificInfo(dsri) .build()); @@ -496,18 +511,20 @@ public class DataNetworkControllerTest extends TelephonyTest { ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder() .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) .setAccessNetworkTechnology(TelephonyManager.NETWORK_TYPE_IWLAN) - .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) + .setRegistrationState(iwlanRegState) .setDomain(NetworkRegistrationInfo.DOMAIN_PS) .build()); ss.addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder() .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN) .setAccessNetworkTechnology(networkType) - .setRegistrationState(regState) + .setRegistrationState(voiceRegState) .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .build()); - ss.setDataRoamingFromRegistration(regState + ss.setDataRoamingFromRegistration(dataRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING); + processServiceStateRegStateForTest(ss); + doReturn(ss).when(mSST).getServiceState(); doReturn(ss).when(mPhone).getServiceState(); @@ -515,6 +532,28 @@ public class DataNetworkControllerTest extends TelephonyTest { processAllMessages(); } + // set SS reg state base on SST impl, where WLAN overrides WWAN's data reg. + private void processServiceStateRegStateForTest(ServiceState ss) { + int wlanRegState = ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN).getRegistrationState(); + if (wlanRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) { + ss.setDataRegState(ServiceState.STATE_IN_SERVICE); + } else { + int cellularRegState = ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_PS, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getRegistrationState(); + int dataState = (cellularRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME + || cellularRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING) + ? ServiceState.STATE_IN_SERVICE : ServiceState.STATE_OUT_OF_SERVICE; + ss.setDataRegState(dataState); + } + int voiceRegState = ss.getNetworkRegistrationInfo(NetworkRegistrationInfo.DOMAIN_CS, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN).getRegistrationState(); + int voiceState = (voiceRegState == NetworkRegistrationInfo.REGISTRATION_STATE_HOME + || voiceRegState == NetworkRegistrationInfo.REGISTRATION_STATE_ROAMING) + ? ServiceState.STATE_IN_SERVICE : ServiceState.STATE_OUT_OF_SERVICE; + ss.setVoiceRegState(voiceState); + } + private void updateTransport(@NetCapability int capability, @TransportType int transport) { doReturn(transport).when(mAccessNetworksManager) .getPreferredTransportByNetworkCapability(capability); @@ -2303,6 +2342,76 @@ public class DataNetworkControllerTest extends TelephonyTest { } @Test + public void testNrAdvancedByEarlyPco() { + Mockito.reset(mMockedWwanDataServiceManager); + mDataNetworkControllerUT.addNetworkRequest( + createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); + processAllMessages(); + + // PCO data arrives before data network entering connected state. + mSimulatedCommands.triggerPcoData(1, "IPV6", 1234, new byte[]{1}); + processAllMessages(); + + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class), + anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), + messageCaptor.capture()); + + // Send setup data call complete message. + Message msg = messageCaptor.getValue(); + msg.getData().putParcelable("data_call_response", + createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE)); + msg.arg1 = DataServiceCallback.RESULT_SUCCESS; + msg.sendToTarget(); + processAllMessages(); + + verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true)); + } + + @Test + public void testNrAdvancedByPcoMultipleNetworks() throws Exception { + testSetupDataNetwork(); + setSuccessfulSetupDataResponse(mMockedDataServiceManagers + .get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), 2); + testSetupImsDataNetwork(); + + verify(mMockedDataNetworkControllerCallback, never()) + .onNrAdvancedCapableByPcoChanged(anyBoolean()); + mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1}); + processAllMessages(); + verify(mMockedDataNetworkControllerCallback).onNrAdvancedCapableByPcoChanged(eq(true)); + } + + @Test + public void testNrAdvancedByEarlyUnrelatedPco() { + Mockito.reset(mMockedWwanDataServiceManager); + mDataNetworkControllerUT.addNetworkRequest( + createNetworkRequest(NetworkCapabilities.NET_CAPABILITY_INTERNET)); + processAllMessages(); + + // Unrelated PCO data arrives before data network entering connected state. + mSimulatedCommands.triggerPcoData(2, "IPV6", 1234, new byte[]{1}); + processAllMessages(); + + ArgumentCaptor<Message> messageCaptor = ArgumentCaptor.forClass(Message.class); + verify(mMockedWwanDataServiceManager).setupDataCall(anyInt(), any(DataProfile.class), + anyBoolean(), anyBoolean(), anyInt(), any(), anyInt(), any(), any(), anyBoolean(), + messageCaptor.capture()); + + // Send setup data call complete message. + Message msg = messageCaptor.getValue(); + msg.getData().putParcelable("data_call_response", + createDataCallResponse(1, DataCallResponse.LINK_STATUS_ACTIVE)); + msg.arg1 = DataServiceCallback.RESULT_SUCCESS; + msg.sendToTarget(); + processAllMessages(); + + verify(mMockedDataNetworkControllerCallback, never()).onNrAdvancedCapableByPcoChanged( + anyBoolean()); + } + + + @Test public void testSetupDataNetworkVcnManaged() throws Exception { // VCN managed setVcnManagerPolicy(true, false); @@ -2778,6 +2887,7 @@ public class DataNetworkControllerTest extends TelephonyTest { .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .build()); + processServiceStateRegStateForTest(ss); doReturn(ss).when(mSST).getServiceState(); doReturn(ss).when(mPhone).getServiceState(); @@ -2827,6 +2937,7 @@ public class DataNetworkControllerTest extends TelephonyTest { .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .build()); + processServiceStateRegStateForTest(ss); doReturn(ss).when(mSST).getServiceState(); doReturn(ss).when(mPhone).getServiceState(); @@ -2885,6 +2996,7 @@ public class DataNetworkControllerTest extends TelephonyTest { .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .build()); + processServiceStateRegStateForTest(ss); doReturn(ss).when(mSST).getServiceState(); doReturn(ss).when(mPhone).getServiceState(); @@ -2948,6 +3060,7 @@ public class DataNetworkControllerTest extends TelephonyTest { .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .build()); + processServiceStateRegStateForTest(ss); doReturn(ss).when(mSST).getServiceState(); doReturn(ss).when(mPhone).getServiceState(); @@ -2994,6 +3107,7 @@ public class DataNetworkControllerTest extends TelephonyTest { .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_HOME) .setDomain(NetworkRegistrationInfo.DOMAIN_CS) .build()); + processServiceStateRegStateForTest(ss); doReturn(ss).when(mSST).getServiceState(); doReturn(ss).when(mPhone).getServiceState(); @@ -3146,4 +3260,39 @@ public class DataNetworkControllerTest extends TelephonyTest { // Data should be torn down on this non-preferred sub. verifyAllDataDisconnected(); } + + @Test + public void testSetupDataOnNonDds() throws Exception { + // Now DDS switched to phone 1 + doReturn(1).when(mMockedPhoneSwitcher).getPreferredDataPhoneId(); + TelephonyNetworkRequest request = createNetworkRequest( + NetworkCapabilities.NET_CAPABILITY_MMS); + + // Test Don't allow setup if both data and voice OOS + serviceStateChanged(TelephonyProtoEnums.NETWORK_TYPE_1XRTT, + // data, voice, Iwlan reg state + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null); + mDataNetworkControllerUT.addNetworkRequest(request); + processAllMessages(); + + verifyAllDataDisconnected(); + + // Test Don't allow setup if CS is in service, but current RAT is already PS(e.g. LTE) + serviceStateChanged(TelephonyProtoEnums.NETWORK_TYPE_LTE, + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, + NetworkRegistrationInfo.REGISTRATION_STATE_HOME, + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null); + + verifyAllDataDisconnected(); + + // Test Allow if voice is in service if RAT is 2g/3g + serviceStateChanged(TelephonyProtoEnums.NETWORK_TYPE_1XRTT, + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, + NetworkRegistrationInfo.REGISTRATION_STATE_HOME, + NetworkRegistrationInfo.REGISTRATION_STATE_NOT_REGISTERED_OR_SEARCHING, null); + + verifyConnectedNetworkHasCapabilities(NetworkCapabilities.NET_CAPABILITY_MMS); + } } |