1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 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 17from collections import defaultdict 18import datetime 19import os 20import re 21import time 22import functools 23import fnmatch 24from statistics import mean 25 26from acts import asserts 27from acts import signals 28from acts.base_test import BaseTestClass 29from acts_contrib.test_utils.gnss import gnss_test_utils as gutils 30from acts.utils import get_current_epoch_time 31from acts.utils import unzip_maintain_permissions 32from acts_contrib.test_utils.wifi.wifi_test_utils import wifi_toggle_state 33from acts_contrib.test_utils.tel.tel_bootloader_utils import flash_radio 34from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection 35from acts_contrib.test_utils.tel.tel_test_utils import check_call_state_connected_by_adb 36from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode 37from acts_contrib.test_utils.tel.tel_voice_utils import hangup_call 38from acts_contrib.test_utils.gnss.gnss_test_utils import get_baseband_and_gms_version 39from acts_contrib.test_utils.gnss.gnss_test_utils import set_attenuator_gnss_signal 40from acts_contrib.test_utils.gnss.gnss_test_utils import _init_device 41from acts_contrib.test_utils.gnss.gnss_test_utils import check_location_service 42from acts_contrib.test_utils.gnss.gnss_test_utils import clear_logd_gnss_qxdm_log 43from acts_contrib.test_utils.gnss.gnss_test_utils import set_mobile_data 44from acts_contrib.test_utils.gnss.gnss_test_utils import set_wifi_and_bt_scanning 45from acts_contrib.test_utils.gnss.gnss_test_utils import get_gnss_qxdm_log 46from acts_contrib.test_utils.gnss.gnss_test_utils import remount_device 47from acts_contrib.test_utils.gnss.gnss_test_utils import reboot 48from acts_contrib.test_utils.gnss.gnss_test_utils import check_network_location 49from acts_contrib.test_utils.gnss.gnss_test_utils import launch_google_map 50from acts_contrib.test_utils.gnss.gnss_test_utils import check_location_api 51from acts_contrib.test_utils.gnss.gnss_test_utils import set_battery_saver_mode 52from acts_contrib.test_utils.gnss.gnss_test_utils import start_gnss_by_gtw_gpstool 53from acts_contrib.test_utils.gnss.gnss_test_utils import process_gnss_by_gtw_gpstool 54from acts_contrib.test_utils.gnss.gnss_test_utils import connect_to_wifi_network 55from acts_contrib.test_utils.gnss.gnss_test_utils import gnss_tracking_via_gtw_gpstool 56from acts_contrib.test_utils.gnss.gnss_test_utils import parse_gtw_gpstool_log 57from acts_contrib.test_utils.gnss.gnss_test_utils import start_toggle_gnss_by_gtw_gpstool 58from acts_contrib.test_utils.gnss.gnss_test_utils import grant_location_permission 59from acts_contrib.test_utils.gnss.gnss_test_utils import is_mobile_data_on 60from acts_contrib.test_utils.gnss.gnss_test_utils import is_wearable_btwifi 61from acts_contrib.test_utils.gnss.gnss_test_utils import is_device_wearable 62from acts_contrib.test_utils.gnss.gnss_test_utils import log_current_epoch_time 63from acts_contrib.test_utils.gnss.testtracker_util import log_testtracker_uuid 64from acts_contrib.test_utils.tel.tel_logging_utils import stop_adb_tcpdump 65from acts_contrib.test_utils.tel.tel_logging_utils import get_tcpdump_log 66 67 68_PPS_KICKIN_WAITING_TIME_IN_SECOND = 30 69 70class GnssFunctionTest(BaseTestClass): 71 """ GNSS Function Tests""" 72 def setup_class(self): 73 super().setup_class() 74 self.ad = self.android_devices[0] 75 req_params = ["pixel_lab_network", 76 "standalone_ws_criteria", "standalone_hs_criteria", 77 "supl_cs_criteria", 78 "supl_hs_criteria", 79 "standalone_cs_criteria", 80 "wearable_reboot_hs_criteria", 81 "first_satellite_criteria", 82 "default_gnss_signal_attenuation", 83 "weak_gnss_signal_attenuation", 84 "gnss_init_error_list", 85 "gnss_init_error_allowlist", "pixel_lab_location", 86 "qdsp6m_path", "ttff_test_cycle", 87 "collect_logs", "dpo_threshold", 88 "brcm_error_log_allowlist", "onchip_interval", "adr_ratio_threshold", 89 "set_attenuator", "weak_signal_criteria", "weak_signal_cs_criteria"] 90 self.unpack_userparams(req_param_names=req_params) 91 # create hashmap for SSID 92 self.ssid_map = {} 93 for network in self.pixel_lab_network: 94 SSID = network["SSID"] 95 self.ssid_map[SSID] = network 96 self.ttff_mode = {"cs": "Cold Start", 97 "ws": "Warm Start", 98 "hs": "Hot Start", 99 "csa": "CSWith Assist"} 100 if self.collect_logs and gutils.check_chipset_vendor_by_qualcomm(self.ad): 101 self.flash_new_radio_or_mbn() 102 self.push_gnss_cfg() 103 self.init_device() 104 105 def init_device(self): 106 gutils._init_device(self.ad) 107 gutils.enable_supl_mode(self.ad) 108 gutils.enable_vendor_orbit_assistance_data(self.ad) 109 gutils.disable_ramdump(self.ad) 110 gutils.enable_compact_and_particle_fusion_log(self.ad) 111 112 def setup_test(self): 113 log_current_epoch_time(self.ad, "test_start_time") 114 log_testtracker_uuid(self.ad, self.current_test_name) 115 get_baseband_and_gms_version(self.ad) 116 if self.collect_logs: 117 clear_logd_gnss_qxdm_log(self.ad) 118 if self.set_attenuator: 119 set_attenuator_gnss_signal(self.ad, self.attenuators, 120 self.default_gnss_signal_attenuation) 121 # TODO (b/202101058:chenstanley): Need to double check how to disable wifi successfully in wearable projects. 122 if is_wearable_btwifi(self.ad): 123 wifi_toggle_state(self.ad, True) 124 connect_to_wifi_network( 125 self.ad, self.ssid_map[self.pixel_lab_network[0]["SSID"]]) 126 else: 127 wifi_toggle_state(self.ad, False) 128 set_mobile_data(self.ad, True) 129 130 if not verify_internet_connection(self.ad.log, self.ad, retries=3, 131 expected_state=True): 132 raise signals.TestFailure("Fail to connect to LTE network.") 133 134 def teardown_test(self): 135 if self.collect_logs: 136 gutils.stop_pixel_logger(self.ad) 137 stop_adb_tcpdump(self.ad) 138 if self.set_attenuator: 139 set_attenuator_gnss_signal(self.ad, self.attenuators, 140 self.default_gnss_signal_attenuation) 141 # TODO(chenstanley): sim structure issue 142 if not is_device_wearable(self.ad): 143 if check_call_state_connected_by_adb(self.ad): 144 hangup_call(self.ad.log, self.ad) 145 if self.ad.droid.connectivityCheckAirplaneMode(): 146 self.ad.log.info("Force airplane mode off") 147 toggle_airplane_mode(self.ad.log, self.ad, new_state=False) 148 if int(self.ad.adb.shell( 149 "settings get global wifi_scan_always_enabled")) != 1: 150 set_wifi_and_bt_scanning(self.ad, True) 151 log_current_epoch_time(self.ad, "test_end_time") 152 153 def keep_logs(self): 154 # for debug cs is faster than ws issue 155 test_name = self.test_name 156 self.ad.take_bug_report(test_name, self.begin_time) 157 get_gnss_qxdm_log(self.ad, self.qdsp6m_path) 158 get_tcpdump_log(self.ad, test_name, self.begin_time) 159 160 def on_fail(self, test_name, begin_time): 161 if self.collect_logs: 162 self.ad.take_bug_report(test_name, begin_time) 163 get_gnss_qxdm_log(self.ad, self.qdsp6m_path) 164 get_tcpdump_log(self.ad, test_name, begin_time) 165 166 def push_gnss_cfg(self): 167 """Push required GNSS cfg file to DUT for PixelLogger to use as 168 default GNSS logging mask.""" 169 gnss_cfg_path = "/vendor/etc/mdlog" 170 gnss_cfg_file = self.user_params.get("gnss_cfg") 171 if isinstance(gnss_cfg_file, list): 172 gnss_cfg_file = gnss_cfg_file[0] 173 os.system("chmod -R 777 %s" % gnss_cfg_file) 174 self.ad.log.info("GNSS Required CFG = %s" % gnss_cfg_file) 175 self.ad.log.info("Push %s to %s" % (gnss_cfg_file, gnss_cfg_path)) 176 self.ad.push_system_file(gnss_cfg_file, gnss_cfg_path) 177 178 def flash_new_radio_or_mbn(self): 179 paths = {} 180 path = self.user_params.get("radio_image") 181 if isinstance(path, list): 182 path = path[0] 183 if not path or "dev/null" in path: 184 self.ad.log.info("Radio image path is not defined in Test flag.") 185 return False 186 for path_key in os.listdir(path): 187 if fnmatch.fnmatch(path_key, "*.img"): 188 paths["radio_image"] = os.path.join(path, path_key) 189 os.system("chmod -R 777 %s" % paths["radio_image"]) 190 self.ad.log.info("radio_image = %s" % paths["radio_image"]) 191 if fnmatch.fnmatch(path_key, "*.zip"): 192 zip_path = os.path.join(path, path_key) 193 self.ad.log.info("Unzip %s", zip_path) 194 dest_path = os.path.join(path, "mbn") 195 unzip_maintain_permissions(zip_path, dest_path) 196 paths["mbn_path"] = dest_path 197 os.system("chmod -R 777 %s" % paths["mbn_path"]) 198 self.ad.log.info("mbn_path = %s" % paths["mbn_path"]) 199 self.ad.log.info(os.listdir(paths["mbn_path"])) 200 if not paths.get("radio_image"): 201 self.ad.log.info("No radio image is provided on X20. " 202 "Skip flashing radio step.") 203 return False 204 else: 205 get_baseband_and_gms_version(self.ad, "Before flash radio") 206 flash_radio(self.ad, paths["radio_image"]) 207 get_baseband_and_gms_version(self.ad, "After flash radio") 208 if not paths.get("mbn_path"): 209 self.ad.log.info("No need to push mbn files") 210 return False 211 else: 212 try: 213 mcfg_ver = self.ad.adb.shell( 214 "cat /vendor/rfs/msm/mpss/readonly/vendor/mbn/mcfg.version") 215 if mcfg_ver: 216 self.ad.log.info("Before push mcfg, mcfg.version = %s", 217 mcfg_ver) 218 else: 219 self.ad.log.info("There is no mcfg.version before push, " 220 "unmatching device") 221 return False 222 except Exception as e: 223 self.ad.log.info("There is no mcfg.version before push, " 224 "unmatching device %s" % e) 225 return False 226 get_baseband_and_gms_version(self.ad, "Before push mcfg") 227 try: 228 remount_device(self.ad) 229 cmd = "%s %s" % (paths["mbn_path"]+"/.", 230 "/vendor/rfs/msm/mpss/readonly/vendor/mbn/") 231 out = self.ad.adb.push(cmd) 232 self.ad.log.info(out) 233 reboot(self.ad) 234 except Exception as e: 235 self.ad.log.error("Push mbn files error %s", e) 236 return False 237 get_baseband_and_gms_version(self.ad, "After push mcfg") 238 try: 239 new_mcfg_ver = self.ad.adb.shell( 240 "cat /vendor/rfs/msm/mpss/readonly/vendor/mbn/mcfg.version") 241 if new_mcfg_ver: 242 self.ad.log.info("New mcfg.version = %s", new_mcfg_ver) 243 if new_mcfg_ver == mcfg_ver: 244 self.ad.log.error("mcfg.version is the same before and " 245 "after push") 246 return True 247 else: 248 self.ad.log.error("Unable to get new mcfg.version") 249 return False 250 except Exception as e: 251 self.ad.log.error("cat mcfg.version with error %s", e) 252 return False 253 254 def standalone_ttff_airplane_mode_on(self, mode, criteria): 255 """Verify Standalone GNSS TTFF functionality while airplane mode is on. 256 257 Args: 258 mode: "cs", "ws" or "hs" 259 criteria: Criteria for the test. 260 """ 261 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 262 self.ad.log.info("Turn airplane mode on") 263 toggle_airplane_mode(self.ad.log, self.ad, new_state=True) 264 """ 265 The change for arguments here is for b/277667310 266 Randomized interval is used for breaking CS GLNS only fix sequence. 267 """ 268 gutils.run_ttff_via_gtw_gpstool( 269 self.ad, 270 mode, 271 criteria, 272 self.ttff_test_cycle, 273 self.pixel_lab_location, 274 raninterval=True, 275 mininterval=15, 276 maxinterval=20,) 277 278 """ Test Cases """ 279 280 def test_cs_first_fixed_system_server_restart(self): 281 """Verify cs first fixed after system server restart. 282 283 Steps: 284 1. Get location fixed within supl_cs_criteria. 285 2. Restarts android runtime. 286 3. Get location fixed within supl_cs_criteria. 287 288 Expected Results: 289 Location fixed within supl_cs_criteria. 290 """ 291 overall_test_result = [] 292 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 293 for test_loop in range(1, 6): 294 gutils.process_gnss_by_gtw_gpstool(self.ad, self.supl_cs_criteria) 295 gutils.start_gnss_by_gtw_gpstool(self.ad, False) 296 self.ad.restart_runtime() 297 self.ad.unlock_screen(password=None) 298 test_result = gutils.process_gnss_by_gtw_gpstool(self.ad, self.supl_cs_criteria) 299 gutils.start_gnss_by_gtw_gpstool(self.ad, False) 300 self.ad.log.info("Iteration %d => %s" % (test_loop, test_result)) 301 overall_test_result.append(test_result) 302 303 asserts.assert_true(all(overall_test_result), 304 "SUPL fail after system server restart.") 305 306 def test_recovery_and_location_time_after_gnss_services_restart(self): 307 """Verify gpsd recover time after gpsd being killed. 308 309 Steps: 310 1. Start GPS tracking 311 2. Restart GPS daemons by killing PID. 312 3. Waiting for GPS service to restart 313 4. Waiting for the first fixed 314 4. Re-run steps 1~4 for 5 times. 315 316 Expected Results: 317 1. The time GPSd services take to restart must be within 3 seconds. 318 2. Location fix time must be within supl_hs_criteria 319 """ 320 if gutils.check_chipset_vendor_by_qualcomm(self.ad): 321 raise signals.TestSkip("Skip the test due to Qualcomm chipset") 322 test_times = 5 323 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 324 satellite_times = defaultdict(list) 325 location_fix_times = defaultdict(list) 326 327 kill_functions = ( 328 gutils.get_gps_process_and_kill_function_by_vendor(self.ad)) 329 for time in range(1, test_times+1): 330 self.ad.log.info("Performing test times %d", time) 331 first_fixed_time = process_gnss_by_gtw_gpstool( 332 self.ad, 333 criteria=self.supl_hs_criteria, 334 clear_data=False) 335 336 begin_time = int(first_fixed_time.timestamp() * 1000) 337 self.ad.log.info("Start tracking") 338 gutils.wait_n_mins_for_gnss_tracking(self.ad, 339 begin_time, 340 testtime=0.5, 341 ignore_hal_crash=False) 342 343 344 for num, (process, kill_function) in enumerate(kill_functions.items()): 345 kill_start_time = kill_function() 346 first_gpsd_update_time = (gutils.get_gpsd_update_time( 347 self.ad, 348 kill_start_time)) 349 self.ad.log.info("Resume tracking ... ") 350 gutils.wait_n_mins_for_gnss_tracking(self.ad, 351 begin_time, 352 testtime=num+1, 353 ignore_hal_crash=True) 354 355 location_fix_time = (gutils. 356 get_location_fix_time_via_gpstool_log( 357 self.ad, first_gpsd_update_time)) 358 359 satellite_times[process].append(first_gpsd_update_time - kill_start_time) 360 location_fix_times[process].append(location_fix_time - first_gpsd_update_time) 361 # gpsd recovery time : Time between gpsd killed to first satellite update. 362 self.ad.log.info("%s recovery time : %d ms", 363 process, (first_gpsd_update_time - kill_start_time)) 364 # TTFF Hot Start : Time between first satellite update to first location fix. 365 self.ad.log.info("TTFF Hot Start %d ms", 366 (location_fix_time - first_gpsd_update_time)) 367 start_gnss_by_gtw_gpstool(self.ad, state=False) 368 369 for num, process in enumerate(kill_functions): 370 prop_basename = gutils.UPLOAD_TO_SPONGE_PREFIX + f"{process}_recovery_time_" 371 self.ad.log.info(prop_basename + "AVG %d", 372 mean(satellite_times[process])) 373 self.ad.log.info(prop_basename + "MAX %d", 374 max(satellite_times[process])) 375 prop_basename = gutils.UPLOAD_TO_SPONGE_PREFIX + f"{process}_ttff_hs_" 376 self.ad.log.info(prop_basename + "AVG %d", 377 mean(location_fix_times[process])) 378 self.ad.log.info(prop_basename + "MAX %d", 379 max(location_fix_times[process])) 380 asserts.assert_true(mean(satellite_times[process])/1000 <= 381 self.first_satellite_criteria, 382 f"{process} takes more than {self.first_satellite_criteria}" 383 "seconds in average to recover") 384 asserts.assert_true(mean(location_fix_times[process])/1000 <= 385 self.supl_hs_criteria, 386 f"Location fix time is more than {self.supl_hs_criteria}" 387 "seconds in average") 388 389 def test_gnss_one_hour_tracking(self): 390 """Verify GNSS tracking performance of signal strength and position 391 error. 392 393 Steps: 394 1. Launch GTW_GPSTool. 395 2. GNSS tracking for 60 minutes. 396 397 Expected Results: 398 DUT could finish 60 minutes test and output track data. 399 """ 400 test_time = 60 401 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 402 gnss_tracking_via_gtw_gpstool(self.ad, self.standalone_cs_criteria, 403 api_type="gnss", testtime=test_time) 404 location_data = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") 405 gutils.validate_location_fix_rate(self.ad, location_data, run_time=test_time, 406 fix_rate_criteria=0.99) 407 gutils.verify_gps_time_should_be_close_to_device_time(self.ad, location_data) 408 409 def test_duty_cycle_function(self): 410 """Verify duty cycle Functionality. 411 412 Steps: 413 1. Launch GTW_GPSTool. 414 2. Enable GnssMeasurement. 415 3. GNSS tracking for 5 minutes. 416 4. Calculate the count diff of "HardwareClockDiscontinuityCount" 417 418 Expected Results: 419 Duty cycle should be engaged in 5 minutes GNSS tracking. 420 """ 421 tracking_minutes = 5 422 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 423 dpo_begin_time = get_current_epoch_time() 424 gnss_tracking_via_gtw_gpstool(self.ad, 425 self.standalone_cs_criteria, 426 api_type="gnss", 427 testtime=tracking_minutes, 428 meas_flag=True) 429 if gutils.check_chipset_vendor_by_qualcomm(self.ad): 430 gutils.check_dpo_rate_via_gnss_meas(self.ad, 431 dpo_begin_time, 432 self.dpo_threshold) 433 else: 434 gutils.check_dpo_rate_via_brcm_log(self.ad, 435 self.dpo_threshold, 436 self.brcm_error_log_allowlist) 437 438 def test_gnss_init_error(self): 439 """Check if there is any GNSS initialization error after reboot. 440 441 Steps: 442 1. Reboot DUT. 443 2. Check logcat if the following error pattern shows up. 444 "E LocSvc.*", ".*avc.*denied.*u:r:location:s0", 445 ".*avc.*denied.*u:r:hal_gnss_qti:s0" 446 447 Expected Results: 448 There should be no GNSS initialization error after reboot. 449 """ 450 error_mismatch = True 451 for attr in self.gnss_init_error_list: 452 error = self.ad.adb.shell("logcat -d | grep -E '%s'" % attr) 453 if error: 454 for allowlist in self.gnss_init_error_allowlist: 455 if allowlist in error: 456 error = re.sub(".*"+allowlist+".*\n?", "", error) 457 self.ad.log.info("\"%s\" is in allow-list and removed " 458 "from error." % allowlist) 459 if error: 460 error_mismatch = False 461 self.ad.log.error("\n%s" % error) 462 else: 463 self.ad.log.info("NO \"%s\" initialization error found." % attr) 464 asserts.assert_true(error_mismatch, "Error message found after GNSS " 465 "init") 466 467 def test_sap_valid_modes(self): 468 """Verify SAP Valid Modes. 469 470 Steps: 471 1. Root DUT. 472 2. Check SAP Valid Modes. 473 474 Expected Results: 475 SAP=PREMIUM 476 """ 477 if not gutils.check_chipset_vendor_by_qualcomm(self.ad): 478 raise signals.TestSkip("Not Qualcomm chipset. Skip the test.") 479 sap_state = str(self.ad.adb.shell("cat vendor/etc/izat.conf | grep " 480 "SAP=")) 481 self.ad.log.info("SAP Valid Modes - %s" % sap_state) 482 asserts.assert_true("SAP=PREMIUM" in sap_state, 483 "Wrong SAP Valid Modes is set") 484 485 def test_network_location_provider_cell(self): 486 """Verify LocationManagerService API reports cell Network Location. 487 488 Steps: 489 1. WiFi scanning and Bluetooth scanning in Location Setting are OFF. 490 2. Launch GTW_GPSTool. 491 3. Verify whether test devices could report cell Network Location. 492 4. Repeat Step 2. to Step 3. for 5 times. 493 494 Expected Results: 495 Test devices could report cell Network Location. 496 """ 497 test_result_all = [] 498 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 499 set_wifi_and_bt_scanning(self.ad, False) 500 for i in range(1, 6): 501 test_result = check_network_location( 502 self.ad, retries=3, location_type="cell") 503 test_result_all.append(test_result) 504 self.ad.log.info("Iteration %d => %s" % (i, test_result)) 505 set_wifi_and_bt_scanning(self.ad, True) 506 asserts.assert_true(all(test_result_all), 507 "Fail to get networkLocationType=cell") 508 509 def test_network_location_provider_wifi(self): 510 """Verify LocationManagerService API reports wifi Network Location. 511 512 Steps: 513 1. WiFi scanning and Bluetooth scanning in Location Setting are ON. 514 2. Launch GTW_GPSTool. 515 3. Verify whether test devices could report wifi Network Location. 516 4. Repeat Step 2. to Step 3. for 5 times. 517 518 Expected Results: 519 Test devices could report wifi Network Location. 520 """ 521 test_result_all = [] 522 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 523 set_wifi_and_bt_scanning(self.ad, True) 524 for i in range(1, 6): 525 test_result = check_network_location( 526 self.ad, retries=3, location_type="wifi") 527 test_result_all.append(test_result) 528 self.ad.log.info("Iteration %d => %s" % (i, test_result)) 529 asserts.assert_true(all(test_result_all), 530 "Fail to get networkLocationType=wifi") 531 532 def test_gmap_location_report_battery_saver(self): 533 """Verify GnssLocationProvider API reports location to Google Map 534 when Battery Saver is enabled. 535 536 Steps: 537 1. GPS and NLP are on. 538 2. Enable Battery Saver. 539 3. Launch Google Map. 540 4. Verify whether test devices could report location. 541 5. Repeat Step 3. to Step 4. for 5 times. 542 6. Disable Battery Saver. 543 544 Expected Results: 545 Test devices could report location to Google Map. 546 """ 547 test_result_all = [] 548 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 549 set_battery_saver_mode(self.ad, True) 550 for i in range(1, 6): 551 grant_location_permission(self.ad, True) 552 launch_google_map(self.ad) 553 test_result = check_location_api(self.ad, retries=3) 554 self.ad.send_keycode("HOME") 555 test_result_all.append(test_result) 556 self.ad.log.info("Iteration %d => %s" % (i, test_result)) 557 set_battery_saver_mode(self.ad, False) 558 asserts.assert_true(all(test_result_all), "Fail to get location update") 559 560 def test_gnss_ttff_cs_airplane_mode_on(self): 561 """Verify Standalone GNSS functionality of TTFF Cold Start while 562 airplane mode is on. 563 564 Steps: 565 1. Turn on airplane mode. 566 2. TTFF Cold Start for 10 iteration. 567 568 Expected Results: 569 All Standalone TTFF Cold Start results should be within 570 standalone_cs_criteria. 571 """ 572 self.standalone_ttff_airplane_mode_on("cs", self.standalone_cs_criteria) 573 574 def test_gnss_ttff_ws_airplane_mode_on(self): 575 """Verify Standalone GNSS functionality of TTFF Warm Start while 576 airplane mode is on. 577 578 Steps: 579 1. Turn on airplane mode. 580 2. TTFF Warm Start for 10 iteration. 581 582 Expected Results: 583 All Standalone TTFF Warm Start results should be within 584 standalone_ws_criteria. 585 """ 586 self.standalone_ttff_airplane_mode_on("ws", self.standalone_ws_criteria) 587 588 def test_gnss_ttff_hs_airplane_mode_on(self): 589 """Verify Standalone GNSS functionality of TTFF Hot Start while 590 airplane mode is on. 591 592 Steps: 593 1. Turn on airplane mode. 594 2. TTFF Hot Start for 10 iteration. 595 596 Expected Results: 597 All Standalone TTFF Hot Start results should be within 598 standalone_hs_criteria. 599 """ 600 self.standalone_ttff_airplane_mode_on("hs", self.standalone_hs_criteria) 601 602 def test_cs_ttff_in_weak_gnss_signal(self): 603 """Verify TTFF cold start under weak GNSS signal. 604 605 Steps: 606 1. Set attenuation value to weak GNSS signal. 607 2. TTFF Cold Start for 10 iteration. 608 609 Expected Results: 610 TTFF CS results should be within weak_signal_cs_criteria. 611 """ 612 gutils.set_attenuator_gnss_signal(self.ad, self.attenuators, 613 self.weak_gnss_signal_attenuation) 614 gutils.run_ttff(self.ad, mode="cs", criteria=self.weak_signal_cs_criteria, 615 test_cycle=self.ttff_test_cycle, base_lat_long=self.pixel_lab_location, 616 collect_logs=self.collect_logs) 617 618 def test_ws_ttff_in_weak_gnss_signal(self): 619 """Verify TTFF warm start under weak GNSS signal. 620 621 Steps: 622 2. Set attenuation value to weak GNSS signal. 623 3. TTFF Warm Start for 10 iteration. 624 625 Expected Results: 626 TTFF WS result should be within weak_signal_criteria. 627 """ 628 gutils.set_attenuator_gnss_signal(self.ad, self.attenuators, 629 self.weak_gnss_signal_attenuation) 630 gutils.run_ttff(self.ad, mode="ws", criteria=self.weak_signal_criteria, 631 test_cycle=self.ttff_test_cycle, base_lat_long=self.pixel_lab_location, 632 collect_logs=self.collect_logs) 633 634 def test_hs_ttff_in_weak_gnss_signal(self): 635 """Verify TTFF hot start under weak GNSS signal. 636 637 Steps: 638 2. Set attenuation value to weak GNSS signal. 639 3. TTFF Hot Start for 10 iteration. 640 641 Expected Results: 642 TTFF HS result should be within weak_signal_criteria. 643 """ 644 gutils.set_attenuator_gnss_signal(self.ad, self.attenuators, 645 self.weak_gnss_signal_attenuation) 646 gutils.run_ttff(self.ad, mode="hs", criteria=self.weak_signal_criteria, 647 test_cycle=self.ttff_test_cycle, base_lat_long=self.pixel_lab_location, 648 collect_logs=self.collect_logs) 649 650 def test_quick_toggle_gnss_state(self): 651 """Verify GNSS can still work properly after quick toggle GNSS off 652 to on. 653 654 Steps: 655 1. Launch GTW_GPSTool. 656 2. Go to "Advance setting" 657 3. Set Cycle = 10 & Time-out = 60 658 4. Go to "Toggle GPS" tab 659 5. Execute "Start" 660 661 Expected Results: 662 No single Timeout is seen in 10 iterations. 663 """ 664 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 665 start_toggle_gnss_by_gtw_gpstool( 666 self.ad, iteration=self.ttff_test_cycle) 667 668 def test_gnss_init_after_reboot(self): 669 """Verify SUPL and XTRA/LTO functionality after reboot. 670 671 Steps: 672 1. Get location fixed within supl_cs_criteria. 673 2. Reboot DUT. 674 3. Get location fixed within supl_hs_criteria. 675 4. Repeat Step 2. to Step 3. for 10 times. 676 677 Expected Results: 678 Location fixed within supl_hs_criteria. 679 """ 680 overall_test_result = [] 681 # As b/252971345 requests, we need the log before reboot for debugging. 682 gutils.start_pixel_logger(self.ad) 683 process_gnss_by_gtw_gpstool(self.ad, self.supl_cs_criteria) 684 start_gnss_by_gtw_gpstool(self.ad, False) 685 gutils.stop_pixel_logger(self.ad) 686 for test_loop in range(1, 11): 687 reboot(self.ad) 688 gutils.start_qxdm_and_tcpdump_log(self.ad, self.collect_logs) 689 if is_device_wearable(self.ad): 690 test_result = process_gnss_by_gtw_gpstool( 691 self.ad, self.wearable_reboot_hs_criteria, clear_data=False) 692 else: 693 test_result = process_gnss_by_gtw_gpstool( 694 self.ad, self.supl_hs_criteria, clear_data=False) 695 start_gnss_by_gtw_gpstool(self.ad, False) 696 self.ad.log.info("Iteration %d => %s" % (test_loop, test_result)) 697 overall_test_result.append(test_result) 698 gutils.stop_pixel_logger(self.ad) 699 stop_adb_tcpdump(self.ad) 700 pass_rate = overall_test_result.count(True)/len(overall_test_result) 701 self.ad.log.info("TestResult Pass_rate %s" % format(pass_rate, ".0%")) 702 asserts.assert_true(all(overall_test_result), 703 "GNSS init fail after reboot.") 704 705 def test_host_gnssstatus_validation(self): 706 """Verify GnssStatus integrity during host tracking for 1 minute. 707 708 Steps: 709 1. Launch GTW_GPSTool. 710 2. GNSS tracking for 1 minute with 1 second frequency. 711 3. Validate all the GnssStatus raw data.(SV, SVID, Elev, Azim) 712 713 Expected Results: 714 GnssStatus obj should return no failures 715 """ 716 gnss_tracking_via_gtw_gpstool(self.ad, self.standalone_cs_criteria, 717 api_type="gnss", testtime=1) 718 parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss", 719 validate_gnssstatus=True) 720 721 def test_onchip_gnssstatus_validation(self): 722 """Verify GnssStatus integrity during onchip tracking for 1 minute. 723 724 Steps: 725 1. Launch GTW_GPSTool. 726 2. GNSS tracking for 1 minute with 6 second frequency. 727 3. Validate all the GnssStatus raw data.(SV, SVID, Elev, Azim) 728 729 Expected Results: 730 GnssStatus obj should return no failures 731 """ 732 if gutils.check_chipset_vendor_by_qualcomm(self.ad): 733 raise signals.TestSkip("Not BRCM chipset. Skip the test.") 734 gnss_tracking_via_gtw_gpstool(self.ad, self.standalone_cs_criteria, 735 api_type="gnss", testtime=1, freq=self.onchip_interval) 736 parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss", 737 validate_gnssstatus=True) 738 739 def test_location_update_after_resuming_from_deep_suspend(self): 740 """Verify the GPS location reported after resume from deep doze mode 741 1. Enable GPS location report for 1 min to make sure the GPS is working 742 2. Force DUT into deep doze mode for 60s 743 3. Enable GPS location report for 5 mins 744 4. Check the report frequency 745 5. Check the location fix rate 746 """ 747 748 gps_enable_minutes = 1 749 gnss_tracking_via_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria, api_type="gnss", 750 testtime=gps_enable_minutes) 751 result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") 752 self.ad.log.debug("Location report details before deep doze") 753 self.ad.log.debug(result) 754 gutils.validate_location_fix_rate(self.ad, result, run_time=gps_enable_minutes, 755 fix_rate_criteria=0.95) 756 757 gutils.enter_deep_doze_mode(self.ad, lasting_time_in_seconds=60) 758 759 gps_enable_minutes = 5 760 gnss_tracking_via_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria, api_type="gnss", 761 testtime=gps_enable_minutes) 762 result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") 763 self.ad.log.debug("Location report details after deep doze") 764 self.ad.log.debug(result) 765 766 location_report_time = list(result.keys()) 767 gutils.check_location_report_interval(self.ad, location_report_time, 768 gps_enable_minutes * 60, tolerance=0.01) 769 gutils.validate_location_fix_rate(self.ad, result, run_time=gps_enable_minutes, 770 fix_rate_criteria=0.99) 771 772 def test_location_mode_in_battery_saver_with_screen_off(self): 773 """Ensure location request with foreground permission can work 774 in battery saver mode (screen off) 775 776 1. unplug power 777 2. enter battery saver mode 778 3. start tracking for 2 mins with screen off 779 4. repest step 3 for 3 times 780 """ 781 try: 782 gutils.set_battery_saver_mode(self.ad, state=True) 783 test_time = 2 784 for i in range(1, 4): 785 self.ad.log.info("Tracking attempt %s" % str(i)) 786 gnss_tracking_via_gtw_gpstool( 787 self.ad, criteria=self.supl_cs_criteria, api_type="gnss", testtime=test_time, 788 is_screen_off=True) 789 result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location, api_type="gnss") 790 gutils.validate_location_fix_rate(self.ad, result, run_time=test_time, 791 fix_rate_criteria=0.99) 792 finally: 793 gutils.set_battery_saver_mode(self.ad, state=False) 794 795 def test_measure_adr_rate_after_10_mins_tracking(self): 796 """Verify ADR rate 797 798 1. Enable "Force full gnss measurement" 799 2. Start tracking with GnssMeasurement enabled for 10 mins 800 3. Check ADR usable rate / valid rate 801 4. Disable "Force full gnss measurement" 802 """ 803 adr_threshold = self.adr_ratio_threshold.get(self.ad.model) 804 if not adr_threshold: 805 self.ad.log.warn((f"Can't get '{self.ad.model}' threshold from config " 806 f"{self.adr_ratio_threshold}, use default threshold 0.5")) 807 adr_threshold = 0.5 808 with gutils.full_gnss_measurement(self.ad): 809 gnss_tracking_via_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria, api_type="gnss", 810 testtime=10, meas_flag=True) 811 gutils.validate_adr_rate(self.ad, pass_criteria=float(adr_threshold)) 812 813 814 def test_hal_crashing_should_resume_tracking(self): 815 """Make sure location request can be resumed after HAL restart. 816 817 1. Start GPS tool and get First Fixed 818 2. Wait for 1 min for tracking 819 3. Restart HAL service 820 4. Wait for 1 min for tracking 821 5. Check fix rate 822 """ 823 824 first_fixed_time = process_gnss_by_gtw_gpstool(self.ad, criteria=self.supl_cs_criteria) 825 begin_time = int(first_fixed_time.timestamp() * 1000) 826 827 self.ad.log.info("Start 2 mins tracking") 828 829 gutils.wait_n_mins_for_gnss_tracking(self.ad, begin_time, testtime=1, 830 ignore_hal_crash=False) 831 gutils.restart_hal_service(self.ad) 832 # The test case is designed to run the tracking for 2 mins, so we assign testime to 2 to 833 # indicate the total run time is 2 mins (starting from begin_time). 834 gutils.wait_n_mins_for_gnss_tracking(self.ad, begin_time, testtime=2, ignore_hal_crash=True) 835 836 start_gnss_by_gtw_gpstool(self.ad, state=False) 837 838 result = parse_gtw_gpstool_log(self.ad, self.pixel_lab_location) 839 gutils.validate_location_fix_rate(self.ad, result, run_time=2, 840 fix_rate_criteria=0.95) 841 842 843 def test_power_save_mode_should_apply_latest_measurement_setting(self): 844 """Ensure power save mode will apply the GNSS measurement setting. 845 846 1. Turn off full GNSS measurement. 847 2. Run tracking for 2 mins 848 3. Check the power save mode status 849 4. Turn on full GNSS measurement and re-register measurement callback 850 6. Run tracking for 30s 851 7. Check the power save mode status 852 8. Turn off full GNSS measurement and re-register measurement callback 853 9. Run tracking for 2 mins 854 10. Check the power save mode status 855 """ 856 def wait_for_power_state_changes(wait_time): 857 gutils.re_register_measurement_callback(self.ad) 858 tracking_begin_time = get_current_epoch_time() 859 gutils.wait_n_mins_for_gnss_tracking(self.ad, tracking_begin_time, testtime=wait_time) 860 return tracking_begin_time 861 862 if self.ad.model.lower() == "sunfish": 863 raise signals.TestSkip( 864 "According to b/241049795, it's HW issue and won't be fixed.") 865 866 gutils.start_pixel_logger(self.ad) 867 with gutils.run_gnss_tracking(self.ad, criteria=self.supl_cs_criteria, meas_flag=True): 868 start_time = wait_for_power_state_changes(wait_time=2) 869 gutils.check_power_save_mode_status( 870 self.ad, full_power=False, begin_time=start_time, 871 brcm_error_allowlist=self.brcm_error_log_allowlist) 872 873 with gutils.full_gnss_measurement(self.ad): 874 start_time = wait_for_power_state_changes(wait_time=0.5) 875 gutils.check_power_save_mode_status( 876 self.ad, full_power=True, begin_time=start_time, 877 brcm_error_allowlist=self.brcm_error_log_allowlist) 878 879 start_time = wait_for_power_state_changes(wait_time=2) 880 gutils.check_power_save_mode_status( 881 self.ad, full_power=False, begin_time=start_time, 882 brcm_error_allowlist=self.brcm_error_log_allowlist) 883 884 gutils.stop_pixel_logger(self.ad) 885 886 def test_the_diff_of_gps_clock_and_elapsed_realtime_should_be_stable(self): 887 gutils.start_pixel_logger(self.ad) 888 with gutils.full_gnss_measurement(self.ad): 889 first_fixed_time = gnss_tracking_via_gtw_gpstool( 890 self.ad, criteria=self.supl_cs_criteria, api_type="gnss", 891 testtime=5, meas_flag=True) 892 gutils.stop_pixel_logger(self.ad) 893 start_time = first_fixed_time + datetime.timedelta( 894 seconds=time.timezone + _PPS_KICKIN_WAITING_TIME_IN_SECOND) 895 self.ad.log.debug("Start time is %s" % start_time) 896 gutils.validate_diff_of_gps_clock_elapsed_realtime(self.ad, start_time) 897