| #!/usr/bin/env python3 |
| # |
| # Copyright 2022 - 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. |
| |
| import random |
| import time |
| |
| from acts.libs.utils.multithread import multithread_func |
| from acts.test_decorators import test_tracker_info |
| from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest |
| from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_ANDROID_STATE_SETTLING |
| from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED |
| from acts_contrib.test_utils.tel.tel_data_utils import wait_for_cell_data_connection |
| from acts_contrib.test_utils.tel.tel_message_utils import mms_send_receive_verify |
| from acts_contrib.test_utils.tel.tel_message_utils import sms_send_receive_verify |
| from acts_contrib.test_utils.tel.tel_parse_utils import parse_mms |
| from acts_contrib.test_utils.tel.tel_parse_utils import parse_sms_delivery_time |
| from acts_contrib.test_utils.tel.tel_parse_utils import print_nested_dict |
| from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_csfb_for_subscription |
| from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte_for_subscription |
| from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_iwlan_for_subscription |
| from acts_contrib.test_utils.tel.tel_subscription_utils import set_message_subid |
| from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_on_same_network_of_host_ad |
| from acts.utils import get_current_epoch_time |
| from acts.utils import rand_ascii_str |
| |
| CALCULATE_EVERY_N_CYCLES = 10 |
| MAX_FAIL_COUNT = 10 |
| |
| |
| class TelLiveRilMessageKpiTest(TelephonyBaseTest): |
| def setup_class(self): |
| TelephonyBaseTest.setup_class(self) |
| self.sms_4g_over_sgs_test_cycle = self.user_params.get( |
| 'sms_4g_over_sgs_test_cycle', 1) |
| self.sms_4g_over_ims_test_cycle = self.user_params.get( |
| 'sms_4g_over_ims_test_cycle', 1) |
| self.sms_iwlan_test_cycle = self.user_params.get( |
| 'sms_iwlan_test_cycle', 1) |
| self.mms_4g_test_cycle = self.user_params.get('mms_4g_test_cycle', 1) |
| self.mms_iwlan_test_cycle = self.user_params.get( |
| 'mms_iwlan_test_cycle', 1) |
| |
| def sms_test(self, ads): |
| """Send and receive a short SMS with random length and content between |
| two UEs. |
| |
| Args: |
| ads: list containing Android objects |
| |
| Returns: |
| True if both sending and receiving are successful. Otherwise False. |
| """ |
| msg_length = random.randint(5, 160) |
| msg_body = rand_ascii_str(msg_length) |
| |
| if not sms_send_receive_verify(self.log, ads[0], ads[1], [msg_body]): |
| ads[0].log.warning('SMS of length %s test failed', msg_length) |
| return False |
| else: |
| ads[0].log.info('SMS of length %s test succeeded', msg_length) |
| return True |
| |
| def mms_test(self, ads, expected_result=True): |
| """Send and receive a MMS with random text length and content between |
| two UEs. |
| |
| Args: |
| ads: list containing Android objects |
| expected_result: True to expect successful MMS sending and reception. |
| Otherwise False. |
| |
| Returns: |
| True if both sending and reception are successful. Otherwise False. |
| """ |
| message_length = random.randint(5, 160) |
| message_array = [('Test Message', rand_ascii_str(message_length), None)] |
| if not mms_send_receive_verify( |
| self.log, |
| ads[0], |
| ads[1], |
| message_array, |
| expected_result=expected_result): |
| self.log.warning('MMS of body length %s test failed', message_length) |
| return False |
| else: |
| self.log.info('MMS of body length %s test succeeded', message_length) |
| self.log.info('MMS test of body lengths %s succeeded', message_length) |
| return True |
| |
| |
| def _test_sms_4g(self, over_iwlan=False, over_ims=False): |
| """ Send/receive SMS over SGs/IMS to measure MO SMS setup time and SMS |
| delivery time. |
| |
| Test steps: |
| 1. Enable VoLTE when over IMS. Otherwise disable VoLTE. |
| 2. Send a SMS from MO UE and receive it by MT UE. |
| 3. Parse logcat of both MO and MT UEs to calculate MO SMS setup time |
| and SMS delivery time. |
| |
| Args: |
| over_iwlan: True for over Wi-Fi and False for over cellular network |
| over_ims: True for over IMS and False for over SGs |
| |
| Returns: |
| True if both sending and reception are successful. Otherwise False. |
| """ |
| ad_mo = self.android_devices[0] |
| ad_mt = self.android_devices[1] |
| |
| mo_sub_id, mt_sub_id, _ = get_subid_on_same_network_of_host_ad( |
| [ad_mo, ad_mt], |
| host_sub_id=None, |
| type="sms") |
| set_message_subid(ad_mt, mt_sub_id) |
| |
| cycle = self.sms_4g_over_sgs_test_cycle |
| phone_setup_func = phone_setup_csfb_for_subscription |
| mo_param = (self.log, ad_mo, mo_sub_id) |
| mt_param = (self.log, ad_mt, mt_sub_id) |
| wording = "SGs" |
| parsing = '4g' |
| if over_ims: |
| cycle = self.sms_4g_over_ims_test_cycle |
| phone_setup_func = phone_setup_volte_for_subscription |
| wording = "IMS" |
| parsing = 'iwlan' |
| |
| if over_iwlan: |
| cycle = self.sms_iwlan_test_cycle |
| phone_setup_func = phone_setup_iwlan_for_subscription |
| |
| mo_param = ( |
| self.log, |
| ad_mo, |
| mo_sub_id, |
| True, |
| WFC_MODE_CELLULAR_PREFERRED, |
| self.wifi_network_ssid, |
| self.wifi_network_pass) |
| |
| mt_param = ( |
| self.log, |
| ad_mt, |
| mt_sub_id, |
| True, |
| WFC_MODE_CELLULAR_PREFERRED, |
| self.wifi_network_ssid, |
| self.wifi_network_pass) |
| |
| wording = 'iwlan' |
| parsing = 'iwlan' |
| |
| tasks = [ |
| (phone_setup_func, mo_param), |
| (phone_setup_func, mt_param)] |
| if not multithread_func(self.log, tasks): |
| self.log.error("Phone Failed to Set Up Properly.") |
| return False |
| |
| time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) |
| |
| sms_test_summary = [] |
| result = True |
| continuous_fail = 0 |
| for attempt in range(cycle): |
| self.log.info( |
| '======> MO/MT SMS over %s %s/%s <======', |
| wording, |
| attempt+1, |
| cycle) |
| res = self.sms_test([ad_mo, ad_mt]) |
| sms_test_summary.append(res) |
| |
| if not res: |
| continuous_fail += 1 |
| if not multithread_func(self.log, tasks): |
| self.log.error("Phone Failed to Set Up Properly.") |
| result = False |
| self._take_bug_report( |
| self.test_name, begin_time=get_current_epoch_time()) |
| else: |
| time.sleep(random.randint(3,10)) |
| |
| if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or ( |
| attempt == cycle - 1) or continuous_fail >= MAX_FAIL_COUNT: |
| parse_sms_delivery_time(self.log, ad_mo, ad_mt, rat=parsing) |
| try: |
| sms_test_fail_rate = sms_test_summary.count( |
| False)/len(sms_test_summary) |
| self.log.info( |
| 'Fail rate of SMS test over %s: %s/%s (%.2f)', |
| wording, |
| sms_test_summary.count(False), |
| len(sms_test_summary), |
| sms_test_fail_rate) |
| except Exception as e: |
| self.log.error( |
| 'Fail rate of SMS test over %s: ERROR (%s)', |
| wording, |
| e) |
| |
| if continuous_fail >= MAX_FAIL_COUNT: |
| self.log.error( |
| 'Failed more than %s times in succession. Test is terminated ' |
| 'forcedly.', |
| MAX_FAIL_COUNT) |
| break |
| |
| return result |
| |
| |
| @test_tracker_info(uuid="13d1a53b-66be-4ac1-b5ee-dfe4c5e4e4e1") |
| @TelephonyBaseTest.tel_test_wrap |
| def test_sms_4g_over_sgs(self): |
| """ Send/receive SMS over SGs to measure MO SMS setup time and SMS |
| delivery time. |
| |
| Test steps: |
| 1. Disable VoLTE. |
| 2. Send a SMS from MO UE and receive it by MT UE. |
| 3. Parse logcat of both MO and MT UEs to calculate MO SMS setup time |
| and SMS delivery time. |
| """ |
| return self._test_sms_4g() |
| |
| |
| @test_tracker_info(uuid="293e2955-b38b-4329-b686-fb31d9e46868") |
| @TelephonyBaseTest.tel_test_wrap |
| def test_sms_4g_over_ims(self): |
| """ Send/receive SMS over IMS to measure MO SMS setup time and SMS |
| delivery time. |
| |
| Test steps: |
| 1. Enable VoLTE. |
| 2. Send a SMS from MO UE and receive it by MT UE. |
| 3. Parse logcat of both MO and MT UEs to calculate MO SMS setup time |
| and SMS delivery time. |
| """ |
| return self._test_sms_4g(over_ims=True) |
| |
| |
| @test_tracker_info(uuid="862fec2d-8e23-482e-b45c-a42cad134022") |
| @TelephonyBaseTest.tel_test_wrap |
| def test_sms_iwlan(self): |
| """ Send/receive SMS on iwlan to measure MO SMS setup time and SMS |
| delivery time. |
| |
| Test steps: |
| 1. Send a SMS from MO UE and receive it by MT UE. |
| 2. Parse logcat of both MO and MT UEs to calculate MO SMS setup time |
| and SMS delivery time. |
| """ |
| return self._test_sms_4g(over_iwlan=True, over_ims=True) |
| |
| |
| def _test_mms_4g(self, over_iwlan=False): |
| """ Send/receive MMS on LTE to measure MO and MT MMS setup time |
| |
| Test steps: |
| 1. Enable VoLTE when over Wi-Fi (iwlan). Otherwise disable VoLTE. |
| 2. Send a MMS from MO UE and receive it by MT UE. |
| 3. Parse logcat of both MO and MT UEs to calculate MO and MT MMS |
| setup time. |
| |
| Args: |
| over_iwlan: True for over Wi-Fi and False for over cellular network |
| |
| Returns: |
| True if both sending and reception are successful. Otherwise False. |
| """ |
| ad_mo = self.android_devices[0] |
| ad_mt = self.android_devices[1] |
| |
| mo_sub_id, mt_sub_id, _ = get_subid_on_same_network_of_host_ad( |
| [ad_mo, ad_mt], |
| host_sub_id=None, |
| type="sms") |
| set_message_subid(ad_mt, mt_sub_id) |
| |
| cycle = self.mms_4g_test_cycle |
| phone_setup_func = phone_setup_csfb_for_subscription |
| mo_param = (self.log, ad_mo, mo_sub_id) |
| mt_param = (self.log, ad_mt, mt_sub_id) |
| wording = "LTE" |
| if over_iwlan: |
| cycle = self.mms_iwlan_test_cycle |
| phone_setup_func = phone_setup_iwlan_for_subscription |
| wording = "iwlan" |
| |
| mo_param = ( |
| self.log, |
| ad_mo, |
| mo_sub_id, |
| True, |
| WFC_MODE_CELLULAR_PREFERRED, |
| self.wifi_network_ssid, |
| self.wifi_network_pass) |
| |
| mt_param = ( |
| self.log, |
| ad_mt, |
| mt_sub_id, |
| True, |
| WFC_MODE_CELLULAR_PREFERRED, |
| self.wifi_network_ssid, |
| self.wifi_network_pass) |
| |
| phone_setup_tasks = [ |
| (phone_setup_func, mo_param), |
| (phone_setup_func, mt_param)] |
| if not multithread_func(self.log, phone_setup_tasks): |
| self.log.error("Phone Failed to Set Up Properly.") |
| return False |
| |
| if not over_iwlan: |
| wait_for_cell_data_connection_tasks = [ |
| (wait_for_cell_data_connection, (self.log, ad_mo, True)), |
| (wait_for_cell_data_connection, (self.log, ad_mt, True))] |
| if not multithread_func(self.log, wait_for_cell_data_connection_tasks): |
| return False |
| |
| time.sleep(WAIT_TIME_ANDROID_STATE_SETTLING) |
| |
| mms_test_summary = [] |
| result = True |
| continuous_fail = 0 |
| for attempt in range(cycle): |
| self.log.info( |
| '==================> MO/MT MMS on %s %s/%s <==================', |
| wording, |
| attempt+1, |
| cycle) |
| res = self.mms_test([ad_mo, ad_mt]) |
| mms_test_summary.append(res) |
| |
| if not res: |
| continuous_fail += 1 |
| if not multithread_func(self.log, phone_setup_tasks): |
| self.log.error("Phone Failed to Set Up Properly.") |
| result = False |
| break |
| |
| if not over_iwlan: |
| if not multithread_func( |
| self.log, wait_for_cell_data_connection_tasks): |
| result = False |
| break |
| self._take_bug_report( |
| self.test_name, begin_time=get_current_epoch_time()) |
| else: |
| time.sleep(random.randint(3,10)) |
| |
| if (attempt+1) % CALCULATE_EVERY_N_CYCLES == 0 or ( |
| attempt == cycle - 1) or continuous_fail >= MAX_FAIL_COUNT: |
| ( |
| mo_res, |
| mo_avg_setup_time, |
| mt_res, mt_avg_setup_time) = parse_mms(ad_mo, ad_mt) |
| |
| ad_mo.log.info('================== Sent MMS ==================') |
| print_nested_dict(ad_mo, mo_res) |
| ad_mt.log.info('================== Received MMS ==================') |
| print_nested_dict(ad_mt, mt_res) |
| |
| try: |
| ad_mo.log.info( |
| 'Average setup time of MO MMS on %s: %.2f sec.', |
| wording, mo_avg_setup_time) |
| except Exception as e: |
| ad_mo.log.error( |
| 'Average setup time of MO MMS on %s: ERROR (%s)', |
| wording, e) |
| |
| try: |
| ad_mt.log.info( |
| 'Average setup time of MT MMS on %s: %.2f sec.', |
| wording, mt_avg_setup_time) |
| except Exception as e: |
| ad_mt.log.error( |
| 'Average setup time of MT MMS on %s: ERROR (%s)', |
| wording, e) |
| |
| try: |
| mms_test_fail_rate = mms_test_summary.count( |
| False)/len(mms_test_summary) |
| self.log.info( |
| 'Fail rate of MMS test on LTE: %s/%s (%.2f)', |
| mms_test_summary.count(False), |
| len(mms_test_summary), |
| mms_test_fail_rate) |
| except Exception as e: |
| self.log.error( |
| 'Fail rate of MMS test on %s: ERROR (%s)', wording, e) |
| |
| if continuous_fail >= MAX_FAIL_COUNT: |
| self.log.error( |
| 'Failed more than %s times in succession. Test is terminated ' |
| 'forcedly.', |
| MAX_FAIL_COUNT) |
| break |
| |
| return result |
| |
| |
| @test_tracker_info(uuid="33d11da8-71f1-40d7-8fc7-86fdc83ce266") |
| @TelephonyBaseTest.tel_test_wrap |
| def test_mms_4g(self): |
| """ Send/receive MMS on LTE to measure MO and MT MMS setup time |
| |
| Test steps: |
| 1. Send a MMS from MO UE and receive it by MT UE. |
| 2. Parse logcat of both MO and MT UEs to calculate MO and MT MMS |
| setup time. |
| """ |
| return self._test_mms_4g() |
| |
| |
| @test_tracker_info(uuid="b8a8affa-6559-41d8-9de7-f74406da9ed5") |
| @TelephonyBaseTest.tel_test_wrap |
| def test_mms_iwlan(self): |
| """ Send/receive MMS on iwlan to measure MO and MT MMS setup time |
| |
| Test steps: |
| 1. Send a MMS from MO UE and receive it by MT UE. |
| 2. Parse logcat of both MO and MT UEs to calculate MO and MT MMS |
| setup time. |
| """ |
| return self._test_mms_4g(over_iwlan=True) |