• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.4
2#
3#   Copyright 2022 - Google
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16"""
17    Test Script for Telephony Stress Call Test
18"""
19
20import collections
21import json
22import os
23import random
24import time
25
26from acts import context
27from acts import signals
28from acts.libs.proc import job
29from acts.test_decorators import test_tracker_info
30from acts_contrib.test_utils.tel.loggers.telephony_metric_logger import TelephonyMetricLogger
31from acts_contrib.test_utils.tel.loggers.telephony_stress_metric_logger import TelephonyStressMetricLogger
32from acts_contrib.test_utils.tel.TelephonyBaseTest import TelephonyBaseTest
33from acts_contrib.test_utils.tel.tel_defines import GEN_3G
34from acts_contrib.test_utils.tel.tel_defines import GEN_4G
35from acts_contrib.test_utils.tel.tel_defines import GOOGLE_CBRS_CARRIER_ID
36from acts_contrib.test_utils.tel.tel_defines import GOOGLE_FI_CARRIER_ID
37from acts_contrib.test_utils.tel.tel_defines import INCALL_UI_DISPLAY_BACKGROUND
38from acts_contrib.test_utils.tel.tel_defines import MAX_WAIT_TIME_SMS_RECEIVE
39from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_WCDMA_ONLY
40from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_GLOBAL
41from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_CDMA
42from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_GSM_ONLY
43from acts_contrib.test_utils.tel.tel_defines import NETWORK_MODE_TDSCDMA_GSM_WCDMA
44from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_AFTER_MODE_CHANGE
45from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_CELLULAR_PREFERRED
46from acts_contrib.test_utils.tel.tel_defines import WFC_MODE_WIFI_PREFERRED
47from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_MESSAGE_SUB_ID
48from acts_contrib.test_utils.tel.tel_defines import WAIT_TIME_CHANGE_VOICE_SUB_ID
49from acts_contrib.test_utils.tel.tel_5g_test_utils import provision_device_for_5g
50from acts_contrib.test_utils.tel.tel_5g_utils import is_current_network_5g
51from acts_contrib.test_utils.tel.tel_data_utils import active_file_download_test
52from acts_contrib.test_utils.tel.tel_ims_utils import set_wfc_mode
53from acts_contrib.test_utils.tel.tel_logging_utils import extract_test_log
54from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers
55from acts_contrib.test_utils.tel.tel_logging_utils import start_sdm_loggers
56from acts_contrib.test_utils.tel.tel_logging_utils import start_adb_tcpdump
57from acts_contrib.test_utils.tel.tel_lookup_tables import is_rat_svd_capable
58from acts_contrib.test_utils.tel.tel_message_utils import sms_send_receive_verify
59from acts_contrib.test_utils.tel.tel_message_utils import mms_send_receive_verify
60from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_network_generation_for_subscription
61from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_csfb
62from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_iwlan
63from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_voice_3g
64from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_voice_2g
65from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_setup_volte
66from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_idle_iwlan
67from acts_contrib.test_utils.tel.tel_phone_setup_utils import phone_idle_volte
68from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index
69from acts_contrib.test_utils.tel.tel_subscription_utils import get_operatorname_from_slot_index
70from acts_contrib.test_utils.tel.tel_subscription_utils import get_carrierid_from_slot_index
71from acts_contrib.test_utils.tel.tel_subscription_utils import get_isopportunistic_from_slot_index
72from acts_contrib.test_utils.tel.tel_subscription_utils import set_subid_for_data
73from acts_contrib.test_utils.tel.tel_subscription_utils import set_subid_for_message
74from acts_contrib.test_utils.tel.tel_subscription_utils import set_subid_for_outgoing_call
75from acts_contrib.test_utils.tel.tel_subscription_utils import set_always_allow_mms_data
76from acts_contrib.test_utils.tel.tel_test_utils import STORY_LINE
77from acts_contrib.test_utils.tel.tel_test_utils import force_connectivity_metrics_upload
78from acts_contrib.test_utils.tel.tel_test_utils import get_device_epoch_time
79from acts_contrib.test_utils.tel.tel_test_utils import get_telephony_signal_strength
80from acts_contrib.test_utils.tel.tel_test_utils import synchronize_device_time
81from acts_contrib.test_utils.tel.tel_test_utils import set_preferred_network_mode_pref
82from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection
83from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection_by_ping
84from acts_contrib.test_utils.tel.tel_test_utils import verify_http_connection
85from acts_contrib.test_utils.tel.tel_data_utils import wait_for_data_connection
86from acts_contrib.test_utils.tel.tel_test_utils import is_current_data_on_cbrs
87from acts_contrib.test_utils.tel.tel_test_utils import check_voice_network_type
88from acts_contrib.test_utils.tel.tel_voice_utils import call_setup_teardown
89from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call
90from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call_by_adb
91from acts_contrib.test_utils.tel.tel_voice_utils import initiate_call
92from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call
93from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_3g
94from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_2g
95from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_csfb
96from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_iwlan
97from acts_contrib.test_utils.tel.tel_voice_utils import is_phone_in_call_volte
98from acts_contrib.test_utils.tel.tel_voice_utils import last_call_drop_reason
99from acts_contrib.test_utils.tel.tel_voice_utils import get_current_voice_rat
100from acts_contrib.test_utils.tel.tel_voice_utils import wait_for_call_id_clearing
101from acts_contrib.test_utils.tel.tel_voice_utils import wait_for_in_call_active
102from acts_contrib.test_utils.tel.tel_wifi_utils import ensure_wifi_connected
103from acts.utils import get_current_epoch_time
104from acts.utils import rand_ascii_str
105from acts.libs.utils.multithread import run_multithread_func
106
107EXCEPTION_TOLERANCE = 5
108BINDER_LOGS = ["/sys/kernel/debug/binder"]
109DEFAULT_FILE_DOWNLOADS = ["1MB", "5MB", "10MB", "20MB", "50MB"]
110RESULTS_LIST = {-2: "UNAVAILABLE_NETWORK_TYPE",
111                -1: "CALL_SETUP_FAILURE",
112                 0: "SUCCESS",
113                 1: "INITIATE_FAILED",
114                 2: "NO_RING_EVENT_OR_ANSWER_FAILED",
115                 3: "NO_CALL_ID_FOUND",
116                 4: "CALL_STATE_NOT_ACTIVE_DURING_ESTABLISHMENT",
117                 5: "AUDIO_STATE_NOT_INCALL_DURING_ESTABLISHMENT",
118                 6: "AUDIO_STATE_NOT_INCALL_AFTER_CONNECTED",
119                 7: "CALL_DROP_OR_WRONG_STATE_DURING_ESTABLISHMENT",
120                 8: "CALL_DROP_OR_WRONG_STATE_AFTER_CONNECTED",
121                 9: "CALL_HANGUP_FAIL",
122                 10: "CALL_ID_CLEANUP_FAIL"}
123voice_call_failure_dict = {}
124
125
126class TelLiveStressTest(TelephonyBaseTest):
127    def setup_class(self):
128        super(TelLiveStressTest, self).setup_class()
129        self.dut = self.android_devices[0]
130        self.single_phone_test = self.user_params.get("single_phone_test",
131                                                      False)
132        # supported file download methods: chrome, sl4a, curl
133        self.file_download_method = self.user_params.get(
134            "file_download_method", "curl")
135        self.get_binder_logs = self.user_params.get("get_binder_logs", False)
136        if len(self.android_devices) == 1:
137            self.single_phone_test = True
138        if self.single_phone_test:
139            self.android_devices = self.android_devices[:1]
140            self.call_server_number = self.user_params.get(
141                "call_server_number", STORY_LINE)
142            if self.file_download_method == "sl4a":
143                # with single device, do not use sl4a file download
144                # due to stability issue
145                self.file_download_method = "curl"
146        else:
147            self.android_devices = self.android_devices[:2]
148        self.sdm_log = self.user_params.get("sdm_log", False)
149        for ad in self.android_devices:
150            setattr(ad, "sdm_log", self.sdm_log)
151            ad.adb.shell("setprop nfc.debug_enable 1")
152            if self.user_params.get("turn_on_tcpdump", False):
153                start_adb_tcpdump(ad, interface="any", mask="all")
154        self.user_params["telephony_auto_rerun"] = 0
155        self.phone_call_iteration = int(
156            self.user_params.get("phone_call_iteration", 500))
157        self.max_phone_call_duration = int(
158            self.user_params.get("max_phone_call_duration", 600))
159        self.min_sleep_time = int(self.user_params.get("min_sleep_time", 30))
160        self.max_sleep_time = int(self.user_params.get("max_sleep_time", 60))
161        self.max_run_time = int(self.user_params.get("max_run_time", 14400))
162        self.max_sms_length = int(self.user_params.get("max_sms_length", 1000))
163        self.max_mms_length = int(self.user_params.get("max_mms_length", 160))
164        self.min_sms_length = int(self.user_params.get("min_sms_length", 1))
165        self.min_mms_length = int(self.user_params.get("min_mms_length", 1))
166        self.min_phone_call_duration = int(
167            self.user_params.get("min_phone_call_duration", 10))
168        self.crash_check_interval = int(
169            self.user_params.get("crash_check_interval", 300))
170        self.cbrs_check_interval = int(
171            self.user_params.get("cbrs_check_interval", 100))
172        self.dut_incall = False
173        self.wfc_nw_gen = self.user_params.get("wfc_nw_gen", None)
174        self.dsds_esim = self.user_params.get("dsds_esim", False)
175        self.cbrs_esim = self.user_params.get("cbrs_esim", False)
176        telephony_info = getattr(self.dut, "telephony", {})
177        self.dut_capabilities = telephony_info.get("capabilities", [])
178        self.dut_wfc_modes = telephony_info.get("wfc_modes", [])
179        self.gps_log_file = self.user_params.get("gps_log_file", None)
180        self.file_name_list = self.user_params.get("file_downloads", DEFAULT_FILE_DOWNLOADS)
181        self.tel_logger = TelephonyMetricLogger.for_test_case()
182        self.tel_logger = TelephonyStressMetricLogger.for_test_case()
183        self.result_collection = {"UNAVAILABLE_NETWORK_TYPE" : 0,
184                                  "CALL_SETUP_FAILURE" : 0,
185                                  "SUCCESS" : 0,
186                                  "INITIATE_FAILED" : 0,
187                                  "NO_RING_EVENT_OR_ANSWER_FAILED" : 0,
188                                  "NO_CALL_ID_FOUND" : 0,
189                                  "CALL_STATE_NOT_ACTIVE_DURING_ESTABLISHMENT" : 0,
190                                  "AUDIO_STATE_NOT_INCALL_DURING_ESTABLISHMENT" : 0,
191                                  "AUDIO_STATE_NOT_INCALL_AFTER_CONNECTED" : 0,
192                                  "CALL_DROP_OR_WRONG_STATE_DURING_ESTABLISHMENT" : 0,
193                                  "CALL_DROP_OR_WRONG_STATE_AFTER_CONNECTED": 0,
194                                  "CALL_HANGUP_FAIL": 0,
195                                  "CALL_ID_CLEANUP_FAIL": 0 }
196        self.call_stats_check = self.user_params.get("call_stats_check", False)
197        self.nsa_5g_for_stress = self.user_params.get("nsa_5g_for_stress", False)
198        self.nr_type = self.user_params.get("nr_type", 'nsa')
199        self.idle_period = self.user_params.get("idle_period", False)
200        self.min_pause_duration = int(self.user_params.get("min_pause_duration", 180))
201        self.max_pause_duration = int(self.user_params.get("max_pause_duration", 600))
202        self.call_pause_intervals = int(self.user_params.get("call_pause_intervals", 10))
203        self.pause=False
204        return True
205
206    def setup_test(self):
207        super(TelLiveStressTest, self).setup_test()
208        self.result_info = collections.defaultdict(int)
209        self._init_perf_json()
210        self.internet_connection_check_method = verify_internet_connection
211
212    def on_fail(self, test_name, begin_time):
213        pass
214
215    def _take_bug_report(self, test_name, begin_time):
216        if self._skip_bug_report(test_name):
217            return
218        src_dir = context.get_current_context().get_full_output_path()
219        dst_dir = os.path.join(self.log_path, test_name)
220
221        # Extract test_run_info.txt, test_run_debug.txt
222        for file_name in ("test_run_info.txt", "test_run_debug.txt"):
223            extract_test_log(self.log, os.path.join(src_dir, file_name),
224                             os.path.join(dst_dir,
225                                          "%s_%s" % (test_name, file_name)),
226                             "\[Test Case\] %s " % test_name)
227        super()._take_bug_report(test_name, begin_time)
228
229    def _ad_take_extra_logs(self, ad, test_name, begin_time):
230        src_file = os.path.join(ad.device_log_path,
231                                'adblog_%s_debug.txt' % ad.serial)
232        dst_file = os.path.join(ad.device_log_path, test_name,
233                                "%s_%s.logcat" % (ad.serial, test_name))
234        extract_test_log(self.log, src_file, dst_file, test_name)
235        return super()._ad_take_extra_logs(ad, test_name, begin_time)
236
237    def _setup_wfc(self):
238        for ad in self.android_devices:
239            if not ensure_wifi_connected(
240                    self.log,
241                    ad,
242                    self.wifi_network_ssid,
243                    self.wifi_network_pass,
244                    retries=3):
245                ad.log.error("Bringing up Wifi connection fails.")
246                return False
247            ad.log.info("Phone WIFI is connected successfully.")
248            if not set_wfc_mode(self.log, ad, WFC_MODE_WIFI_PREFERRED):
249                ad.log.error("Phone failed to enable Wifi-Calling.")
250                return False
251            ad.log.info("Phone is set in Wifi-Calling successfully.")
252            if not phone_idle_iwlan(self.log, ad):
253                ad.log.error("Phone is not in WFC enabled state.")
254                return False
255            ad.log.info("Phone is in WFC enabled state.")
256        return True
257
258    def _setup_wfc_apm(self):
259        for ad in self.android_devices:
260            if not phone_setup_iwlan(
261                    self.log, ad, True, WFC_MODE_CELLULAR_PREFERRED,
262                    self.wifi_network_ssid, self.wifi_network_pass,
263                    nw_gen=self.wfc_nw_gen, nr_type= self.nr_type):
264                ad.log.error("Failed to setup WFC.")
265                return False
266        return True
267
268    def _setup_lte_volte_enabled(self):
269        for ad in self.android_devices:
270            if not phone_setup_volte(self.log, ad):
271                ad.log.error("Phone failed to enable VoLTE.")
272                return False
273            ad.log.info("Phone VOLTE is enabled successfully.")
274            # TODO: b/186865335 Move 5G methods to NR directory
275            if self.nsa_5g_for_stress:
276                if not provision_device_for_5g(
277                        self.log, ad, nr_type=self.nr_type):
278                    ad.log.error("Phone failed to attach 5G NSA.")
279                    return False
280                ad.log.info("Phone 5G NSA VOLTE is enabled successfully.")
281        return True
282
283    def _setup_lte_volte_disabled(self):
284        for ad in self.android_devices:
285            if not phone_setup_csfb(self.log, ad):
286                ad.log.error("Phone failed to setup CSFB.")
287                return False
288            ad.log.info("Phone VOLTE is disabled successfully.")
289        return True
290
291    def _setup_3g(self):
292        for ad in self.android_devices:
293            if not phone_setup_voice_3g(self.log, ad):
294                ad.log.error("Phone failed to setup 3g.")
295                return False
296            ad.log.info("Phone RAT 3G is enabled successfully.")
297        return True
298
299    def _setup_2g(self):
300        for ad in self.android_devices:
301            if not phone_setup_voice_2g(self.log, ad):
302                ad.log.error("Phone failed to setup 2g.")
303                return False
304            ad.log.info("RAT 2G is enabled successfully.")
305        return True
306
307    def _get_network_rat(self, slot_id):
308        rat = self.dut.adb.getprop("gsm.network.type")
309        if "," in rat:
310            if self.dsds_esim:
311                rat = rat.split(',')[slot_id]
312            else:
313                (rat1, rat2) = rat.split(',')
314                if rat1 == "Unknown":
315                    rat = rat2
316                else:
317                    rat = rat1
318        return rat
319
320    def _send_message(self, max_wait_time=2 * MAX_WAIT_TIME_SMS_RECEIVE):
321        slot_id_rx = None
322        if self.pause and self.idle_period:
323            self.log.info("PAUSE MESSAGE TEST FOR %s seconds", self.pause_duration)
324            time.sleep(self.pause_duration)
325        if self.single_phone_test:
326            ads = [self.dut, self.dut]
327        else:
328            ads = self.android_devices[:]
329            random.shuffle(ads)
330        slot_id = random.randint(0,1)
331        if self.dsds_esim:
332            sub_id = get_subid_from_slot_index(self.log, ads[0], slot_id)
333            ads[0].log.info("Message - MO - slot_Id %d", slot_id)
334            set_subid_for_message(ads[0], sub_id)
335            time.sleep(WAIT_TIME_CHANGE_MESSAGE_SUB_ID)
336            slot_id_rx = random.randint(0,1)
337            ads[1].log.info("Message - MT - slot_id %d", slot_id_rx)
338        selection = random.randrange(0, 2)
339        message_type_map = {0: "SMS", 1: "MMS"}
340        max_length_map = {0: self.max_sms_length, 1: self.max_mms_length}
341        min_length_map = {0: self.min_sms_length, 1: self.min_mms_length}
342        length = random.randrange(min_length_map[selection],
343                                  max_length_map[selection] + 1)
344        message_func_map = {
345            0: sms_send_receive_verify,
346            1: mms_send_receive_verify
347        }
348        rat = self._get_network_rat(slot_id)
349        self.dut.log.info("Network in RAT %s", rat)
350        if self.dut_incall and not is_rat_svd_capable(rat.upper()):
351            self.dut.log.info("In call data not supported, test SMS only")
352            selection = 0
353        message_type = message_type_map[selection]
354        the_number = self.result_info["%s Total" % message_type] + 1
355        begin_time = get_device_epoch_time(self.dut)
356        test_name = "%s_No_%s_%s" % (self.test_name, the_number, message_type)
357        if self.sdm_log:
358            start_sdm_loggers(self.log, self.android_devices)
359        else:
360            start_qxdm_loggers(self.log, self.android_devices)
361        log_msg = "[Test Case] %s" % test_name
362        self.log.info("%s begin", log_msg)
363        for ad in self.android_devices:
364            if self.user_params.get("turn_on_tcpdump", False):
365                start_adb_tcpdump(ad, interface="any", mask="all")
366            if not getattr(ad, "messaging_droid", None):
367                ad.messaging_droid, ad.messaging_ed = ad.get_droid()
368                ad.messaging_ed.start()
369            else:
370                try:
371                    if not ad.messaging_droid.is_live:
372                        ad.messaging_droid, ad.messaging_ed = ad.get_droid()
373                        ad.messaging_ed.start()
374                    else:
375                        ad.messaging_ed.clear_all_events()
376                except Exception:
377                    ad.log.info("Create new sl4a session for messaging")
378                    ad.messaging_droid, ad.messaging_ed = ad.get_droid()
379                    ad.messaging_ed.start()
380            ad.messaging_droid.logI("[BEGIN]%s" % log_msg)
381
382        text = "%s:" % test_name
383        text_length = len(text)
384        if length < text_length:
385            text = text[:length]
386        else:
387            text += rand_ascii_str(length - text_length)
388        message_content_map = {0: [text], 1: [(test_name, text, None)]}
389
390        result = message_func_map[selection](self.log, ads[0], ads[1],
391                                             message_content_map[selection],
392                                             max_wait_time,
393                                             slot_id_rx=slot_id_rx)
394        self.log.info("%s end", log_msg)
395        for ad in self.android_devices:
396            ad.messaging_droid.logI("[END]%s" % log_msg)
397        if not result:
398            self.result_info["%s Total" % message_type] += 1
399            if message_type == "SMS":
400                self.log.error("%s fails", log_msg)
401                self.result_info["%s Failure" % message_type] += 1
402            else:
403                rat = self._get_network_rat(slot_id)
404                self.dut.log.info("Network in RAT %s", rat)
405                if self.dut_incall and not is_rat_svd_capable(rat.upper()):
406                    self.dut.log.info(
407                        "In call data not supported, MMS failure expected")
408                    self.result_info["Expected In-call MMS failure"] += 1
409                    return True
410                else:
411                    self.log.error("%s fails", log_msg)
412                    self.result_info["MMS Failure"] += 1
413            try:
414                self._take_bug_report(test_name, begin_time)
415            except Exception as e:
416                self.log.exception(e)
417            return False
418        else:
419            self.result_info["%s Total" % message_type] += 1
420            self.log.info("%s succeed", log_msg)
421            self.result_info["%s Success" % message_type] += 1
422            return True
423
424    def _make_phone_call(self, call_verification_func=None, voice_stress_only = False):
425        ads = self.android_devices[:]
426        slot_id_callee = None
427        if not voice_stress_only:
428            if not self.single_phone_test:
429                random.shuffle(ads)
430        if self.dsds_esim:
431            slot_id = random.randint(0,1)
432            sub_id = get_subid_from_slot_index(self.log, ads[0], slot_id)
433            ads[0].log.info("Voice - MO - slot_Id %d", slot_id)
434            set_subid_for_outgoing_call(ads[0], sub_id)
435            time.sleep(WAIT_TIME_CHANGE_VOICE_SUB_ID)
436            slot_id_callee = random.randint(0,1)
437            ads[1].log.info("Voice - MT - slot_id %d", slot_id_callee)
438        the_number = self.result_info["Call Total"] + 1
439        if voice_stress_only:
440            duration = 30
441        else:
442            duration = random.randrange(self.min_phone_call_duration,
443                                    self.max_phone_call_duration)
444        result = True
445        test_name = "%s_No_%s_phone_call" % (self.test_name, the_number)
446        log_msg = "[Test Case] %s" % test_name
447        self.log.info("%s for %s seconds begin", log_msg, duration)
448
449        if self.idle_period:
450            call_iteration = self.call_pause_intervals if self.call_pause_intervals != 0 else 1
451            if the_number % call_iteration == 0:
452                self.pause=True
453                self.pause_duration = random.randrange(
454                    self.min_pause_duration, self.max_pause_duration)
455                self.log.info("PAUSE CALLING TEST FOR %s seconds", self.pause_duration)
456                time.sleep(self.pause_duration)
457                self.pause=False
458
459        if self.call_stats_check:
460            voice_type_init = check_voice_network_type(ads, voice_init=True)
461        else:
462            voice_type_init = None
463
464        begin_time = get_device_epoch_time(ads[0])
465        for ad in self.android_devices:
466            if self.user_params.get("turn_on_tcpdump", False):
467                start_adb_tcpdump(ad, interface="any", mask="all")
468            if not getattr(ad, "droid", None):
469                ad.droid, ad.ed = ad.get_droid()
470                ad.ed.start()
471            else:
472                try:
473                    if not ad.droid.is_live:
474                        ad.droid, ad.ed = ad.get_droid()
475                        ad.ed.start()
476                    else:
477                        ad.ed.clear_all_events()
478                except Exception:
479                    ad.log.info("Create new sl4a session for phone call")
480                    ad.droid, ad.ed = ad.get_droid()
481                    ad.ed.start()
482            ad.droid.logI("[BEGIN]%s" % log_msg)
483        if self.sdm_log:
484            for ad in ads:
485                ad.adb.shell("i2cset -fy 3 64 6 1 b", ignore_status=True)
486                ad.adb.shell("i2cset -fy 3 65 6 1 b", ignore_status=True)
487            start_sdm_loggers(self.log, self.android_devices)
488        else:
489            start_qxdm_loggers(self.log, self.android_devices)
490        if self.cbrs_esim:
491            self._cbrs_data_check_test(begin_time, expected_cbrs=True,
492                                       test_time="before")
493        failure_reasons = set()
494        self.dut_incall = True
495        if self.single_phone_test:
496            call_setup_result = initiate_call(
497                self.log,
498                self.dut,
499                self.call_server_number,
500                incall_ui_display=INCALL_UI_DISPLAY_BACKGROUND
501            ) and wait_for_in_call_active(self.dut, 60, 3)
502        else:
503            call_setup_result = call_setup_teardown(
504                self.log,
505                ads[0],
506                ads[1],
507                ad_hangup=None,
508                verify_caller_func=call_verification_func,
509                verify_callee_func=call_verification_func,
510                wait_time_in_call=0,
511                incall_ui_display=INCALL_UI_DISPLAY_BACKGROUND,
512                slot_id_callee=slot_id_callee,
513                call_stats_check=self.call_stats_check,
514                voice_type_init=voice_type_init,
515                result_info = self.result_info)
516
517        if not call_setup_result:
518            get_telephony_signal_strength(ads[0])
519            if not self.single_phone_test:
520                get_telephony_signal_strength(ads[1])
521            call_logs = ads[0].search_logcat(
522                "ActivityManager: START u0 {act=android.intent.action.CALL",
523                begin_time)
524            messaging_logs = ads[0].search_logcat(
525                "com.google.android.apps.messaging/.ui.conversation.ConversationActivity",
526                begin_time)
527            if call_logs and messaging_logs:
528                if (messaging_logs[-1]["datetime_obj"] -
529                        call_logs[-1]["datetime_obj"]).seconds < 5:
530                    ads[0].log.info(
531                        "Call setup failure due to simultaneous activities")
532                    self.result_info[
533                        "Call Setup Failure With Simultaneous Activity"] += 1
534                    return True
535            self.log.error("%s: Setup Call failed.", log_msg)
536            failure_reasons.add("Setup")
537            if self.call_stats_check:
538                network = ads[0].droid.telephonyGetCurrentVoiceNetworkType()
539                ads[0].log.debug("Call Setup failure RAT is %s", network)
540                self.result_info["Call Failures"] = self._update_call_failure(str(ads[0].serial),
541                                                                             "Call Setup Failure",
542                                                                             network)
543            result = False
544        else:
545            elapsed_time = 0
546            check_interval = 5
547            if self.sdm_log:
548                for ad in ads:
549                    ad.adb.shell("i2cset -fy 3 64 6 1 b", ignore_status=True)
550                    ad.adb.shell("i2cset -fy 3 65 6 1 b", ignore_status=True)
551            if self.cbrs_esim:
552                time.sleep(5)
553                self._cbrs_data_check_test(begin_time, expected_cbrs=False,
554                                           test_time="during")
555            while (elapsed_time < duration):
556                check_interval = min(check_interval, duration - elapsed_time)
557                time.sleep(check_interval)
558                elapsed_time += check_interval
559                time_message = "at <%s>/<%s> second." % (elapsed_time,
560                                                         duration)
561                for ad in ads:
562                    get_telephony_signal_strength(ad)
563                    if not call_verification_func(self.log, ad):
564                        ad.log.warning("Call is NOT in correct %s state at %s",
565                                       call_verification_func.__name__,
566                                       time_message)
567                        if call_verification_func.__name__ == "is_phone_in_call_iwlan":
568                            if is_phone_in_call(self.log, ad):
569                                if getattr(ad, "data_rat_state_error_count",
570                                           0) < 1:
571                                    setattr(ad, "data_rat_state_error_count",
572                                            1)
573                                    continue
574                        failure_reasons.add("Maintenance")
575                        if self.call_stats_check:
576                            network = ad.droid.telephonyGetCurrentVoiceNetworkType()
577                            ad.log.debug("Call Maintenance failure RAT is %s", network)
578                            self.result_info["Call Failures"] = self._update_call_failure(
579                                                                      str(ad.serial),
580                                                                      "Call Maintenance Failure",
581                                                                      network)
582                        last_call_drop_reason(ad, begin_time)
583                        hangup_call(self.log, ads[0])
584                        result = False
585                    else:
586                        ad.log.info("Call is in correct %s state at %s",
587                                    call_verification_func.__name__,
588                                    time_message)
589                if not result:
590                    break
591        if not hangup_call(self.log, ads[0]):
592            failure_reasons.add("Teardown")
593            result = False
594        else:
595            if self.nsa_5g_for_stress:
596                for ad in (ads[0], ads[1]):
597                    if not is_current_network_5g(ad, nr_type=self.nr_type):
598                        ad.log.error("Phone not attached on 5G")
599        for ad in ads:
600            if not wait_for_call_id_clearing(ad,
601                                             []) or ad.droid.telecomIsInCall():
602                ad.log.error("Fail to hang up call")
603                failure_reasons.add("Teardown")
604                result = False
605        self.result_info["Call Total"] += 1
606        for ad in self.android_devices:
607            try:
608                ad.droid.logI("[END]%s" % log_msg)
609            except:
610                pass
611        self.log.info("%s end", log_msg)
612        self.dut_incall = False
613        if self.cbrs_esim:
614            time.sleep(30)
615            self._cbrs_data_check_test(begin_time, expected_cbrs=True,
616                                       test_time="after")
617        if not result:
618            self.log.info("%s failed", log_msg)
619            if self.gps_log_file:
620                gps_info = job.run(
621                    "tail %s" % self.gps_log_file, ignore_status=True)
622                if gps_info.stdout:
623                    gps_log_path = os.path.join(self.log_path, test_name)
624                    os.makedirs(gps_log_path, exist_ok=True)
625                    job.run(
626                        "tail %s > %s" %
627                        (self.gps_log_file,
628                         os.path.join(gps_log_path, "gps_logs.txt")),
629                        ignore_status=True)
630                    self.log.info("gps log:\n%s", gps_info.stdout)
631                else:
632                    self.log.warning("Fail to get gps log %s",
633                                     self.user_params["gps_log_file"])
634            for reason in failure_reasons:
635                self.result_info["Call %s Failure" % reason] += 1
636            if self.get_binder_logs:
637                for ad in ads:
638                    log_path = os.path.join(self.log_path, test_name,
639                                        "%s_binder_logs" % ad.serial)
640                    os.makedirs(log_path, exist_ok=True)
641                    ad.pull_files(BINDER_LOGS, log_path)
642            try:
643                self._take_bug_report(test_name, begin_time)
644            except Exception as e:
645                self.log.exception(e)
646            for ad in ads:
647                if ad.droid.telecomIsInCall():
648                    hangup_call_by_adb(ad)
649        else:
650            self.log.info("%s test succeed", log_msg)
651            self.result_info["Call Success"] += 1
652            if self.result_info["Call Total"] % 50 == 0:
653                for ad in ads:
654                    synchronize_device_time(ad)
655                    force_connectivity_metrics_upload(ad)
656                    if self.get_binder_logs:
657                        log_path = os.path.join(self.log_path, test_name,
658                                                "%s_binder_logs" % ad.serial)
659                        os.makedirs(log_path, exist_ok=True)
660                        ad.pull_files(BINDER_LOGS, log_path)
661        return result
662
663    def _prefnetwork_mode_change(self, sub_id):
664        # ModePref change to non-LTE
665        begin_time = get_device_epoch_time(self.dut)
666        if self.sdm_log:
667            start_sdm_loggers(self.log, self.android_devices)
668        else:
669            start_qxdm_loggers(self.log, self.android_devices)
670        self.result_info["Network Change Request Total"] += 1
671        test_name = "%s_network_change_iter_%s" % (
672            self.test_name, self.result_info["Network Change Request Total"])
673        log_msg = "[Test Case] %s" % test_name
674        self.log.info("%s begin", log_msg)
675        self.dut.droid.logI("[BEGIN]%s" % log_msg)
676        network_preference_list = [
677            NETWORK_MODE_TDSCDMA_GSM_WCDMA, NETWORK_MODE_WCDMA_ONLY,
678            NETWORK_MODE_GLOBAL, NETWORK_MODE_CDMA, NETWORK_MODE_GSM_ONLY
679        ]
680        network_preference = random.choice(network_preference_list)
681        set_preferred_network_mode_pref(self.log, self.dut, sub_id,
682                                        network_preference)
683        time.sleep(WAIT_TIME_AFTER_MODE_CHANGE)
684        self.dut.log.info("Current Voice RAT is %s",
685                          get_current_voice_rat(self.log, self.dut))
686
687        # ModePref change back to with LTE
688        if not phone_setup_volte(self.log, self.dut):
689            self.dut.log.error("Phone failed to enable VoLTE.")
690            self.result_info["VoLTE Setup Failure"] += 1
691            self.dut.droid.logI("%s end" % log_msg)
692            self.dut.log.info("[END]%s", log_msg)
693            try:
694                self._ad_take_extra_logs(self.dut, test_name, begin_time)
695                self._ad_take_bugreport(self.dut, test_name, begin_time)
696            except Exception as e:
697                self.log.exception(e)
698            return False
699        else:
700            self.result_info["VoLTE Setup Success"] += 1
701            return True
702
703    def _mobile_data_toggling(self, setup="volte"):
704        # ModePref change to non-LTE
705        begin_time = get_device_epoch_time(self.dut)
706        if self.sdm_log:
707            start_sdm_loggers(self.log, self.android_devices)
708        else:
709            start_qxdm_loggers(self.log, self.android_devices)
710        result = True
711        self.result_info["Data Toggling Request Total"] += 1
712        test_name = "%s_data_toggling_iter_%s" % (
713            self.test_name, self.result_info["Data Toggling Request Total"])
714        log_msg = "[Test Case] %s" % test_name
715        self.log.info("%s begin", log_msg)
716        self.dut.droid.logI("[BEGIN]%s" % log_msg)
717        self.dut.adb.shell("svc data disable")
718        time.sleep(WAIT_TIME_AFTER_MODE_CHANGE)
719        self.dut.adb.shell("svc data enable")
720        if not self._check_data():
721            result = False
722        elif setup == "volte" and not phone_idle_volte(self.log, self.dut):
723            result = False
724        self.dut.droid.logI("%s end" % log_msg)
725        self.dut.log.info("[END]%s", log_msg)
726        if not result:
727            self.result_info["Data Toggling Failure"] += 1
728            try:
729                self._ad_take_extra_logs(self.dut, test_name, begin_time)
730                self._ad_take_bugreport(self.dut, test_name, begin_time)
731            except Exception as e:
732                self.log.exception(e)
733            return False
734        else:
735            self.result_info["Data Toggling Success"] += 1
736            return True
737
738    def _get_result_message(self):
739        msg_list = [
740            "%s: %s" % (count, self.result_info[count])
741            for count in sorted(self.result_info.keys())
742        ]
743        return ", ".join(msg_list)
744
745    def _write_perf_json(self):
746        json_str = json.dumps(self.perf_data, indent=4, sort_keys=True)
747        with open(self.perf_file, 'w') as f:
748            f.write(json_str)
749
750    def _init_perf_json(self):
751        self.perf_file = os.path.join(self.log_path, "%s_perf_data_%s.json" %
752                                      (self.test_name, self.begin_time))
753        self.perf_data = self.dut.build_info.copy()
754        self.perf_data["build_fingerprint"] = self.dut.adb.getprop(
755            "ro.build.fingerprint")
756        self.perf_data["model"] = self.dut.model
757        self.perf_data["carrier"] = self.dut.adb.getprop(
758            "gsm.sim.operator.alpha")
759        self._write_perf_json()
760
761    def _update_perf_json(self):
762        for result_key, result_value in self.result_info.items():
763            self.perf_data[result_key] = result_value
764        self._write_perf_json()
765
766    def crash_check_test(self):
767        failure = 0
768        while time.time() < self.finishing_time:
769            try:
770                self.log.info(dict(self.result_info))
771                self._update_perf_json()
772                begin_time = get_device_epoch_time(self.dut)
773                run_time_in_seconds = (begin_time - self.begin_time) / 1000
774                test_name = "%s_crash_%s_seconds_after_start" % (
775                    self.test_name, run_time_in_seconds)
776                time.sleep(self.crash_check_interval)
777                for ad in self.android_devices:
778                    crash_report = ad.check_crash_report(
779                        test_name, begin_time, log_crash_report=True)
780                    if crash_report:
781                        ad.log.error("Find new crash reports %s", crash_report)
782                        failure += 1
783                        self.result_info["Crashes"] += len(crash_report)
784                        for crash in crash_report:
785                            if "ramdump_modem" in crash:
786                                self.result_info["Crashes-Modem"] += 1
787                        try:
788                            ad.take_bug_report(test_name, begin_time)
789                        except Exception as e:
790                            self.log.exception(e)
791            except Exception as e:
792                self.log.error("Exception error %s", str(e))
793                self.result_info["Exception Errors"] += 1
794            self.log.info("Crashes found: %s", failure)
795            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
796                self.log.error("Too many exception errors, quit test")
797                return False
798        if failure:
799            return False
800        else:
801            return True
802
803    def _update_call_failure(self, dut, key, network):
804        if dut not in voice_call_failure_dict.keys():
805            voice_call_failure_dict[dut] = {key:{network:0}}
806        if key not in voice_call_failure_dict[dut].keys():
807            voice_call_failure_dict[dut].update({key:{network:0}})
808        if network not in voice_call_failure_dict[dut][key].keys():
809            voice_call_failure_dict[dut][key].update({network:0})
810        voice_call_failure_dict[dut][key][network] += 1
811        return voice_call_failure_dict
812
813    def _cbrs_data_check_test(self, begin_time, expected_cbrs=True,
814                              test_time="before"):
815        cbrs_fail_count = 0
816        the_number = self.result_info["CBRS Total"] + 1
817        test_name = "%s_cbrs_%s_call_No_%s" % (self.test_name,
818                                               test_time, the_number)
819        for ad in self.android_devices:
820            current_state = is_current_data_on_cbrs(ad, ad.cbrs)
821            if current_state == expected_cbrs:
822                self.result_info["CBRS-Check-Pass"] += 1
823            else:
824                self.result_info["CBRS-Check-Fail"] += 1
825                cbrs_fail_count += 1
826                try:
827                    self._ad_take_extra_logs(ad, test_name, begin_time)
828                    self._ad_take_bugreport(ad, test_name, begin_time)
829                except Exception as e:
830                    self.log.warning(e)
831        if cbrs_fail_count > 0:
832            ad.log.error("Found %d checks failed, expected cbrs %s",
833                         cbrs_fail_count, expected_cbrs)
834            cbrs_fail_count += 1
835        self.result_info["CBRS Total"] += 1
836        return True
837
838    def call_test(self, call_verification_func=None):
839        while time.time() < self.finishing_time:
840            time.sleep(
841                random.randrange(self.min_sleep_time, self.max_sleep_time))
842            try:
843                self._make_phone_call(call_verification_func)
844            except Exception as e:
845                self.log.exception("Exception error %s", str(e))
846                self.result_info["Exception Errors"] += 1
847            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
848                self.log.error("Too many exception errors, quit test")
849                return False
850            self.log.info("%s", dict(self.result_info))
851        if any([
852                self.result_info["Call Setup Failure"],
853                self.result_info["Call Maintenance Failure"],
854                self.result_info["Call Teardown Failure"]
855        ]):
856            return False
857        else:
858            return True
859
860    def message_test(self, max_wait_time=MAX_WAIT_TIME_SMS_RECEIVE):
861        while time.time() < self.finishing_time:
862            try:
863                self._send_message(max_wait_time=max_wait_time)
864            except Exception as e:
865                self.log.exception("Exception error %s", str(e))
866                self.result_info["Exception Errors"] += 1
867            self.log.info(dict(self.result_info))
868            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
869                self.log.error("Too many exception errors, quit test")
870                return False
871            time.sleep(
872                random.randrange(self.min_sleep_time, self.max_sleep_time))
873        if self.result_info["SMS Failure"] or (
874                self.result_info["MMS Failure"] / self.result_info["MMS Total"]
875                > 0.3):
876            return False
877        else:
878            return True
879
880    def _data_download(self, file_names=[]):
881        begin_time = get_current_epoch_time()
882        slot_id = random.randint(0,1)
883        if self.pause and self.idle_period:
884            self.log.info("PAUSE DATA TEST FOR %s seconds", self.pause_duration)
885            time.sleep(self.pause_duration)
886        if self.dsds_esim:
887            sub_id = get_subid_from_slot_index(self.log, self.dut, slot_id)
888            self.dut.log.info("Data - slot_Id %d", slot_id)
889            set_subid_for_data(self.dut, sub_id)
890            self.dut.droid.telephonyToggleDataConnection(True)
891        if self.sdm_log:
892            start_sdm_loggers(self.log, self.android_devices)
893        else:
894            start_qxdm_loggers(self.log, self.android_devices)
895        self.dut.log.info(dict(self.result_info))
896        selection = random.randrange(0, len(file_names))
897        file_name = file_names[selection]
898        self.result_info["Internet Connection Check Total"] += 1
899
900        rat = self._get_network_rat(slot_id)
901        if not self.internet_connection_check_method(self.log, self.dut):
902            self.dut.log.info("Network in RAT %s", rat)
903            if self.dut_incall and not is_rat_svd_capable(rat.upper()):
904                self.result_info[
905                    "Expected Incall Internet Connection Check Failure"] += 1
906                return True
907            else:
908                self.result_info["Internet Connection Check Failure"] += 1
909                test_name = "%s_internet_connection_No_%s_failure" % (
910                    self.test_name,
911                    self.result_info["Internet Connection Check Failure"])
912                try:
913                    self._ad_take_extra_logs(self.dut, test_name, begin_time)
914                    self._ad_take_bugreport(self.dut, test_name, begin_time)
915                except Exception as e:
916                    self.log.exception(e)
917                return False
918        else:
919            self.result_info["Internet Connection Check Success"] += 1
920
921        self.result_info["File Download Total"] += 1
922        self.result_info["Data Download Total"] += int(file_name[:-2])
923        if not active_file_download_test(
924                self.log, self.dut, file_name,
925                method=self.file_download_method):
926            self.result_info["File Download Failure"] += 1
927            self.result_info["Data Failure Total"] += int(file_name[:-2])
928            if self.result_info["File Download Failure"] == 1:
929                try:
930                    self._ad_take_extra_logs(
931                        self.dut, "%s_file_download_failure" % self.test_name,
932                        begin_time)
933                    self._ad_take_bugreport(
934                        self.dut, "%s_file_download_failure" % self.test_name,
935                        begin_time)
936                except Exception as e:
937                    self.log.exception(e)
938            return False
939        else:
940            self.result_info["File Download Success"] += 1
941            self.result_info["Data Success Total"] += int(file_name[:-2])
942            return True
943
944    def data_test(self):
945        while time.time() < self.finishing_time:
946            try:
947                self._data_download(self.file_name_list)
948            except Exception as e:
949                self.log.error("Exception error %s", str(e))
950                self.result_info["Exception Errors"] += 1
951            self.log.info("%s", dict(self.result_info))
952            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
953                self.log.error("Too many exception errors, quit test")
954                return False
955            time.sleep(
956                random.randrange(self.min_sleep_time, self.max_sleep_time))
957        if self.result_info["Internet Connection Check Failure"]:
958            return False
959        else:
960            return True
961
962    def _check_data(self):
963        self.result_info["Data Connection Check Total"] += 1
964        if not wait_for_data_connection(self.log, self.dut, True):
965            self.result_info["Data Connection Setup Failure"] += 1
966            return False
967        if not self.internet_connection_check_method(self.log, self.dut):
968            rat = self.dut.adb.getprop("gsm.network.type")
969            self.dut.log.info("Network in RAT %s", rat)
970            self.result_info["Internet Connection Check Failure"] += 1
971            return False
972        return True
973
974    def _data_call_test(self, sub_id, generation):
975        self.dut.log.info(dict(self.result_info))
976        begin_time = get_device_epoch_time(self.dut)
977        if self.sdm_log:
978            start_sdm_loggers(self.log, self.android_devices)
979        else:
980            start_qxdm_loggers(self.log, self.android_devices)
981        self.result_info["Network Change Request Total"] += 1
982        test_name = "%s_network_change_test_iter_%s" % (
983            self.test_name, self.result_info["Network Change Request Total"])
984        log_msg = "[Test Case] %s" % test_name
985        self.log.info("%s begin", log_msg)
986        self.dut.droid.logI("[BEGIN]%s" % log_msg)
987        if not ensure_network_generation_for_subscription(
988                self.log, self.dut, sub_id,
989                generation) or not self._check_data():
990            self.result_info["Network Change Failure"] += 1
991            self.dut.droid.logI("%s end" % log_msg)
992            self.dut.log.info("[END]%s", log_msg)
993            try:
994                self._ad_take_extra_logs(self.dut, test_name, begin_time)
995                self._ad_take_bugreport(self.dut, test_name, begin_time)
996            except Exception as e:
997                self.log.warning(e)
998            return False
999        if not self._mobile_data_toggling(setup=None):
1000            return False
1001        return True
1002
1003    def data_call_stress_test(self):
1004        result = True
1005        sub_id = self.dut.droid.subscriptionGetDefaultSubId()
1006        while time.time() < self.finishing_time:
1007            for generation in (GEN_4G, GEN_3G):
1008                try:
1009                    if not self._data_call_test(sub_id, generation):
1010                        result = False
1011                except Exception as e:
1012                    self.log.error("Exception error %s", str(e))
1013                    self.result_info["Exception Errors"] += 1
1014            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
1015                self.log.error("Too many exception errors, quit test")
1016                return False
1017        return result
1018
1019    def check_incall_data(self):
1020        if verify_internet_connection_by_ping(self.log, self.dut):
1021            self.internet_connection_check_method = verify_internet_connection_by_ping
1022        elif verify_http_connection(self.log, self.dut):
1023            self.internet_connection_check_method = verify_http_connection
1024        else:
1025            self.dut.log.error("Data test failed")
1026            raise signals.TestFailure("Data check failed")
1027        if self.single_phone_test:
1028            if not initiate_call(
1029                    self.log, self.dut,
1030                    self.call_server_number) and wait_for_in_call_active(
1031                        self.dut, 60, 3):
1032                self._take_bug_report(self.test_name, self.begin_time)
1033                raise signals.TestFailure("Unable to make phone call")
1034        else:
1035            if not call_setup_teardown(
1036                    self.log, self.dut, self.android_devices[1],
1037                    ad_hangup=None):
1038                self._take_bug_report(self.test_name, self.begin_time)
1039                raise signals.TestFailure("Unable to make phone call")
1040        voice_rat = self.dut.droid.telephonyGetCurrentVoiceNetworkType()
1041        data_rat = self.dut.droid.telephonyGetCurrentDataNetworkType()
1042        self.dut.log.info("Voice in RAT %s, Data in RAT %s", voice_rat,
1043                          data_rat)
1044        try:
1045            if "wfc" in self.test_name or is_rat_svd_capable(
1046                    voice_rat.upper()) and is_rat_svd_capable(
1047                        data_rat.upper()):
1048                self.dut.log.info("Capable for simultaneous voice and data")
1049
1050                if not self.internet_connection_check_method(
1051                        self.log, self.dut):
1052                    self.dut.log.error("Incall data check failed")
1053                    raise signals.TestFailure("Incall data check failed")
1054                else:
1055                    return True
1056            else:
1057                self.dut.log.info(
1058                    "Not capable for simultaneous voice and data")
1059                return False
1060            hangup_call(self.log, self.dut)
1061        finally:
1062            for ad in self.android_devices:
1063                if ad.droid.telecomIsInCall():
1064                    hangup_call(self.log, ad)
1065
1066    def parallel_tests(self, setup_func=None, call_verification_func=None):
1067        self.log.info(self._get_result_message())
1068        if setup_func and not setup_func():
1069            msg = "%s setup %s failed" % (self.test_name, setup_func.__name__)
1070            self.log.error(msg)
1071            self._take_bug_report("%s%s" % (self.test_name,
1072                                            setup_func.__name__),
1073                                  self.begin_time)
1074            return False
1075        if not call_verification_func:
1076            call_verification_func = is_phone_in_call
1077        self.finishing_time = time.time() + self.max_run_time
1078        # CBRS setup
1079        if self.cbrs_esim:
1080            cbrs_sub_count = 0
1081            for ad in self.android_devices:
1082                if not getattr(ad, 'cbrs', {}):
1083                    setattr(ad, 'cbrs', None)
1084                for i in range(0, 2):
1085                    sub_id = get_subid_from_slot_index(ad.log, ad, i)
1086                    operator = get_operatorname_from_slot_index(ad, i)
1087                    carrier_id = get_carrierid_from_slot_index(ad, i)
1088                    is_opportunistic = get_isopportunistic_from_slot_index(ad, i)
1089                    ad.log.info("Slot %d - Sub %s - %s - %d", i, sub_id, operator, carrier_id)
1090                    if carrier_id == GOOGLE_CBRS_CARRIER_ID or (carrier_id == GOOGLE_FI_CARRIER_ID and is_opportunistic):
1091                        ad.cbrs = sub_id
1092                        cbrs_sub_count += 1
1093            if cbrs_sub_count != 2:
1094                self.log.error("Expecting - 2 CBRS subs, found - %d", cbrs_sub_count)
1095                raise signals.TestAbortClass("Cannot find all expected CBRS subs")
1096        # DSDS setup
1097        if self.dsds_esim:
1098            for ad in self.android_devices:
1099                for i in range(0, 2):
1100                    sub_id = get_subid_from_slot_index(ad.log, ad, i)
1101                    set_always_allow_mms_data(ad, sub_id)
1102                    operator = get_operatorname_from_slot_index(ad, i)
1103                    ad.log.info("Slot %d - Sub %s - %s", i, sub_id, operator)
1104        # Actual test trigger
1105        if not self.dsds_esim and self.check_incall_data():
1106            self.log.info(
1107                "==== Start parallel voice/message/data stress test ====")
1108            self.perf_data["testing method"] = "parallel"
1109            results = run_multithread_func(
1110                self.log, [(self.call_test, [call_verification_func]),
1111                           (self.message_test, []), (self.data_test, []),
1112                           (self.crash_check_test, [])])
1113        else:
1114            self.log.info(
1115                "==== Start sequential voice/message/data stress test ====")
1116            self.perf_data["testing method"] = "sequential"
1117            results = run_multithread_func(
1118                self.log, [(self.sequential_tests, [call_verification_func]),
1119                           (self.crash_check_test, [])])
1120        result_message = self._get_result_message()
1121        self.log.info(result_message)
1122        self._update_perf_json()
1123        self.result_detail = result_message
1124        return all(results)
1125
1126    def sequential_tests(self, call_verification_func):
1127        funcs = [(self._make_phone_call, [call_verification_func]),
1128                 (self._send_message, []), (self._data_download, [["5MB"]])]
1129        while time.time() < self.finishing_time:
1130            selection = random.randrange(0, 3)
1131            try:
1132                funcs[selection][0](*funcs[selection][1])
1133            except Exception as e:
1134                self.log.error("Exception error %s", str(e))
1135                self.result_info["Exception Errors"] += 1
1136            self.log.info("%s", dict(self.result_info))
1137            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
1138                self.log.error("Too many exception errors, quit test")
1139                return False
1140            time.sleep(
1141                random.randrange(self.min_sleep_time, self.max_sleep_time))
1142        if any([
1143                self.result_info["Call Setup Failure"],
1144                self.result_info["Call Maintenance Failure"],
1145                self.result_info["Call Teardown Failure"],
1146                self.result_info["SMS Failure"],
1147                self.result_info["MMS Failure"],
1148                self.result_info["Internet Connection Check Failure"]
1149        ]):
1150            return False
1151        return True
1152
1153    def volte_modechange_volte_test(self):
1154        sub_id = self.dut.droid.subscriptionGetDefaultSubId()
1155        result = True
1156        while time.time() < self.finishing_time:
1157            try:
1158                if self._prefnetwork_mode_change(sub_id):
1159                    run_multithread_func(
1160                        self.log,
1161                        [(self._data_download, [["5MB"]]),
1162                         (self._make_phone_call, [is_phone_in_call_volte]),
1163                         (self._send_message, [])])
1164                else:
1165                    result = False
1166                if self._mobile_data_toggling():
1167                    run_multithread_func(
1168                        self.log,
1169                        [(self._data_download, [["5MB"]]),
1170                         (self._make_phone_call, [is_phone_in_call_volte]),
1171                         (self._send_message, [])])
1172                else:
1173                    result = False
1174            except Exception as e:
1175                self.log.error("Exception error %s", str(e))
1176                self.result_info["Exception Errors"] += 1
1177            self.log.info(dict(self.result_info))
1178            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
1179                self.log.error("Too many exception errors, quit test")
1180                return False
1181        return result
1182
1183    def parallel_with_network_change_tests(self, setup_func=None):
1184        if setup_func and not setup_func():
1185            self.log.error("Test setup %s failed", setup_func.__name__)
1186            return False
1187        self.finishing_time = time.time() + self.max_run_time
1188        results = run_multithread_func(self.log,
1189                                       [(self.volte_modechange_volte_test, []),
1190                                        (self.crash_check_test, [])])
1191        result_message = self._get_result_message()
1192        self.log.info(result_message)
1193        self._update_perf_json()
1194        self.result_detail = result_message
1195        return all(results)
1196
1197    def connect_to_wifi(self):
1198        for ad in self.android_devices:
1199            if not ensure_wifi_connected(
1200                    self.log,
1201                    ad,
1202                    self.wifi_network_ssid,
1203                    self.wifi_network_pass,
1204                    retries=3):
1205                ad.log.error("Bringing up Wifi connection fails.")
1206                return False
1207        ad.log.info("Phone WIFI is connected successfully.")
1208        return True
1209
1210    def performance_tests(self, setup_func=None, call_verification_func=None):
1211        self.log.info(self._get_result_message())
1212        if setup_func and not setup_func():
1213            msg = "%s setup %s failed" % (self.test_name, setup_func.__name__)
1214            self.log.error(msg)
1215            self._take_bug_report("%s%s" % (self.test_name,
1216                                            setup_func.__name__),
1217                                  self.begin_time)
1218            return False
1219        if not call_verification_func:
1220            call_verification_func = is_phone_in_call
1221        self.finishing_time = time.time() + self.max_run_time
1222
1223        self.log.info(
1224            "==== Start voice stress test ====")
1225        self.perf_data["testing method"] = "parallel"
1226        results = self.call_performance_test(call_verification_func)
1227
1228        result_message = self._get_result_message()
1229        self.log.info(result_message)
1230        self._update_perf_json()
1231        self.result_detail = result_message
1232        total_call = self.result_info["Call Total"]
1233        success_call = self.result_info["Call Success Total"]
1234        call_fail = total_call - success_call
1235        if call_fail != 0:
1236            call_fail_rate = ( call_fail / total_call ) * 100
1237        else:
1238            call_fail_rate = 0
1239        call_success_rate = (success_call / total_call) * 100
1240
1241        self.log.info("Call Success Rate is %s", call_success_rate)
1242        self.log.info("Call Drop Rate is %s", call_success_rate)
1243
1244        return results
1245
1246    def _update_initiate_call_fail_count(self):
1247        self.result_info["Call Initiate Fail"] += 1
1248
1249    def call_performance_test(self, call_verification_func=None):
1250        count = 0
1251        while count < self.phone_call_iteration:
1252            time.sleep(15)
1253            count += 1
1254            try:
1255                self._make_phone_call(call_verification_func, True)
1256            except Exception as e:
1257                self.log.exception("Exception error %s", str(e))
1258                self.result_info["Exception Errors"] += 1
1259            if self.result_info["Exception Errors"] >= EXCEPTION_TOLERANCE:
1260                self.log.error("Too many exception errors, quit test")
1261                return False
1262            self.log.info("%s", dict(self.result_info))
1263            self.result_info["Call Success Total"] += 1
1264        if any([
1265                self.result_info["Call Setup Failure"],
1266                self.result_info["Call Maintenance Failure"],
1267                self.result_info["Call Teardown Failure"]
1268        ]):
1269            return False
1270        else:
1271            return True
1272
1273    """ Tests Begin """
1274
1275    @test_tracker_info(uuid="d035e5b9-476a-4e3d-b4e9-6fd86c51a68d")
1276    @TelephonyBaseTest.tel_test_wrap
1277    def test_default_parallel_stress(self):
1278        """ Default state stress test"""
1279        return self.parallel_tests()
1280
1281    @test_tracker_info(uuid="798a3c34-db75-4bcf-b8ef-e1116414a7fe")
1282    @TelephonyBaseTest.tel_test_wrap
1283    def test_default_parallel_stress_with_wifi(self):
1284        """ Default state stress test with Wifi enabled."""
1285        if self.connect_to_wifi():
1286            return self.parallel_tests()
1287
1288    @test_tracker_info(uuid="c21e1f17-3282-4f0b-b527-19f048798098")
1289    @TelephonyBaseTest.tel_test_wrap
1290    def test_lte_volte_parallel_stress(self):
1291        """ VoLTE on stress test"""
1292        return self.parallel_tests(
1293            setup_func=self._setup_lte_volte_enabled,
1294            call_verification_func=is_phone_in_call_volte)
1295
1296    @test_tracker_info(uuid="a317c23a-41e0-4ef8-af67-661451cfefcf")
1297    @TelephonyBaseTest.tel_test_wrap
1298    def test_csfb_parallel_stress(self):
1299        """ LTE non-VoLTE stress test"""
1300        return self.parallel_tests(
1301            setup_func=self._setup_lte_volte_disabled,
1302            call_verification_func=is_phone_in_call_csfb)
1303
1304    @test_tracker_info(uuid="fdb791bf-c414-4333-9fa3-cc18c9b3b234")
1305    @TelephonyBaseTest.tel_test_wrap
1306    def test_wfc_parallel_stress(self):
1307        """ Wifi calling APM mode off stress test"""
1308        if WFC_MODE_WIFI_PREFERRED not in self.dut_wfc_modes:
1309            raise signals.TestSkip("WFC_MODE_WIFI_PREFERRED is not supported")
1310        return self.parallel_tests(
1311            setup_func=self._setup_wfc,
1312            call_verification_func=is_phone_in_call_iwlan)
1313
1314    @test_tracker_info(uuid="e334c1b3-4378-49bb-bf57-1573fa1b23fa")
1315    @TelephonyBaseTest.tel_test_wrap
1316    def test_wfc_apm_parallel_stress(self):
1317        """ Wifi calling in APM mode on stress test"""
1318        return self.parallel_tests(
1319            setup_func=self._setup_wfc_apm,
1320            call_verification_func=is_phone_in_call_iwlan)
1321
1322    @test_tracker_info(uuid="4566eef6-55de-4ac8-87ee-58f2ef41a3e8")
1323    @TelephonyBaseTest.tel_test_wrap
1324    def test_3g_parallel_stress(self):
1325        """ 3G stress test"""
1326        return self.parallel_tests(
1327            setup_func=self._setup_3g,
1328            call_verification_func=is_phone_in_call_3g)
1329
1330    @test_tracker_info(uuid="f34f1a31-3948-4675-8698-372a83b8088d")
1331    @TelephonyBaseTest.tel_test_wrap
1332    def test_2g_parallel_stress(self):
1333        """ 2G call stress test"""
1334        return self.parallel_tests(
1335            setup_func=self._setup_2g,
1336            call_verification_func=is_phone_in_call_2g)
1337
1338    @test_tracker_info(uuid="af580fca-fea6-4ca5-b981-b8c710302d37")
1339    @TelephonyBaseTest.tel_test_wrap
1340    def test_volte_modeprefchange_parallel_stress(self):
1341        """ VoLTE Mode Pref call stress test"""
1342        return self.parallel_with_network_change_tests(
1343            setup_func=self._setup_lte_volte_enabled)
1344
1345    @test_tracker_info(uuid="10e34247-5fd3-4f87-81bf-3c17a6b71ab2")
1346    @TelephonyBaseTest.tel_test_wrap
1347    def test_data_call_stress(self):
1348        """ Default state stress test"""
1349        self.finishing_time = time.time() + self.max_run_time
1350        results = run_multithread_func(self.log,
1351                                       [(self.data_call_stress_test, []),
1352                                        (self.crash_check_test, [])])
1353        result_message = self._get_result_message()
1354        self.log.info(result_message)
1355        self._update_perf_json()
1356        self.result_detail = result_message
1357        return all(results)
1358
1359    @test_tracker_info(uuid="4212d0e0-fb87-47e5-ba48-9df9a4a6bb9b")
1360    @TelephonyBaseTest.tel_test_wrap
1361    def test_voice_performance_stress(self):
1362        """ Voice Performance stress test"""
1363        return self.performance_tests()
1364
1365    @test_tracker_info(uuid="a126793e-6e78-4920-a8c4-b382a444c4b7")
1366    @TelephonyBaseTest.tel_test_wrap
1367    def test_voice_performance_stress_nr(self):
1368        """ Voice Performance stress test"""
1369        return self.performance_tests(
1370            setup_func=self._setup_lte_volte_enabled)
1371
1372    """ Tests End """
1373