Merge "Fixed the mismatched protocol anomaly detector" into tm-qpr-dev
diff --git a/src/java/com/android/internal/telephony/NetworkTypeController.java b/src/java/com/android/internal/telephony/NetworkTypeController.java
index b1b02d6..5c9c848 100644
--- a/src/java/com/android/internal/telephony/NetworkTypeController.java
+++ b/src/java/com/android/internal/telephony/NetworkTypeController.java
@@ -157,6 +157,7 @@
     private boolean mIsTimerResetEnabledForLegacyStateRRCIdle;
     private int mLtePlusThresholdBandwidth;
     private int mNrAdvancedThresholdBandwidth;
+    private boolean mIncludeLteForNrAdvancedThresholdBandwidth;
     private int[] mAdditionalNrAdvancedBandsList;
     private String mPrimaryTimerState;
     private String mSecondaryTimerState;
@@ -267,6 +268,9 @@
                 CarrierConfigManager.KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT);
         mNrAdvancedThresholdBandwidth = CarrierConfigManager.getDefaultConfig().getInt(
                 CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT);
+        mIncludeLteForNrAdvancedThresholdBandwidth = CarrierConfigManager.getDefaultConfig()
+                .getBoolean(CarrierConfigManager
+                        .KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL);
         mEnableNrAdvancedWhileRoaming = CarrierConfigManager.getDefaultConfig().getBoolean(
                 CarrierConfigManager.KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL);
 
@@ -302,6 +306,9 @@
                 mNrAdvancedThresholdBandwidth = b.getInt(
                         CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT,
                         mNrAdvancedThresholdBandwidth);
+                mIncludeLteForNrAdvancedThresholdBandwidth = b.getBoolean(CarrierConfigManager
+                        .KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL,
+                        mIncludeLteForNrAdvancedThresholdBandwidth);
                 mAdditionalNrAdvancedBandsList = b.getIntArray(
                         CarrierConfigManager.KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY);
                 mNrAdvancedCapablePcoId = b.getInt(
@@ -1261,11 +1268,19 @@
             return false;
         }
 
+        int bandwidths = 0;
+        if (mPhone.getServiceStateTracker().getPhysicalChannelConfigList() != null) {
+            bandwidths = mPhone.getServiceStateTracker().getPhysicalChannelConfigList()
+                    .stream()
+                    .filter(config -> mIncludeLteForNrAdvancedThresholdBandwidth
+                            || config.getNetworkType() == TelephonyManager.NETWORK_TYPE_NR)
+                    .map(PhysicalChannelConfig::getCellBandwidthDownlinkKhz)
+                    .mapToInt(Integer::intValue)
+                    .sum();
+        }
         // Check if meeting minimum bandwidth requirement. For most carriers, there is no minimum
         // bandwidth requirement and mNrAdvancedThresholdBandwidth is 0.
-        if (mNrAdvancedThresholdBandwidth > 0
-                && IntStream.of(mPhone.getServiceState().getCellBandwidths()).sum()
-                < mNrAdvancedThresholdBandwidth) {
+        if (mNrAdvancedThresholdBandwidth > 0 && bandwidths < mNrAdvancedThresholdBandwidth) {
             return false;
         }
 
diff --git a/src/java/com/android/internal/telephony/SubscriptionController.java b/src/java/com/android/internal/telephony/SubscriptionController.java
index ab61f72..82799be 100644
--- a/src/java/com/android/internal/telephony/SubscriptionController.java
+++ b/src/java/com/android/internal/telephony/SubscriptionController.java
@@ -2855,15 +2855,9 @@
                         subId);
 
         TelecomManager telecomManager = mContext.getSystemService(TelecomManager.class);
-        PhoneAccountHandle currentHandle = telecomManager.getUserSelectedOutgoingPhoneAccount();
-        logd("[setDefaultVoiceSubId] current phoneAccountHandle=" + currentHandle);
 
