Merge "Regression for MSIM to SSIM Voice Tests"
diff --git a/acts/framework/acts/test_utils/tel/TelephonyBaseTest.py b/acts/framework/acts/test_utils/tel/TelephonyBaseTest.py
index 9cebbee..ad2bfcb 100644
--- a/acts/framework/acts/test_utils/tel/TelephonyBaseTest.py
+++ b/acts/framework/acts/test_utils/tel/TelephonyBaseTest.py
@@ -34,6 +34,8 @@
 
 from acts.test_utils.tel.tel_subscription_utils import \
     initial_set_up_for_subid_infomation
+from acts.test_utils.tel.tel_subscription_utils import \
+    set_default_sub_for_all_services
 from acts.test_utils.tel.tel_test_utils import build_id_override
 from acts.test_utils.tel.tel_test_utils import disable_qxdm_logger
 from acts.test_utils.tel.tel_test_utils import enable_connectivity_metrics
@@ -72,6 +74,7 @@
 from acts.test_utils.tel.tel_test_utils import activate_google_fi_account
 from acts.test_utils.tel.tel_test_utils import check_google_fi_activated
 from acts.test_utils.tel.tel_test_utils import check_fi_apk_installed
+from acts.test_utils.tel.tel_test_utils import phone_switch_to_msim_mode
 from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND
 from acts.test_utils.tel.tel_defines import SINGLE_SIM_CONFIG, MULTI_SIM_CONFIG
 from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND
@@ -264,6 +267,16 @@
                 if not activate_google_fi_account(ad):
                     return False
                 check_google_fi_activated(ad)
+            if hasattr(ad, "dsds"):
+                sim_mode = ad.droid.telephonyGetPhoneCount()
+                if sim_mode == 1:
+                    ad.log.info("Phone in Single SIM Mode")
+                    if not phone_switch_to_msim_mode(ad):
+                        ad.log.error("Failed to switch to Dual SIM Mode")
+                        return False
+                elif sim_mode == 2:
+                    ad.log.info("Phone already in Dual SIM Mode")
+                set_default_sub_for_all_services(ad)
         if get_sim_state(ad) in (SIM_STATE_ABSENT, SIM_STATE_UNKNOWN):
             ad.log.info("Device has no or unknown SIM in it")
             ensure_phone_idle(self.log, ad)
diff --git a/acts/framework/acts/test_utils/tel/tel_defines.py b/acts/framework/acts/test_utils/tel/tel_defines.py
index 7fa5aa3..d409ec0 100644
--- a/acts/framework/acts/test_utils/tel/tel_defines.py
+++ b/acts/framework/acts/test_utils/tel/tel_defines.py
@@ -119,7 +119,7 @@
 
 # Time to wait after call setup before declaring
 # that the call is actually successful
-WAIT_TIME_IN_CALL = 15
+WAIT_TIME_IN_CALL = 30
 
 # (For IMS, e.g. VoLTE-VoLTE, WFC-WFC, VoLTE-WFC test only)
 # Time to wait after call setup before declaring
diff --git a/acts/framework/acts/test_utils/tel/tel_subscription_utils.py b/acts/framework/acts/test_utils/tel/tel_subscription_utils.py
index d4dd106..6007854 100644
--- a/acts/framework/acts/test_utils/tel/tel_subscription_utils.py
+++ b/acts/framework/acts/test_utils/tel/tel_subscription_utils.py
@@ -214,3 +214,37 @@
     ad.droid.telecomSetUserSelectedOutgoingPhoneAccountBySubId(sub_id)
     if hasattr(ad, "outgoing_voice_sub_id"):
         ad.outgoing_voice_sub_id = sub_id
