Loading src/java/com/android/internal/telephony/data/DataConfigManager.java +3 −2 Original line number Diff line number Diff line Loading @@ -1006,7 +1006,7 @@ public class DataConfigManager extends Handler { * @return {@code true} if tearing down IMS data network should be delayed until the voice call * ends. */ public boolean isImsDelayTearDownEnabled() { public boolean isImsDelayTearDownUntilVoiceCallEndEnabled() { return mCarrierConfig.getBoolean( CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL); } Loading Loading @@ -1368,7 +1368,8 @@ public class DataConfigManager extends Handler { + shouldPersistIwlanDataNetworksWhenDataServiceRestarted()); pw.println("Bandwidth estimation source=" + mResources.getString( com.android.internal.R.string.config_bandwidthEstimateSource)); pw.println("isDelayTearDownImsEnabled=" + isImsDelayTearDownEnabled()); pw.println("isImsDelayTearDownUntilVoiceCallEndEnabled=" + isImsDelayTearDownUntilVoiceCallEndEnabled()); pw.println("isEnhancedIwlanHandoverCheckEnabled=" + isEnhancedIwlanHandoverCheckEnabled()); pw.println("isTetheringProfileDisabledForRoaming=" + isTetheringProfileDisabledForRoaming()); Loading src/java/com/android/internal/telephony/data/DataEvaluation.java +7 −1 Original line number Diff line number Diff line Loading @@ -321,7 +321,9 @@ public class DataEvaluation { /** Only one data network is allowed at one time. */ ONLY_ALLOWED_SINGLE_NETWORK(true), /** Data enabled settings are not ready. */ DATA_SETTINGS_NOT_READY(true); DATA_SETTINGS_NOT_READY(true), /** Handover max retry stopped but network is not on the preferred transport. */ HANDOVER_RETRY_STOPPED(true); private final boolean mIsHardReason; Loading Loading @@ -359,6 +361,10 @@ public class DataEvaluation { * The normal reason. This is the most common case. */ NORMAL, /** * Data is allowed because an ongoing VoPS call depends on this network */ IN_VOICE_CALL, /** * The network brought up by this network request is unmetered. Should allowed no matter * the user enables or disables data. Loading src/java/com/android/internal/telephony/data/DataNetwork.java +5 −3 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.telephony.Annotation.NetCapability; import android.telephony.Annotation.NetworkType; import android.telephony.Annotation.ValidationStatus; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.DataSpecificRegistrationInfo; import android.telephony.LinkCapacityEstimate; Loading Loading @@ -2590,11 +2591,12 @@ public class DataNetwork extends StateMachine { } /** * @return {@code true} if this is an IMS network and tear down should be delayed until call * ends on this data network. * @return {@code true} if we shall delay tear down this network because an active voice call is * relying on it and * {@link CarrierConfigManager#KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL} is enabled. */ public boolean shouldDelayImsTearDownDueToInCall() { return mDataConfigManager.isImsDelayTearDownEnabled() return mDataConfigManager.isImsDelayTearDownUntilVoiceCallEndEnabled() && mNetworkCapabilities != null && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL) && mPhone.getImsPhone() != null Loading src/java/com/android/internal/telephony/data/DataNetworkController.java +72 −32 Original line number Diff line number Diff line Loading @@ -894,24 +894,7 @@ public class DataNetworkController extends Handler { public void onDataNetworkHandoverRetryStopped( @NonNull DataNetwork dataNetwork) { Objects.requireNonNull(dataNetwork); int preferredTransport = mAccessNetworksManager .getPreferredTransportByNetworkCapability( dataNetwork.getApnTypeNetworkCapability()); if (dataNetwork.getTransport() == preferredTransport) { log("onDataNetworkHandoverRetryStopped: " + dataNetwork + " is already " + "on the preferred transport " + AccessNetworkConstants.transportTypeToString( preferredTransport)); return; } if (dataNetwork.shouldDelayImsTearDownDueToInCall()) { log("onDataNetworkHandoverRetryStopped: Delay IMS tear down until call " + "ends. " + dataNetwork); return; } tearDownGracefully(dataNetwork, DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED); DataNetworkController.this.onDataNetworkHandoverRetryStopped(dataNetwork); } }); mImsManager = mPhone.getContext().getSystemService(ImsManager.class); Loading Loading @@ -1747,15 +1730,20 @@ public class DataNetworkController extends Handler { } } boolean isMmtel = false; // If the data network is IMS that supports voice call, and has MMTEL request (client // specified VoPS is required.) if (dataNetwork.getAttachedNetworkRequestList().get( new int[]{NetworkCapabilities.NET_CAPABILITY_MMTEL}) != null) { // When reaching here, it means the network supports MMTEL, and also has MMTEL request // attached to it. isMmtel = true; if (!dataNetwork.shouldDelayImsTearDownDueToInCall()) { boolean vopsIsRequired = dataNetwork.hasNetworkCapabilityInNetworkRequests( NetworkCapabilities.NET_CAPABILITY_MMTEL); // Check an active call relying on this network and config for "delay tear down due to vops // call" is enabled. if (dataNetwork.shouldDelayImsTearDownDueToInCall()) { if (vopsIsRequired) { log("Ignored VoPS check due to delay IMS tear down until call ends."); } } else { // Reach here means we should ignore active calls even if there are any. // Check if VoPS requirement is met. if (vopsIsRequired) { if (dataNetwork.getTransport() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, Loading @@ -1770,8 +1758,15 @@ public class DataNetworkController extends Handler { } } } } else { log("Ignored VoPS check due to delay IMS tear down until call ends."); } // Check if handover retry stopped and preferred transport still not matched. int preferredTransport = mAccessNetworksManager .getPreferredTransportByNetworkCapability( dataNetwork.getApnTypeNetworkCapability()); if (preferredTransport != dataNetwork.getTransport() && mDataRetryManager.isDataNetworkHandoverRetryStopped(dataNetwork)) { evaluation.addDataDisallowedReason(DataDisallowedReason.HANDOVER_RETRY_STOPPED); } } Loading Loading @@ -1802,9 +1797,7 @@ public class DataNetworkController extends Handler { // Sometimes network temporarily OOS and network type becomes UNKNOWN. We don't // tear down network in that case. if (networkType != TelephonyManager.NETWORK_TYPE_UNKNOWN && !dataProfile.getApnSetting().canSupportLingeringNetworkType(networkType) // delay IMS tear down if SRVCC in progress && !(isMmtel && mIsSrvccHandoverInProcess)) { && !dataProfile.getApnSetting().canSupportLingeringNetworkType(networkType)) { log("networkType=" + TelephonyManager.getNetworkTypeName(networkType) + ", networkTypeBitmask=" + TelephonyManager.convertNetworkTypeBitmaskToString( Loading Loading @@ -1866,6 +1859,15 @@ public class DataNetworkController extends Handler { } } // Check if we allow additional lingering for active VoPS call network if // a. this network is SRVCC handover in progress // or b. "delay tear down due to active VoPS call" is enabled boolean isInSrvcc = vopsIsRequired && mIsSrvccHandoverInProcess; if (evaluation.containsOnly(DataDisallowedReason.DATA_NETWORK_TYPE_NOT_ALLOWED) && (dataNetwork.shouldDelayImsTearDownDueToInCall() || isInSrvcc)) { evaluation.addDataAllowedReason(DataAllowedReason.IN_VOICE_CALL); } log("Evaluated " + dataNetwork + ", " + evaluation); return evaluation; } Loading Loading @@ -2058,6 +2060,8 @@ public class DataNetworkController extends Handler { return DataNetwork.TEAR_DOWN_REASON_VOPS_NOT_SUPPORTED; case ONLY_ALLOWED_SINGLE_NETWORK: return DataNetwork.TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK; case HANDOVER_RETRY_STOPPED: return DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED; } } return DataNetwork.TEAR_DOWN_REASON_NONE; Loading Loading @@ -2767,6 +2771,32 @@ public class DataNetworkController extends Handler { tryHandoverDataNetwork(dataNetwork, preferredTransport, dataHandoverRetryEntry); } /** * Called when data network reached max handover retry count. * * @param dataNetwork The data network. */ private void onDataNetworkHandoverRetryStopped(@NonNull DataNetwork dataNetwork) { int preferredTransport = mAccessNetworksManager .getPreferredTransportByNetworkCapability( dataNetwork.getApnTypeNetworkCapability()); if (dataNetwork.getTransport() == preferredTransport) { log("onDataNetworkHandoverRetryStopped: " + dataNetwork + " is already " + "on the preferred transport " + AccessNetworkConstants.transportTypeToString( preferredTransport)); return; } if (dataNetwork.shouldDelayImsTearDownDueToInCall()) { log("onDataNetworkHandoverRetryStopped: Delay IMS tear down until call " + "ends. " + dataNetwork); return; } tearDownGracefully(dataNetwork, DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED); } /** * Called when data network validation status changed. * Loading Loading @@ -3103,6 +3133,16 @@ public class DataNetworkController extends Handler { logl("Start handover " + dataNetwork + " to " + AccessNetworkConstants.transportTypeToString(targetTransport)); dataNetwork.startHandover(targetTransport, dataHandoverRetryEntry); } else if (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE) && dataNetwork.shouldDelayImsTearDownDueToInCall()) { // We try to preserve voice call in the case of temporary preferred transport mismatch if (dataHandoverRetryEntry != null) { dataHandoverRetryEntry.setState(DataRetryEntry.RETRY_STATE_FAILED); } mDataRetryManager.evaluateDataHandoverRetry(dataNetwork, DataFailCause.HANDOVER_FAILED, DataCallResponse.RETRY_DURATION_UNDEFINED /* retry mills */); logl("tryHandoverDataNetwork: Scheduled retry due to in voice call and target OOS"); } else if (dataEvaluation.containsAny(DataDisallowedReason.NOT_ALLOWED_BY_POLICY, DataDisallowedReason.NOT_IN_SERVICE, DataDisallowedReason.VOPS_NOT_SUPPORTED)) { Loading src/java/com/android/internal/telephony/data/DataRetryManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -1298,6 +1298,24 @@ public class DataRetryManager extends Handler { } } /** * @param dataNetwork The data network to check. * @return {@code true} if the data network had failed the maximum number of attempts for * handover according to any retry rules. */ public boolean isDataNetworkHandoverRetryStopped(@NonNull DataNetwork dataNetwork) { // Matching the rule in configured order. for (DataHandoverRetryRule retryRule : mDataHandoverRetryRuleList) { int failedCount = getRetryFailedCount(dataNetwork, retryRule); if (failedCount == retryRule.getMaxRetries()) { log("Data handover retry failed for " + failedCount + " times. Stopped " + "handover retry."); return true; } } return false; } /** Cancel all retries and throttling entries. */ private void onReset(@RetryResetReason int reason) { logl("Remove all retry and throttling entries, reason=" + resetReasonToString(reason)); Loading Loading
src/java/com/android/internal/telephony/data/DataConfigManager.java +3 −2 Original line number Diff line number Diff line Loading @@ -1006,7 +1006,7 @@ public class DataConfigManager extends Handler { * @return {@code true} if tearing down IMS data network should be delayed until the voice call * ends. */ public boolean isImsDelayTearDownEnabled() { public boolean isImsDelayTearDownUntilVoiceCallEndEnabled() { return mCarrierConfig.getBoolean( CarrierConfigManager.KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL); } Loading Loading @@ -1368,7 +1368,8 @@ public class DataConfigManager extends Handler { + shouldPersistIwlanDataNetworksWhenDataServiceRestarted()); pw.println("Bandwidth estimation source=" + mResources.getString( com.android.internal.R.string.config_bandwidthEstimateSource)); pw.println("isDelayTearDownImsEnabled=" + isImsDelayTearDownEnabled()); pw.println("isImsDelayTearDownUntilVoiceCallEndEnabled=" + isImsDelayTearDownUntilVoiceCallEndEnabled()); pw.println("isEnhancedIwlanHandoverCheckEnabled=" + isEnhancedIwlanHandoverCheckEnabled()); pw.println("isTetheringProfileDisabledForRoaming=" + isTetheringProfileDisabledForRoaming()); Loading
src/java/com/android/internal/telephony/data/DataEvaluation.java +7 −1 Original line number Diff line number Diff line Loading @@ -321,7 +321,9 @@ public class DataEvaluation { /** Only one data network is allowed at one time. */ ONLY_ALLOWED_SINGLE_NETWORK(true), /** Data enabled settings are not ready. */ DATA_SETTINGS_NOT_READY(true); DATA_SETTINGS_NOT_READY(true), /** Handover max retry stopped but network is not on the preferred transport. */ HANDOVER_RETRY_STOPPED(true); private final boolean mIsHardReason; Loading Loading @@ -359,6 +361,10 @@ public class DataEvaluation { * The normal reason. This is the most common case. */ NORMAL, /** * Data is allowed because an ongoing VoPS call depends on this network */ IN_VOICE_CALL, /** * The network brought up by this network request is unmetered. Should allowed no matter * the user enables or disables data. Loading
src/java/com/android/internal/telephony/data/DataNetwork.java +5 −3 Original line number Diff line number Diff line Loading @@ -54,6 +54,7 @@ import android.telephony.Annotation.NetCapability; import android.telephony.Annotation.NetworkType; import android.telephony.Annotation.ValidationStatus; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DataFailCause; import android.telephony.DataSpecificRegistrationInfo; import android.telephony.LinkCapacityEstimate; Loading Loading @@ -2590,11 +2591,12 @@ public class DataNetwork extends StateMachine { } /** * @return {@code true} if this is an IMS network and tear down should be delayed until call * ends on this data network. * @return {@code true} if we shall delay tear down this network because an active voice call is * relying on it and * {@link CarrierConfigManager#KEY_DELAY_IMS_TEAR_DOWN_UNTIL_CALL_END_BOOL} is enabled. */ public boolean shouldDelayImsTearDownDueToInCall() { return mDataConfigManager.isImsDelayTearDownEnabled() return mDataConfigManager.isImsDelayTearDownUntilVoiceCallEndEnabled() && mNetworkCapabilities != null && mNetworkCapabilities.hasCapability(NetworkCapabilities.NET_CAPABILITY_MMTEL) && mPhone.getImsPhone() != null Loading
src/java/com/android/internal/telephony/data/DataNetworkController.java +72 −32 Original line number Diff line number Diff line Loading @@ -894,24 +894,7 @@ public class DataNetworkController extends Handler { public void onDataNetworkHandoverRetryStopped( @NonNull DataNetwork dataNetwork) { Objects.requireNonNull(dataNetwork); int preferredTransport = mAccessNetworksManager .getPreferredTransportByNetworkCapability( dataNetwork.getApnTypeNetworkCapability()); if (dataNetwork.getTransport() == preferredTransport) { log("onDataNetworkHandoverRetryStopped: " + dataNetwork + " is already " + "on the preferred transport " + AccessNetworkConstants.transportTypeToString( preferredTransport)); return; } if (dataNetwork.shouldDelayImsTearDownDueToInCall()) { log("onDataNetworkHandoverRetryStopped: Delay IMS tear down until call " + "ends. " + dataNetwork); return; } tearDownGracefully(dataNetwork, DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED); DataNetworkController.this.onDataNetworkHandoverRetryStopped(dataNetwork); } }); mImsManager = mPhone.getContext().getSystemService(ImsManager.class); Loading Loading @@ -1747,15 +1730,20 @@ public class DataNetworkController extends Handler { } } boolean isMmtel = false; // If the data network is IMS that supports voice call, and has MMTEL request (client // specified VoPS is required.) if (dataNetwork.getAttachedNetworkRequestList().get( new int[]{NetworkCapabilities.NET_CAPABILITY_MMTEL}) != null) { // When reaching here, it means the network supports MMTEL, and also has MMTEL request // attached to it. isMmtel = true; if (!dataNetwork.shouldDelayImsTearDownDueToInCall()) { boolean vopsIsRequired = dataNetwork.hasNetworkCapabilityInNetworkRequests( NetworkCapabilities.NET_CAPABILITY_MMTEL); // Check an active call relying on this network and config for "delay tear down due to vops // call" is enabled. if (dataNetwork.shouldDelayImsTearDownDueToInCall()) { if (vopsIsRequired) { log("Ignored VoPS check due to delay IMS tear down until call ends."); } } else { // Reach here means we should ignore active calls even if there are any. // Check if VoPS requirement is met. if (vopsIsRequired) { if (dataNetwork.getTransport() == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) { NetworkRegistrationInfo nri = mServiceState.getNetworkRegistrationInfo( NetworkRegistrationInfo.DOMAIN_PS, Loading @@ -1770,8 +1758,15 @@ public class DataNetworkController extends Handler { } } } } else { log("Ignored VoPS check due to delay IMS tear down until call ends."); } // Check if handover retry stopped and preferred transport still not matched. int preferredTransport = mAccessNetworksManager .getPreferredTransportByNetworkCapability( dataNetwork.getApnTypeNetworkCapability()); if (preferredTransport != dataNetwork.getTransport() && mDataRetryManager.isDataNetworkHandoverRetryStopped(dataNetwork)) { evaluation.addDataDisallowedReason(DataDisallowedReason.HANDOVER_RETRY_STOPPED); } } Loading Loading @@ -1802,9 +1797,7 @@ public class DataNetworkController extends Handler { // Sometimes network temporarily OOS and network type becomes UNKNOWN. We don't // tear down network in that case. if (networkType != TelephonyManager.NETWORK_TYPE_UNKNOWN && !dataProfile.getApnSetting().canSupportLingeringNetworkType(networkType) // delay IMS tear down if SRVCC in progress && !(isMmtel && mIsSrvccHandoverInProcess)) { && !dataProfile.getApnSetting().canSupportLingeringNetworkType(networkType)) { log("networkType=" + TelephonyManager.getNetworkTypeName(networkType) + ", networkTypeBitmask=" + TelephonyManager.convertNetworkTypeBitmaskToString( Loading Loading @@ -1866,6 +1859,15 @@ public class DataNetworkController extends Handler { } } // Check if we allow additional lingering for active VoPS call network if // a. this network is SRVCC handover in progress // or b. "delay tear down due to active VoPS call" is enabled boolean isInSrvcc = vopsIsRequired && mIsSrvccHandoverInProcess; if (evaluation.containsOnly(DataDisallowedReason.DATA_NETWORK_TYPE_NOT_ALLOWED) && (dataNetwork.shouldDelayImsTearDownDueToInCall() || isInSrvcc)) { evaluation.addDataAllowedReason(DataAllowedReason.IN_VOICE_CALL); } log("Evaluated " + dataNetwork + ", " + evaluation); return evaluation; } Loading Loading @@ -2058,6 +2060,8 @@ public class DataNetworkController extends Handler { return DataNetwork.TEAR_DOWN_REASON_VOPS_NOT_SUPPORTED; case ONLY_ALLOWED_SINGLE_NETWORK: return DataNetwork.TEAR_DOWN_REASON_ONLY_ALLOWED_SINGLE_NETWORK; case HANDOVER_RETRY_STOPPED: return DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED; } } return DataNetwork.TEAR_DOWN_REASON_NONE; Loading Loading @@ -2767,6 +2771,32 @@ public class DataNetworkController extends Handler { tryHandoverDataNetwork(dataNetwork, preferredTransport, dataHandoverRetryEntry); } /** * Called when data network reached max handover retry count. * * @param dataNetwork The data network. */ private void onDataNetworkHandoverRetryStopped(@NonNull DataNetwork dataNetwork) { int preferredTransport = mAccessNetworksManager .getPreferredTransportByNetworkCapability( dataNetwork.getApnTypeNetworkCapability()); if (dataNetwork.getTransport() == preferredTransport) { log("onDataNetworkHandoverRetryStopped: " + dataNetwork + " is already " + "on the preferred transport " + AccessNetworkConstants.transportTypeToString( preferredTransport)); return; } if (dataNetwork.shouldDelayImsTearDownDueToInCall()) { log("onDataNetworkHandoverRetryStopped: Delay IMS tear down until call " + "ends. " + dataNetwork); return; } tearDownGracefully(dataNetwork, DataNetwork.TEAR_DOWN_REASON_HANDOVER_FAILED); } /** * Called when data network validation status changed. * Loading Loading @@ -3103,6 +3133,16 @@ public class DataNetworkController extends Handler { logl("Start handover " + dataNetwork + " to " + AccessNetworkConstants.transportTypeToString(targetTransport)); dataNetwork.startHandover(targetTransport, dataHandoverRetryEntry); } else if (dataEvaluation.containsOnly(DataDisallowedReason.NOT_IN_SERVICE) && dataNetwork.shouldDelayImsTearDownDueToInCall()) { // We try to preserve voice call in the case of temporary preferred transport mismatch if (dataHandoverRetryEntry != null) { dataHandoverRetryEntry.setState(DataRetryEntry.RETRY_STATE_FAILED); } mDataRetryManager.evaluateDataHandoverRetry(dataNetwork, DataFailCause.HANDOVER_FAILED, DataCallResponse.RETRY_DURATION_UNDEFINED /* retry mills */); logl("tryHandoverDataNetwork: Scheduled retry due to in voice call and target OOS"); } else if (dataEvaluation.containsAny(DataDisallowedReason.NOT_ALLOWED_BY_POLICY, DataDisallowedReason.NOT_IN_SERVICE, DataDisallowedReason.VOPS_NOT_SUPPORTED)) { Loading
src/java/com/android/internal/telephony/data/DataRetryManager.java +18 −0 Original line number Diff line number Diff line Loading @@ -1298,6 +1298,24 @@ public class DataRetryManager extends Handler { } } /** * @param dataNetwork The data network to check. * @return {@code true} if the data network had failed the maximum number of attempts for * handover according to any retry rules. */ public boolean isDataNetworkHandoverRetryStopped(@NonNull DataNetwork dataNetwork) { // Matching the rule in configured order. for (DataHandoverRetryRule retryRule : mDataHandoverRetryRuleList) { int failedCount = getRetryFailedCount(dataNetwork, retryRule); if (failedCount == retryRule.getMaxRetries()) { log("Data handover retry failed for " + failedCount + " times. Stopped " + "handover retry."); return true; } } return false; } /** Cancel all retries and throttling entries. */ private void onReset(@RetryResetReason int reason) { logl("Remove all retry and throttling entries, reason=" + resetReasonToString(reason)); Loading