-        if (!Objects.equals(currentHandle, newHandle)) {
-            telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
-            logd("[setDefaultVoiceSubId] change to phoneAccountHandle=" + newHandle);
-        } else {
-            logd("[setDefaultVoiceSubId] default phoneAccountHandle not changed.");
-        }
+        telecomManager.setUserSelectedOutgoingPhoneAccount(newHandle);
+        logd("[setDefaultVoiceSubId] requesting change to phoneAccountHandle=" + newHandle);
 
         if (previousDefaultSub != getDefaultSubId()) {
             sendDefaultChangedBroadcast(getDefaultSubId());
diff --git a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
index 3ab229a..60f9a62 100644
--- a/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
+++ b/src/java/com/android/internal/telephony/SubscriptionInfoUpdater.java
@@ -1194,7 +1194,8 @@
             loge("Cannot manage subId=" + currentSubId + ", carrierPackage=" + configPackageName);
         } else {
             boolean isOpportunistic = config.getBoolean(
-                    CarrierConfigManager.KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, false);
+                    CarrierConfigManager.KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL,
+                    currentSubInfo.isOpportunistic());
             if (currentSubInfo.isOpportunistic() != isOpportunistic) {
                 if (DBG) logd("Set SubId=" + currentSubId + " isOpportunistic=" + isOpportunistic);
                 cv.put(SubscriptionManager.IS_OPPORTUNISTIC, isOpportunistic ? "1" : "0");
diff --git a/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java b/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java
index 1934136..0b10651 100644
--- a/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java
+++ b/src/java/com/android/internal/telephony/VisualVoicemailSmsFilter.java
@@ -305,7 +305,8 @@
              * received message. However, the message is most likely encoded with UTF-8. Therefore,
              * we need to retry decoding the received message with UTF-8.
              */
-            if ((body == null || message.getReceivedEncodingType() == ENCODING_8BIT)
+            if ((body == null || (message.is3gpp()
+                    && message.getReceivedEncodingType() == ENCODING_8BIT))
                     && message.getUserData() != null) {
                 Log.d(TAG, "getFullMessage decode using UTF-8");
                 // Attempt to interpret the user data as UTF-8. UTF-8 string over data SMS using
diff --git a/src/java/com/android/internal/telephony/data/DataNetworkController.java b/src/java/com/android/internal/telephony/data/DataNetworkController.java
index bf3bab1..d004293 100644
--- a/src/java/com/android/internal/telephony/data/DataNetworkController.java
+++ b/src/java/com/android/internal/telephony/data/DataNetworkController.java
@@ -2293,8 +2293,7 @@
                 + "carrier specific. mSimState="
                 + SubscriptionInfoUpdater.simStateString(mSimState));
         updateNetworkRequestsPriority();
-        sendMessage(obtainMessage(EVENT_REEVALUATE_UNSATISFIED_NETWORK_REQUESTS,
-                DataEvaluationReason.DATA_CONFIG_CHANGED));
+        onReevaluateUnsatisfiedNetworkRequests(DataEvaluationReason.DATA_CONFIG_CHANGED);
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/data/DataSettingsManager.java b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
index c593f88..24fee82 100644
--- a/src/java/com/android/internal/telephony/data/DataSettingsManager.java
+++ b/src/java/com/android/internal/telephony/data/DataSettingsManager.java
@@ -544,42 +544,37 @@
      * has not manually set the value. The default value is {@link #isDefaultDataRoamingEnabled()}.
      */
     public void setDefaultDataRoamingEnabled() {
-        // For SSSS, this is a per-phone property from DATA_ROAMING_IS_USER_SETTING_KEY.
-        // For DSDS, this is a per-sub property from Settings.Global.DATA_ROAMING + subId.
         // If the user has not manually set the value, use the default value.
-        boolean useCarrierSpecificDefault = false;
-        if (mPhone.getContext().getSystemService(TelephonyManager.class).getSimCount() != 1) {
-            String setting = Settings.Global.DATA_ROAMING + mPhone.getSubId();
-            try {
-                Settings.Global.getInt(mResolver, setting);
-            } catch (Settings.SettingNotFoundException ex) {
-                // For multi-SIM phones, use the default value if uninitialized.
-                useCarrierSpecificDefault = true;
-            }
-        } else if (!isDataRoamingFromUserAction()) {
-            // For single-SIM phones, use the default value if user action is not set.
-            useCarrierSpecificDefault = true;
-        }
-        log("setDefaultDataRoamingEnabled: useCarrierSpecificDefault=" + useCarrierSpecificDefault);
-        if (useCarrierSpecificDefault) {
-            boolean defaultVal = isDefaultDataRoamingEnabled();
-            setDataRoamingEnabledInternal(defaultVal);
+        if (!isDataRoamingFromUserAction()) {
+            setDataRoamingEnabledInternal(isDefaultDataRoamingEnabled());
         }
     }
 
     /**
-     * Get whether the user has manually enabled or disabled data roaming from settings.
-     * @return {@code true} if the user has enabled data roaming and {@code false} if they have not.
+     * Get whether the user has manually enabled or disabled data roaming from settings for the
+     * current subscription.
+     * @return {@code true} if the user has manually enabled data roaming for the current
+     *         subscription and {@code false} if they have not.
      */
     private boolean isDataRoamingFromUserAction() {
-        final SharedPreferences sp = PreferenceManager
-                .getDefaultSharedPreferences(mPhone.getContext());
-        // Since we don't want to unset user preferences after a system update, default to true if
-        // the preference does not exist and set it to false explicitly from factory reset.
-        if (!sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) {
-            sp.edit().putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, false).commit();
+        String key = Phone.DATA_ROAMING_IS_USER_SETTING_KEY + mPhone.getSubId();
+        final SharedPreferences sp =
+                PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
+
+        // Set the default roaming from user action value if the preference doesn't exist
+        if (!sp.contains(key)) {
+            if (sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) {
+                log("Reusing previous roaming from user action value for backwards compatibility.");
+                sp.edit().putBoolean(key, true).commit();
+            } else {
+                log("Clearing roaming from user action value for new or upgrading devices.");
+                sp.edit().putBoolean(key, false).commit();
+            }
         }
-        return sp.getBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true);
+
+        boolean isUserSetting = sp.getBoolean(key, true);
+        log("isDataRoamingFromUserAction: key=" + key + ", isUserSetting=" + isUserSetting);
+        return isUserSetting;
     }
 
     /**
@@ -588,9 +583,11 @@
      * {@link #isDefaultDataRoamingEnabled()} will continue to be used.
      */
     private void setDataRoamingFromUserAction() {
-        final SharedPreferences.Editor sp = PreferenceManager
-                .getDefaultSharedPreferences(mPhone.getContext()).edit();
-        sp.putBoolean(Phone.DATA_ROAMING_IS_USER_SETTING_KEY, true).commit();
+        String key = Phone.DATA_ROAMING_IS_USER_SETTING_KEY + mPhone.getSubId();
+        log("setDataRoamingFromUserAction: key=" + key);
+        final SharedPreferences.Editor sp =
+                PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()).edit();
+        sp.putBoolean(key, true).commit();
     }
 
     private @NonNull DataEnabledOverride getDataEnabledOverride() {
diff --git a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
index dec2468..8e5fb00 100644
--- a/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
+++ b/src/java/com/android/internal/telephony/gsm/GsmMmiCode.java
@@ -1333,8 +1333,8 @@
         }
     }
     //***** Private instance methods
-
-    private CharSequence getErrorMessage(AsyncResult ar) {
+    @VisibleForTesting
+    public CharSequence getErrorMessage(AsyncResult ar) {
 
         if (ar.exception instanceof CommandException) {
             CommandException.Error err = ((CommandException)(ar.exception)).getCommandError();
@@ -1362,6 +1362,13 @@
             } else if (err == CommandException.Error.OEM_ERROR_1) {
                 Rlog.i(LOG_TAG, "OEM_ERROR_1 USSD_MODIFIED_TO_DIAL_VIDEO");
                 return mContext.getText(com.android.internal.R.string.stk_cc_ussd_to_dial_video);
+            } else if (err == CommandException.Error.REQUEST_NOT_SUPPORTED
+                || err == CommandException.Error.OPERATION_NOT_ALLOWED) {
+                Rlog.i(LOG_TAG, "REQUEST_NOT_SUPPORTED/OPERATION_NOT_ALLOWED");
+                // getResources().getText() is the same as getText(), however getText() is final and
+                // cannot be mocked in tests.
+                return mContext.getResources().getText(
+                        com.android.internal.R.string.mmiErrorNotSupported);
             }
         }
 
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index dc41bb4..5968ba6 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -2827,6 +2827,12 @@
             conn.getCall().detach(conn);
             removeConnection(conn);
 
+            // If the call being disconnected was the pending MO call we should clear it.
+            if (mPendingMO == conn) {
+                mPendingMO.finalize();
+                mPendingMO = null;
+            }
+
             // remove conference participants from the cached list when call is disconnected
             List<ConferenceParticipant> cpList = imsCall.getConferenceParticipants();
             if (cpList != null) {
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 359079d..27a8697 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -1330,7 +1330,8 @@
                 mContext.getText(com.android.internal.R.string.mmiError);
     }
 
-    private CharSequence getMmiErrorMessage(AsyncResult ar) {
+    @VisibleForTesting
+    public CharSequence getMmiErrorMessage(AsyncResult ar) {
         if (ar.exception instanceof ImsException) {
             switch (((ImsException) ar.exception).getCode()) {
                 case ImsReasonInfo.CODE_FDN_BLOCKED:
@@ -1360,6 +1361,12 @@
                 return mContext.getText(com.android.internal.R.string.stk_cc_ss_to_dial_video);
             } else if (err.getCommandError() == CommandException.Error.INTERNAL_ERR) {
                 return mContext.getText(com.android.internal.R.string.mmiError);
+            } else if (err.getCommandError() == CommandException.Error.REQUEST_NOT_SUPPORTED
+                    || err.getCommandError() == CommandException.Error.OPERATION_NOT_ALLOWED) {
+                // getResources().getText() is the same as getText(), however getText() is final and
+                // cannot be mocked in tests.
+                return mContext.getResources().getText(
+                        com.android.internal.R.string.mmiErrorNotSupported);
             }
         }
         return null;
diff --git a/src/java/com/android/internal/telephony/metrics/ImsStats.java b/src/java/com/android/internal/telephony/metrics/ImsStats.java
index d93210c..427595f 100644
--- a/src/java/com/android/internal/telephony/metrics/ImsStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ImsStats.java
@@ -369,7 +369,6 @@
      * TelephonyManager#NETWORK_TYPE_UNKNOWN} if there isn't any.
      */
     @NetworkType
-    @VisibleForTesting
     public synchronized int getImsVoiceRadioTech() {
         if (mLastRegistrationStats == null
                 || !mLastAvailableFeatures.isCapable(CAPABILITY_TYPE_VOICE)) {
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index 6882899..a44cf19 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -49,7 +49,6 @@
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_RAT_USAGE;
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION;
 
-import android.annotation.Nullable;
 import android.app.StatsManager;
 import android.content.Context;
 import android.util.StatsEvent;
@@ -124,11 +123,6 @@
     private static final long DURATION_BUCKET_MILLIS =
             DBG ? 2L * SECOND_IN_MILLIS : 5L * MINUTE_IN_MILLIS;
 
-    private static final StatsManager.PullAtomMetadata POLICY_PULL_DAILY =
-            new StatsManager.PullAtomMetadata.Builder()
-                    .setCoolDownMillis(MIN_COOLDOWN_MILLIS)
-                    .build();
-
     private final PersistAtomsStorage mStorage;
     private final StatsManager mStatsManager;
     private final AirplaneModeStats mAirplaneModeStats;
@@ -146,35 +140,34 @@
         mStorage = storage;
         mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
         if (mStatsManager != null) {
-            registerAtom(CELLULAR_DATA_SERVICE_SWITCH, POLICY_PULL_DAILY);
-            registerAtom(CELLULAR_SERVICE_STATE, POLICY_PULL_DAILY);
-            registerAtom(SIM_SLOT_STATE, null);
-            registerAtom(SUPPORTED_RADIO_ACCESS_FAMILY, null);
-            registerAtom(VOICE_CALL_RAT_USAGE, POLICY_PULL_DAILY);
-            registerAtom(VOICE_CALL_SESSION, POLICY_PULL_DAILY);
-            registerAtom(INCOMING_SMS, POLICY_PULL_DAILY);
-            registerAtom(OUTGOING_SMS, POLICY_PULL_DAILY);
-            registerAtom(CARRIER_ID_TABLE_VERSION, null);
-            registerAtom(DATA_CALL_SESSION, POLICY_PULL_DAILY);
-            registerAtom(IMS_REGISTRATION_STATS, POLICY_PULL_DAILY);
-            registerAtom(IMS_REGISTRATION_TERMINATION, POLICY_PULL_DAILY);
-            registerAtom(TELEPHONY_NETWORK_REQUESTS_V2, POLICY_PULL_DAILY);
-            registerAtom(IMS_REGISTRATION_FEATURE_TAG_STATS, POLICY_PULL_DAILY);
-            registerAtom(RCS_CLIENT_PROVISIONING_STATS, POLICY_PULL_DAILY);
-            registerAtom(RCS_ACS_PROVISIONING_STATS, POLICY_PULL_DAILY);
-            registerAtom(SIP_DELEGATE_STATS, POLICY_PULL_DAILY);
-            registerAtom(SIP_TRANSPORT_FEATURE_TAG_STATS, POLICY_PULL_DAILY);
-            registerAtom(SIP_MESSAGE_RESPONSE, POLICY_PULL_DAILY);
-            registerAtom(SIP_TRANSPORT_SESSION, POLICY_PULL_DAILY);
-            registerAtom(DEVICE_TELEPHONY_PROPERTIES, null);
-            registerAtom(IMS_DEDICATED_BEARER_LISTENER_EVENT, POLICY_PULL_DAILY);
-            registerAtom(IMS_DEDICATED_BEARER_EVENT, POLICY_PULL_DAILY);
-            registerAtom(IMS_REGISTRATION_SERVICE_DESC_STATS, POLICY_PULL_DAILY);
-            registerAtom(UCE_EVENT_STATS, POLICY_PULL_DAILY);
-            registerAtom(PRESENCE_NOTIFY_EVENT, POLICY_PULL_DAILY);
-            registerAtom(GBA_EVENT, POLICY_PULL_DAILY);
-            registerAtom(PER_SIM_STATUS, null);
-
+            registerAtom(CELLULAR_DATA_SERVICE_SWITCH);
+            registerAtom(CELLULAR_SERVICE_STATE);
+            registerAtom(SIM_SLOT_STATE);
+            registerAtom(SUPPORTED_RADIO_ACCESS_FAMILY);
+            registerAtom(VOICE_CALL_RAT_USAGE);
+            registerAtom(VOICE_CALL_SESSION);
+            registerAtom(INCOMING_SMS);
+            registerAtom(OUTGOING_SMS);
+            registerAtom(CARRIER_ID_TABLE_VERSION);
+            registerAtom(DATA_CALL_SESSION);
+            registerAtom(IMS_REGISTRATION_STATS);
+            registerAtom(IMS_REGISTRATION_TERMINATION);
+            registerAtom(TELEPHONY_NETWORK_REQUESTS_V2);
+            registerAtom(IMS_REGISTRATION_FEATURE_TAG_STATS);
+            registerAtom(RCS_CLIENT_PROVISIONING_STATS);
+            registerAtom(RCS_ACS_PROVISIONING_STATS);
+            registerAtom(SIP_DELEGATE_STATS);
+            registerAtom(SIP_TRANSPORT_FEATURE_TAG_STATS);
+            registerAtom(SIP_MESSAGE_RESPONSE);
+            registerAtom(SIP_TRANSPORT_SESSION);
+            registerAtom(DEVICE_TELEPHONY_PROPERTIES);
+            registerAtom(IMS_DEDICATED_BEARER_LISTENER_EVENT);
+            registerAtom(IMS_DEDICATED_BEARER_EVENT);
+            registerAtom(IMS_REGISTRATION_SERVICE_DESC_STATS);
+            registerAtom(UCE_EVENT_STATS);
+            registerAtom(PRESENCE_NOTIFY_EVENT);
+            registerAtom(GBA_EVENT);
+            registerAtom(PER_SIM_STATUS);
             Rlog.d(TAG, "registered");
         } else {
             Rlog.e(TAG, "could not get StatsManager, atoms not registered");
@@ -691,9 +684,10 @@
         return result;
     }
 
-    /** Registers a pulled atom ID {@code atomId} with optional {@code policy} for pulling. */
-    private void registerAtom(int atomId, @Nullable StatsManager.PullAtomMetadata policy) {
-        mStatsManager.setPullAtomCallback(atomId, policy, ConcurrentUtils.DIRECT_EXECUTOR, this);
+    /** Registers a pulled atom ID {@code atomId}. */
+    private void registerAtom(int atomId) {
+        mStatsManager.setPullAtomCallback(atomId, /* metadata= */ null,
+                ConcurrentUtils.DIRECT_EXECUTOR, this);
     }
 
     private static StatsEvent buildStatsEvent(CellularDataServiceSwitch serviceSwitch) {
diff --git a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
index 42dc55d..9d9088e 100644
--- a/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
+++ b/src/java/com/android/internal/telephony/metrics/ServiceStateStats.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.telephony.metrics;
 
-import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
-
 import android.annotation.Nullable;
 import android.os.SystemClock;
 import android.telephony.AccessNetworkConstants;
@@ -27,6 +25,10 @@
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
 
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN;
+
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.PhoneFactory;
@@ -193,6 +195,9 @@
             case TelephonyManager.NETWORK_TYPE_LTE_CA:
                 band = AccessNetworkUtils.getOperatingBandForEarfcn(chNumber);
                 break;
+            case TelephonyManager.NETWORK_TYPE_NR:
+                band = AccessNetworkUtils.getOperatingBandForNrarfcn(chNumber);
+                break;
             default:
                 Rlog.w(TAG, "getBand: unknown WWAN RAT " + rat);
                 band = 0;
@@ -241,22 +246,7 @@
      * despite that the device may have emergency service over a certain RAT.
      */
     static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state) {
-        if (state == null) {
-            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
-        }
-        ImsPhone imsPhone = (ImsPhone) phone.getImsPhone();
-        if (imsPhone != null) {
-            @NetworkType int imsVoiceRat = imsPhone.getImsStats().getImsVoiceRadioTech();
-            if (imsVoiceRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
-                // If IMS is over WWAN but WWAN PS is not in-service, then IMS RAT is invalid
-                boolean isImsVoiceRatValid =
-                        (imsVoiceRat == TelephonyManager.NETWORK_TYPE_IWLAN
-                                || getRat(state, NetworkRegistrationInfo.DOMAIN_PS)
-                                        != TelephonyManager.NETWORK_TYPE_UNKNOWN);
-                return isImsVoiceRatValid ? imsVoiceRat : TelephonyManager.NETWORK_TYPE_UNKNOWN;
-            }
-        }
-        return getRat(state, NetworkRegistrationInfo.DOMAIN_CS);
+        return getVoiceRat(phone, state, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN);
     }
 
     /**
@@ -265,6 +255,7 @@
      * <p>If the device is not in service, {@code TelephonyManager.NETWORK_TYPE_UNKNOWN} is returned
      * despite that the device may have emergency service over a certain RAT.
      */
+    @VisibleForTesting public
     static @NetworkType int getVoiceRat(Phone phone, @Nullable ServiceState state, int bearer) {
         if (state == null) {
             return TelephonyManager.NETWORK_TYPE_UNKNOWN;
@@ -273,15 +264,22 @@
         if (bearer != VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS && imsPhone != null) {
             @NetworkType int imsVoiceRat = imsPhone.getImsStats().getImsVoiceRadioTech();
             if (imsVoiceRat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
-                // If IMS is over WWAN but WWAN PS is not in-service, then IMS RAT is invalid
+                // If IMS is registered over WWAN but WWAN PS is not in service,
+                // fallback to WWAN CS RAT
                 boolean isImsVoiceRatValid =
                         (imsVoiceRat == TelephonyManager.NETWORK_TYPE_IWLAN
                                 || getRat(state, NetworkRegistrationInfo.DOMAIN_PS)
                                         != TelephonyManager.NETWORK_TYPE_UNKNOWN);
-                return isImsVoiceRatValid ? imsVoiceRat : TelephonyManager.NETWORK_TYPE_UNKNOWN;
+                if (isImsVoiceRatValid) {
+                    return imsVoiceRat;
+                }
             }
         }
-        return getRat(state, NetworkRegistrationInfo.DOMAIN_CS);
+        if (bearer == VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS) {
+            return TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        } else {
+            return getRat(state, NetworkRegistrationInfo.DOMAIN_CS);
+        }
     }
 
     /** Returns RAT used by WWAN if WWAN is in service. */
@@ -304,8 +302,7 @@
     }
 
     private static boolean isEndc(ServiceState state) {
-        if (getRat(state, NetworkRegistrationInfo.DOMAIN_PS)
-                != TelephonyManager.NETWORK_TYPE_LTE) {
+        if (getRat(state, NetworkRegistrationInfo.DOMAIN_PS) != TelephonyManager.NETWORK_TYPE_LTE) {
             return false;
         }
         int nrState = state.getNrState();
diff --git a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
index 4c6bff9..d700831 100644
--- a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
@@ -465,8 +465,14 @@
         proto.isRoaming = serviceState != null ? serviceState.getVoiceRoaming() : false;
         proto.isMultiparty = conn.isMultiparty();
         proto.lastKnownRat = rat;
+
         // internal fields for tracking
-        proto.setupBeginMillis = getTimeMillis();
+        if (getDirection(conn) == VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MT) {
+            // MT call setup hasn't begun hence set to 0
+            proto.setupBeginMillis = 0L;
+        } else {
+            proto.setupBeginMillis = getTimeMillis();
+        }
 
         // audio codec might have already been set
         int codec = audioQualityToCodec(bearer, conn.getAudioCodec());
@@ -492,6 +498,12 @@
             loge("finishCall: could not find call to be removed, connectionId=%d", connectionId);
             return;
         }
+
+        // Compute time it took to fail setup (except for MT calls that have never been picked up)
+        if (proto.setupFailed && proto.setupBeginMillis != 0L && proto.setupDurationMillis == 0) {
+            proto.setupDurationMillis = (int) (getTimeMillis() - proto.setupBeginMillis);
+        }
+
         mCallProtos.delete(connectionId);
         proto.concurrentCallCountAtEnd = mCallProtos.size();
 
@@ -514,6 +526,17 @@
             proto.carrierId = mPhone.getCarrierId();
         }
 
+        // Update end RAT
+        @NetworkType
+        int rat = ServiceStateStats.getVoiceRat(mPhone, getServiceState(), proto.bearerAtEnd);
+        if (proto.ratAtEnd != rat) {
+            proto.ratSwitchCount++;
+            proto.ratAtEnd = rat;
+            if (rat != TelephonyManager.NETWORK_TYPE_UNKNOWN) {
+                proto.lastKnownRat = rat;
+            }
+        }
+
         mAtomsStorage.addVoiceCallSession(proto);
 
         // merge RAT usages to PersistPullers when the call session ends (i.e. no more active calls)
diff --git a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
index 0230645..359010e 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/NetworkTypeControllerTest.java
@@ -1323,7 +1323,12 @@
         doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
         doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
         doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
-        doReturn(new int[] {20001}).when(mServiceState).getCellBandwidths();
+        List<PhysicalChannelConfig> lastPhysicalChannelConfigList = new ArrayList<>();
+        lastPhysicalChannelConfigList.add(new PhysicalChannelConfig.Builder()
+                .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+                .setCellBandwidthDownlinkKhz(20001)
+                .build());
+        doReturn(lastPhysicalChannelConfigList).when(mSST).getPhysicalChannelConfigList();
         mBundle.putInt(CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
         broadcastCarrierConfigs();
 
@@ -1333,6 +1338,34 @@
     }
 
     @Test
+    public void testTransitionToCurrentStateNrConnectedWithHighBandwidthIncludingLte()
+            throws Exception {
+        assertEquals("DefaultState", getCurrentState().getName());
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
+        doReturn(NetworkRegistrationInfo.NR_STATE_CONNECTED).when(mServiceState).getNrState();
+        doReturn(ServiceState.FREQUENCY_RANGE_MMWAVE).when(mServiceState).getNrFrequencyRange();
+        List<PhysicalChannelConfig> lastPhysicalChannelConfigList = new ArrayList<>();
+        lastPhysicalChannelConfigList.add(new PhysicalChannelConfig.Builder()
+                .setNetworkType(TelephonyManager.NETWORK_TYPE_NR)
+                .setCellBandwidthDownlinkKhz(20000)
+                .build());
+        lastPhysicalChannelConfigList.add(new PhysicalChannelConfig.Builder()
+                .setNetworkType(TelephonyManager.NETWORK_TYPE_LTE)
+                .setCellBandwidthDownlinkKhz(10000)
+                .build());
+        doReturn(lastPhysicalChannelConfigList).when(mSST).getPhysicalChannelConfigList();
+        mBundle.putInt(CarrierConfigManager.KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
+        mBundle.putBoolean(
+                CarrierConfigManager.KEY_INCLUDE_LTE_FOR_NR_ADVANCED_THRESHOLD_BANDWIDTH_BOOL,
+                true);
+        broadcastCarrierConfigs();
+
+        mNetworkTypeController.sendMessage(NetworkTypeController.EVENT_UPDATE);
+        processAllMessages();
+        assertEquals("connected_mmwave", getCurrentState().getName());
+    }
+
+    @Test
     public void testNrAdvancedDisabledWhileRoaming() throws Exception {
         assertEquals("DefaultState", getCurrentState().getName());
         doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mServiceState).getDataNetworkType();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
index ea38e2d..c669810 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SubscriptionInfoUpdaterTest.java
@@ -794,6 +794,38 @@
 
     @Test
     @SmallTest
+    public void testOpportunisticSubscriptionNotUnsetWithEmptyConfigKey() throws Exception {
+        final int phoneId = mPhone.getPhoneId();
+        PersistableBundle carrierConfig = new PersistableBundle();
+
+        String carrierPackageName = "FakeCarrierPackageName";
+
+        doReturn(FAKE_SUB_ID_1).when(mSubscriptionController).getSubIdUsingPhoneId(phoneId);
+        doReturn(mSubInfo).when(mSubscriptionController).getSubscriptionInfo(eq(FAKE_SUB_ID_1));
+        doReturn(true).when(mSubInfo).isOpportunistic();
+        doReturn(carrierPackageName).when(mTelephonyManager)
+                .getCarrierServicePackageNameForLogicalSlot(eq(phoneId));
+        ((MockContentResolver) mContext.getContentResolver()).addProvider(
+                SubscriptionManager.CONTENT_URI.getAuthority(),
+                new FakeSubscriptionContentProvider());
+
+        mUpdater.updateSubscriptionByCarrierConfig(mPhone.getPhoneId(),
+                carrierPackageName, carrierConfig);
+
+        ArgumentCaptor<ContentValues> cvCaptor = ArgumentCaptor.forClass(ContentValues.class);
+        verify(mContentProvider, times(1)).update(
+                eq(SubscriptionManager.getUriForSubscriptionId(FAKE_SUB_ID_1)),
+                cvCaptor.capture(), eq(null), eq(null));
+        // no key is added for the opportunistic bit
+        assertNull(cvCaptor.getValue().getAsInteger(SubscriptionManager.IS_OPPORTUNISTIC));
+        // only carrier certs updated
+        assertEquals(1, cvCaptor.getValue().size());
+        verify(mSubscriptionController, times(1)).refreshCachedActiveSubscriptionInfoList();
+        verify(mSubscriptionController, times(1)).notifySubscriptionInfoChanged();
+    }
+
+    @Test
+    @SmallTest
     public void testUpdateFromCarrierConfigOpportunisticAddToGroup() throws Exception {
         final int phoneId = mPhone.getPhoneId();
         PersistableBundle carrierConfig = getCarrierConfigForSubInfoUpdate(
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
new file mode 100644
index 0000000..db543e5
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataSettingsManagerTest.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.data;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+
+import android.os.Looper;
+import android.os.PersistableBundle;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper;
+
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.data.DataSettingsManager.DataSettingsManagerCallback;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+@RunWith(AndroidTestingRunner.class)
+@TestableLooper.RunWithLooper
+public class DataSettingsManagerTest extends TelephonyTest {
+    private static final String DATA_ROAMING_IS_USER_SETTING = "data_roaming_is_user_setting_key0";
+
+    // Mocked
+    DataSettingsManagerCallback mMockedDataSettingsManagerCallback;
+
+    DataSettingsManager mDataSettingsManagerUT;
+    PersistableBundle mBundle;
+
+    @Before
+    public void setUp() throws Exception {
+        logd("DataSettingsManagerTest +Setup!");
+        super.setUp(getClass().getSimpleName());
+        mMockedDataSettingsManagerCallback = Mockito.mock(DataSettingsManagerCallback.class);
+        mBundle = mContextFixture.getCarrierConfigBundle();
+        doReturn(true).when(mDataConfigManager).isConfigCarrierSpecific();
+
+        doReturn("").when(mSubscriptionController).getDataEnabledOverrideRules(anyInt());
+
+        mDataSettingsManagerUT = new DataSettingsManager(mPhone, mDataNetworkController,
+                Looper.myLooper(), mMockedDataSettingsManagerCallback);
+        logd("DataSettingsManagerTest -Setup!");
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        logd("tearDown");
+        super.tearDown();
+    }
+
+    @Test
+    public void testDefaultDataRoamingEnabled() {
+        doReturn(true).when(mDataConfigManager).isDataRoamingEnabledByDefault();
+        mDataSettingsManagerUT.setDefaultDataRoamingEnabled();
+        assertTrue(mDataSettingsManagerUT.isDataRoamingEnabled());
+
+        mDataSettingsManagerUT.setDataRoamingEnabled(false);
+        processAllMessages();
+        assertFalse(mDataSettingsManagerUT.isDataRoamingEnabled());
+
+        mDataSettingsManagerUT.setDefaultDataRoamingEnabled();
+        assertFalse(mDataSettingsManagerUT.isDataRoamingEnabled());
+    }
+
+    @Test
+    public void testDefaultDataRoamingEnabledFromUpgrade() {
+        doReturn(true).when(mDataConfigManager).isDataRoamingEnabledByDefault();
+        mContext.getSharedPreferences("", 0).edit()
+                .putBoolean(DATA_ROAMING_IS_USER_SETTING, true).commit();
+        mDataSettingsManagerUT.setDefaultDataRoamingEnabled();
+        assertFalse(mDataSettingsManagerUT.isDataRoamingEnabled());
+    }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
index 8c1caa5..aaee7b9 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/GsmMmiCodeTest.java
@@ -18,15 +18,21 @@
 
 import static junit.framework.Assert.fail;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.eq;
+import static org.mockito.Mockito.verify;
 
+import android.os.AsyncResult;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.GsmCdmaPhone;
 import com.android.internal.telephony.PhoneConstants;
 import com.android.internal.telephony.TelephonyTest;
@@ -102,6 +108,20 @@
         }
     }
 
+    @Test
+    public void testOperationNotSupported() {
+        // Contrived; this is just to get a simple instance of the class.
+        mGsmMmiCode = GsmMmiCode.newNetworkInitiatedUssd(null, true, mGsmCdmaPhoneUT, null);
+
+        assertThat(mGsmMmiCode).isNotNull();
+        // Emulate request not supported from the network.
+        AsyncResult ar = new AsyncResult(null, null,
+                new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED));
+        mGsmMmiCode.getErrorMessage(ar);
+        verify(mContext.getResources()).getText(
+                eq(com.android.internal.R.string.mmiErrorNotSupported));
+    }
+
     private void setCarrierSupportsCallerIdVerticalServiceCodesCarrierConfig() {
         final PersistableBundle bundle = new PersistableBundle();
         bundle.putBoolean(CarrierConfigManager
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
index ec2209d..c0b9923 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneCallTrackerTest.java
@@ -1899,6 +1899,30 @@
         }
     }
 
+    /**
+     * Tests the case where a dialed call has not yet moved beyond the "pending MO" phase, but the
+     * user then disconnects.  In such a case we need to ensure that the pending MO reference is
+     * cleared so that another call can be placed.
+     */
+    @Test
+    @SmallTest
+    public void testCallDisconnectBeforeActive() {
+        ImsPhoneConnection connection = placeCall();
+        assertEquals(1, mCTUT.getConnections().size());
+        // Call is the pending MO right now.
+        assertEquals(connection, mCTUT.getPendingMO());
+        assertEquals(Call.State.DIALING, mCTUT.mForegroundCall.getState());
+        assertEquals(PhoneConstants.State.OFFHOOK, mCTUT.getState());
+
+        mImsCallListener.onCallTerminated(connection.getImsCall(),
+                new ImsReasonInfo(ImsReasonInfo.CODE_USER_TERMINATED_BY_REMOTE, 0));
+        // Make sure pending MO got nulled out.
+        assertNull(mCTUT.getPendingMO());
+
+        // Try making another call; it should not fail.
+        ImsPhoneConnection connection2 = placeCall();
+    }
+
     private void sendCarrierConfigChanged() {
         Intent intent = new Intent(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED);
         intent.putExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, mPhone.getSubId());
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
index 23b6bb9..3cbf8bd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
@@ -20,15 +20,19 @@
 
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
 
+import android.os.AsyncResult;
 import android.os.PersistableBundle;
 import android.telephony.CarrierConfigManager;
 import android.telephony.ServiceState;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 
+import com.android.internal.telephony.CommandException;
 import com.android.internal.telephony.TelephonyTest;
 
 import org.junit.After;
@@ -117,4 +121,19 @@
                 .KEY_CARRIER_SUPPORTS_CALLER_ID_VERTICAL_SERVICE_CODES_BOOL, true);
         doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
     }
+
+    /**
+     * Ensure that when an operation is not supported that the correct message is returned.
+     */
+    @Test
+    public void testOperationNotSupported() {
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+
+        // Emulate request not supported from the network.
+        AsyncResult ar = new AsyncResult(null, null,
+                new CommandException(CommandException.Error.REQUEST_NOT_SUPPORTED));
+        mImsPhoneMmiCode.getMmiErrorMessage(ar);
+        verify(mContext.getResources()).getText(
+                eq(com.android.internal.R.string.mmiErrorNotSupported));
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
index 96db966..8406bc5 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/ServiceStateStatsTest.java
@@ -35,6 +35,10 @@
 import android.telephony.TelephonyManager;
 import android.test.suitebuilder.annotation.SmallTest;
 
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS;
+import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN;
+
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
@@ -149,6 +153,7 @@
         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getDataRegState();
         doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mServiceState).getVoiceNetworkType();
         doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mServiceState).getDataNetworkType();
+        mockWwanCsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
         mockWwanPsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
         mServiceStateStats.onServiceStateChanged(mServiceState);
 
@@ -248,6 +253,7 @@
         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getDataRegState();
         doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mServiceState).getVoiceNetworkType();
         doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mServiceState).getDataNetworkType();
+        mockWwanCsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
         mockWwanPsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
         doReturn(-1).when(mPhone).getCarrierId();
         mServiceStateStats.onServiceStateChanged(mServiceState);
@@ -395,6 +401,7 @@
     @SmallTest
     public void onServiceStateChanged_differentDataRats() throws Exception {
         doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mServiceState).getDataNetworkType();
+        mockWwanCsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
         mockWwanPsRat(TelephonyManager.NETWORK_TYPE_UNKNOWN);
 
         mServiceStateStats.onServiceStateChanged(mServiceState);
@@ -881,6 +888,29 @@
         verifyNoMoreInteractions(mPersistAtomsStorage);
     }
 
+    @Test
+    @SmallTest
+    public void getVoiceRat_bearer() throws Exception {
+        mockWwanPsRat(TelephonyManager.NETWORK_TYPE_LTE);
+        mockWwanCsRat(TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mImsStats).getImsVoiceRadioTech();
+        assertEquals(TelephonyManager.NETWORK_TYPE_UNKNOWN, mServiceStateStats.getVoiceRat(
+                mPhone, mServiceState, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS));
+        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mServiceStateStats.getVoiceRat(
+                mPhone, mServiceState, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS));
+        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mServiceStateStats.getVoiceRat(
+                mPhone, mServiceState, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN));
+        mockWwanPsRat(TelephonyManager.NETWORK_TYPE_UMTS);
+        mockWwanCsRat(TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mServiceStateStats.getVoiceRat(
+                mPhone, mServiceState, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS));
+        assertEquals(TelephonyManager.NETWORK_TYPE_UMTS, mServiceStateStats.getVoiceRat(
+                mPhone, mServiceState, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_CS));
+        assertEquals(TelephonyManager.NETWORK_TYPE_LTE, mServiceStateStats.getVoiceRat(
+                mPhone, mServiceState, VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_UNKNOWN));
+    }
+
     private void mockWwanPsRat(@NetworkType int rat) {
         mockWwanRat(
                 NetworkRegistrationInfo.DOMAIN_PS,
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
index fd6cbff..ac554dd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
@@ -217,6 +217,8 @@
     @SmallTest
     public void singleImsCall_moRejected() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(0L).when(mImsConnection0).getDurationMillis();
@@ -272,6 +274,8 @@
     @SmallTest
     public void singleImsCall_moFailed() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(0L).when(mImsConnection0).getDurationMillis();
@@ -284,6 +288,7 @@
                         TelephonyManager.NETWORK_TYPE_LTE,
                         ImsReasonInfo.CODE_SIP_FORBIDDEN);
         expectedCall.setupFailed = true;
+        expectedCall.setupDurationMillis = 200;
         expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
         VoiceCallRatUsage expectedRatUsage =
@@ -313,6 +318,8 @@
     @SmallTest
     public void singleImsCall_moStartFailed() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(0L).when(mImsConnection0).getDurationMillis();
@@ -325,6 +332,7 @@
                         TelephonyManager.NETWORK_TYPE_LTE,
                         ImsReasonInfo.CODE_SIP_REQUEST_CANCELLED);
         expectedCall.setupFailed = true;
