1#!/usr/bin/env python3 2# 3# Copyright 2016 - 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 Base Class for Defining Common Telephony Test Functionality 18""" 19 20import logging 21import os 22import re 23import shutil 24import time 25 26from acts import asserts 27from acts import logger as acts_logger 28from acts import signals 29from acts.base_test import BaseTestClass 30from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH 31from acts.controllers.android_device import DEFAULT_SDM_LOG_PATH 32from acts.keys import Config 33from acts import records 34from acts import utils 35 36from acts.test_utils.tel.tel_subscription_utils import \ 37 initial_set_up_for_subid_infomation 38from acts.test_utils.tel.tel_subscription_utils import \ 39 set_default_sub_for_all_services 40from acts.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index 41from acts.test_utils.tel.tel_test_utils import build_id_override 42from acts.test_utils.tel.tel_test_utils import disable_qxdm_logger 43from acts.test_utils.tel.tel_test_utils import enable_connectivity_metrics 44from acts.test_utils.tel.tel_test_utils import enable_radio_log_on 45from acts.test_utils.tel.tel_test_utils import ensure_phone_default_state 46from acts.test_utils.tel.tel_test_utils import ensure_phone_idle 47from acts.test_utils.tel.tel_test_utils import ensure_wifi_connected 48from acts.test_utils.tel.tel_test_utils import force_connectivity_metrics_upload 49from acts.test_utils.tel.tel_test_utils import get_operator_name 50from acts.test_utils.tel.tel_test_utils import get_screen_shot_log 51from acts.test_utils.tel.tel_test_utils import get_sim_state 52from acts.test_utils.tel.tel_test_utils import get_tcpdump_log 53from acts.test_utils.tel.tel_test_utils import multithread_func 54from acts.test_utils.tel.tel_test_utils import print_radio_info 55from acts.test_utils.tel.tel_test_utils import reboot_device 56from acts.test_utils.tel.tel_test_utils import recover_build_id 57from acts.test_utils.tel.tel_test_utils import run_multithread_func 58from acts.test_utils.tel.tel_test_utils import setup_droid_properties 59from acts.test_utils.tel.tel_test_utils import set_phone_screen_on 60from acts.test_utils.tel.tel_test_utils import set_phone_silent_mode 61from acts.test_utils.tel.tel_test_utils import set_qxdm_logger_command 62from acts.test_utils.tel.tel_test_utils import start_qxdm_logger 63from acts.test_utils.tel.tel_test_utils import start_qxdm_loggers 64from acts.test_utils.tel.tel_test_utils import start_sdm_loggers 65from acts.test_utils.tel.tel_test_utils import start_sdm_logger 66from acts.test_utils.tel.tel_test_utils import start_tcpdumps 67from acts.test_utils.tel.tel_test_utils import stop_qxdm_logger 68from acts.test_utils.tel.tel_test_utils import stop_sdm_loggers 69from acts.test_utils.tel.tel_test_utils import stop_sdm_logger 70from acts.test_utils.tel.tel_test_utils import stop_tcpdumps 71from acts.test_utils.tel.tel_test_utils import synchronize_device_time 72from acts.test_utils.tel.tel_test_utils import unlock_sim 73from acts.test_utils.tel.tel_test_utils import wait_for_sim_ready_by_adb 74from acts.test_utils.tel.tel_test_utils import wait_for_sims_ready_by_adb 75from acts.test_utils.tel.tel_test_utils import activate_wfc_on_device 76from acts.test_utils.tel.tel_test_utils import install_googleaccountutil_apk 77from acts.test_utils.tel.tel_test_utils import add_google_account 78from acts.test_utils.tel.tel_test_utils import install_googlefi_apk 79from acts.test_utils.tel.tel_test_utils import activate_google_fi_account 80from acts.test_utils.tel.tel_test_utils import check_google_fi_activated 81from acts.test_utils.tel.tel_test_utils import check_fi_apk_installed 82from acts.test_utils.tel.tel_test_utils import phone_switch_to_msim_mode 83from acts.test_utils.tel.tel_test_utils import activate_esim_using_suw 84from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND 85from acts.test_utils.tel.tel_defines import SINGLE_SIM_CONFIG, MULTI_SIM_CONFIG 86from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND 87from acts.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING 88from acts.test_utils.tel.tel_defines import SIM_STATE_ABSENT 89from acts.test_utils.tel.tel_defines import SIM_STATE_UNKNOWN 90from acts.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_ENABLED 91from acts.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_DISABLED 92from acts.test_utils.tel.tel_defines import INVALID_SUB_ID 93 94 95class TelephonyBaseTest(BaseTestClass): 96 # Use for logging in the test cases to facilitate 97 # faster log lookup and reduce ambiguity in logging. 98 @staticmethod 99 def tel_test_wrap(fn): 100 def _safe_wrap_test_case(self, *args, **kwargs): 101 test_id = "%s:%s:%s" % (self.__class__.__name__, self.test_name, 102 self.log_begin_time.replace(' ', '-')) 103 self.test_id = test_id 104 self.result_detail = "" 105 self.testsignal_details = "" 106 self.testsignal_extras = {} 107 tries = int(self.user_params.get("telephony_auto_rerun", 1)) 108 for ad in self.android_devices: 109 ad.log_path = self.log_path 110 for i in range(tries + 1): 111 result = True 112 if i > 0: 113 log_string = "[Test Case] RERUN %s" % self.test_name 114 self.log.info(log_string) 115 self._teardown_test(self.test_name) 116 self._setup_test(self.test_name) 117 try: 118 result = fn(self, *args, **kwargs) 119 except signals.TestFailure as e: 120 self.testsignal_details = e.details 121 self.testsignal_extras = e.extras 122 result = False 123 except signals.TestSignal: 124 raise 125 except Exception as e: 126 self.log.exception(e) 127 asserts.fail(self.result_detail) 128 if result is False: 129 if i < tries: 130 continue 131 else: 132 break 133 if self.user_params.get("check_crash", True): 134 new_crash = ad.check_crash_report(self.test_name, 135 self.begin_time, True) 136 if new_crash: 137 msg = "Find new crash reports %s" % new_crash 138 ad.log.error(msg) 139 self.result_detail = "%s %s %s" % (self.result_detail, 140 ad.serial, msg) 141 result = False 142 if result is not False: 143 asserts.explicit_pass(self.result_detail) 144 else: 145 if self.result_detail: 146 asserts.fail(self.result_detail) 147 else: 148 asserts.fail(self.testsignal_details, self.testsignal_extras) 149 150 return _safe_wrap_test_case 151 152 def setup_class(self): 153 super().setup_class() 154 self.wifi_network_ssid = self.user_params.get( 155 "wifi_network_ssid") or self.user_params.get( 156 "wifi_network_ssid_2g") or self.user_params.get( 157 "wifi_network_ssid_5g") 158 self.wifi_network_pass = self.user_params.get( 159 "wifi_network_pass") or self.user_params.get( 160 "wifi_network_pass_2g") or self.user_params.get( 161 "wifi_network_ssid_5g") 162 163 self.log_path = getattr(logging, "log_path", None) 164 self.qxdm_log = self.user_params.get("qxdm_log", True) 165 self.sdm_log = self.user_params.get("sdm_log", False) 166 self.enable_radio_log_on = self.user_params.get( 167 "enable_radio_log_on", False) 168 self.cbrs_esim = self.user_params.get("cbrs_esim", False) 169 self.account_util = self.user_params.get("account_util", None) 170 self.save_passing_logs = self.user_params.get("save_passing_logs", False) 171 if isinstance(self.account_util, list): 172 self.account_util = self.account_util[0] 173 self.fi_util = self.user_params.get("fi_util", None) 174 if isinstance(self.fi_util, list): 175 self.fi_util = self.fi_util[0] 176 tasks = [(self._init_device, [ad]) for ad in self.android_devices] 177 multithread_func(self.log, tasks) 178 self.skip_reset_between_cases = self.user_params.get( 179 "skip_reset_between_cases", True) 180 self.log_path = getattr(logging, "log_path", None) 181 self.sim_config = { 182 "config":SINGLE_SIM_CONFIG, 183 "number_of_sims":1 184 } 185 186 for ad in self.android_devices: 187 if hasattr(ad, "dsds"): 188 self.sim_config = { 189 "config":MULTI_SIM_CONFIG, 190 "number_of_sims":2 191 } 192 break 193 if "anritsu_md8475a_ip_address" in self.user_params: 194 return 195 qxdm_log_mask_cfg = self.user_params.get("qxdm_log_mask_cfg", None) 196 if isinstance(qxdm_log_mask_cfg, list): 197 qxdm_log_mask_cfg = qxdm_log_mask_cfg[0] 198 if qxdm_log_mask_cfg and "dev/null" in qxdm_log_mask_cfg: 199 qxdm_log_mask_cfg = None 200 sim_conf_file = self.user_params.get("sim_conf_file") 201 if not sim_conf_file: 202 self.log.info("\"sim_conf_file\" is not provided test bed config!") 203 else: 204 if isinstance(sim_conf_file, list): 205 sim_conf_file = sim_conf_file[0] 206 # If the sim_conf_file is not a full path, attempt to find it 207 # relative to the config file. 208 if not os.path.isfile(sim_conf_file): 209 sim_conf_file = os.path.join( 210 self.user_params[Config.key_config_path.value], 211 sim_conf_file) 212 if not os.path.isfile(sim_conf_file): 213 self.log.error("Unable to load user config %s ", 214 sim_conf_file) 215 216 tasks = [(self._setup_device, [ad, sim_conf_file, qxdm_log_mask_cfg]) 217 for ad in self.android_devices] 218 return multithread_func(self.log, tasks) 219 220 def _init_device(self, ad): 221 synchronize_device_time(ad) 222 ad.log_path = self.log_path 223 print_radio_info(ad) 224 unlock_sim(ad) 225 ad.wakeup_screen() 226 ad.adb.shell("input keyevent 82") 227 228 def wait_for_sim_ready(self,ad): 229 wait_for_sim_ready_on_sim_config = { 230 SINGLE_SIM_CONFIG : lambda:wait_for_sim_ready_by_adb(self.log,ad), 231 MULTI_SIM_CONFIG : lambda:wait_for_sims_ready_by_adb(self.log,ad) 232 } 233 if not wait_for_sim_ready_on_sim_config[self.sim_config["config"]]: 234 raise signals.TestAbortClass("unable to load the SIM") 235 236 def _setup_device(self, ad, sim_conf_file, qxdm_log_mask_cfg=None): 237 ad.qxdm_log = getattr(ad, "qxdm_log", self.qxdm_log) 238 ad.sdm_log = getattr(ad, "sdm_log", self.sdm_log) 239 if self.user_params.get("enable_connectivity_metrics", False): 240 enable_connectivity_metrics(ad) 241 if self.user_params.get("build_id_override", False): 242 build_postfix = self.user_params.get("build_id_postfix", 243 "LAB_TEST") 244 build_id_override( 245 ad, 246 new_build_id=self.user_params.get("build_id_override_with", 247 None), 248 postfix=build_postfix) 249 if self.enable_radio_log_on: 250 enable_radio_log_on(ad) 251 list_of_models = ["sdm", "msm", "kon", "lit"] 252 if any(model in ad.model for model in list_of_models): 253 phone_mode = "ssss" 254 if hasattr(ad, "mtp_dsds"): 255 phone_mode = "dsds" 256 if ad.adb.getprop("persist.radio.multisim.config") != phone_mode: 257 ad.adb.shell("setprop persist.radio.multisim.config %s" \ 258 % phone_mode) 259 reboot_device(ad) 260 261 stop_qxdm_logger(ad) 262 if ad.qxdm_log: 263 qxdm_log_mask = getattr(ad, "qxdm_log_mask", None) 264 if qxdm_log_mask_cfg: 265 qxdm_mask_path = self.user_params.get("qxdm_log_path", 266 DEFAULT_QXDM_LOG_PATH) 267 ad.adb.shell("mkdir %s" % qxdm_mask_path) 268 ad.log.info("Push %s to %s", qxdm_log_mask_cfg, qxdm_mask_path) 269 ad.adb.push("%s %s" % (qxdm_log_mask_cfg, qxdm_mask_path)) 270 mask_file_name = os.path.split(qxdm_log_mask_cfg)[-1] 271 qxdm_log_mask = os.path.join(qxdm_mask_path, mask_file_name) 272 set_qxdm_logger_command(ad, mask=qxdm_log_mask) 273 start_qxdm_logger(ad, utils.get_current_epoch_time()) 274 elif ad.sdm_log: 275 start_sdm_logger(ad) 276 else: 277 disable_qxdm_logger(ad) 278 if not unlock_sim(ad): 279 raise signals.TestAbortClass("unable to unlock the SIM") 280 281 # eSIM enablement 282 if hasattr(ad, "fi_esim"): 283 if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, 284 self.wifi_network_pass): 285 ad.log.error("Failed to connect to wifi") 286 if check_google_fi_activated(ad): 287 ad.log.info("Google Fi is already Activated") 288 else: 289 install_googleaccountutil_apk(ad, self.account_util) 290 add_google_account(ad) 291 install_googlefi_apk(ad, self.fi_util) 292 if not activate_google_fi_account(ad): 293 ad.log.error("Failed to activate Fi") 294 check_google_fi_activated(ad) 295 if hasattr(ad, "dsds"): 296 sim_mode = ad.droid.telephonyGetPhoneCount() 297 if sim_mode == 1: 298 ad.log.info("Phone in Single SIM Mode") 299 if not phone_switch_to_msim_mode(ad): 300 ad.log.error("Failed to switch to Dual SIM Mode") 301 return False 302 elif sim_mode == 2: 303 ad.log.info("Phone already in Dual SIM Mode") 304 if get_sim_state(ad) in (SIM_STATE_ABSENT, SIM_STATE_UNKNOWN): 305 ad.log.info("Device has no or unknown SIM in it") 306 # eSIM needs activation 307 activate_esim_using_suw(ad) 308 ensure_phone_idle(self.log, ad) 309 elif self.user_params.get("Attenuator"): 310 ad.log.info("Device in chamber room") 311 ensure_phone_idle(self.log, ad) 312 setup_droid_properties(self.log, ad, sim_conf_file) 313 else: 314 self.wait_for_sim_ready(ad) 315 ensure_phone_default_state(self.log, ad) 316 setup_droid_properties(self.log, ad, sim_conf_file) 317 318 default_slot = getattr(ad, "default_slot", 0) 319 if get_subid_from_slot_index(ad.log, ad, default_slot) != INVALID_SUB_ID: 320 ad.log.info("Slot %s is the default slot.", default_slot) 321 set_default_sub_for_all_services(ad, default_slot) 322 else: 323 ad.log.warning("Slot %s is NOT a valid slot. Slot %s will be used by default.", 324 default_slot, 1-default_slot) 325 set_default_sub_for_all_services(ad, 1-default_slot) 326 327 # Activate WFC on Verizon, AT&T and Canada operators as per # b/33187374 & 328 # b/122327716 329 activate_wfc_on_device(self.log, ad) 330 331 # Sub ID setup 332 initial_set_up_for_subid_infomation(self.log, ad) 333 334 # If device is setup already, skip the following setup procedures 335 if getattr(ad, "telephony_test_setup", None): 336 return True 337 338 try: 339 ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_ENABLED) 340 except Exception: 341 pass 342 343 # Disable Emergency alerts 344 # Set chrome browser start with no-first-run verification and 345 # disable-fre. Give permission to read from and write to storage. 346 for cmd in ("pm disable com.android.cellbroadcastreceiver", 347 "pm grant com.android.chrome " 348 "android.permission.READ_EXTERNAL_STORAGE", 349 "pm grant com.android.chrome " 350 "android.permission.WRITE_EXTERNAL_STORAGE", 351 "rm /data/local/chrome-command-line", 352 "am set-debug-app --persistent com.android.chrome", 353 'echo "chrome --no-default-browser-check --no-first-run ' 354 '--disable-fre" > /data/local/tmp/chrome-command-line'): 355 ad.adb.shell(cmd, ignore_status=True) 356 357 # Curl for 2016/7 devices 358 if not getattr(ad, "curl_capable", False): 359 try: 360 out = ad.adb.shell("/data/curl --version") 361 if not out or "not found" in out: 362 if int(ad.adb.getprop("ro.product.first_api_level")) >= 25: 363 tel_data = self.user_params.get("tel_data", "tel_data") 364 if isinstance(tel_data, list): 365 tel_data = tel_data[0] 366 curl_file_path = os.path.join(tel_data, "curl") 367 if not os.path.isfile(curl_file_path): 368 curl_file_path = os.path.join( 369 self.user_params[Config.key_config_path.value], 370 curl_file_path) 371 if os.path.isfile(curl_file_path): 372 ad.log.info("Pushing Curl to /data dir") 373 ad.adb.push("%s /data" % (curl_file_path)) 374 ad.adb.shell( 375 "chmod 777 /data/curl", ignore_status=True) 376 else: 377 setattr(ad, "curl_capable", True) 378 except Exception: 379 ad.log.info("Failed to push curl on this device") 380 381 # Ensure that a test class starts from a consistent state that 382 # improves chances of valid network selection and facilitates 383 # logging. 384 try: 385 if not set_phone_screen_on(self.log, ad): 386 self.log.error("Failed to set phone screen-on time.") 387 return False 388 if not set_phone_silent_mode(self.log, ad): 389 self.log.error("Failed to set phone silent mode.") 390 return False 391 ad.droid.telephonyAdjustPreciseCallStateListenLevel( 392 PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND, True) 393 ad.droid.telephonyAdjustPreciseCallStateListenLevel( 394 PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING, True) 395 ad.droid.telephonyAdjustPreciseCallStateListenLevel( 396 PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND, True) 397 except Exception as e: 398 self.log.error("Failure with %s", e) 399 setattr(ad, "telephony_test_setup", True) 400 return True 401 402 def _teardown_device(self, ad): 403 try: 404 stop_qxdm_logger(ad) 405 stop_sdm_logger(ad) 406 except Exception as e: 407 self.log.error("Failure with %s", e) 408 try: 409 ad.droid.disableDevicePassword() 410 except Exception as e: 411 self.log.error("Failure with %s", e) 412 if self.user_params.get("enable_connectivity_metrics", False): 413 if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, 414 self.wifi_network_pass): 415 ad.log.error("Failed to connect to wifi") 416 force_connectivity_metrics_upload(ad) 417 time.sleep(30) 418 try: 419 ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_DISABLED) 420 except Exception as e: 421 self.log.error("Failure with %s", e) 422 try: 423 if self.user_params.get("build_id_override", 424 False) and self.user_params.get( 425 "recover_build_id", False): 426 recover_build_id(ad) 427 except Exception as e: 428 self.log.error("Failure with %s", e) 429 430 def teardown_class(self): 431 tasks = [(self._teardown_device, [ad]) for ad in self.android_devices] 432 multithread_func(self.log, tasks) 433 return True 434 435 def setup_test(self): 436 if getattr(self, "qxdm_log", True): 437 if not self.user_params.get("qxdm_log_mask_cfg", None): 438 if "wfc" in self.test_name: 439 for ad in self.android_devices: 440 if not getattr(ad, "qxdm_logger_command", None) or ( 441 "IMS_DS_CNE_LnX_Golden.cfg" not in getattr( 442 ad, "qxdm_logger_command", "")): 443 set_qxdm_logger_command( 444 ad, "IMS_DS_CNE_LnX_Golden.cfg") 445 else: 446 for ad in self.android_devices: 447 if not getattr(ad, "qxdm_logger_command", None) or ( 448 "IMS_DS_CNE_LnX_Golden.cfg" in getattr( 449 ad, "qxdm_logger_command", "")): 450 set_qxdm_logger_command(ad, None) 451 start_qxdm_loggers(self.log, self.android_devices, self.begin_time) 452 if getattr(self, "sdm_log", False): 453 start_sdm_loggers(self.log, self.android_devices) 454 if getattr(self, "tcpdump_log", False) or "wfc" in self.test_name: 455 mask = getattr(self, "tcpdump_mask", "all") 456 interface = getattr(self, "tcpdump_interface", "wlan0") 457 start_tcpdumps( 458 self.android_devices, 459 begin_time=self.begin_time, 460 interface=interface, 461 mask=mask) 462 else: 463 stop_tcpdumps(self.android_devices) 464 for ad in self.android_devices: 465 if self.skip_reset_between_cases: 466 ensure_phone_idle(self.log, ad) 467 else: 468 ensure_phone_default_state(self.log, ad) 469 for session in ad._sl4a_manager.sessions.values(): 470 ed = session.get_event_dispatcher() 471 ed.clear_all_events() 472 output = ad.adb.logcat("-t 1") 473 match = re.search(r"\d+-\d+\s\d+:\d+:\d+.\d+", output) 474 if match: 475 ad.test_log_begin_time = match.group(0) 476 477 def teardown_test(self): 478 stop_tcpdumps(self.android_devices) 479 480 def on_fail(self, test_name, begin_time): 481 self._take_bug_report(test_name, begin_time) 482 483 def on_pass(self, test_name, begin_time): 484 if self.save_passing_logs: 485 self._take_bug_report(test_name, begin_time) 486 487 def _ad_take_extra_logs(self, ad, test_name, begin_time): 488 ad.adb.wait_for_device() 489 result = True 490 491 try: 492 # get tcpdump and screen shot log 493 get_tcpdump_log(ad, test_name, begin_time) 494 get_screen_shot_log(ad, test_name, begin_time) 495 except Exception as e: 496 ad.log.error("Exception error %s", e) 497 result = False 498 499 try: 500 ad.check_crash_report(test_name, begin_time, log_crash_report=True) 501 except Exception as e: 502 ad.log.error("Failed to check crash report for %s with error %s", 503 test_name, e) 504 result = False 505 506 extra_qxdm_logs_in_seconds = self.user_params.get( 507 "extra_qxdm_logs_in_seconds", 60 * 3) 508 if getattr(ad, "qxdm_log", True): 509 # Gather qxdm log modified 3 minutes earlier than test start time 510 if begin_time: 511 qxdm_begin_time = begin_time - 1000 * extra_qxdm_logs_in_seconds 512 else: 513 qxdm_begin_time = None 514 try: 515 time.sleep(10) 516 ad.get_qxdm_logs(test_name, qxdm_begin_time) 517 except Exception as e: 518 ad.log.error("Failed to get QXDM log for %s with error %s", 519 test_name, e) 520 result = False 521 if getattr(ad, "sdm_log", False): 522 # Gather sdm log modified 3 minutes earlier than test start time 523 if begin_time: 524 sdm_begin_time = begin_time - 1000 * extra_qxdm_logs_in_seconds 525 else: 526 sdm_begin_time = None 527 try: 528 time.sleep(10) 529 ad.get_sdm_logs(test_name, sdm_begin_time) 530 except Exception as e: 531 ad.log.error("Failed to get SDM log for %s with error %s", 532 test_name, e) 533 result = False 534 535 return result 536 537 def _take_bug_report(self, test_name, begin_time): 538 if self._skip_bug_report(test_name): 539 return 540 dev_num = getattr(self, "number_of_devices", None) or len( 541 self.android_devices) 542 tasks = [(self._ad_take_bugreport, (ad, test_name, begin_time)) 543 for ad in self.android_devices[:dev_num]] 544 tasks.extend([(self._ad_take_extra_logs, (ad, test_name, begin_time)) 545 for ad in self.android_devices[:dev_num]]) 546 run_multithread_func(self.log, tasks) 547 for ad in self.android_devices[:dev_num]: 548 if getattr(ad, "reboot_to_recover", False): 549 reboot_device(ad) 550 ad.reboot_to_recover = False 551 # Zip log folder 552 if not self.user_params.get("zip_log", False): return 553 src_dir = os.path.join(self.log_path, test_name) 554 os.makedirs(src_dir, exist_ok=True) 555 file_name = "%s_%s" % (src_dir, begin_time) 556 self.log.info("Zip folder %s to %s.zip", src_dir, file_name) 557 shutil.make_archive(file_name, "zip", src_dir) 558 shutil.rmtree(src_dir) 559 560 def _block_all_test_cases(self, tests, reason='Failed class setup'): 561 """Over-write _block_all_test_cases in BaseTestClass.""" 562 for (i, (test_name, test_func)) in enumerate(tests): 563 signal = signals.TestFailure(reason) 564 record = records.TestResultRecord(test_name, self.TAG) 565 record.test_begin() 566 # mark all test cases as FAIL 567 record.test_fail(signal) 568 self.results.add_record(record) 569 # only gather bug report for the first test case 570 if i == 0: 571 self.on_fail(test_name, record.begin_time) 572 573 def get_stress_test_number(self): 574 """Gets the stress_test_number param from user params. 575 576 Gets the stress_test_number param. If absent, returns default 100. 577 """ 578 return int(self.user_params.get("stress_test_number", 100)) 579