+
+
+def set_incoming_voice_sub_id(ad, sub_id):
+    """Set default subId for voice calls
+
+    Args:
+        ad: android device object.
+        sub_id: subscription id (integer)
+
+    Returns:
+        None
+    """
+    ad.droid.subscriptionSetDefaultVoiceSubId(sub_id)
+    if hasattr(ad, "incoming_voice_sub_id"):
+        ad.incoming_voice_sub_id = sub_id
+
+
+def set_default_sub_for_all_services(ad, slot_id=0):
+    """Set subId for all services
+
+    Args:
+        ad: android device object.
+        slot_id: 0 or 1 (integer)
+
+    Returns:
+        None
+    """
+    sub_id = get_subid_from_slot_index(ad.log, ad, slot_id)
+    ad.log.info("Subid is %s", sub_id)
+    set_subid_for_outgoing_call(ad, sub_id)
+    set_incoming_voice_sub_id(ad, sub_id)
+    set_subid_for_data(ad, sub_id)
+    set_subid_for_message(ad, sub_id)
+    ad.droid.telephonyToggleDataConnection(True)
diff --git a/acts/framework/acts/test_utils/tel/tel_test_utils.py b/acts/framework/acts/test_utils/tel/tel_test_utils.py
index 9ac4069..7bd9e42 100644
--- a/acts/framework/acts/test_utils/tel/tel_test_utils.py
+++ b/acts/framework/acts/test_utils/tel/tel_test_utils.py
@@ -3071,6 +3071,12 @@
 
 def phone_switch_to_msim_mode(ad, retries=3, timeout=60):
     result = False
+    if not ad.is_apk_installed("com.google.mdstest"):
+        raise signals.TestSkipClass("mdstest is not installed")
+    mode = ad.droid.telephonyGetPhoneCount()
+    if mode == 2:
+        ad.log.info("Device already in MSIM mode")
+        return True
     for i in range(retries):
         ad.adb.shell(
         "setprop persist.vendor.sys.modem.diag.mdlog false", ignore_status=True)
@@ -3087,8 +3093,8 @@
         ad.adb.shell("setprop persist.radio.multisim.config dsds")
         reboot_device(ad)
         # Verify if device is really in msim mode
-        rat = ad.adb.getprop("gsm.network.type")
-        if "," in rat:
+        mode = ad.droid.telephonyGetPhoneCount()
+        if mode == 2:
             ad.log.info("Device correctly switched to MSIM mode")
             result = True
             break
@@ -3099,6 +3105,12 @@
 
 def phone_switch_to_ssim_mode(ad, retries=3, timeout=30):
     result = False
+    if not ad.is_apk_installed("com.google.mdstest"):
+        raise signals.TestSkipClass("mdstest is not installed")
+    mode = ad.droid.telephonyGetPhoneCount()
+    if mode == 1:
+        ad.log.info("Device already in SSIM mode")
+        return True
     for i in range(retries):
         ad.adb.shell(
         "setprop persist.vendor.sys.modem.diag.mdlog false", ignore_status=True)
@@ -3120,8 +3132,8 @@
         ad.adb.shell("setprop persist.radio.multisim.config ssss")
         reboot_device(ad)
         # Verify if device is really in ssim mode
-        rat = ad.adb.getprop("gsm.network.type")
-        if "," not in rat:
+        mode = ad.droid.telephonyGetPhoneCount()
+        if mode == 1:
             ad.log.info("Device correctly switched to SSIM mode")
             result = True
             break
@@ -4966,6 +4978,10 @@
                                            network_preference):
         return False
 
+    if hasattr(ad, "dsds") and voice_or_data == "data" and sub_id != get_default_data_sub_id(ad):
+        ad.log.info("MSIM - Non DDS, ignore data RAT")
+        return True
+
     if is_droid_in_network_generation_for_subscription(
             log, ad, sub_id, generation, voice_or_data):
         return True