+        expectedCall.setupDurationMillis = 200;
         expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
         VoiceCallRatUsage expectedRatUsage =
@@ -354,6 +362,8 @@
     @SmallTest
     public void singleImsCall_moAccepted() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(1000L).when(mImsConnection0).getDurationMillis();
@@ -415,6 +425,8 @@
     @SmallTest
     public void singleImsCall_mtRejected() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(0L).when(mImsConnection0).getDurationMillis();
@@ -462,6 +474,8 @@
     @SmallTest
     public void singleImsCall_mtStartFailed() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(0L).when(mImsConnection0).getDurationMillis();
@@ -509,6 +523,8 @@
     @SmallTest
     public void singleImsCall_mtAccepted() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -570,6 +586,8 @@
         doReturn(mEsimSlot).when(mUiccController).getUiccSlot(eq(1));
         doReturn(mEsimSlot).when(mUiccController).getUiccSlotForPhone(eq(1));
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -615,6 +633,8 @@
         doReturn(mEsimSlot).when(mUiccController).getUiccSlot(eq(1));
         doReturn(mEsimSlot).when(mUiccController).getUiccSlotForPhone(eq(1));
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -660,6 +680,8 @@
         doReturn(mEsimSlot).when(mUiccController).getUiccSlot(eq(1));
         doReturn(mEsimSlot).when(mUiccController).getUiccSlotForPhone(eq(1));
         setServiceState(mSecondServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mSecondPhone).getImsPhone();
         doReturn(true).when(mImsConnection1).isIncoming();
         doReturn(2000L).when(mImsConnection1).getCreateTime();
         doReturn(mImsCall1).when(mImsConnection1).getCall();
