| #!/usr/bin/env python3 |
| # |
| # Copyright 2016 - Google |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| """ |
| Base Class for Defining Common Telephony Test Functionality |
| """ |
| |
| import logging |
| import os |
| import re |
| import shutil |
| import time |
| |
| from acts import asserts |
| from acts import records |
| from acts import signals |
| from acts import utils |
| from acts.base_test import BaseTestClass |
| from acts.controllers.adb_lib.error import AdbCommandError |
| from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH |
| from acts.keys import Config |
| from acts.libs.utils.multithread import multithread_func |
| from acts.libs.utils.multithread import run_multithread_func |
| from acts_contrib.test_utils.tel.tel_bootloader_utils import flash_radio |
| from acts_contrib.test_utils.tel.tel_defines import CHIPSET_MODELS_LIST |
| from acts_contrib.test_utils.tel.tel_defines import INVALID_SUB_ID |
| from acts_contrib.test_utils.tel.tel_defines import MULTI_SIM_CONFIG, SINGLE_SIM_CONFIG |
| from acts_contrib.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND |
| from acts_contrib.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND |
| from acts_contrib.test_utils.tel.tel_defines import PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING |
| from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_ABSENT |
| from acts_contrib.test_utils.tel.tel_defines import SIM_STATE_UNKNOWN |
| from acts_contrib.test_utils.tel.tel_defines import WIFI_VERBOSE_LOGGING_DISABLED |
| from acts_contrib.test_utils.tel.tel_ims_utils import activate_wfc_on_device |
| from acts_contrib.test_utils.tel.tel_logging_utils import disable_qxdm_logger |
| from acts_contrib.test_utils.tel.tel_logging_utils import get_screen_shot_log |
| from acts_contrib.test_utils.tel.tel_logging_utils import get_tcpdump_log |
| from acts_contrib.test_utils.tel.tel_logging_utils import set_qxdm_logger_command |
| from acts_contrib.test_utils.tel.tel_logging_utils import start_dsp_logger |
| from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_logger |
| from acts_contrib.test_utils.tel.tel_logging_utils import start_qxdm_loggers |
| from acts_contrib.test_utils.tel.tel_logging_utils import start_sdm_logger |
| from acts_contrib.test_utils.tel.tel_logging_utils import start_sdm_loggers |
| from acts_contrib.test_utils.tel.tel_logging_utils import start_tcpdumps |
| from acts_contrib.test_utils.tel.tel_logging_utils import stop_qxdm_logger |
| from acts_contrib.test_utils.tel.tel_logging_utils import stop_sdm_logger |
| from acts_contrib.test_utils.tel.tel_logging_utils import stop_tcpdumps |
| from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_default_state |
| from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phones_default_state |
| from acts_contrib.test_utils.tel.tel_phone_setup_utils import ensure_phone_idle |
| from acts_contrib.test_utils.tel.tel_subscription_utils import get_subid_from_slot_index |
| from acts_contrib.test_utils.tel.tel_subscription_utils import initial_set_up_for_subid_information |
| from acts_contrib.test_utils.tel.tel_subscription_utils import set_default_sub_for_all_services |
| from acts_contrib.test_utils.tel.tel_test_utils import activate_esim_using_suw |
| from acts_contrib.test_utils.tel.tel_test_utils import activate_google_fi_account |
| from acts_contrib.test_utils.tel.tel_test_utils import adb_disable_verity |
| from acts_contrib.test_utils.tel.tel_test_utils import add_google_account |
| from acts_contrib.test_utils.tel.tel_test_utils import build_id_override |
| from acts_contrib.test_utils.tel.tel_test_utils import check_google_fi_activated |
| from acts_contrib.test_utils.tel.tel_test_utils import enable_connectivity_metrics |
| from acts_contrib.test_utils.tel.tel_test_utils import enable_radio_log_on |
| from acts_contrib.test_utils.tel.tel_test_utils import force_connectivity_metrics_upload |
| from acts_contrib.test_utils.tel.tel_test_utils import get_sim_state |
| from acts_contrib.test_utils.tel.tel_test_utils import install_apk |
| from acts_contrib.test_utils.tel.tel_test_utils import install_googleaccountutil_apk |
| from acts_contrib.test_utils.tel.tel_test_utils import install_googlefi_apk |
| from acts_contrib.test_utils.tel.tel_test_utils import phone_switch_to_msim_mode |
| from acts_contrib.test_utils.tel.tel_test_utils import print_radio_info |
| from acts_contrib.test_utils.tel.tel_test_utils import reboot_device |
| from acts_contrib.test_utils.tel.tel_test_utils import recover_build_id |
| from acts_contrib.test_utils.tel.tel_test_utils import set_phone_screen_on |
| from acts_contrib.test_utils.tel.tel_test_utils import set_phone_silent_mode |
| from acts_contrib.test_utils.tel.tel_test_utils import setup_droid_properties |
| from acts_contrib.test_utils.tel.tel_test_utils import synchronize_device_time |
| from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode |
| from acts_contrib.test_utils.tel.tel_test_utils import unlock_sim |
| from acts_contrib.test_utils.tel.tel_test_utils import wait_for_sim_ready_by_adb |
| from acts_contrib.test_utils.tel.tel_test_utils import wait_for_sims_ready_by_adb |
| from acts_contrib.test_utils.tel.tel_wifi_utils import ensure_wifi_connected |
| |
| |
| REMOUNT_REBOOT_MSG = "Now reboot your device for settings to take effect" |
| |
| |
| class TelephonyBaseTest(BaseTestClass): |
| # Use for logging in the test cases to facilitate |
| # faster log lookup and reduce ambiguity in logging. |
| @staticmethod |
| def tel_test_wrap(fn): |
| def _safe_wrap_test_case(self, *args, **kwargs): |
| test_id = "%s:%s:%s" % (self.__class__.__name__, self.test_name, |
| self.log_begin_time.replace(' ', '-')) |
| self.test_id = test_id |
| self.result_detail = "" |
| self.testsignal_details = "" |
| self.testsignal_extras = {} |
| tries = int(self.user_params.get("telephony_auto_rerun", 1)) |
| for ad in self.android_devices: |
| ad.log_path = self.log_path |
| for i in range(tries + 1): |
| result = True |
| if i > 0: |
| log_string = "[Test Case] RERUN %s" % self.test_name |
| self.log.info(log_string) |
| self._teardown_test(self.test_name) |
| self._setup_test(self.test_name) |
| try: |
| result = fn(self, *args, **kwargs) |
| except signals.TestFailure as e: |
| self.testsignal_details = e.details |
| self.testsignal_extras = e.extras |
| result = False |
| except signals.TestSignal: |
| raise |
| except Exception as e: |
| self.log.exception(e) |
| asserts.fail(self.result_detail) |
| if result is False: |
| if i < tries: |
| continue |
| else: |
| break |
| if self.user_params.get("check_crash", True): |
| new_crash = ad.check_crash_report(self.test_name, |
| self.begin_time, True) |
| if new_crash: |
| msg = "Find new crash reports %s" % new_crash |
| ad.log.error(msg) |
| self.result_detail = "%s %s %s" % (self.result_detail, |
| ad.serial, msg) |
| result = False |
| if result is not False: |
| asserts.explicit_pass(self.result_detail) |
| else: |
| if self.result_detail: |
| asserts.fail(self.result_detail) |
| else: |
| asserts.fail(self.testsignal_details, self.testsignal_extras) |
| |
| return _safe_wrap_test_case |
| |
| def setup_class(self): |
| super().setup_class() |
| self.wifi_network_ssid = self.user_params.get( |
| "wifi_network_ssid") or self.user_params.get( |
| "wifi_network_ssid_2g") or self.user_params.get( |
| "wifi_network_ssid_5g") |
| self.wifi_network_pass = self.user_params.get( |
| "wifi_network_pass") or self.user_params.get( |
| "wifi_network_pass_2g") or self.user_params.get( |
| "wifi_network_ssid_5g") |
| |
| self.log_path = getattr(logging, "log_path", None) |
| self.qxdm_log = self.user_params.get("qxdm_log", True) |
| self.sdm_log = self.user_params.get("sdm_log", False) |
| self.tcpdump_log = self.user_params.get("tcpdump_log", True) |
| self.dsp_log = self.user_params.get("dsp_log", False) |
| self.dsp_log_p21 = self.user_params.get("dsp_log_p21", False) |
| self.enable_radio_log_on = self.user_params.get( |
| "enable_radio_log_on", False) |
| self.cbrs_esim = self.user_params.get("cbrs_esim", False) |
| self.account_util = self.user_params.get("account_util", None) |
| self.save_passing_logs = self.user_params.get("save_passing_logs", False) |
| if isinstance(self.account_util, list): |
| self.account_util = self.account_util[0] |
| self.fi_util = self.user_params.get("fi_util", None) |
| if isinstance(self.fi_util, list): |
| self.fi_util = self.fi_util[0] |
| self.radio_img = self.user_params.get("radio_img", None) |
| if isinstance(self.radio_img, list): |
| self.radio_img = self.radio_img[0] |
| self.modem_bin = self.user_params.get("modem_bin", None) |
| if isinstance(self.modem_bin, list): |
| self.modem_bin = self.modem_bin[0] |
| self.extra_apk = self.user_params.get("extra_apk", None) |
| if isinstance(self.extra_apk, list): |
| self.extra_apk = self.extra_apk[0] |
| self.extra_package = self.user_params.get("extra_package", None) |
| |
| if self.radio_img or self.modem_bin: |
| sideload_img = True |
| if self.radio_img: |
| file_path = self.radio_img |
| elif self.modem_bin: |
| file_path = self.modem_bin |
| sideload_img = False |
| tasks = [(flash_radio, [ad, file_path, True, sideload_img]) |
| for ad in self.android_devices] |
| multithread_func(self.log, tasks) |
| if self.extra_apk and self.extra_package: |
| tasks = [(install_apk, [ad, self.extra_apk, self.extra_package]) |
| for ad in self.android_devices] |
| multithread_func(self.log, tasks) |
| |
| tasks = [(self._init_device, [ad]) for ad in self.android_devices] |
| multithread_func(self.log, tasks) |
| self.reboot_before_test = self.user_params.get( |
| "reboot_before_test", False) |
| self.skip_reset_between_cases = self.user_params.get( |
| "skip_reset_between_cases", True) |
| self.log_path = getattr(logging, "log_path", None) |
| self.sim_config = { |
| "config":SINGLE_SIM_CONFIG, |
| "number_of_sims":1 |
| } |
| |
| for ad in self.android_devices: |
| if getattr(ad, 'dsds', False): |
| self.sim_config = { |
| "config":MULTI_SIM_CONFIG, |
| "number_of_sims":2 |
| } |
| break |
| if "anritsu_md8475a_ip_address" in self.user_params: |
| return |
| qxdm_log_mask_cfg = self.user_params.get("qxdm_log_mask_cfg", None) |
| if isinstance(qxdm_log_mask_cfg, list): |
| qxdm_log_mask_cfg = qxdm_log_mask_cfg[0] |
| if qxdm_log_mask_cfg and "dev/null" in qxdm_log_mask_cfg: |
| qxdm_log_mask_cfg = None |
| sim_conf_file = self.user_params.get("sim_conf_file") |
| if not sim_conf_file: |
| self.log.info("\"sim_conf_file\" is not provided test bed config!") |
| else: |
| if isinstance(sim_conf_file, list): |
| sim_conf_file = sim_conf_file[0] |
| # If the sim_conf_file is not a full path, attempt to find it |
| # relative to the config file. |
| if not os.path.isfile(sim_conf_file): |
| sim_conf_file = os.path.join( |
| self.user_params[Config.key_config_path.value], |
| sim_conf_file) |
| if not os.path.isfile(sim_conf_file): |
| self.log.error("Unable to load user config %s ", |
| sim_conf_file) |
| |
| tasks = [(self._setup_device, [ad, sim_conf_file, qxdm_log_mask_cfg]) |
| for ad in self.android_devices] |
| return multithread_func(self.log, tasks) |
| |
| def _init_device(self, ad): |
| synchronize_device_time(ad) |
| ad.log_path = self.log_path |
| print_radio_info(ad) |
| unlock_sim(ad) |
| ad.wakeup_screen() |
| ad.adb.shell("input keyevent 82") |
| |
| def wait_for_sim_ready(self,ad): |
| wait_for_sim_ready_on_sim_config = { |
| SINGLE_SIM_CONFIG : lambda:wait_for_sim_ready_by_adb(self.log,ad), |
| MULTI_SIM_CONFIG : lambda:wait_for_sims_ready_by_adb(self.log,ad) |
| } |
| if not wait_for_sim_ready_on_sim_config[self.sim_config["config"]]: |
| raise signals.TestAbortClass("unable to load the SIM") |
| |
| def _setup_device(self, ad, sim_conf_file, qxdm_log_mask_cfg=None): |
| ad.qxdm_log = getattr(ad, "qxdm_log", self.qxdm_log) |
| ad.sdm_log = getattr(ad, "sdm_log", self.sdm_log) |
| ad.dsp_log = getattr(ad, "dsp_log", self.dsp_log) |
| ad.dsp_log_p21 = getattr(ad, "dsp_log_p21", self.dsp_log_p21) |
| if self.user_params.get("enable_connectivity_metrics", False): |
| enable_connectivity_metrics(ad) |
| if self.user_params.get("build_id_override", False): |
| build_postfix = self.user_params.get("build_id_postfix", |
| "LAB_TEST") |
| build_id_override( |
| ad, |
| new_build_id=self.user_params.get("build_id_override_with", |
| None), |
| postfix=build_postfix) |
| |
| if self.enable_radio_log_on: |
| enable_radio_log_on(ad) |
| list_of_models = CHIPSET_MODELS_LIST |
| if any(model in ad.model for model in list_of_models): |
| phone_mode = "ssss" |
| if hasattr(ad, "mtp_dsds"): |
| phone_mode = "dsds" |
| if ad.adb.getprop("persist.radio.multisim.config") != phone_mode: |
| ad.adb.shell("setprop persist.radio.multisim.config %s" \ |
| % phone_mode) |
| reboot_device(ad) |
| |
| if "_test" not in ad.build_info["build_id"]: |
| ad.ensure_verity_disabled() |
| try: |
| ad.adb.remount() |
| except AdbCommandError as e: |
| if REMOUNT_REBOOT_MSG in e.stderr: |
| ad.reboot() |
| ad.adb.remount() |
| build_id = ad.build_info["build_id"].replace(".", r"\.") |
| ad.adb.shell("sed -i '/^ro.build.id=/ " |
| f"s/{build_id}/&_test/g' /system/build.prop") |
| ad.adb.shell("sed -i '/^ro.build.description=/ " |
| f"s/{build_id}/&_test/g' /system/build.prop") |
| |
| if ad.dsp_log: |
| start_dsp_logger(ad) |
| elif ad.dsp_log_p21: |
| start_dsp_logger(ad, p21=True) |
| else: |
| ad.reboot() |
| stop_qxdm_logger(ad) |
| if ad.qxdm_log: |
| qxdm_log_mask = getattr(ad, "qxdm_log_mask", None) |
| if qxdm_log_mask_cfg: |
| qxdm_mask_path = self.user_params.get("qxdm_log_path", |
| DEFAULT_QXDM_LOG_PATH) |
| ad.adb.shell("mkdir %s" % qxdm_mask_path, ignore_status=True) |
| ad.log.info("Push %s to %s", qxdm_log_mask_cfg, qxdm_mask_path) |
| ad.adb.push("%s %s" % (qxdm_log_mask_cfg, qxdm_mask_path)) |
| mask_file_name = os.path.split(qxdm_log_mask_cfg)[-1] |
| qxdm_log_mask = os.path.join(qxdm_mask_path, mask_file_name) |
| set_qxdm_logger_command(ad, mask=qxdm_log_mask) |
| start_qxdm_logger(ad, utils.get_current_epoch_time()) |
| elif ad.sdm_log: |
| start_sdm_logger(ad) |
| else: |
| disable_qxdm_logger(ad) |
| if not unlock_sim(ad): |
| raise signals.TestAbortClass("unable to unlock the SIM") |
| |
| # If device is setup already, skip the following setup procedures |
| if getattr(ad, "telephony_test_setup", None): |
| return True |
| |
| # eSIM enablement |
| if hasattr(ad, "fi_esim"): |
| if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, |
| self.wifi_network_pass): |
| ad.log.error("Failed to connect to wifi") |
| if check_google_fi_activated(ad): |
| ad.log.info("Google Fi is already Activated") |
| else: |
| install_googleaccountutil_apk(ad, self.account_util) |
| add_google_account(ad) |
| install_googlefi_apk(ad, self.fi_util) |
| if not activate_google_fi_account(ad): |
| ad.log.error("Failed to activate Fi") |
| check_google_fi_activated(ad) |
| if getattr(ad, 'dsds', False): |
| sim_mode = ad.droid.telephonyGetPhoneCount() |
| if sim_mode == 1: |
| ad.log.info("Phone in Single SIM Mode") |
| if not phone_switch_to_msim_mode(ad): |
| ad.log.error("Failed to switch to Dual SIM Mode") |
| return False |
| elif sim_mode == 2: |
| ad.log.info("Phone already in Dual SIM Mode") |
| if get_sim_state(ad) in (SIM_STATE_ABSENT, SIM_STATE_UNKNOWN): |
| ad.log.info("Device has no or unknown SIM in it") |
| # eSIM needs activation |
| activate_esim_using_suw(ad) |
| ensure_phone_idle(self.log, ad) |
| if getattr(ad, 'mep', False): |
| setup_droid_properties(self.log, ad, sim_conf_file, True) |
| else: |
| setup_droid_properties(self.log, ad, sim_conf_file) |
| elif self.user_params.get("Attenuator"): |
| ad.log.info("Device in chamber room") |
| ensure_phone_idle(self.log, ad) |
| if getattr(ad, 'mep', False): |
| setup_droid_properties(self.log, ad, sim_conf_file, True) |
| else: |
| setup_droid_properties(self.log, ad, sim_conf_file) |
| else: |
| self.wait_for_sim_ready(ad) |
| ensure_phone_default_state(self.log, ad) |
| if getattr(ad, 'mep', False): |
| setup_droid_properties(self.log, ad, sim_conf_file, True) |
| else: |
| setup_droid_properties(self.log, ad, sim_conf_file) |
| |
| if getattr(ad, 'mep', False): |
| default_slot = getattr(ad, "default_slot", 1) |
| if get_subid_from_slot_index(ad.log, ad, default_slot) != INVALID_SUB_ID: |
| ad.log.info("Slot %s is the default slot.", default_slot) |
| set_default_sub_for_all_services(ad, default_slot) |
| else: |
| ad.log.warning("Slot %s is NOT a valid slot. Slot %s will be used by default.", |
| default_slot, 1-default_slot) |
| set_default_sub_for_all_services(ad, 1-default_slot) |
| setattr(ad, "default_slot", 1-default_slot) |
| elif getattr(ad, 'dsds', False): |
| default_slot = getattr(ad, "default_slot", 0) |
| if get_subid_from_slot_index(ad.log, ad, default_slot) != INVALID_SUB_ID: |
| ad.log.info("Slot %s is the default slot.", default_slot) |
| set_default_sub_for_all_services(ad, default_slot) |
| else: |
| ad.log.warning("Slot %s is NOT a valid slot. Slot %s will be used by default.", |
| default_slot, 1-default_slot) |
| set_default_sub_for_all_services(ad, 1-default_slot) |
| setattr(ad, "default_slot", 1-default_slot) |
| |
| # Activate WFC on Verizon, AT&T and Canada operators as per # b/33187374 & |
| # b/122327716 |
| activate_wfc_on_device(self.log, ad) |
| |
| # Sub ID setup |
| initial_set_up_for_subid_information(self.log, ad) |
| |
| |
| #try: |
| # ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_ENABLED) |
| #except Exception: |
| # pass |
| |
| # Disable Emergency alerts |
| # Set chrome browser start with no-first-run verification and |
| # disable-fre. Give permission to read from and write to storage. |
| for cmd in ("pm disable com.android.cellbroadcastreceiver", |
| "pm grant com.android.chrome " |
| "android.permission.READ_EXTERNAL_STORAGE", |
| "pm grant com.android.chrome " |
| "android.permission.WRITE_EXTERNAL_STORAGE", |
| "rm /data/local/chrome-command-line", |
| "am set-debug-app --persistent com.android.chrome", |
| 'echo "chrome --no-default-browser-check --no-first-run ' |
| '--disable-fre" > /data/local/tmp/chrome-command-line'): |
| ad.adb.shell(cmd, ignore_status=True) |
| |
| # Curl for 2016/7 devices |
| if not getattr(ad, "curl_capable", False): |
| try: |
| out = ad.adb.shell("/data/curl --version") |
| if not out or "not found" in out: |
| if int(ad.adb.getprop("ro.product.first_api_level")) >= 25: |
| tel_data = self.user_params.get("tel_data", "tel_data") |
| if isinstance(tel_data, list): |
| tel_data = tel_data[0] |
| curl_file_path = os.path.join(tel_data, "curl") |
| if not os.path.isfile(curl_file_path): |
| curl_file_path = os.path.join( |
| self.user_params[Config.key_config_path.value], |
| curl_file_path) |
| if os.path.isfile(curl_file_path): |
| ad.log.info("Pushing Curl to /data dir") |
| ad.adb.push("%s /data" % (curl_file_path)) |
| ad.adb.shell( |
| "chmod 777 /data/curl", ignore_status=True) |
| else: |
| setattr(ad, "curl_capable", True) |
| except Exception: |
| ad.log.info("Failed to push curl on this device") |
| |
| # Ensure that a test class starts from a consistent state that |
| # improves chances of valid network selection and facilitates |
| # logging. |
| try: |
| if not set_phone_screen_on(self.log, ad): |
| self.log.error("Failed to set phone screen-on time.") |
| return False |
| if not set_phone_silent_mode(self.log, ad): |
| self.log.error("Failed to set phone silent mode.") |
| return False |
| ad.droid.telephonyAdjustPreciseCallStateListenLevel( |
| PRECISE_CALL_STATE_LISTEN_LEVEL_FOREGROUND, True) |
| ad.droid.telephonyAdjustPreciseCallStateListenLevel( |
| PRECISE_CALL_STATE_LISTEN_LEVEL_RINGING, True) |
| ad.droid.telephonyAdjustPreciseCallStateListenLevel( |
| PRECISE_CALL_STATE_LISTEN_LEVEL_BACKGROUND, True) |
| except Exception as e: |
| self.log.error("Failure with %s", e) |
| setattr(ad, "telephony_test_setup", True) |
| return True |
| |
| def _teardown_device(self, ad): |
| try: |
| stop_qxdm_logger(ad) |
| stop_sdm_logger(ad) |
| except Exception as e: |
| self.log.error("Failure with %s", e) |
| try: |
| ad.droid.disableDevicePassword() |
| except Exception as e: |
| self.log.error("Failure with %s", e) |
| if self.user_params.get("enable_connectivity_metrics", False): |
| if not ensure_wifi_connected(self.log, ad, self.wifi_network_ssid, |
| self.wifi_network_pass): |
| ad.log.error("Failed to connect to wifi") |
| force_connectivity_metrics_upload(ad) |
| time.sleep(30) |
| try: |
| ad.droid.wifiEnableVerboseLogging(WIFI_VERBOSE_LOGGING_DISABLED) |
| except Exception as e: |
| self.log.error("Failure with %s", e) |
| try: |
| if self.user_params.get("build_id_override", |
| False) and self.user_params.get( |
| "recover_build_id", False): |
| recover_build_id(ad) |
| except Exception as e: |
| self.log.error("Failure with %s", e) |
| |
| def teardown_class(self): |
| tasks = [(self._teardown_device, [ad]) for ad in self.android_devices] |
| multithread_func(self.log, tasks) |
| return True |
| |
| def setup_test(self): |
| if getattr(self, "qxdm_log", True): |
| if not self.user_params.get("qxdm_log_mask_cfg", None): |
| if "wfc" in self.test_name: |
| for ad in self.android_devices: |
| if not getattr(ad, "qxdm_logger_command", None) or ( |
| "IMS_DS_CNE_LnX_Golden.cfg" not in getattr( |
| ad, "qxdm_logger_command", "")): |
| set_qxdm_logger_command( |
| ad, "IMS_DS_CNE_LnX_Golden.cfg") |
| else: |
| for ad in self.android_devices: |
| if not getattr(ad, "qxdm_logger_command", None) or ( |
| "IMS_DS_CNE_LnX_Golden.cfg" in getattr( |
| ad, "qxdm_logger_command", "")): |
| set_qxdm_logger_command(ad, None) |
| start_qxdm_loggers(self.log, self.android_devices, self.begin_time) |
| if getattr(self, "sdm_log", False): |
| start_sdm_loggers(self.log, self.android_devices) |
| if getattr(self, "tcpdump_log", True): |
| mask = getattr(self, "tcpdump_mask", "all") |
| if "wfc" in self.test_name or "iwlan" in self.test_name: |
| interface = getattr(self, "tcpdump_interface", "wlan0") |
| else: |
| interface = getattr(self, "tcpdump_interface", "any") |
| start_tcpdumps( |
| self.android_devices, |
| begin_time=self.begin_time, |
| interface=interface, |
| mask=mask) |
| else: |
| stop_tcpdumps(self.android_devices) |
| for ad in self.android_devices: |
| if self.reboot_before_test: |
| ad.reboot() |
| if self.skip_reset_between_cases: |
| ensure_phone_idle(self.log, ad) |
| else: |
| ensure_phone_default_state(self.log, ad) |
| for session in ad._sl4a_manager.sessions.values(): |
| ed = session.get_event_dispatcher() |
| ed.clear_all_events() |
| output = ad.adb.logcat("-t 1") |
| match = re.search(r"\d+-\d+\s\d+:\d+:\d+.\d+", output) |
| if match: |
| ad.test_log_begin_time = match.group(0) |
| if self.user_params.get("apm_before_test", None): |
| toggle_airplane_mode(self.log, ad, True, False) |
| toggle_airplane_mode(self.log, ad, False, False) |
| |
| def teardown_test(self): |
| stop_tcpdumps(self.android_devices) |
| |
| def on_fail(self, test_name, begin_time): |
| for ad in self.android_devices: |
| # open Phone information page |
| ad.adb.shell("am start -n com.android.phone/.settings.RadioInfo") |
| time.sleep(3) |
| ad.screenshot(f"{ad.serial}_last_screen") |
| self._take_bug_report(test_name, begin_time) |
| ensure_phones_default_state(self.log, self.android_devices) |
| |
| def on_pass(self, test_name, begin_time): |
| if self.save_passing_logs: |
| self._take_bug_report(test_name, begin_time) |
| |
| def _ad_take_extra_logs(self, ad, test_name, begin_time): |
| ad.adb.wait_for_device() |
| result = True |
| |
| try: |
| # get tcpdump and screen shot log |
| get_tcpdump_log(ad, test_name, begin_time) |
| get_screen_shot_log(ad, test_name, begin_time) |
| except Exception as e: |
| ad.log.error("Exception error %s", e) |
| result = False |
| |
| try: |
| ad.check_crash_report(test_name, begin_time, log_crash_report=True) |
| except Exception as e: |
| ad.log.error("Failed to check crash report for %s with error %s", |
| test_name, e) |
| result = False |
| |
| extra_qxdm_logs_in_seconds = self.user_params.get( |
| "extra_qxdm_logs_in_seconds", 60 * 3) |
| if getattr(ad, "qxdm_log", True): |
| # Gather qxdm log modified 3 minutes earlier than test start time |
| if begin_time: |
| qxdm_begin_time = begin_time - 1000 * extra_qxdm_logs_in_seconds |
| else: |
| qxdm_begin_time = None |
| try: |
| time.sleep(10) |
| ad.get_qxdm_logs(test_name, qxdm_begin_time) |
| except Exception as e: |
| ad.log.error("Failed to get QXDM log for %s with error %s", |
| test_name, e) |
| result = False |
| if getattr(ad, "sdm_log", False): |
| # Gather sdm log modified 3 minutes earlier than test start time |
| if begin_time: |
| sdm_begin_time = begin_time - 1000 * extra_qxdm_logs_in_seconds |
| else: |
| sdm_begin_time = None |
| try: |
| time.sleep(10) |
| ad.get_sdm_logs(test_name, sdm_begin_time) |
| except Exception as e: |
| ad.log.error("Failed to get SDM log for %s with error %s", |
| test_name, e) |
| result = False |
| |
| return result |
| |
| def _take_bug_report(self, test_name, begin_time): |
| if self._skip_bug_report(test_name): |
| return |
| dev_num = getattr(self, "number_of_devices", None) or len( |
| self.android_devices) |
| tasks = [(self._ad_take_bugreport, (ad, test_name, begin_time)) |
| for ad in self.android_devices[:dev_num]] |
| tasks.extend([(self._ad_take_extra_logs, (ad, test_name, begin_time)) |
| for ad in self.android_devices[:dev_num]]) |
| run_multithread_func(self.log, tasks) |
| for ad in self.android_devices[:dev_num]: |
| if getattr(ad, "reboot_to_recover", False): |
| reboot_device(ad) |
| ad.reboot_to_recover = False |
| # Zip log folder |
| if not self.user_params.get("zip_log", False): return |
| src_dir = os.path.join(self.log_path, test_name) |
| os.makedirs(src_dir, exist_ok=True) |
| file_name = "%s_%s" % (src_dir, begin_time) |
| self.log.info("Zip folder %s to %s.zip", src_dir, file_name) |
| shutil.make_archive(file_name, "zip", src_dir) |
| shutil.rmtree(src_dir) |
| |
| def _block_all_test_cases(self, tests, reason='Failed class setup'): |
| """Over-write _block_all_test_cases in BaseTestClass.""" |
| for (i, (test_name, test_func)) in enumerate(tests): |
| signal = signals.TestFailure(reason) |
| record = records.TestResultRecord(test_name, self.TAG) |
| record.test_begin() |
| # mark all test cases as FAIL |
| record.test_fail(signal) |
| self.results.add_record(record) |
| # only gather bug report for the first test case |
| if i == 0: |
| self.on_fail(test_name, record.begin_time) |
| |
| def get_stress_test_number(self): |
| """Gets the stress_test_number param from user params. |
| |
| Gets the stress_test_number param. If absent, returns default 100. |
| """ |
| return int(self.user_params.get("stress_test_number", 100)) |