diff --git a/acts/tests/google/tel/live/TelLiveDSDSVoiceTest.py b/acts/tests/google/tel/live/TelLiveDSDSVoiceTest.py
new file mode 100644
index 0000000..a44e723
--- /dev/null
+++ b/acts/tests/google/tel/live/TelLiveDSDSVoiceTest.py
@@ -0,0 +1,504 @@
+#!/usr/bin/env python3.4
+#
+#   Copyright 2019 - Google
+#
+#   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.
+"""
+    Test Script for DSDS devices
+"""
+
+import time
+from queue import Empty
+from acts.test_decorators import test_tracker_info
+from acts.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
+from acts.test_utils.tel.tel_defines import DIRECTION_MOBILE_ORIGINATED
+from acts.test_utils.tel.tel_defines import DIRECTION_MOBILE_TERMINATED
+from acts.test_utils.tel.tel_defines import GEN_3G
+from acts.test_utils.tel.tel_defines import GEN_4G
+from acts.test_utils.tel.tel_defines import INVALID_WIFI_RSSI
+from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_CALL_DROP
+from acts.test_utils.tel.tel_defines import MAX_WAIT_TIME_NW_SELECTION
+from acts.test_utils.tel.tel_defines import NETWORK_SERVICE_DATA
+from acts.test_utils.tel.tel_defines import NETWORK_SERVICE_VOICE
+from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND
+from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND
+from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING
+from acts.test_utils.tel.tel_defines import RAT_LTE
+from acts.test_utils.tel.tel_defines import RAT_IWLAN
+from acts.test_utils.tel.tel_defines import RAT_WCDMA
+from acts.test_utils.tel.tel_defines import WAIT_TIME_BETWEEN_REG_AND_CALL
+from acts.test_utils.tel.tel_defines import WAIT_TIME_IN_CALL
+from acts.test_utils.tel.tel_defines import WAIT_TIME_WIFI_RSSI_CALIBRATION_SCREEN_ON
+from acts.test_utils.tel.tel_defines import WAIT_TIME_WIFI_RSSI_CALIBRATION_WIFI_CONNECTED
+from acts.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
+from acts.test_utils.tel.tel_defines import WFC_MODE_DISABLED
+from acts.test_utils.tel.tel_defines import WFC_MODE_WIFI_ONLY
+from acts.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
+from acts.test_utils.tel.tel_defines import WIFI_WEAK_RSSI_VALUE
+from acts.test_utils.tel.tel_defines import EventNetworkCallback
+from acts.test_utils.tel.tel_defines import NetworkCallbackAvailable
+from acts.test_utils.tel.tel_defines import NetworkCallbackLost
+from acts.test_utils.tel.tel_defines import SignalStrengthContainer
+from acts.test_utils.tel.tel_test_utils import wifi_toggle_state
+from acts.test_utils.tel.tel_test_utils import ensure_network_generation
+from acts.test_utils.tel.tel_test_utils import ensure_phones_default_state
+from acts.test_utils.tel.tel_test_utils import ensure_wifi_connected
+from acts.test_utils.tel.tel_test_utils import get_network_rat
+from acts.test_utils.tel.tel_test_utils import get_phone_number
+from acts.test_utils.tel.tel_test_utils import get_phone_number_for_subscription
+from acts.test_utils.tel.tel_test_utils import hangup_call
+from acts.test_utils.tel.tel_test_utils import initiate_call
+from acts.test_utils.tel.tel_test_utils import is_network_call_back_event_match
+from acts.test_utils.tel.tel_test_utils import is_phone_in_call
+from acts.test_utils.tel.tel_test_utils import is_phone_not_in_call
+from acts.test_utils.tel.tel_test_utils import set_wfc_mode
+from acts.test_utils.tel.tel_test_utils import toggle_airplane_mode
+from acts.test_utils.tel.tel_test_utils import toggle_volte
+from acts.test_utils.tel.tel_test_utils import wait_and_answer_call
+from acts.test_utils.tel.tel_test_utils import wait_for_cell_data_connection
+from acts.test_utils.tel.tel_test_utils import wait_for_droid_not_in_call
+from acts.test_utils.tel.tel_test_utils import wait_for_wfc_disabled
+from acts.test_utils.tel.tel_test_utils import wait_for_wfc_enabled
+from acts.test_utils.tel.tel_test_utils import wait_for_wifi_data_connection
+from acts.test_utils.tel.tel_test_utils import verify_http_connection
+from acts.test_utils.tel.tel_test_utils import get_telephony_signal_strength
+from acts.test_utils.tel.tel_test_utils import get_wifi_signal_strength
+from acts.test_utils.tel.tel_test_utils import wait_for_state
+from acts.test_utils.tel.tel_test_utils import is_phone_in_call
+from acts.test_utils.tel.tel_voice_utils import is_phone_in_call_3g
+from acts.test_utils.tel.tel_voice_utils import is_phone_in_call_2g
+from acts.test_utils.tel.tel_voice_utils import is_phone_in_call_csfb
+from acts.test_utils.tel.tel_voice_utils import is_phone_in_call_iwlan
+from acts.test_utils.tel.tel_voice_utils import is_phone_in_call_not_iwlan
+from acts.test_utils.tel.tel_voice_utils import is_phone_in_call_volte
+from acts.test_utils.tel.tel_voice_utils import phone_setup_voice_general
+from acts.test_utils.tel.tel_voice_utils import phone_setup_volte
+from acts.test_utils.tel.tel_voice_utils import phone_setup_voice_3g
+from acts.test_utils.tel.tel_voice_utils import phone_setup_voice_2g
+from acts.test_utils.tel.tel_voice_utils import phone_idle_3g
+from acts.test_utils.tel.tel_voice_utils import phone_idle_2g
+from acts.test_utils.tel.tel_voice_utils import phone_idle_csfb
+from acts.test_utils.tel.tel_voice_utils import phone_idle_iwlan
+from acts.test_utils.tel.tel_voice_utils import phone_idle_not_iwlan
+from acts.test_utils.tel.tel_voice_utils import phone_idle_volte
+from acts.test_utils.tel.tel_subscription_utils import set_subid_for_outgoing_call
+from acts.test_utils.tel.tel_subscription_utils import set_incoming_voice_sub_id
+from acts.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index
+
+
+DEFAULT_LONG_DURATION_CALL_TOTAL_DURATION = 1 * 60 * 60  # default value 1 hour
+DEFAULT_PING_DURATION = 120  # in seconds
+
+
+class TelLiveDSDSVoiceTest(TelephonyBaseTest):
+    def __init__(self, controllers):
+        TelephonyBaseTest.__init__(self, controllers)
+        self.number_of_devices = 2
+        self.stress_test_number = self.get_stress_test_number()
+
+
+    def _msim_call_sequence(self, ads, mo_mt, slot_id,
+                            msim_phone_setup_func,
+                            verify_msim_initial_idle_func,
+                            verify_msim_in_call_state_func,
+                            incall_msim_setting_check_func, expected_result):
+        """_msim_call_sequence
+
+        Args:
+            ads: list of android devices. This list should have 2 ad.
+            mo_mt: indicating this call sequence is MO or MT.
+                Valid input: DIRECTION_MOBILE_ORIGINATED and
+                DIRECTION_MOBILE_TERMINATED.
+            slot_id: either 0 or 1
+
+        Returns:
+            if expected_result is True,
+                Return True if call sequence finish without exception.
+            if expected_result is string,
+                Return True if expected exception happened. Otherwise False.
+
+        """
+
+        class _MSIMCallSequenceException(Exception):
+            pass
+
+        if (len(ads) != 2) or (mo_mt not in [
+                DIRECTION_MOBILE_ORIGINATED, DIRECTION_MOBILE_TERMINATED
+        ]):
+            self.log.error("Invalid parameters.")
+            return False
+
+        sub_id = get_subid_from_slot_index(ads[0].log, ads[0], slot_id)
+        if mo_mt == DIRECTION_MOBILE_ORIGINATED:
+            ad_caller = ads[0]
+            ad_callee = ads[1]
+            set_subid_for_outgoing_call(ads[0], sub_id)
+            caller_number = get_phone_number(self.log, ad_caller)
+            callee_number = get_phone_number(self.log, ad_callee)
+        else:
+            ad_caller = ads[1]
+            ad_callee = ads[0]
+            caller_number = get_phone_number(self.log, ad_caller)
+            callee_number = get_phone_number_for_subscription(ads[0].log,
+                                                          ads[0], sub_id)
+            setattr(ads[0], "incoming_voice_sub_id", sub_id)
+
+        self.log.info("-->Begin msim_call_sequence: %s to %s<--",
+                      caller_number, callee_number)
+
+        try:
+            # Setup
+            if msim_phone_setup_func and not msim_phone_setup_func():
+                raise _MSIMCallSequenceException("msim_phone_setup_func fail.")
+            if not phone_setup_voice_general(self.log, ads[1]):
+                raise _MSIMCallSequenceException(
+                    "phone_setup_voice_general fail.")
+            time.sleep(WAIT_TIME_BETWEEN_REG_AND_CALL)
+
+            # Ensure idle status correct
+            if verify_msim_initial_idle_func and not \
+                verify_msim_initial_idle_func():
+                raise _MSIMCallSequenceException(
+                    "verify_msim_initial_idle_func fail.")
+
+            # Make MO/MT call.
+            if not initiate_call(self.log, ad_caller, callee_number):
+                raise _MSIMCallSequenceException("initiate_call fail.")
+            if not wait_and_answer_call(self.log, ad_callee, caller_number):
+                raise _MSIMCallSequenceException("wait_and_answer_call fail.")
+            time.sleep(1)
+
+            # Check state, wait 30 seconds, check again.
+            if (verify_msim_in_call_state_func and not
+                    verify_msim_in_call_state_func()):
+                raise _MSIMCallSequenceException(
+                    "verify_msim_in_call_state_func fail.")
+
+            if is_phone_not_in_call(self.log, ads[1]):
+                raise _MSIMCallSequenceException("PhoneB not in call.")
+            time.sleep(WAIT_TIME_IN_CALL)
+
+            if (verify_msim_in_call_state_func and not
+                    verify_msim_in_call_state_func()):
+                raise _MSIMCallSequenceException(
+                    "verify_msim_in_call_state_func fail after 30 seconds.")
+            if is_phone_not_in_call(self.log, ads[1]):
+                raise _MSIMCallSequenceException(
+                    "PhoneB not in call after 30 seconds.")
+
+            # in call change setting and check
+            if (incall_msim_setting_check_func and not
+                    incall_msim_setting_check_func()):
+                raise _MSIMCallSequenceException(
+                    "incall_msim_setting_check_func fail.")
+
+            # Hangup call
+            if is_phone_in_call(self.log, ads[0]):
+                if not hangup_call(self.log, ads[0]):
+                    raise _MSIMCallSequenceException("hangup_call fail.")
+            else:
+                if incall_msim_setting_check_func is None:
+                    raise _MSIMCallSequenceException("Unexpected call drop.")
+
+        except _MSIMCallSequenceException as e:
+            if str(e) == expected_result:
+                self.log.info("Expected exception: <%s>, return True.", e)
+                return True
+            else:
+                self.log.info("Unexpected exception: <%s>, return False.", e)
+                return False
+
+        self.log.info("msim_call_sequence finished, return %s",
+                      expected_result is True)
+        return (expected_result is True)
+
+    def _phone_idle_iwlan(self):
+        return phone_idle_iwlan(self.log, self.android_devices[0])
+
+    def _phone_idle_not_iwlan(self):
+        return phone_idle_not_iwlan(self.log, self.android_devices[0])
+
+    def _phone_idle_volte(self):
+        return phone_idle_volte(self.log, self.android_devices[0])
+
+    def _phone_idle_csfb(self):
+        return phone_idle_csfb(self.log, self.android_devices[0])
+
+    def _phone_idle_3g(self):
+        return phone_idle_3g(self.log, self.android_devices[0])
+
+    def _phone_idle_2g(self):
+        return phone_idle_2g(self.log, self.android_devices[0])
+
+    def _is_phone_in_call_iwlan(self):
+        return is_phone_in_call_iwlan(self.log, self.android_devices[0])
+
+    def _is_phone_in_call_not_iwlan(self):
+        return is_phone_in_call_not_iwlan(self.log, self.android_devices[0])
+
+    def _is_phone_not_in_call(self):
+        if is_phone_in_call(self.log, self.android_devices[0]):
+            self.log.info("{} in call.".format(self.android_devices[0].serial))
+            return False
+        self.log.info("{} not in call.".format(self.android_devices[0].serial))
+        return True
+
+    def _is_phone_in_call_volte(self):
+        return is_phone_in_call_volte(self.log, self.android_devices[0])
+
+    def _is_phone_in_call_3g(self):
+        return is_phone_in_call_3g(self.log, self.android_devices[0])
+
+    def _is_phone_in_call_2g(self):
+        return is_phone_in_call_2g(self.log, self.android_devices[0])
+
+    def _is_phone_in_call_csfb(self):
+        return is_phone_in_call_csfb(self.log, self.android_devices[0])
+
+    def _is_phone_in_call(self):
+        return is_phone_in_call(self.log, self.android_devices[0])
+
+    def _phone_setup_voice_general(self):
+        return phone_setup_voice_general(self.log, self.android_devices[0])
+
+    def _phone_setup_volte(self):
+        return phone_setup_volte(self.log, self.android_devices[0])
+
+    def _phone_setup_3g(self):
+        return phone_setup_voice_3g(self.log, self.android_devices[0])
+
+    def _phone_setup_2g(self):
+        return phone_setup_voice_2g(self.log, self.android_devices[0])
+
+
+    """ Tests Begin """
+
+
+    @test_tracker_info(uuid="5a3ff3c0-5956-4b18-86a1-61ac60546330")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mo_to_ssim_voice_general(self):
+        """ Test MSIM to SSIM MO Voice General
+
+        Make Sure PhoneA Slot0 is attached to Voice
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneA to PhoneB, call should succeed
+        Make Sure PhoneA Slot1 is attached to Voice
+        Call from PhoneA to PhoneB, call should succeed
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mo_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 0,
+            self._phone_setup_voice_general, None, self._is_phone_in_call,
+            None, True)
+
+        mo_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 1,
+            self._phone_setup_voice_general, None, self._is_phone_in_call,
+            None, True)
+
+        self.log.info("MO Slot0: %s, MO Slot1: %s", mo_result_0, mo_result_1)
+        return ((mo_result_0 is True) and (mo_result_1 is True))
+
+
+    @test_tracker_info(uuid="5adc17d4-8258-42aa-82ab-0ef92ac7b660")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mt_to_ssim_voice_general(self):
+        """ Test SSIM to MSIM MT Voice General
+
+        Make Sure PhoneA Slot0 is attached to Voice
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneB to PhoneA, call should succeed
+        Make Sure PhoneA Slot1 is attached to Voice
+        Call from PhoneB to PhoneA, call should succeed
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mt_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 0,
+            self._phone_setup_voice_general, None, self._is_phone_in_call,
+            None, True)
+
+        mt_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 1,
+            self._phone_setup_voice_general, None, self._is_phone_in_call,
+            None, True)
+
+        self.log.info("MT Slot0: %s, MT Slot1: %s", mt_result_0, mt_result_1)
+        return ((mt_result_0 is True) and (mt_result_1 is True))
+
+
+    @test_tracker_info(uuid="3988e411-b9f8-4798-b3a6-dd3bf0d2035c")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mo_to_ssim_volte(self):
+        """ Test MSIM to SSIM MO VoLTE
+
+        Make Sure PhoneA Slot0 is on VoLTE
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneA to PhoneB, call should succeed on VoLTE
+        Make Sure PhoneA Slot1 is on VoLTE
+        Call from PhoneA to PhoneB, call should succeed on VoLTE
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mo_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 0, self._phone_setup_volte,
+            self._phone_idle_volte, self._is_phone_in_call_volte, None, True)
+
+        mo_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 1, self._phone_setup_volte,
+            self._phone_idle_volte, self._is_phone_in_call_volte, None, True)
+
+        self.log.info("MO Slot0: %s, MO Slot1: %s", mo_result_0, mo_result_1)
+        return ((mo_result_0 is True) and (mo_result_1 is True))
+
+
+    @test_tracker_info(uuid="4fe74a11-6f13-4305-becd-ad77e13a3193")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mt_to_ssim_volte(self):
+        """ Test SSIM to MSIM MT VoLTE
+
+        Make Sure PhoneA Slot0 is on VoLTE
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneB to PhoneA, call should succeed on VoLTE
+        Make Sure PhoneA Slot1 is on VoLTE
+        Call from PhoneB to PhoneA, call should succeed on VoLTE
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mt_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 0, self._phone_setup_volte,
+            self._phone_idle_volte, self._is_phone_in_call_volte, None, True)
+
+        mt_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 1, self._phone_setup_volte,
+            self._phone_idle_volte, self._is_phone_in_call_volte, None, True)
+
+        self.log.info("MT Slot0: %s, MT Slot1: %s", mt_result_0, mt_result_1)
+        return ((mt_result_0 is True) and (mt_result_1 is True))
+
+
+    @test_tracker_info(uuid="ffc7a414-8ec3-4bf4-a509-0bec59f2a3b9")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mo_to_ssim_3g(self):
+        """ Test MSIM to SSIM MO 3G
+
+        Make Sure PhoneA Slot0 is on 3G
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneA to PhoneB, call should succeed on 3G
+        Make Sure PhoneA Slot1 is on 3G
+        Call from PhoneA to PhoneB, call should succeed on 3G
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mo_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 0, self._phone_setup_3g,
+            self._phone_idle_3g, self._is_phone_in_call_3g, None, True)
+
+        mo_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 1, self._phone_setup_3g,
+            self._phone_idle_3g, self._is_phone_in_call_3g, None, True)
+
+        self.log.info("MO Slot0: %s, MO Slot1: %s", mo_result_0, mo_result_1)
+        return ((mo_result_0 is True) and (mo_result_1 is True))
+
+
+    @test_tracker_info(uuid="21221072-01f2-4951-ad55-fe1f4fe1b044")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mt_to_ssim_3g(self):
+        """ Test SSIM to MSIM MT 3G
+
+        Make Sure PhoneA Slot0 is on 3G
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneB to PhoneA, call should succeed on 3G
+        Make Sure PhoneA Slot1 is on 3G
+        Call from PhoneB to PhoneA, call should succeed on 3G
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mt_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 0, self._phone_setup_3g,
+            self._phone_idle_3g, self._is_phone_in_call_3g, None, True)
+
+        mt_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 1, self._phone_setup_3g,
+            self._phone_idle_3g, self._is_phone_in_call_3g, None, True)
+
+        self.log.info("MT Slot0: %s, MT Slot1: %s", mt_result_0, mt_result_1)
+        return ((mt_result_0 is True) and (mt_result_1 is True))
+
+
+    @test_tracker_info(uuid="65448385-42fe-429c-ad8e-6c75be93f83e")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mo_to_ssim_2g(self):
+        """ Test MSIM to SSIM MO 2G
+
+        Make Sure PhoneA Slot0 is on 2G
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneA to PhoneB, call should succeed on 2G
+        Make Sure PhoneA Slot1 is on 2G
+        Call from PhoneA to PhoneB, call should succeed on 2G
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mo_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 0, self._phone_setup_2g,
+            self._phone_idle_2g, self._is_phone_in_call_2g, None, True)
+
+        mo_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_ORIGINATED, 1, self._phone_setup_2g,
+            self._phone_idle_2g, self._is_phone_in_call_2g, None, True)
+
+        self.log.info("MO Slot0: %s, MO Slot1: %s", mo_result_0, mo_result_1)
+        return ((mo_result_0 is True) and (mo_result_1 is True))
+
+
+    @test_tracker_info(uuid="44d1ef0a-c981-4db1-958c-0af06eb0c503")
+    @TelephonyBaseTest.tel_test_wrap
+    def test_msim_mt_to_ssim_2g(self):
+        """ Test SSIM to MSIM MT 2G
+
+        Make Sure PhoneA Slot0 is on 2G
+        Make Sure PhoneB is able to make MO/MT call
+        Call from PhoneB to PhoneA, call should succeed on 2G
+        Make Sure PhoneA Slot1 is on 2G
+        Call from PhoneB to PhoneA, call should succeed on 2G
+
+        Returns:
+            True if pass; False if fail.
+        """
+        ads = [self.android_devices[0], self.android_devices[1]]
+        mt_result_0 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 0, self._phone_setup_2g,
+            self._phone_idle_2g, self._is_phone_in_call_2g, None, True)
+
+        mt_result_1 = self._msim_call_sequence(
+            ads, DIRECTION_MOBILE_TERMINATED, 1, self._phone_setup_2g,
+            self._phone_idle_2g, self._is_phone_in_call_2g, None, True)
+
+        self.log.info("MT Slot0: %s, MT Slot1: %s", mt_result_0, mt_result_1)
+        return ((mt_result_0 is True) and (mt_result_1 is True))