1#!/usr/bin/env python3.5 2# 3# Copyright 2019 - Google 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16 17import time 18import re 19import os 20import math 21import shutil 22import fnmatch 23import posixpath 24from collections import namedtuple 25 26from acts import utils 27from acts import signals 28from acts.controllers.android_device import list_adb_devices 29from acts.controllers.android_device import list_fastboot_devices 30from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH 31from acts.controllers.android_device import SL4A_APK_NAME 32from acts.test_utils.wifi import wifi_test_utils as wutils 33from acts.test_utils.tel import tel_test_utils as tutils 34from acts.utils import get_current_epoch_time 35 36WifiEnums = wutils.WifiEnums 37PULL_TIMEOUT = 300 38GNSSSTATUS_LOG_PATH = ( 39 "/storage/emulated/0/Android/data/com.android.gpstool/files/") 40QXDM_MASKS = ["GPS.cfg", "GPS-general.cfg", "default.cfg"] 41TTFF_REPORT = namedtuple("TTFF_REPORT", "ttff_loop ttff_sec ttff_pe ttff_cn") 42TRACK_REPORT = namedtuple( 43 "TRACK_REPORT", "track_l5flag track_pe track_top4cn track_cn") 44LOCAL_PROP_FILE_CONTENTS = """\ 45log.tag.LocationManagerService=VERBOSE 46log.tag.GnssLocationProvider=VERBOSE 47log.tag.GnssMeasurementsProvider=VERBOSE 48log.tag.GpsNetInitiatedHandler=VERBOSE 49log.tag.GnssNetworkConnectivityHandler=VERBOSE 50log.tag.ConnectivityService=VERBOSE 51log.tag.ConnectivityManager=VERBOSE 52log.tag.GnssVisibilityControl=VERBOSE""" 53 54 55class GnssTestUtilsError(Exception): 56 pass 57 58 59def remount_device(ad): 60 """Remount device file system to read and write. 61 62 Args: 63 ad: An AndroidDevice object. 64 """ 65 for retries in range(5): 66 ad.root_adb() 67 remount_result = ad.adb.remount() 68 ad.log.info("Attempt %d - %s" % (retries + 1, remount_result)) 69 if "remount succeeded" in remount_result: 70 break 71 if ad.adb.getprop("ro.boot.veritymode") == "enforcing": 72 disable_verity_result = ad.adb.disable_verity() 73 reboot(ad) 74 75 76def reboot(ad): 77 """Reboot device and check if mobile data is available. 78 79 Args: 80 ad: An AndroidDevice object. 81 """ 82 ad.log.info("Reboot device to make changes take effect.") 83 ad.reboot() 84 ad.unlock_screen(password=None) 85 if not int(ad.adb.shell("settings get global mobile_data")) == 1: 86 set_mobile_data(ad, True) 87 utils.sync_device_time(ad) 88 89 90def enable_gnss_verbose_logging(ad): 91 """Enable GNSS VERBOSE Logging and persistent logcat. 92 93 Args: 94 ad: An AndroidDevice object. 95 """ 96 remount_device(ad) 97 ad.log.info("Enable GNSS VERBOSE Logging and persistent logcat.") 98 ad.adb.shell("echo DEBUG_LEVEL = 5 >> /vendor/etc/gps.conf") 99 ad.adb.shell("echo %r >> /data/local.prop" % LOCAL_PROP_FILE_CONTENTS) 100 ad.adb.shell("chmod 644 /data/local.prop") 101 ad.adb.shell("setprop persist.logd.logpersistd.size 20000") 102 ad.adb.shell("setprop persist.logd.size 16777216") 103 ad.adb.shell("setprop persist.vendor.radio.adb_log_on 1") 104 ad.adb.shell("setprop persist.logd.logpersistd logcatd") 105 ad.adb.shell("setprop log.tag.copresGcore VERBOSE") 106 ad.adb.shell("sync") 107 108 109def get_am_flags(value): 110 """Returns the (value, type) flags for a given python value.""" 111 if type(value) is bool: 112 return str(value).lower(), 'boolean' 113 elif type(value) is str: 114 return value, 'string' 115 raise ValueError("%s should be either 'boolean' or 'string'" % value) 116 117 118def enable_compact_and_particle_fusion_log(ad): 119 """Enable CompactLog, FLP particle fusion log and disable gms 120 location-based quake monitoring. 121 122 Args: 123 ad: An AndroidDevice object. 124 """ 125 ad.root_adb() 126 ad.log.info("Enable FLP flags and Disable GMS location-based quake " 127 "monitoring.") 128 overrides = { 129 'compact_log_enabled': True, 130 'flp_use_particle_fusion': True, 131 'flp_particle_fusion_extended_bug_report': True, 132 'flp_event_log_size': '86400', 133 'proks_config': '28', 134 'flp_particle_fusion_bug_report_window_sec': '86400', 135 'flp_particle_fusion_bug_report_max_buffer_size': '86400', 136 'seismic_data_collection': False, 137 'Ealert__enable': False, 138 } 139 for flag, python_value in overrides.items(): 140 value, type = get_am_flags(python_value) 141 cmd = ("am broadcast -a com.google.android.gms.phenotype.FLAG_OVERRIDE " 142 "--es package com.google.android.location --es user \* " 143 "--esa flags %s --esa values %s --esa types %s " 144 "com.google.android.gms" % (flag, value, type)) 145 ad.adb.shell(cmd) 146 ad.adb.shell("am force-stop com.google.android.gms") 147 ad.adb.shell("am broadcast -a com.google.android.gms.INITIALIZE") 148 149 150def disable_xtra_throttle(ad): 151 """Disable XTRA throttle will have no limit to download XTRA data. 152 153 Args: 154 ad: An AndroidDevice object. 155 """ 156 remount_device(ad) 157 ad.log.info("Disable XTRA Throttle.") 158 ad.adb.shell("echo XTRA_TEST_ENABLED=1 >> /vendor/etc/gps.conf") 159 ad.adb.shell("echo XTRA_THROTTLE_ENABLED=0 >> /vendor/etc/gps.conf") 160 161 162def enable_supl_mode(ad): 163 """Enable SUPL back on for next test item. 164 165 Args: 166 ad: An AndroidDevice object. 167 """ 168 remount_device(ad) 169 ad.log.info("Enable SUPL mode.") 170 ad.adb.shell("echo SUPL_MODE=1 >> /etc/gps_debug.conf") 171 172 173def disable_supl_mode(ad): 174 """Kill SUPL to test XTRA only test item. 175 176 Args: 177 ad: An AndroidDevice object. 178 """ 179 remount_device(ad) 180 ad.log.info("Disable SUPL mode.") 181 ad.adb.shell("echo SUPL_MODE=0 >> /etc/gps_debug.conf") 182 reboot(ad) 183 184 185def kill_xtra_daemon(ad): 186 """Kill XTRA daemon to test SUPL only test item. 187 188 Args: 189 ad: An AndroidDevice object. 190 """ 191 ad.root_adb() 192 ad.log.info("Disable XTRA-daemon until next reboot.") 193 ad.adb.shell("killall xtra-daemon") 194 195 196def disable_private_dns_mode(ad): 197 """Due to b/118365122, it's better to disable private DNS mode while 198 testing. 8.8.8.8 private dns sever is unstable now, sometimes server 199 will not response dns query suddenly. 200 201 Args: 202 ad: An AndroidDevice object. 203 """ 204 tutils.get_operator_name(ad.log, ad, subId=None) 205 if ad.adb.shell("settings get global private_dns_mode") != "off": 206 ad.log.info("Disable Private DNS mode.") 207 ad.adb.shell("settings put global private_dns_mode off") 208 209 210def _init_device(ad): 211 """Init GNSS test devices. 212 213 Args: 214 ad: An AndroidDevice object. 215 """ 216 enable_gnss_verbose_logging(ad) 217 enable_compact_and_particle_fusion_log(ad) 218 disable_xtra_throttle(ad) 219 enable_supl_mode(ad) 220 ad.adb.shell("settings put system screen_off_timeout 1800000") 221 wutils.wifi_toggle_state(ad, False) 222 ad.log.info("Setting Bluetooth state to False") 223 ad.droid.bluetoothToggleState(False) 224 set_gnss_qxdm_mask(ad, QXDM_MASKS) 225 check_location_service(ad) 226 set_wifi_and_bt_scanning(ad, True) 227 disable_private_dns_mode(ad) 228 init_gtw_gpstool(ad) 229 reboot(ad) 230 231 232def connect_to_wifi_network(ad, network): 233 """Connection logic for open and psk wifi networks. 234 235 Args: 236 ad: An AndroidDevice object. 237 network: Dictionary with network info. 238 """ 239 SSID = network[WifiEnums.SSID_KEY] 240 ad.ed.clear_all_events() 241 wutils.reset_wifi(ad) 242 wutils.start_wifi_connection_scan_and_ensure_network_found(ad, SSID) 243 wutils.wifi_connect(ad, network, num_of_tries=5) 244 245 246def set_wifi_and_bt_scanning(ad, state=True): 247 """Set Wi-Fi and Bluetooth scanning on/off in Settings -> Location 248 249 Args: 250 ad: An AndroidDevice object. 251 state: True to turn on "Wi-Fi and Bluetooth scanning". 252 False to turn off "Wi-Fi and Bluetooth scanning". 253 """ 254 ad.root_adb() 255 if state: 256 ad.adb.shell("settings put global wifi_scan_always_enabled 1") 257 ad.adb.shell("settings put global ble_scan_always_enabled 1") 258 ad.log.info("Wi-Fi and Bluetooth scanning are enabled") 259 else: 260 ad.adb.shell("settings put global wifi_scan_always_enabled 0") 261 ad.adb.shell("settings put global ble_scan_always_enabled 0") 262 ad.log.info("Wi-Fi and Bluetooth scanning are disabled") 263 264 265def check_location_service(ad): 266 """Set location service on. 267 Verify if location service is available. 268 269 Args: 270 ad: An AndroidDevice object. 271 """ 272 remount_device(ad) 273 utils.set_location_service(ad, True) 274 location_mode = int(ad.adb.shell("settings get secure location_mode")) 275 ad.log.info("Current Location Mode >> %d" % location_mode) 276 if location_mode != 3: 277 raise signals.TestError("Failed to turn Location on") 278 279 280def clear_logd_gnss_qxdm_log(ad): 281 """Clear /data/misc/logd, 282 /storage/emulated/0/Android/data/com.android.gpstool/files and 283 /data/vendor/radio/diag_logs/logs from previous test item then reboot. 284 285 Args: 286 ad: An AndroidDevice object. 287 """ 288 remount_device(ad) 289 ad.log.info("Clear Logd, GNSS and QXDM Log from previous test item.") 290 ad.adb.shell("rm -rf /data/misc/logd", ignore_status=True) 291 ad.adb.shell('find %s -name "*.txt" -type f -delete' % GNSSSTATUS_LOG_PATH) 292 output_path = posixpath.join(DEFAULT_QXDM_LOG_PATH, "logs") 293 ad.adb.shell("rm -rf %s" % output_path, ignore_status=True) 294 reboot(ad) 295 296 297def get_gnss_qxdm_log(ad, qdb_path): 298 """Get /storage/emulated/0/Android/data/com.android.gpstool/files and 299 /data/vendor/radio/diag_logs/logs for test item. 300 301 Args: 302 ad: An AndroidDevice object. 303 qdb_path: The path of qdsp6m.qdb on different projects. 304 """ 305 log_path = ad.device_log_path 306 os.makedirs(log_path, exist_ok=True) 307 gnss_log_name = "gnssstatus_log_%s_%s" % (ad.model, ad.serial) 308 gnss_log_path = posixpath.join(log_path, gnss_log_name) 309 os.makedirs(gnss_log_path, exist_ok=True) 310 ad.log.info("Pull GnssStatus Log to %s" % gnss_log_path) 311 ad.adb.pull("%s %s" % (GNSSSTATUS_LOG_PATH+".", gnss_log_path), 312 timeout=PULL_TIMEOUT, ignore_status=True) 313 shutil.make_archive(gnss_log_path, "zip", gnss_log_path) 314 shutil.rmtree(gnss_log_path) 315 output_path = posixpath.join(DEFAULT_QXDM_LOG_PATH, "logs/.") 316 file_count = ad.adb.shell( 317 "find %s -type f -iname *.qmdl | wc -l" % output_path) 318 if not int(file_count) == 0: 319 qxdm_log_name = "QXDM_%s_%s" % (ad.model, ad.serial) 320 qxdm_log_path = posixpath.join(log_path, qxdm_log_name) 321 os.makedirs(qxdm_log_path, exist_ok=True) 322 ad.log.info("Pull QXDM Log %s to %s" % (output_path, qxdm_log_path)) 323 ad.adb.pull("%s %s" % (output_path, qxdm_log_path), 324 timeout=PULL_TIMEOUT, ignore_status=True) 325 for path in qdb_path: 326 output = ad.adb.pull("%s %s" % (path, qxdm_log_path), 327 timeout=PULL_TIMEOUT, ignore_status=True) 328 if "No such file or directory" in output: 329 continue 330 break 331 shutil.make_archive(qxdm_log_path, "zip", qxdm_log_path) 332 shutil.rmtree(qxdm_log_path) 333 else: 334 ad.log.error("QXDM file count is %d. There is no QXDM log on device." 335 % int(file_count)) 336 337 338def set_mobile_data(ad, state): 339 """Set mobile data on or off and check mobile data state. 340 341 Args: 342 ad: An AndroidDevice object. 343 state: True to enable mobile data. False to disable mobile data. 344 """ 345 ad.root_adb() 346 if state: 347 ad.log.info("Enable mobile data.") 348 ad.adb.shell("svc data enable") 349 else: 350 ad.log.info("Disable mobile data.") 351 ad.adb.shell("svc data disable") 352 time.sleep(5) 353 out = int(ad.adb.shell("settings get global mobile_data")) 354 if state and out == 1: 355 ad.log.info("Mobile data is enabled and set to %d" % out) 356 elif not state and out == 0: 357 ad.log.info("Mobile data is disabled and set to %d" % out) 358 else: 359 ad.log.error("Mobile data is at unknown state and set to %d" % out) 360 361 362def gnss_trigger_modem_ssr_by_adb(ad, dwelltime=60): 363 """Trigger modem SSR crash by adb and verify if modem crash and recover 364 successfully. 365 366 Args: 367 ad: An AndroidDevice object. 368 dwelltime: Waiting time for modem reset. Default is 60 seconds. 369 370 Returns: 371 True if success. 372 False if failed. 373 """ 374 begin_time = get_current_epoch_time() 375 ad.root_adb() 376 cmds = ("echo restart > /sys/kernel/debug/msm_subsys/modem", 377 r"echo 'at+cfun=1,1\r' > /dev/at_mdm0") 378 for cmd in cmds: 379 ad.log.info("Triggering modem SSR crash by %s" % cmd) 380 output = ad.adb.shell(cmd, ignore_status=True) 381 if "No such file or directory" in output: 382 continue 383 break 384 time.sleep(dwelltime) 385 ad.send_keycode("HOME") 386 logcat_results = ad.search_logcat("SSRObserver", begin_time) 387 if logcat_results: 388 for ssr in logcat_results: 389 if "mSubsystem='modem', mCrashReason" in ssr["log_message"]: 390 ad.log.debug(ssr["log_message"]) 391 ad.log.info("Triggering modem SSR crash successfully.") 392 return True 393 raise signals.TestError("Failed to trigger modem SSR crash") 394 raise signals.TestError("No SSRObserver found in logcat") 395 396 397def gnss_trigger_modem_ssr_by_mds(ad, dwelltime=60): 398 """Trigger modem SSR crash by mds tool and verify if modem crash and recover 399 successfully. 400 401 Args: 402 ad: An AndroidDevice object. 403 dwelltime: Waiting time for modem reset. Default is 60 seconds. 404 """ 405 mds_check = ad.adb.shell("pm path com.google.mdstest") 406 if not mds_check: 407 raise signals.TestError("MDS Tool is not properly installed.") 408 ad.root_adb() 409 cmd = ('am instrument -w -e request "4b 25 03 00" ' 410 '"com.google.mdstest/com.google.mdstest.instrument' 411 '.ModemCommandInstrumentation"') 412 ad.log.info("Triggering modem SSR crash by MDS") 413 output = ad.adb.shell(cmd, ignore_status=True) 414 ad.log.debug(output) 415 time.sleep(dwelltime) 416 ad.send_keycode("HOME") 417 if "SUCCESS" in output: 418 ad.log.info("Triggering modem SSR crash by MDS successfully.") 419 else: 420 raise signals.TestError( 421 "Failed to trigger modem SSR crash by MDS. \n%s" % output) 422 423 424def pull_mdstool(ad): 425 """Pull ModemDiagnosticSystemTest.apk from device. 426 427 Args: 428 ad: An AndroidDevice object. 429 """ 430 out = ad.adb.shell("pm path com.google.mdstest") 431 result = re.search(r"package:(.*)", out) 432 if not result: 433 raise signals.TestError("No ModemDiagnosticSystemTest.apk found.") 434 else: 435 mds_tool = result.group(1) 436 ad.log.info("Get ModemDiagnosticSystemTest.apk from %s" % mds_tool) 437 apkdir = "/tmp/MDS/" 438 os.makedirs(apkdir, exist_ok=True) 439 ad.pull_files([mds_tool], apkdir) 440 441 442def reinstall_mdstool(ad): 443 """Reinstall ModemDiagnosticSystemTest.apk. 444 445 Args: 446 ad: An AndroidDevice object. 447 """ 448 ad.log.info("Re-install ModemDiagnosticSystemTest.apk") 449 ad.adb.install("-r -g -t /tmp/MDS/base.apk") 450 mds_check = ad.adb.shell("pm path com.google.mdstest") 451 if not mds_check: 452 raise signals.TestError("MDS Tool is not properly re-installed.") 453 ad.log.info("MDS Tool is re-installed successfully.") 454 455 456def check_xtra_download(ad, begin_time): 457 """Verify XTRA download success log message in logcat. 458 459 Args: 460 ad: An AndroidDevice object. 461 begin_time: test begin time 462 463 Returns: 464 True: xtra_download if XTRA downloaded and injected successfully 465 otherwise return False. 466 """ 467 ad.send_keycode("HOME") 468 logcat_results = ad.search_logcat("XTRA download success. " 469 "inject data into modem", begin_time) 470 if logcat_results: 471 ad.log.debug("%s" % logcat_results[-1]["log_message"]) 472 ad.log.info("XTRA downloaded and injected successfully.") 473 return True 474 ad.log.error("XTRA downloaded FAIL.") 475 return False 476 477 478def pull_gtw_gpstool(ad): 479 """Pull GTW_GPSTool apk from device. 480 481 Args: 482 ad: An AndroidDevice object. 483 """ 484 out = ad.adb.shell("pm path com.android.gpstool") 485 result = re.search(r"package:(.*)", out) 486 if not result: 487 tutils.abort_all_tests(ad.log, "Couldn't find GTW GPSTool apk") 488 else: 489 GTW_GPSTool_apk = result.group(1) 490 ad.log.info("Get GTW GPSTool apk from %s" % GTW_GPSTool_apk) 491 apkdir = "/tmp/GNSS/" 492 os.makedirs(apkdir, exist_ok=True) 493 ad.pull_files([GTW_GPSTool_apk], apkdir) 494 495 496def reinstall_gtw_gpstool(ad): 497 """Reinstall GTW_GPSTool apk. 498 499 Args: 500 ad: An AndroidDevice object. 501 """ 502 ad.log.info("Re-install GTW GPSTool") 503 ad.adb.install("-r -g -t /tmp/GNSS/base.apk") 504 gpstool_check = ad.adb.shell("pm path com.android.gpstool") 505 if not gpstool_check: 506 raise signals.TestError("GTW GPSTool is not properly re-installed.") 507 ad.log.info("GTW GPSTool is re-installed successfully.") 508 509 510def init_gtw_gpstool(ad): 511 """Init GTW_GPSTool apk. 512 513 Args: 514 ad: An AndroidDevice object. 515 """ 516 remount_device(ad) 517 pull_gtw_gpstool(ad) 518 ad.adb.shell("settings put global verifier_verify_adb_installs 0") 519 reinstall_gtw_gpstool(ad) 520 521 522def fastboot_factory_reset(ad): 523 """Factory reset the device in fastboot mode. 524 Pull sl4a apk from device. Terminate all sl4a sessions, 525 Reboot the device to bootloader, 526 factory reset the device by fastboot. 527 Reboot the device. wait for device to complete booting 528 Re-install and start an sl4a session. 529 530 Args: 531 ad: An AndroidDevice object. 532 533 Returns: 534 True if factory reset process complete. 535 """ 536 status = True 537 skip_setup_wizard = True 538 out = ad.adb.shell("pm path %s" % SL4A_APK_NAME) 539 result = re.search(r"package:(.*)", out) 540 if not result: 541 tutils.abort_all_tests(ad.log, "Couldn't find sl4a apk") 542 else: 543 sl4a_apk = result.group(1) 544 ad.log.info("Get sl4a apk from %s" % sl4a_apk) 545 ad.pull_files([sl4a_apk], "/tmp/") 546 pull_gtw_gpstool(ad) 547 pull_mdstool(ad) 548 tutils.stop_qxdm_logger(ad) 549 ad.stop_services() 550 attempts = 3 551 for i in range(1, attempts + 1): 552 try: 553 if ad.serial in list_adb_devices(): 554 ad.log.info("Reboot to bootloader") 555 ad.adb.reboot("bootloader", ignore_status=True) 556 time.sleep(10) 557 if ad.serial in list_fastboot_devices(): 558 ad.log.info("Factory reset in fastboot") 559 ad.fastboot._w(timeout=300, ignore_status=True) 560 time.sleep(30) 561 ad.log.info("Reboot in fastboot") 562 ad.fastboot.reboot() 563 ad.wait_for_boot_completion() 564 ad.root_adb() 565 if ad.skip_sl4a: 566 break 567 if ad.is_sl4a_installed(): 568 break 569 ad.log.info("Re-install sl4a") 570 ad.adb.shell("settings put global verifier_verify_adb_installs 0") 571 ad.adb.install("-r -g -t /tmp/base.apk") 572 reinstall_gtw_gpstool(ad) 573 reinstall_mdstool(ad) 574 time.sleep(10) 575 break 576 except Exception as e: 577 ad.log.error(e) 578 if i == attempts: 579 tutils.abort_all_tests(ad.log, str(e)) 580 time.sleep(5) 581 try: 582 ad.start_adb_logcat() 583 except Exception as e: 584 ad.log.error(e) 585 if skip_setup_wizard: 586 ad.exit_setup_wizard() 587 if ad.skip_sl4a: 588 return status 589 tutils.bring_up_sl4a(ad) 590 return status 591 592 593def clear_aiding_data_by_gtw_gpstool(ad): 594 """Launch GTW GPSTool and Clear all GNSS aiding data. 595 Wait 5 seconds for GTW GPStool to clear all GNSS aiding 596 data properly. 597 598 Args: 599 ad: An AndroidDevice object. 600 """ 601 ad.log.info("Launch GTW GPSTool and Clear all GNSS aiding data") 602 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode clear") 603 time.sleep(10) 604 605 606def start_gnss_by_gtw_gpstool(ad, state, type="gnss", bgdisplay=False): 607 """Start or stop GNSS on GTW_GPSTool. 608 609 Args: 610 ad: An AndroidDevice object. 611 state: True to start GNSS. False to Stop GNSS. 612 type: Different API for location fix. Use gnss/flp/nmea 613 bgdisplay: true to run GTW when Display off. 614 false to not run GTW when Display off. 615 """ 616 if state and not bgdisplay: 617 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool " 618 "--es mode gps --es type %s" % type) 619 elif state and bgdisplay: 620 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode " 621 "gps --es type {} --ez BG {}".format(type, bgdisplay)) 622 if not state: 623 ad.log.info("Stop %s on GTW_GPSTool." % type) 624 ad.adb.shell("am broadcast -a com.android.gpstool.stop_gps_action") 625 time.sleep(3) 626 627 628def process_gnss_by_gtw_gpstool(ad, criteria, type="gnss"): 629 """Launch GTW GPSTool and Clear all GNSS aiding data 630 Start GNSS tracking on GTW_GPSTool. 631 632 Args: 633 ad: An AndroidDevice object. 634 criteria: Criteria for current test item. 635 type: Different API for location fix. Use gnss/flp/nmea 636 637 Returns: 638 True: First fix TTFF are within criteria. 639 False: First fix TTFF exceed criteria. 640 """ 641 retries = 3 642 for i in range(retries): 643 begin_time = get_current_epoch_time() 644 clear_aiding_data_by_gtw_gpstool(ad) 645 ad.log.info("Start %s on GTW_GPSTool - attempt %d" % (type.upper(), 646 i+1)) 647 start_gnss_by_gtw_gpstool(ad, True, type) 648 for _ in range(10 + criteria): 649 logcat_results = ad.search_logcat("First fixed", begin_time) 650 if logcat_results: 651 ad.log.debug(logcat_results[-1]["log_message"]) 652 first_fixed = int(logcat_results[-1]["log_message"].split()[-1]) 653 ad.log.info("%s First fixed = %.3f seconds" % 654 (type.upper(), first_fixed/1000)) 655 if (first_fixed/1000) <= criteria: 656 return True 657 start_gnss_by_gtw_gpstool(ad, False, type) 658 raise signals.TestFailure("Fail to get %s location fixed " 659 "within %d seconds criteria." 660 % (type.upper(), criteria)) 661 time.sleep(1) 662 if not ad.is_adb_logcat_on: 663 ad.start_adb_logcat() 664 check_currrent_focus_app(ad) 665 start_gnss_by_gtw_gpstool(ad, False, type) 666 raise signals.TestFailure("Fail to get %s location fixed within %d " 667 "attempts." % (type.upper(), retries)) 668 669def start_ttff_by_gtw_gpstool(ad, ttff_mode, iteration, aid_data=False): 670 """Identify which TTFF mode for different test items. 671 672 Args: 673 ad: An AndroidDevice object. 674 ttff_mode: TTFF Test mode for current test item. 675 iteration: Iteration of TTFF cycles. 676 aid_data: Boolean for identify aid_data existed or not 677 """ 678 begin_time = get_current_epoch_time() 679 if (ttff_mode == "hs" or ttff_mode == "ws") and not aid_data: 680 ad.log.info("Wait 5 minutes to start TTFF %s..." % ttff_mode.upper()) 681 time.sleep(300) 682 if ttff_mode == "cs": 683 ad.log.info("Start TTFF Cold Start...") 684 time.sleep(3) 685 for i in range(1, 4): 686 ad.adb.shell("am broadcast -a com.android.gpstool.ttff_action " 687 "--es ttff %s --es cycle %d" % (ttff_mode, iteration)) 688 time.sleep(1) 689 if ad.search_logcat("act=com.android.gpstool.start_test_action", 690 begin_time): 691 ad.log.info("Send TTFF start_test_action successfully.") 692 break 693 else: 694 check_currrent_focus_app(ad) 695 raise signals.TestError("Fail to send TTFF start_test_action.") 696 697 698def gnss_tracking_via_gtw_gpstool(ad, criteria, type="gnss", testtime=60): 699 """Start GNSS/FLP tracking tests for input testtime on GTW_GPSTool. 700 701 Args: 702 ad: An AndroidDevice object. 703 criteria: Criteria for current TTFF. 704 type: Different API for location fix. Use gnss/flp/nmea 705 testtime: Tracking test time for minutes. Default set to 60 minutes. 706 """ 707 process_gnss_by_gtw_gpstool(ad, criteria, type) 708 ad.log.info("Start %s tracking test for %d minutes" % (type.upper(), 709 testtime)) 710 begin_time = get_current_epoch_time() 711 while get_current_epoch_time() - begin_time < testtime * 60 * 1000 : 712 if not ad.is_adb_logcat_on: 713 ad.start_adb_logcat() 714 crash_result = ad.search_logcat("Force finishing activity " 715 "com.android.gpstool/.GPSTool", 716 begin_time) 717 if crash_result: 718 raise signals.TestError("GPSTool crashed. Abort test.") 719 ad.log.info("Successfully tested for %d minutes" % testtime) 720 start_gnss_by_gtw_gpstool(ad, False, type) 721 722 723def parse_gtw_gpstool_log(ad, true_position, type="gnss"): 724 """Process GNSS/FLP API logs from GTW GPSTool and output track_data to 725 test_run_info for ACTS plugin to parse and display on MobileHarness as 726 Property. 727 728 Args: 729 ad: An AndroidDevice object. 730 true_position: Coordinate as [latitude, longitude] to calculate 731 position error. 732 type: Different API for location fix. Use gnss/flp/nmea 733 """ 734 test_logfile = {} 735 track_data = {} 736 history_top4_cn = 0 737 history_cn = 0 738 l5flag = "false" 739 file_count = int(ad.adb.shell("find %s -type f -iname *.txt | wc -l" 740 % GNSSSTATUS_LOG_PATH)) 741 if file_count != 1: 742 ad.log.error("%d API logs exist." % file_count) 743 dir = ad.adb.shell("ls %s" % GNSSSTATUS_LOG_PATH).split() 744 for path_key in dir: 745 if fnmatch.fnmatch(path_key, "*.txt"): 746 logpath = posixpath.join(GNSSSTATUS_LOG_PATH, path_key) 747 out = ad.adb.shell("wc -c %s" % logpath) 748 file_size = int(out.split(" ")[0]) 749 if file_size < 2000: 750 ad.log.info("Skip log %s due to log size %d bytes" % 751 (path_key, file_size)) 752 continue 753 test_logfile = logpath 754 if not test_logfile: 755 raise signals.TestError("Failed to get test log file in device.") 756 lines = ad.adb.shell("cat %s" % test_logfile).split("\n") 757 for line in lines: 758 if "History Avg Top4" in line: 759 history_top4_cn = float(line.split(":")[-1].strip()) 760 if "History Avg" in line: 761 history_cn = float(line.split(":")[-1].strip()) 762 if "L5 used in fix" in line: 763 l5flag = line.split(":")[-1].strip() 764 if "Latitude" in line: 765 track_lat = float(line.split(":")[-1].strip()) 766 if "Longitude" in line: 767 track_long = float(line.split(":")[-1].strip()) 768 if "Time" in line: 769 track_utc = line.split("Time:")[-1].strip() 770 if track_utc in track_data.keys(): 771 continue 772 track_pe = calculate_position_error(ad, track_lat, track_long, 773 true_position) 774 track_data[track_utc] = TRACK_REPORT(track_l5flag=l5flag, 775 track_pe=track_pe, 776 track_top4cn=history_top4_cn, 777 track_cn=history_cn) 778 ad.log.debug(track_data) 779 prop_basename = "TestResult %s_tracking_" % type.upper() 780 time_list = sorted(track_data.keys()) 781 l5flag_list = [track_data[key].track_l5flag for key in time_list] 782 pe_list = [float(track_data[key].track_pe) for key in time_list] 783 top4cn_list = [float(track_data[key].track_top4cn) for key in time_list] 784 cn_list = [float(track_data[key].track_cn) for key in time_list] 785 ad.log.info(prop_basename+"StartTime %s" % time_list[0].replace(" ", "-")) 786 ad.log.info(prop_basename+"EndTime %s" % time_list[-1].replace(" ", "-")) 787 ad.log.info(prop_basename+"TotalFixPoints %d" % len(time_list)) 788 ad.log.info(prop_basename+"L5FixRate "+'{percent:.2%}'.format( 789 percent=l5flag_list.count("true")/len(l5flag_list))) 790 ad.log.info(prop_basename+"AvgDis %.1f" % (sum(pe_list)/len(pe_list))) 791 ad.log.info(prop_basename+"MaxDis %.1f" % max(pe_list)) 792 ad.log.info(prop_basename+"AvgTop4Signal %.1f" % top4cn_list[-1]) 793 ad.log.info(prop_basename+"AvgSignal %.1f" % cn_list[-1]) 794 795 796def process_ttff_by_gtw_gpstool(ad, begin_time, true_position, type="gnss"): 797 """Process TTFF and record results in ttff_data. 798 799 Args: 800 ad: An AndroidDevice object. 801 begin_time: test begin time. 802 true_position: Coordinate as [latitude, longitude] to calculate 803 position error. 804 type: Different API for location fix. Use gnss/flp/nmea 805 806 Returns: 807 ttff_data: A dict of all TTFF data. 808 """ 809 ttff_data = {} 810 ttff_loop_time = get_current_epoch_time() 811 while True: 812 if get_current_epoch_time() - ttff_loop_time >= 120000: 813 raise signals.TestError("Fail to search specific GPSService " 814 "message in logcat. Abort test.") 815 if not ad.is_adb_logcat_on: 816 ad.start_adb_logcat() 817 stop_gps_results = ad.search_logcat("stop gps test", begin_time) 818 if stop_gps_results: 819 ad.send_keycode("HOME") 820 break 821 crash_result = ad.search_logcat("Force finishing activity " 822 "com.android.gpstool/.GPSTool", 823 begin_time) 824 if crash_result: 825 raise signals.TestError("GPSTool crashed. Abort test.") 826 logcat_results = ad.search_logcat("write TTFF log", begin_time) 827 if logcat_results: 828 ttff_log = logcat_results[-1]["log_message"].split() 829 ttff_loop = int(ttff_log[8].split(":")[-1]) 830 if ttff_loop in ttff_data.keys(): 831 continue 832 ttff_loop_time = get_current_epoch_time() 833 ttff_sec = float(ttff_log[11]) 834 if ttff_sec != 0.0: 835 ttff_cn = float(ttff_log[18].strip("]")) 836 if type == "gnss": 837 gnss_results = ad.search_logcat("GPSService: Check item", 838 begin_time) 839 if gnss_results: 840 ad.log.debug(gnss_results[-1]["log_message"]) 841 gnss_location_log = \ 842 gnss_results[-1]["log_message"].split() 843 ttff_lat = float( 844 gnss_location_log[8].split("=")[-1].strip(",")) 845 ttff_lon = float( 846 gnss_location_log[9].split("=")[-1].strip(",")) 847 elif type == "flp": 848 flp_results = ad.search_logcat("GPSService: FLP Location", 849 begin_time) 850 if flp_results: 851 ad.log.debug(flp_results[-1]["log_message"]) 852 flp_location_log = \ 853 flp_results[-1]["log_message"].split() 854 ttff_lat = float(flp_location_log[8].split(",")[0]) 855 ttff_lon = float(flp_location_log[8].split(",")[1]) 856 else: 857 ttff_cn = float(ttff_log[19].strip("]")) 858 ttff_lat = 0.0 859 ttff_lon = 0.0 860 ad.log.debug("TTFF Loop %d - (Lat, Lon) = (%s, %s)" % (ttff_loop, 861 ttff_lat, 862 ttff_lon)) 863 ttff_pe = calculate_position_error(ad, ttff_lat, ttff_lon, 864 true_position) 865 ttff_data[ttff_loop] = TTFF_REPORT(ttff_loop=ttff_loop, 866 ttff_sec=ttff_sec, 867 ttff_pe=ttff_pe, 868 ttff_cn=ttff_cn) 869 ad.log.info("Loop %d = %.1f seconds, " 870 "Position Error = %.1f meters, " 871 "Average Signal = %.1f dbHz" 872 % (ttff_loop, ttff_sec, ttff_pe, ttff_cn)) 873 return ttff_data 874 875 876def check_ttff_data(ad, ttff_data, ttff_mode, criteria): 877 """Verify all TTFF results from ttff_data. 878 879 Args: 880 ad: An AndroidDevice object. 881 ttff_data: TTFF data of secs, position error and signal strength. 882 ttff_mode: TTFF Test mode for current test item. 883 criteria: Criteria for current test item. 884 885 Returns: 886 True: All TTFF results are within criteria. 887 False: One or more TTFF results exceed criteria or Timeout. 888 """ 889 ad.log.info("%d iterations of TTFF %s tests finished." 890 % (len(ttff_data.keys()), ttff_mode)) 891 ad.log.info("%s PASS criteria is %d seconds" % (ttff_mode, criteria)) 892 ad.log.debug("%s TTFF data: %s" % (ttff_mode, ttff_data)) 893 ttff_property_key_and_value(ad, ttff_data, ttff_mode) 894 if len(ttff_data.keys()) == 0: 895 ad.log.error("GTW_GPSTool didn't process TTFF properly.") 896 return False 897 elif any(float(ttff_data[key].ttff_sec) == 0.0 for key in ttff_data.keys()): 898 ad.log.error("One or more TTFF %s Timeout" % ttff_mode) 899 return False 900 elif any(float(ttff_data[key].ttff_sec) >= criteria for key in 901 ttff_data.keys()): 902 ad.log.error("One or more TTFF %s are over test criteria %d seconds" 903 % (ttff_mode, criteria)) 904 return False 905 ad.log.info("All TTFF %s are within test criteria %d seconds." 906 % (ttff_mode, criteria)) 907 return True 908 909 910def ttff_property_key_and_value(ad, ttff_data, ttff_mode): 911 """Output ttff_data to test_run_info for ACTS plugin to parse and display 912 on MobileHarness as Property. 913 914 Args: 915 ad: An AndroidDevice object. 916 ttff_data: TTFF data of secs, position error and signal strength. 917 ttff_mode: TTFF Test mode for current test item. 918 """ 919 prop_basename = "TestResult "+ttff_mode.replace(" ", "_")+"_TTFF_" 920 sec_list = [float(ttff_data[key].ttff_sec) for key in ttff_data.keys()] 921 pe_list = [float(ttff_data[key].ttff_pe) for key in ttff_data.keys()] 922 cn_list = [float(ttff_data[key].ttff_cn) for key in ttff_data.keys()] 923 timeoutcount = sec_list.count(0.0) 924 if len(sec_list) == timeoutcount: 925 avgttff = 9527 926 else: 927 avgttff = sum(sec_list)/(len(sec_list) - timeoutcount) 928 if timeoutcount != 0: 929 maxttff = 9527 930 else: 931 maxttff = max(sec_list) 932 avgdis = sum(pe_list)/len(pe_list) 933 maxdis = max(pe_list) 934 avgcn = sum(cn_list)/len(cn_list) 935 ad.log.info(prop_basename+"AvgTime %.1f" % avgttff) 936 ad.log.info(prop_basename+"MaxTime %.1f" % maxttff) 937 ad.log.info(prop_basename+"TimeoutCount %d" % timeoutcount) 938 ad.log.info(prop_basename+"AvgDis %.1f" % avgdis) 939 ad.log.info(prop_basename+"MaxDis %.1f" % maxdis) 940 ad.log.info(prop_basename+"AvgSignal %.1f" % avgcn) 941 942 943def calculate_position_error(ad, latitude, longitude, true_position): 944 """Use haversine formula to calculate position error base on true location 945 coordinate. 946 947 Args: 948 ad: An AndroidDevice object. 949 latitude: latitude of location fixed in the present. 950 longitude: longitude of location fixed in the present. 951 true_position: [latitude, longitude] of true location coordinate. 952 953 Returns: 954 position_error of location fixed in the present. 955 """ 956 radius = 6371009 957 dlat = math.radians(latitude - true_position[0]) 958 dlon = math.radians(longitude - true_position[1]) 959 a = math.sin(dlat/2) * math.sin(dlat/2) + \ 960 math.cos(math.radians(true_position[0])) * \ 961 math.cos(math.radians(latitude)) * math.sin(dlon/2) * math.sin(dlon/2) 962 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) 963 return radius * c 964 965 966def launch_google_map(ad): 967 """Launch Google Map via intent. 968 969 Args: 970 ad: An AndroidDevice object. 971 """ 972 ad.log.info("Launch Google Map.") 973 try: 974 ad.adb.shell("am start -S -n com.google.android.apps.maps/" 975 "com.google.android.maps.MapsActivity") 976 ad.send_keycode("BACK") 977 ad.force_stop_apk("com.google.android.apps.maps") 978 ad.adb.shell("am start -S -n com.google.android.apps.maps/" 979 "com.google.android.maps.MapsActivity") 980 except Exception as e: 981 ad.log.error(e) 982 raise signals.TestError("Failed to launch google map.") 983 check_currrent_focus_app(ad) 984 985 986def check_currrent_focus_app(ad): 987 """Check to see current focused window and app. 988 989 Args: 990 ad: An AndroidDevice object. 991 """ 992 time.sleep(1) 993 current = ad.adb.shell( 994 "dumpsys window | grep -E 'mCurrentFocus|mFocusedApp'") 995 ad.log.debug("\n"+current) 996 997 998def check_location_api(ad, retries): 999 """Verify if GnssLocationProvider API reports location. 1000 1001 Args: 1002 ad: An AndroidDevice object. 1003 retries: Retry time. 1004 1005 Returns: 1006 True: GnssLocationProvider API reports location. 1007 otherwise return False. 1008 """ 1009 for i in range(retries): 1010 begin_time = get_current_epoch_time() 1011 ad.log.info("Try to get location report from GnssLocationProvider API " 1012 "- attempt %d" % (i+1)) 1013 while get_current_epoch_time() - begin_time <= 30000: 1014 logcat_results = ad.search_logcat("REPORT_LOCATION", begin_time) 1015 if logcat_results: 1016 ad.log.info("%s" % logcat_results[-1]["log_message"]) 1017 ad.log.info("GnssLocationProvider reports location " 1018 "successfully.") 1019 return True 1020 if not ad.is_adb_logcat_on: 1021 ad.start_adb_logcat() 1022 ad.log.error("GnssLocationProvider is unable to report location.") 1023 return False 1024 1025def check_network_location(ad, retries, location_type, criteria=30): 1026 """Verify if NLP reports location after requesting via GPSTool. 1027 1028 Args: 1029 ad: An AndroidDevice object. 1030 retries: Retry time. 1031 location_type: neworkLocationType of cell or wifi. 1032 criteria: expected nlp return time, default 30 seconds 1033 1034 Returns: 1035 True: NLP reports location. 1036 otherwise return False. 1037 """ 1038 criteria = criteria * 1000 1039 for i in range(retries): 1040 time.sleep(1) 1041 begin_time = get_current_epoch_time() 1042 ad.log.info("Try to get NLP status - attempt %d" % (i+1)) 1043 ad.adb.shell( 1044 "am start -S -n com.android.gpstool/.GPSTool --es mode nlp") 1045 while get_current_epoch_time() - begin_time <= criteria: 1046 logcat_results = ad.search_logcat("LocationManagerService: " 1047 "incoming location: Location", 1048 begin_time) 1049 if logcat_results: 1050 for logcat_result in logcat_results: 1051 if location_type in logcat_result["log_message"]: 1052 ad.log.info(logcat_result["log_message"]) 1053 ad.send_keycode("BACK") 1054 return True 1055 if not ad.is_adb_logcat_on: 1056 ad.start_adb_logcat() 1057 ad.send_keycode("BACK") 1058 ad.log.error("Unable to report network location \"%s\"." % location_type) 1059 return False 1060 1061 1062def set_attenuator_gnss_signal(ad, attenuator, atten_value): 1063 """Set attenuation value for different GNSS signal. 1064 1065 Args: 1066 ad: An AndroidDevice object. 1067 attenuator: The attenuator object. 1068 atten_value: attenuation value 1069 """ 1070 try: 1071 ad.log.info( 1072 "Set attenuation value to \"%d\" for GNSS signal." % atten_value) 1073 attenuator[0].set_atten(atten_value) 1074 except Exception as e: 1075 ad.log.error(e) 1076 1077 1078def set_battery_saver_mode(ad, state): 1079 """Enable or diable battery saver mode via adb. 1080 1081 Args: 1082 ad: An AndroidDevice object. 1083 state: True is enable Battery Saver mode. False is disable. 1084 """ 1085 ad.root_adb() 1086 if state: 1087 ad.log.info("Enable Battery Saver mode.") 1088 ad.adb.shell("cmd battery unplug") 1089 ad.adb.shell("settings put global low_power 1") 1090 else: 1091 ad.log.info("Disable Battery Saver mode.") 1092 ad.adb.shell("settings put global low_power 0") 1093 ad.adb.shell("cmd battery reset") 1094 1095 1096def set_gnss_qxdm_mask(ad, masks): 1097 """Find defined gnss qxdm mask and set as default logging mask. 1098 1099 Args: 1100 ad: An AndroidDevice object. 1101 masks: Defined gnss qxdm mask. 1102 """ 1103 try: 1104 for mask in masks: 1105 if not tutils.find_qxdm_log_mask(ad, mask): 1106 continue 1107 tutils.set_qxdm_logger_command(ad, mask) 1108 break 1109 except Exception as e: 1110 ad.log.error(e) 1111 raise signals.TestError("Failed to set any QXDM masks.") 1112 1113 1114def start_youtube_video(ad, url=None, retries=0): 1115 """Start youtube video and verify if audio is in music state. 1116 1117 Args: 1118 ad: An AndroidDevice object. 1119 url: Youtube video url. 1120 retries: Retry times if audio is not in music state. 1121 1122 Returns: 1123 True if youtube video is playing normally. 1124 False if youtube video is not playing properly. 1125 """ 1126 for i in range(retries): 1127 ad.log.info("Open an youtube video - attempt %d" % (i+1)) 1128 ad.adb.shell("am start -a android.intent.action.VIEW -d \"%s\"" % url) 1129 time.sleep(2) 1130 out = ad.adb.shell( 1131 "dumpsys activity | grep NewVersionAvailableActivity") 1132 if out: 1133 ad.log.info("Skip Youtube New Version Update.") 1134 ad.send_keycode("BACK") 1135 if tutils.wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1): 1136 ad.log.info("Started a video in youtube, audio is in MUSIC state") 1137 return True 1138 ad.log.info("Force-Stop youtube and reopen youtube again.") 1139 ad.force_stop_apk("com.google.android.youtube") 1140 check_currrent_focus_app(ad) 1141 raise signals.TestError("Started a video in youtube, " 1142 "but audio is not in MUSIC state") 1143 1144 1145def get_baseband_and_gms_version(ad, extra_msg=""): 1146 """Get current radio baseband and GMSCore version of AndroidDevice object. 1147 1148 Args: 1149 ad: An AndroidDevice object. 1150 """ 1151 try: 1152 build_version = ad.adb.getprop("ro.build.id") 1153 baseband_version = ad.adb.getprop("gsm.version.baseband") 1154 gms_version = ad.adb.shell( 1155 "dumpsys package com.google.android.gms | grep versionName" 1156 ).split("\n")[0].split("=")[1] 1157 mpss_version = ad.adb.shell("cat /sys/devices/soc0/images | grep MPSS " 1158 "| cut -d ':' -f 3") 1159 if not extra_msg: 1160 ad.log.info("TestResult Build_Version %s" % build_version) 1161 ad.log.info("TestResult Baseband_Version %s" % baseband_version) 1162 ad.log.info( 1163 "TestResult GMS_Version %s" % gms_version.replace(" ", "")) 1164 ad.log.info("TestResult MPSS_Version %s" % mpss_version) 1165 else: 1166 ad.log.info( 1167 "%s, Baseband_Version = %s" % (extra_msg, baseband_version)) 1168 except Exception as e: 1169 ad.log.error(e) 1170 1171 1172def start_toggle_gnss_by_gtw_gpstool(ad, iteration): 1173 """Send toggle gnss off/on start_test_action 1174 1175 Args: 1176 ad: An AndroidDevice object. 1177 iteration: Iteration of toggle gnss off/on cycles. 1178 """ 1179 msg_list = [] 1180 begin_time = get_current_epoch_time() 1181 try: 1182 for i in range(1, 4): 1183 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool " 1184 "--es mode toggle --es cycle %d" % iteration) 1185 time.sleep(1) 1186 if ad.search_logcat("cmp=com.android.gpstool/.ToggleGPS", 1187 begin_time): 1188 ad.log.info("Send ToggleGPS start_test_action successfully.") 1189 break 1190 else: 1191 check_currrent_focus_app(ad) 1192 raise signals.TestError("Fail to send ToggleGPS " 1193 "start_test_action within 3 attempts.") 1194 time.sleep(2) 1195 test_start = ad.search_logcat("GPSTool_ToggleGPS: startService", 1196 begin_time) 1197 if test_start: 1198 ad.log.info(test_start[-1]["log_message"].split(":")[-1].strip()) 1199 else: 1200 raise signals.TestError("Fail to start toggle GPS off/on test.") 1201 # Every iteration is expected to finish within 4 minutes. 1202 while get_current_epoch_time() - begin_time <= iteration * 240000: 1203 crash_end = ad.search_logcat("Force finishing activity " 1204 "com.android.gpstool/.GPSTool", 1205 begin_time) 1206 if crash_end: 1207 raise signals.TestError("GPSTool crashed. Abort test.") 1208 toggle_results = ad.search_logcat("GPSTool : msg", begin_time) 1209 if toggle_results: 1210 for toggle_result in toggle_results: 1211 msg = toggle_result["log_message"] 1212 if not msg in msg_list: 1213 ad.log.info(msg.split(":")[-1].strip()) 1214 msg_list.append(msg) 1215 if "timeout" in msg: 1216 raise signals.TestFailure("Fail to get location fixed " 1217 "within 60 seconds.") 1218 if "Test end" in msg: 1219 raise signals.TestPass("Completed quick toggle GNSS " 1220 "off/on test.") 1221 raise signals.TestFailure("Fail to finish toggle GPS off/on test " 1222 "within %d minutes" % (iteration * 4)) 1223 finally: 1224 ad.send_keycode("HOME") 1225