| #!/usr/bin/env python3 |
| # |
| # Copyright 2020 - The Android Open Source Project |
| # |
| # Licensed under the Apache License, Version 2.0 (the "License"); |
| # you may not use this file except in compliance with the License. |
| # You may obtain a copy of the License at |
| # |
| # http://www.apache.org/licenses/LICENSE-2.0 |
| # |
| # Unless required by applicable law or agreed to in writing, software |
| # distributed under the License is distributed on an "AS IS" BASIS, |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| # See the License for the specific language governing permissions and |
| # limitations under the License. |
| |
| import os |
| import re |
| import fnmatch |
| |
| from acts import asserts |
| from acts import signals |
| from acts.base_test import BaseTestClass |
| from acts_contrib.test_utils.gnss import gnss_test_utils as gutils |
| from acts.utils import get_current_epoch_time |
| from acts.utils import unzip_maintain_permissions |
| from acts_contrib.test_utils.wifi.wifi_test_utils import wifi_toggle_state |
| from acts_contrib.test_utils.tel.tel_bootloader_utils import flash_radio |
| from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection |
| from acts_contrib.test_utils.tel.tel_test_utils import check_call_state_connected_by_adb |
| from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode |
| from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call |
| from acts_contrib.test_utils.gnss.gnss_test_utils import get_baseband_and_gms_version |
| from acts_contrib.test_utils.gnss.gnss_test_utils import set_attenuator_gnss_signal |
| from acts_contrib.test_utils.gnss.gnss_test_utils import _init_device |
| from acts_contrib.test_utils.gnss.gnss_test_utils import check_location_service |
| from acts_contrib.test_utils.gnss.gnss_test_utils import clear_logd_gnss_qxdm_log |
| from acts_contrib.test_utils.gnss.gnss_test_utils import set_mobile_data |
| from acts_contrib.test_utils.gnss.gnss_test_utils import set_wifi_and_bt_scanning |
| from acts_contrib.test_utils.gnss.gnss_test_utils import get_gnss_qxdm_log |
| from acts_contrib.test_utils.gnss.gnss_test_utils import remount_device |
| from acts_contrib.test_utils.gnss.gnss_test_utils import reboot |
| from acts_contrib.test_utils.gnss.gnss_test_utils import check_network_location |
| from acts_contrib.test_utils.gnss.gnss_test_utils import launch_google_map |
| from acts_contrib.test_utils.gnss.gnss_test_utils import check_location_api |
| from acts_contrib.test_utils.gnss.gnss_test_utils import set_battery_saver_mode |
| from acts_contrib.test_utils.gnss.gnss_test_utils import start_gnss_by_gtw_gpstool |
| from acts_contrib.test_utils.gnss.gnss_test_utils import process_gnss_by_gtw_gpstool |
| from acts_contrib.test_utils.gnss.gnss_test_utils import connect_to_wifi_network |
| from acts_contrib.test_utils.gnss.gnss_test_utils import gnss_tracking_via_gtw_gpstool |
| from acts_contrib.test_utils.gnss.gnss_test_utils import parse_gtw_gpstool_log |
| from acts_contrib.test_utils.gnss.gnss_test_utils import start_toggle_gnss_by_gtw_gpstool |
| from acts_contrib.test_utils.gnss.gnss_test_utils import grant_location_permission |
| from acts_contrib.test_utils.gnss.gnss_test_utils import is_mobile_data_on |
| from acts_contrib.test_utils.gnss.gnss_test_utils import is_wearable_btwifi |
| from acts_contrib.test_utils.gnss.gnss_test_utils import is_device_wearable |
| from acts_contrib.test_utils.gnss.gnss_test_utils import log_current_epoch_time |
| from acts_contrib.test_utils.gnss.testtracker_util import log_testtracker_uuid |
| from acts_contrib.test_utils.tel.tel_logging_utils import stop_adb_tcpdump |
| from acts_contrib.test_utils.tel.tel_logging_utils import get_tcpdump_log |
| |
| |
| class GnssFunctionTest(BaseTestClass): |
| """ GNSS Function Tests""" |
| def setup_class(self): |
| super().setup_class() |
| self.ad = self.android_devices[0] |
| req_params = ["pixel_lab_network", |
| "standalone_ws_criteria", "standalone_hs_criteria", |
| "supl_cs_criteria", |
| "supl_hs_criteria", |
| "standalone_cs_criteria", |
| "wearable_reboot_hs_criteria", |
| "default_gnss_signal_attenuation", |
| "weak_gnss_signal_attenuation", |
| "gnss_init_error_list", |
| "gnss_init_error_allowlist", "pixel_lab_location", |
| "qdsp6m_path", "ttff_test_cycle", |
| "collect_logs", "dpo_threshold", |
| "brcm_error_log_allowlist", "onchip_interval", "adr_ratio_threshold", |
| "set_attenuator", "weak_signal_criteria", "weak_signal_cs_criteria"] |
| self.unpack_userparams(req_param_names=req_params) |
| # create hashmap for SSID |
| self.ssid_map = {} |
| for network in self.pixel_lab_network: |
| SSID = network["SSID"] |
| self.ssid_map[SSID] = network |
| self.ttff_mode = {"cs": "Cold Start", |
| "ws": "Warm Start", |
| "hs": "Hot Start", |
| "csa": "CSWith Assist"} |
| if self.collect_logs and gutils.check_chipset_vendor_by_qualcomm(self.ad): |
| self.flash_new_radio_or_mbn() |
| self.push_gnss_cfg() |
| self.init_device() |
| |
| def init_device(self): |
| gutils._init_device(self.ad) |
| gutils.enable_supl_mode(self.ad) |
| gutils.enable_vendor_orbit_assistance_data(self.ad) |
| gutils.disable_ramdump(self.ad) |
| |
| def setup_test(self): |
| log_current_epoch_time(self.ad, "test_start_time") |
| log_testtracker_uuid(self.ad, self.current_test_name) |
| get_baseband_and_gms_version(self.ad) |
| if self.collect_logs: |
| clear_logd_gnss_qxdm_log(self.ad) |
| if self.set_attenuator: |
| set_attenuator_gnss_signal(self.ad, self.attenuators, |
| self.default_gnss_signal_attenuation) |
| # TODO (b/202101058:chenstanley): Need to double check how to disable wifi successfully in wearable projects. |
| if is_wearable_btwifi(self.ad): |
| wifi_toggle_state(self.ad, True) |
| connect_to_wifi_network( |
| self.ad, self.ssid_map[self.pixel_lab_network[0]["SSID"]]) |
| else: |
| wifi_toggle_state(self.ad, False) |
| set_mobile_data(self.ad, True) |
| |
| if not verify_internet_connection(self.ad.log, self.ad, retries=3, |
| expected_state=True): |
| raise signals.TestFailure("Fail to connect to LTE network.") |
| |
| def teardown_test(self): |
| if self.collect_logs: |
| gutils.stop_pixel_logger(self.ad) |
| stop_adb_tcpdump(self.ad) |
| if self.set_attenuator: |
| set_attenuator_gnss_signal(self.ad, self.attenuators, |
| self.default_gnss_signal_attenuation) |
| # TODO(chenstanley): sim structure issue |
| if not is_device_wearable(self.ad): |
| if check_call_state_connected_by_adb(self.ad): |
| hangup_call(self.ad.log, self.ad) |
| if self.ad.droid.connectivityCheckAirplaneMode(): |
| self.ad.log.info("Force airplane mode off") |
| toggle_airplane_mode(self.ad.log, self.ad, new_state=False) |
| if int(self.ad.adb.shell( |
| "settings get global wifi_scan_always_enabled")) != 1: |
| set_wifi_and_bt_scanning(self.ad, True) |
| log_current_epoch_time(self.ad, "test_end_time") |
| |
| def on_fail(self, test_name, begin_time): |
| if self.collect_logs: |
| self.ad.take_bug_report(test_name, begin_time) |
| get_gnss_qxdm_log(self.ad, self.qdsp6m_path) |
| get_tcpdump_log(self.ad, test_name, begin_time) |
| |
| def push_gnss_cfg(self): |
| """Push required GNSS cfg file to DUT for PixelLogger to use as |
| default GNSS logging mask.""" |
| gnss_cfg_path = "/vendor/etc/mdlog" |
| gnss_cfg_file = self.user_params.get("gnss_cfg") |
| if isinstance(gnss_cfg_file, list): |
| gnss_cfg_file = gnss_cfg_file[0] |
| os.system("chmod -R 777 %s" % gnss_cfg_file) |
| self.ad.log.info("GNSS Required CFG = %s" % gnss_cfg_file) |
| self.ad.log.info("Push %s to %s" % (gnss_cfg_file, gnss_cfg_path)) |
| self.ad.push_system_file(gnss_cfg_file, gnss_cfg_path) |
| |
| def flash_new_radio_or_mbn(self): |
| paths = {} |
| path = self.user_params.get("radio_image") |
| if isinstance(path, list): |
| path = path[0] |
| if "dev/null" in path: |
| self.ad.log.info("Radio image path is not defined in Test flag.") |
| return False |
| for path_key in os.listdir(path): |
| if fnmatch.fnmatch(path_key, "*.img"): |
| paths["radio_image"] = os.path.join(path, path_key) |
| os.system("chmod -R 777 %s" % paths["radio_image"]) |
| self.ad.log.info("radio_image = %s" % paths["radio_image"]) |
| if fnmatch.fnmatch(path_key, "*.zip"): |
| zip_path = os.path.join(path, path_key) |
| self.ad.log.info("Unzip %s", zip_path) |
| dest_path = os.path.join(path, "mbn") |
| unzip_maintain_permissions(zip_path, dest_path) |
| paths["mbn_path"] = dest_path |
| os.system("chmod -R 777 %s" % paths["mbn_path"]) |
| self.ad.log.info("mbn_path = %s" % paths["mbn_path"]) |
| self.ad.log.info(os.listdir(paths["mbn_path"])) |
| if not paths.get("radio_image"): |
| self.ad.log.info("No radio image is provided on X20. " |
| "Skip flashing radio step.") |
| return False |
| else: |
| get_baseband_and_gms_version(self.ad, "Before flash radio") |
| flash_radio(self.ad, paths["radio_image"]) |
| get_baseband_and_gms_version(self.ad, "After flash radio") |
| if not paths.get("mbn_path"): |
| self.ad.log.info("No need to push mbn files") |
| return False |
| else: |
| try: |
| mcfg_ver = self.ad.adb.shell( |
| "cat /vendor/rfs/msm/mpss/readonly/vendor/mbn/mcfg.version") |
| if mcfg_ver: |
| self.ad.log.info("Before push mcfg, mcfg.version = %s", |
| mcfg_ver) |
| else: |
| self.ad.log.info("There is no mcfg.version before push, " |
| "unmatching device") |
| return False |
| except Exception as e: |
| self.ad.log.info("There is no mcfg.version before push, " |
| "unmatching device %s" % e) |
| return False |
| get_baseband_and_gms_version(self.ad, "Before push mcfg") |
| try: |
| remount_device(self.ad) |
| cmd = "%s %s" % (paths["mbn_path"]+"/.", |
| "/vendor/rfs/msm/mpss/readonly/vendor/mbn/") |
| out = self.ad.adb.push(cmd) |
| self.ad.log.info(out) |
| reboot(self.ad) |
| except Exception as e: |
| self.ad.log.error("Push mbn files error %s", e) |
| return False |
| get_baseband_and_gms_version(self.ad, "After push mcfg") |
| try: |
| new_mcfg_ver = self.ad.adb.shell( |
| "cat /vendor/rfs/msm/mpss/readonly/vendor/mbn/mcfg.version") |
| if new_mcfg_ver: |
| self.ad.log.info("New mcfg.version = %s", new_mcfg_ver) |
| if new_mcfg_ver == mcfg_ver: |
| self.ad.log.error("mcfg.version is the same before and " |
| "after push") |
| return True |
| else: |
| self.ad.log.error("Unable to get new mcfg.version") |
| return False |
| except Exception as e: |
| self.ad.log.error("cat mcfg.version with error %s", e) |
| return False |
| |
| def standalone_ttff_airplane_mode_on(self, mode, criteria): |
| """Verify Standalone GNSS TTFF functionality while airplane mode is on. |
| |
| Args: |
| mode: "cs", "ws" or "hs" |
| criteria: Criteria for the test. |
| """ |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| self.ad.log.info("Turn airplane mode on") |
| toggle_airplane_mode(self.ad.log, self.ad, new_state=True) |
| gutils.run_ttff_via_gtw_gpstool( |
| self.ad, mode, criteria, self.ttff_test_cycle, self.pixel_lab_location) |
| |
| """ Test Cases """ |
| |
| def test_cs_first_fixed_system_server_restart(self): |
| """Verify cs first fixed after system server restart. |
| |
| Steps: |
| 1. Get location fixed within supl_cs_criteria. |
| 2. Restarts android runtime. |
| 3. Get location fixed within supl_cs_criteria. |
| |
| Expected Results: |
| Location fixed within supl_cs_criteria. |
| """ |
| overall_test_result = [] |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| for test_loop in range(1, 6): |
| gutils.process_gnss_by_gtw_gpstool(self.ad, self.supl_cs_criteria) |
| gutils.start_gnss_by_gtw_gpstool(self.ad, False) |
| self.ad.restart_runtime() |
| self.ad.unlock_screen(password=None) |
| test_result = gutils.process_gnss_by_gtw_gpstool(self.ad, self.supl_cs_criteria) |
| gutils.start_gnss_by_gtw_gpstool(self.ad, False) |
| self.ad.log.info("Iteration %d => %s" % (test_loop, test_result)) |
| overall_test_result.append(test_result) |
| |
| asserts.assert_true(all(overall_test_result), |
| "SUPL fail after system server restart.") |
| |
| def test_cs_ttff_after_gps_service_restart(self): |
| """Verify cs ttff after modem silent reboot / GPS daemons restart. |
| |
| Steps: |
| 1. Trigger modem crash by adb/Restart GPS daemons by killing PID. |
| 2. Wait 1 minute for modem to recover. |
| 3. TTFF Cold Start for 3 iteration. |
| 4. Repeat Step 1. to Step 3. for 5 times. |
| |
| Expected Results: |
| All SUPL TTFF Cold Start results should be within supl_cs_criteria. |
| """ |
| supl_ssr_test_result_all = [] |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| for times in range(1, 6): |
| begin_time = get_current_epoch_time() |
| if gutils.check_chipset_vendor_by_qualcomm(self.ad): |
| test_info = "Modem SSR" |
| gutils.gnss_trigger_modem_ssr_by_mds(self.ad) |
| else: |
| test_info = "restarting GPS daemons" |
| gutils.restart_gps_daemons(self.ad) |
| if not verify_internet_connection(self.ad.log, self.ad, retries=3, |
| expected_state=True): |
| raise signals.TestFailure("Fail to connect to LTE network.") |
| gutils.process_gnss_by_gtw_gpstool(self.ad, self.standalone_cs_criteria) |
| gutils.start_ttff_by_gtw_gpstool(self.ad, ttff_mode="cs", iteration=3) |
| ttff_data = gutils.process_ttff_by_gtw_gpstool(self.ad, begin_time, |
| self.pixel_lab_location) |
| supl_ssr_test_result = gutils.check_ttff_data( |
| self.ad, ttff_data, ttff_mode="Cold Start", |
| criteria=self.supl_cs_criteria) |
| self.ad.log.info("SUPL after %s test %d times -> %s" % ( |
| test_info, times, supl_ssr_test_result)) |
| supl_ssr_test_result_all.append(supl_ssr_test_result) |
| |
| asserts.assert_true(all(supl_ssr_test_result_all), |
| "TTFF fails to reach designated criteria") |
| |
| def test_gnss_one_hour_tracking(self): |
| """Verify GNSS tracking performance of signal strength and position |
| error. |
| |
| Steps: |
| 1. Launch GTW_GPSTool. |
| 2. GNSS tracking for 60 minutes. |
| |
| Expected Results: |
| DUT could finish 60 minutes test and output track data. |
| """ |
| test_time = 60 |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| gnss_tracking_via_gtw_gpstool(self.ad, self.standalone_cs_criteria, |
| api_type="gnss", testtime=test_time) |
| location_data = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") |
| gutils.validate_location_fix_rate(self.ad, location_data, run_time=test_time, |
| fix_rate_criteria=0.99) |
| gutils.verify_gps_time_should_be_close_to_device_time(self.ad, location_data) |
| |
| def test_duty_cycle_function(self): |
| """Verify duty cycle Functionality. |
| |
| Steps: |
| 1. Launch GTW_GPSTool. |
| 2. Enable GnssMeasurement. |
| 3. GNSS tracking for 5 minutes. |
| 4. Calculate the count diff of "HardwareClockDiscontinuityCount" |
| |
| Expected Results: |
| Duty cycle should be engaged in 5 minutes GNSS tracking. |
| """ |
| tracking_minutes = 5 |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| dpo_begin_time = get_current_epoch_time() |
| gnss_tracking_via_gtw_gpstool(self.ad, |
| self.standalone_cs_criteria, |
| api_type="gnss", |
| testtime=tracking_minutes, |
| meas_flag=True) |
| if gutils.check_chipset_vendor_by_qualcomm(self.ad): |
| gutils.check_dpo_rate_via_gnss_meas(self.ad, |
| dpo_begin_time, |
| self.dpo_threshold) |
| else: |
| gutils.check_dpo_rate_via_brcm_log(self.ad, |
| self.dpo_threshold, |
| self.brcm_error_log_allowlist) |
| |
| def test_gnss_init_error(self): |
| """Check if there is any GNSS initialization error after reboot. |
| |
| Steps: |
| 1. Reboot DUT. |
| 2. Check logcat if the following error pattern shows up. |
| "E LocSvc.*", ".*avc.*denied.*u:r:location:s0", |
| ".*avc.*denied.*u:r:hal_gnss_qti:s0" |
| |
| Expected Results: |
| There should be no GNSS initialization error after reboot. |
| """ |
| error_mismatch = True |
| for attr in self.gnss_init_error_list: |
| error = self.ad.adb.shell("logcat -d | grep -E '%s'" % attr) |
| if error: |
| for allowlist in self.gnss_init_error_allowlist: |
| if allowlist in error: |
| error = re.sub(".*"+allowlist+".*\n?", "", error) |
| self.ad.log.info("\"%s\" is in allow-list and removed " |
| "from error." % allowlist) |
| if error: |
| error_mismatch = False |
| self.ad.log.error("\n%s" % error) |
| else: |
| self.ad.log.info("NO \"%s\" initialization error found." % attr) |
| asserts.assert_true(error_mismatch, "Error message found after GNSS " |
| "init") |
| |
| def test_sap_valid_modes(self): |
| """Verify SAP Valid Modes. |
| |
| Steps: |
| 1. Root DUT. |
| 2. Check SAP Valid Modes. |
| |
| Expected Results: |
| SAP=PREMIUM |
| """ |
| if not gutils.check_chipset_vendor_by_qualcomm(self.ad): |
| raise signals.TestSkip("Not Qualcomm chipset. Skip the test.") |
| sap_state = str(self.ad.adb.shell("cat vendor/etc/izat.conf | grep " |
| "SAP=")) |
| self.ad.log.info("SAP Valid Modes - %s" % sap_state) |
| asserts.assert_true("SAP=PREMIUM" in sap_state, |
| "Wrong SAP Valid Modes is set") |
| |
| def test_network_location_provider_cell(self): |
| """Verify LocationManagerService API reports cell Network Location. |
| |
| Steps: |
| 1. WiFi scanning and Bluetooth scanning in Location Setting are OFF. |
| 2. Launch GTW_GPSTool. |
| 3. Verify whether test devices could report cell Network Location. |
| 4. Repeat Step 2. to Step 3. for 5 times. |
| |
| Expected Results: |
| Test devices could report cell Network Location. |
| """ |
| test_result_all = [] |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| set_wifi_and_bt_scanning(self.ad, False) |
| for i in range(1, 6): |
| test_result = check_network_location( |
| self.ad, retries=3, location_type="cell") |
| test_result_all.append(test_result) |
| self.ad.log.info("Iteration %d => %s" % (i, test_result)) |
| set_wifi_and_bt_scanning(self.ad, True) |
| asserts.assert_true(all(test_result_all), |
| "Fail to get networkLocationType=cell") |
| |
| def test_network_location_provider_wifi(self): |
| """Verify LocationManagerService API reports wifi Network Location. |
| |
| Steps: |
| 1. WiFi scanning and Bluetooth scanning in Location Setting are ON. |
| 2. Launch GTW_GPSTool. |
| 3. Verify whether test devices could report wifi Network Location. |
| 4. Repeat Step 2. to Step 3. for 5 times. |
| |
| Expected Results: |
| Test devices could report wifi Network Location. |
| """ |
| test_result_all = [] |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| set_wifi_and_bt_scanning(self.ad, True) |
| for i in range(1, 6): |
| test_result = check_network_location( |
| self.ad, retries=3, location_type="wifi") |
| test_result_all.append(test_result) |
| self.ad.log.info("Iteration %d => %s" % (i, test_result)) |
| asserts.assert_true(all(test_result_all), |
| "Fail to get networkLocationType=wifi") |
| |
| def test_gmap_location_report_battery_saver(self): |
| """Verify GnssLocationProvider API reports location to Google Map |
| when Battery Saver is enabled. |
| |
| Steps: |
| 1. GPS and NLP are on. |
| 2. Enable Battery Saver. |
| 3. Launch Google Map. |
| 4. Verify whether test devices could report location. |
| 5. Repeat Step 3. to Step 4. for 5 times. |
| 6. Disable Battery Saver. |
| |
| Expected Results: |
| Test devices could report location to Google Map. |
| """ |
| test_result_all = [] |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| set_battery_saver_mode(self.ad, True) |
| for i in range(1, 6): |
| grant_location_permission(self.ad, True) |
| launch_google_map(self.ad) |
| test_result = check_location_api(self.ad, retries=3) |
| self.ad.send_keycode("HOME") |
| test_result_all.append(test_result) |
| self.ad.log.info("Iteration %d => %s" % (i, test_result)) |
| set_battery_saver_mode(self.ad, False) |
| asserts.assert_true(all(test_result_all), "Fail to get location update") |
| |
| def test_gnss_ttff_cs_airplane_mode_on(self): |
| """Verify Standalone GNSS functionality of TTFF Cold Start while |
| airplane mode is on. |
| |
| Steps: |
| 1. Turn on airplane mode. |
| 2. TTFF Cold Start for 10 iteration. |
| |
| Expected Results: |
| All Standalone TTFF Cold Start results should be within |
| standalone_cs_criteria. |
| """ |
| self.standalone_ttff_airplane_mode_on("cs", self.standalone_cs_criteria) |
| |
| def test_gnss_ttff_ws_airplane_mode_on(self): |
| """Verify Standalone GNSS functionality of TTFF Warm Start while |
| airplane mode is on. |
| |
| Steps: |
| 1. Turn on airplane mode. |
| 2. TTFF Warm Start for 10 iteration. |
| |
| Expected Results: |
| All Standalone TTFF Warm Start results should be within |
| standalone_ws_criteria. |
| """ |
| self.standalone_ttff_airplane_mode_on("ws", self.standalone_ws_criteria) |
| |
| def test_gnss_ttff_hs_airplane_mode_on(self): |
| """Verify Standalone GNSS functionality of TTFF Hot Start while |
| airplane mode is on. |
| |
| Steps: |
| 1. Turn on airplane mode. |
| 2. TTFF Hot Start for 10 iteration. |
| |
| Expected Results: |
| All Standalone TTFF Hot Start results should be within |
| standalone_hs_criteria. |
| """ |
| self.standalone_ttff_airplane_mode_on("hs", self.standalone_hs_criteria) |
| |
| def test_cs_ttff_in_weak_gnss_signal(self): |
| """Verify TTFF cold start under weak GNSS signal. |
| |
| Steps: |
| 1. Set attenuation value to weak GNSS signal. |
| 2. TTFF Cold Start for 10 iteration. |
| |
| Expected Results: |
| TTFF CS results should be within weak_signal_cs_criteria. |
| """ |
| gutils.set_attenuator_gnss_signal(self.ad, self.attenuators, |
| self.weak_gnss_signal_attenuation) |
| gutils.run_ttff(self.ad, mode="cs", criteria=self.weak_signal_cs_criteria, |
| test_cycle=self.ttff_test_cycle, base_lat_long=self.pixel_lab_location, |
| collect_logs=self.collect_logs) |
| |
| def test_ws_ttff_in_weak_gnss_signal(self): |
| """Verify TTFF warm start under weak GNSS signal. |
| |
| Steps: |
| 2. Set attenuation value to weak GNSS signal. |
| 3. TTFF Warm Start for 10 iteration. |
| |
| Expected Results: |
| TTFF WS result should be within weak_signal_criteria. |
| """ |
| gutils.set_attenuator_gnss_signal(self.ad, self.attenuators, |
| self.weak_gnss_signal_attenuation) |
| gutils.run_ttff(self.ad, mode="ws", criteria=self.weak_signal_criteria, |
| test_cycle=self.ttff_test_cycle, base_lat_long=self.pixel_lab_location, |
| collect_logs=self.collect_logs) |
| |
| def test_hs_ttff_in_weak_gnss_signal(self): |
| """Verify TTFF hot start under weak GNSS signal. |
| |
| Steps: |
| 2. Set attenuation value to weak GNSS signal. |
| 3. TTFF Hot Start for 10 iteration. |
| |
| Expected Results: |
| TTFF HS result should be within weak_signal_criteria. |
| """ |
| gutils.set_attenuator_gnss_signal(self.ad, self.attenuators, |
| self.weak_gnss_signal_attenuation) |
| gutils.run_ttff(self.ad, mode="hs", criteria=self.weak_signal_criteria, |
| test_cycle=self.ttff_test_cycle, base_lat_long=self.pixel_lab_location, |
| collect_logs=self.collect_logs) |
| |
| def test_quick_toggle_gnss_state(self): |
| """Verify GNSS can still work properly after quick toggle GNSS off |
| to on. |
| |
| Steps: |
| 1. Launch GTW_GPSTool. |
| 2. Go to "Advance setting" |
| 3. Set Cycle = 10 & Time-out = 60 |
| 4. Go to "Toggle GPS" tab |
| 5. Execute "Start" |
| |
| Expected Results: |
| No single Timeout is seen in 10 iterations. |
| """ |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| start_toggle_gnss_by_gtw_gpstool( |
| self.ad, iteration=self.ttff_test_cycle) |
| |
| def test_gnss_init_after_reboot(self): |
| """Verify SUPL and XTRA/LTO functionality after reboot. |
| |
| Steps: |
| 1. Get location fixed within supl_cs_criteria. |
| 2. Reboot DUT. |
| 3. Get location fixed within supl_hs_criteria. |
| 4. Repeat Step 2. to Step 3. for 10 times. |
| |
| Expected Results: |
| Location fixed within supl_hs_criteria. |
| """ |
| overall_test_result = [] |
| # As b/252971345 requests, we need the log before reboot for debugging. |
| gutils.start_pixel_logger(self.ad) |
| process_gnss_by_gtw_gpstool(self.ad, self.supl_cs_criteria) |
| start_gnss_by_gtw_gpstool(self.ad, False) |
| gutils.stop_pixel_logger(self.ad) |
| for test_loop in range(1, 11): |
| reboot(self.ad) |
| gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) |
| if is_device_wearable(self.ad): |
| test_result = process_gnss_by_gtw_gpstool( |
| self.ad, self.wearable_reboot_hs_criteria, clear_data=False) |
| else: |
| test_result = process_gnss_by_gtw_gpstool( |
| self.ad, self.supl_hs_criteria, clear_data=False) |
| start_gnss_by_gtw_gpstool(self.ad, False) |
| self.ad.log.info("Iteration %d => %s" % (test_loop, test_result)) |
| overall_test_result.append(test_result) |
| gutils.stop_pixel_logger(self.ad) |
| stop_adb_tcpdump(self.ad) |
| pass_rate = overall_test_result.count(True)/len(overall_test_result) |
| self.ad.log.info("TestResult Pass_rate %s" % format(pass_rate, ".0%")) |
| asserts.assert_true(all(overall_test_result), |
| "GNSS init fail after reboot.") |
| |
| def test_host_gnssstatus_validation(self): |
| """Verify GnssStatus integrity during host tracking for 1 minute. |
| |
| Steps: |
| 1. Launch GTW_GPSTool. |
| 2. GNSS tracking for 1 minute with 1 second frequency. |
| 3. Validate all the GnssStatus raw data.(SV, SVID, Elev, Azim) |
| |
| Expected Results: |
| GnssStatus obj should return no failures |
| """ |
| gnss_tracking_via_gtw_gpstool(self.ad, self.standalone_cs_criteria, |
| api_type="gnss", testtime=1) |
| parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss", |
| validate_gnssstatus=True) |
| |
| def test_onchip_gnssstatus_validation(self): |
| """Verify GnssStatus integrity during onchip tracking for 1 minute. |
| |
| Steps: |
| 1. Launch GTW_GPSTool. |
| 2. GNSS tracking for 1 minute with 6 second frequency. |
| 3. Validate all the GnssStatus raw data.(SV, SVID, Elev, Azim) |
| |
| Expected Results: |
| GnssStatus obj should return no failures |
| """ |
| if gutils.check_chipset_vendor_by_qualcomm(self.ad): |
| raise signals.TestSkip("Not BRCM chipset. Skip the test.") |
| gnss_tracking_via_gtw_gpstool(self.ad, self.standalone_cs_criteria, |
| api_type="gnss", testtime=1, freq=self.onchip_interval) |
| parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss", |
| validate_gnssstatus=True) |
| |
| def test_location_update_after_resuming_from_deep_suspend(self): |
| """Verify the GPS location reported after resume from suspend mode |
| 1. Enable GPS location report for 1 min to make sure the GPS is working |
| 2. Force DUT into deep suspend mode for a while(3 times with 15s interval) |
| 3. Enable GPS location report for 5 mins |
| 4. Check the report frequency |
| 5. Check the location fix rate |
| """ |
| |
| gps_enable_minutes = 1 |
| gnss_tracking_via_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria, api_type="gnss", |
| testtime=gps_enable_minutes) |
| result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") |
| self.ad.log.debug("Location report details before suspend") |
| self.ad.log.debug(result) |
| gutils.validate_location_fix_rate(self.ad, result, run_time=gps_enable_minutes, |
| fix_rate_criteria=0.95) |
| |
| gutils.deep_suspend_device(self.ad) |
| |
| gps_enable_minutes = 5 |
| gnss_tracking_via_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria, api_type="gnss", |
| testtime=gps_enable_minutes) |
| result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") |
| self.ad.log.debug("Location report details after suspend") |
| self.ad.log.debug(result) |
| |
| location_report_time = list(result.keys()) |
| gutils.check_location_report_interval(self.ad, location_report_time, |
| gps_enable_minutes * 60, tolerance=0.01) |
| gutils.validate_location_fix_rate(self.ad, result, run_time=gps_enable_minutes, |
| fix_rate_criteria=0.99) |
| |
| def test_location_mode_in_battery_saver_with_screen_off(self): |
| """Ensure location request with foreground permission can work |
| in battery saver mode (screen off) |
| |
| 1. unplug power |
| 2. enter battery saver mode |
| 3. start tracking for 2 mins with screen off |
| 4. repest step 3 for 3 times |
| """ |
| try: |
| gutils.set_battery_saver_mode(self.ad, state=True) |
| test_time = 2 |
| for i in range(1, 4): |
| self.ad.log.info("Tracking attempt %s" % str(i)) |
| gnss_tracking_via_gtw_gpstool( |
| self.ad, criteria=self.supl_cs_criteria, api_type="gnss", testtime=test_time, |
| is_screen_off=True) |
| result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") |
| gutils.validate_location_fix_rate(self.ad, result, run_time=test_time, |
| fix_rate_criteria=0.99) |
| finally: |
| gutils.set_battery_saver_mode(self.ad, state=False) |
| |
| def test_measure_adr_rate_after_10_mins_tracking(self): |
| """Verify ADR rate |
| |
| 1. Enable "Force full gnss measurement" |
| 2. Start tracking with GnssMeasurement enabled for 10 mins |
| 3. Check ADR usable rate / valid rate |
| 4. Disable "Force full gnss measurement" |
| """ |
| adr_threshold = self.adr_ratio_threshold.get(self.ad.model) |
| if not adr_threshold: |
| self.ad.log.warn((f"Can't get '{self.ad.model}' threshold from config " |
| f"{self.adr_ratio_threshold}, use default threshold 0.5")) |
| adr_threshold = 0.5 |
| with gutils.full_gnss_measurement(self.ad): |
| gnss_tracking_via_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria, api_type="gnss", |
| testtime=10, meas_flag=True) |
| gutils.validate_adr_rate(self.ad, pass_criteria=float(adr_threshold)) |
| |
| |
| def test_hal_crashing_should_resume_tracking(self): |
| """Make sure location request can be resumed after HAL restart. |
| |
| 1. Start GPS tool and get First Fixed |
| 2. Wait for 1 min for tracking |
| 3. Restart HAL service |
| 4. Wait for 1 min for tracking |
| 5. Check fix rate |
| """ |
| |
| first_fixed_time = process_gnss_by_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria) |
| begin_time = int(first_fixed_time.timestamp() * 1000) |
| |
| self.ad.log.info("Start 2 mins tracking") |
| |
| gutils.wait_n_mins_for_gnss_tracking(self.ad, begin_time, testtime=1, |
| ignore_hal_crash=False) |
| gutils.restart_hal_service(self.ad) |
| # The test case is designed to run the tracking for 2 mins, so we assign testime to 2 to |
| # indicate the total run time is 2 mins (starting from begin_time). |
| gutils.wait_n_mins_for_gnss_tracking(self.ad, begin_time, testtime=2, ignore_hal_crash=True) |
| |
| start_gnss_by_gtw_gpstool(self.ad, state=False) |
| |
| result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location) |
| gutils.validate_location_fix_rate(self.ad, result, run_time=2, |
| fix_rate_criteria=0.95) |
| |
| |
| def test_power_save_mode_should_apply_latest_measurement_setting(self): |
| """Ensure power save mode will apply the GNSS measurement setting. |
| |
| 1. Turn off full GNSS measurement. |
| 2. Run tracking for 2 mins |
| 3. Check the power save mode status |
| 4. Turn on full GNSS measurement and re-register measurement callback |
| 6. Run tracking for 30s |
| 7. Check the power save mode status |
| 8. Turn off full GNSS measurement and re-register measurement callback |
| 9. Run tracking for 2 mins |
| 10. Check the power save mode status |
| """ |
| def wait_for_power_state_changes(wait_time): |
| gutils.re_register_measurement_callback(self.ad) |
| tracking_begin_time = get_current_epoch_time() |
| gutils.wait_n_mins_for_gnss_tracking(self.ad, tracking_begin_time, testtime=wait_time) |
| return tracking_begin_time |
| |
| if self.ad.model.lower() == "sunfish": |
| raise signals.TestSkip( |
| "According to b/241049795, it's HW issue and won't be fixed.") |
| |
| gutils.start_pixel_logger(self.ad) |
| with gutils.run_gnss_tracking(self.ad, criteria=self.supl_cs_criteria, meas_flag=True): |
| start_time = wait_for_power_state_changes(wait_time=2) |
| gutils.check_power_save_mode_status( |
| self.ad, full_power=False, begin_time=start_time, |
| brcm_error_allowlist=self.brcm_error_log_allowlist) |
| |
| with gutils.full_gnss_measurement(self.ad): |
| start_time = wait_for_power_state_changes(wait_time=0.5) |
| gutils.check_power_save_mode_status( |
| self.ad, full_power=True, begin_time=start_time, |
| brcm_error_allowlist=self.brcm_error_log_allowlist) |
| |
| start_time = wait_for_power_state_changes(wait_time=2) |
| gutils.check_power_save_mode_status( |
| self.ad, full_power=False, begin_time=start_time, |
| brcm_error_allowlist=self.brcm_error_log_allowlist) |
| |
| gutils.stop_pixel_logger(self.ad) |
| |