@@ -699,6 +721,8 @@
     @SmallTest
     public void singleImsCall_emergency() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(true).when(mImsConnection0).isEmergencyCall();
@@ -740,6 +764,8 @@
     @SmallTest
     public void singleImsCall_roaming() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mServiceState).getVoiceRoaming();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
@@ -781,6 +807,8 @@
     @SmallTest
     public void singleImsCall_codecSwitch() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(300000L).when(mImsConnection0).getDurationMillis();
@@ -835,6 +863,8 @@
     @SmallTest
     public void singleImsCall_ratSwitch() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(600001L).when(mImsConnection0).getDurationMillis();
@@ -885,9 +915,11 @@
         mVoiceCallSessionStats0.onCallStateChanged(mImsCall0);
         mVoiceCallSessionStats0.setTimeMillis(4000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_HSPA);
+        doReturn(TelephonyManager.NETWORK_TYPE_HSPA).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(6000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(8000L);
         mVoiceCallSessionStats0.onImsCallTerminated(
@@ -910,6 +942,8 @@
     @SmallTest
     public void singleImsCall_ratSwitchToUnknown() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(600001L).when(mImsConnection0).getDurationMillis();
@@ -966,12 +1000,15 @@
         mVoiceCallSessionStats0.onCallStateChanged(mImsCall0);
         mVoiceCallSessionStats0.setTimeMillis(4000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_HSPA);
+        doReturn(TelephonyManager.NETWORK_TYPE_HSPA).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(6000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(8000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UNKNOWN);
+        doReturn(TelephonyManager.NETWORK_TYPE_UNKNOWN).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(10000L);
         mVoiceCallSessionStats0.onImsCallTerminated(
@@ -997,6 +1034,8 @@
     @SmallTest
     public void singleImsCall_rttOnDial() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(true).when(mImsConnection0).hasRttTextStream();
@@ -1041,6 +1080,8 @@
     @SmallTest
     public void singleImsCall_rttStartedMidCall() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -1094,6 +1135,8 @@
     @SmallTest
     public void concurrentImsCalls_firstCallHangupFirst() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         // call 0 starts first, MO
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
@@ -1190,6 +1233,7 @@
         // RAT change, LTE to HSPA
         mVoiceCallSessionStats0.setTimeMillis(80000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_HSPA);
+        doReturn(TelephonyManager.NETWORK_TYPE_HSPA).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         // call 0 hangup by remote
         mVoiceCallSessionStats0.setTimeMillis(90000L);
@@ -1199,6 +1243,7 @@
         // RAT change, HSPA to UMTS
         mVoiceCallSessionStats0.setTimeMillis(100000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         // call 1 hangup by local
         mVoiceCallSessionStats0.setTimeMillis(120000L);
@@ -1224,6 +1269,8 @@
     @SmallTest
     public void concurrentImsCalls_firstCallHangupLast() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         // call 0 starts first, MO
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
@@ -1320,6 +1367,7 @@
         // RAT change, LTE to HSPA
         mVoiceCallSessionStats0.setTimeMillis(80000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_HSPA);
+        doReturn(TelephonyManager.NETWORK_TYPE_HSPA).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         // call 1 hangup by remote
         mVoiceCallSessionStats0.setTimeMillis(90000L);
@@ -1329,6 +1377,7 @@
         // RAT change, HSPA to UMTS
         mVoiceCallSessionStats0.setTimeMillis(100000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         // call 0 hangup by local
         mVoiceCallSessionStats0.setTimeMillis(120000L);
@@ -1354,6 +1403,8 @@
     @SmallTest
     public void concurrentImsCalls_firstCallHangupDuringSecondCallSetup() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
         // call 0 starts first, MO
         doReturn(false).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
@@ -1445,6 +1496,7 @@
         // RAT change, LTE to HSPA
         mVoiceCallSessionStats0.setTimeMillis(80000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_HSPA);
+        doReturn(TelephonyManager.NETWORK_TYPE_HSPA).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         // call 1 hangup by remote
         mVoiceCallSessionStats0.setTimeMillis(90000L);
@@ -1547,6 +1599,7 @@
         expectedCall.bandAtEnd = 0;
         expectedCall.ratSwitchCount = 1L;
         expectedCall.setupFailed = true;
+        expectedCall.setupDurationMillis = 13000;
         expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
         expectedCall.codecBitmask = 0L;
         expectedCall.mainCodecQuality =
@@ -1562,12 +1615,14 @@
 
         mVoiceCallSessionStats0.setTimeMillis(2000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
         doReturn(Call.State.DIALING).when(mCsCall0).getState();
         doReturn(Call.State.DIALING).when(mGsmConnection0).getState();
         doReturn(DisconnectCause.NOT_DISCONNECTED).when(mGsmConnection0).getDisconnectCause();
         mVoiceCallSessionStats0.onRilDial(mGsmConnection0);
         mVoiceCallSessionStats0.setTimeMillis(3000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(15000L);
         doReturn(DisconnectCause.LOST_SIGNAL).when(mGsmConnection0).getDisconnectCause();
@@ -1770,6 +1825,7 @@
     @SmallTest
     public void singleCall_srvccFailed() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -1820,6 +1876,7 @@
                 TelephonyManager.SRVCC_STATE_HANDOVER_STARTED);
         mVoiceCallSessionStats0.setTimeMillis(10000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(11000L);
         mVoiceCallSessionStats0.onRilSrvccStateChanged(
@@ -1849,6 +1906,7 @@
     @SmallTest
     public void singleCall_srvccCanceled() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -1917,6 +1975,7 @@
     @SmallTest
     public void singleCall_srvccSuccess() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
         doReturn(true).when(mImsConnection0).isIncoming();
         doReturn(2000L).when(mImsConnection0).getCreateTime();
         doReturn(mImsCall0).when(mImsConnection0).getCall();
@@ -1982,6 +2041,7 @@
                 TelephonyManager.SRVCC_STATE_HANDOVER_STARTED);
         mVoiceCallSessionStats0.setTimeMillis(7000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(8000L);
         mVoiceCallSessionStats0.onRilSrvccStateChanged(
@@ -2011,6 +2071,7 @@
     @SmallTest
     public void concurrentCalls_srvcc() {
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
         doReturn(mImsPhone).when(mPhone).getImsPhone();
         doReturn(new ArrayList(List.of(mImsConnection0, mImsConnection1)))
                 .when(mImsPhone)
@@ -2118,6 +2179,7 @@
         // RAT change, LTE to UMTS
         mVoiceCallSessionStats0.setTimeMillis(80000L);
         setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_UMTS);
+        doReturn(TelephonyManager.NETWORK_TYPE_UMTS).when(mImsStats).getImsVoiceRadioTech();
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
         mVoiceCallSessionStats0.setTimeMillis(85000L);
         mVoiceCallSessionStats0.onRilSrvccStateChanged(