1#!/usr/bin/env python3 2# 3# Copyright 2020 - 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 24import tempfile 25from collections import namedtuple 26 27from acts import utils 28from acts import asserts 29from acts import signals 30from acts.libs.proc import job 31from acts.controllers.android_device import list_adb_devices 32from acts.controllers.android_device import list_fastboot_devices 33from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH 34from acts.controllers.android_device import SL4A_APK_NAME 35from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 36from acts_contrib.test_utils.tel import tel_test_utils as tutils 37from acts_contrib.test_utils.instrumentation.device.command.instrumentation_command_builder import InstrumentationCommandBuilder 38from acts_contrib.test_utils.instrumentation.device.command.instrumentation_command_builder import InstrumentationTestCommandBuilder 39from acts.utils import get_current_epoch_time 40from acts.utils import epoch_to_human_time 41 42WifiEnums = wutils.WifiEnums 43PULL_TIMEOUT = 300 44GNSSSTATUS_LOG_PATH = ( 45 "/storage/emulated/0/Android/data/com.android.gpstool/files/") 46QXDM_MASKS = ["GPS.cfg", "GPS-general.cfg", "default.cfg"] 47TTFF_REPORT = namedtuple( 48 "TTFF_REPORT", "utc_time ttff_loop ttff_sec ttff_pe ttff_ant_cn " 49 "ttff_base_cn") 50TRACK_REPORT = namedtuple( 51 "TRACK_REPORT", "l5flag pe ant_top4cn ant_cn base_top4cn base_cn") 52LOCAL_PROP_FILE_CONTENTS = """\ 53log.tag.LocationManagerService=VERBOSE 54log.tag.GnssLocationProvider=VERBOSE 55log.tag.GnssMeasurementsProvider=VERBOSE 56log.tag.GpsNetInitiatedHandler=VERBOSE 57log.tag.GnssNetInitiatedHandler=VERBOSE 58log.tag.GnssNetworkConnectivityHandler=VERBOSE 59log.tag.ConnectivityService=VERBOSE 60log.tag.ConnectivityManager=VERBOSE 61log.tag.GnssVisibilityControl=VERBOSE 62log.tag.NtpTimeHelper=VERBOSE 63log.tag.NtpTrustedTime=VERBOSE 64log.tag.GnssPsdsDownloader=VERBOSE 65log.tag.Gnss=VERBOSE 66log.tag.GnssConfiguration=VERBOSE""" 67TEST_PACKAGE_NAME = "com.google.android.apps.maps" 68LOCATION_PERMISSIONS = [ 69 "android.permission.ACCESS_FINE_LOCATION", 70 "android.permission.ACCESS_COARSE_LOCATION" 71] 72GNSSTOOL_PACKAGE_NAME = "com.android.gpstool" 73GNSSTOOL_PERMISSIONS = [ 74 "android.permission.ACCESS_FINE_LOCATION", 75 "android.permission.READ_EXTERNAL_STORAGE", 76 "android.permission.ACCESS_COARSE_LOCATION", 77 "android.permission.CALL_PHONE", 78 "android.permission.WRITE_CONTACTS", 79 "android.permission.CAMERA", 80 "android.permission.WRITE_EXTERNAL_STORAGE", 81 "android.permission.READ_CONTACTS", 82 "android.permission.ACCESS_BACKGROUND_LOCATION" 83] 84DISABLE_LTO_FILE_CONTENTS = """\ 85LONGTERM_PSDS_SERVER_1="http://" 86LONGTERM_PSDS_SERVER_2="http://" 87LONGTERM_PSDS_SERVER_3="http://" 88NORMAL_PSDS_SERVER="http://" 89REALTIME_PSDS_SERVER="http://" 90""" 91 92 93class GnssTestUtilsError(Exception): 94 pass 95 96 97def remount_device(ad): 98 """Remount device file system to read and write. 99 100 Args: 101 ad: An AndroidDevice object. 102 """ 103 for retries in range(5): 104 ad.root_adb() 105 if ad.adb.getprop("ro.boot.veritymode") == "enforcing": 106 ad.adb.disable_verity() 107 reboot(ad) 108 remount_result = ad.adb.remount() 109 ad.log.info("Attempt %d - %s" % (retries + 1, remount_result)) 110 if "remount succeeded" in remount_result: 111 break 112 113 114def reboot(ad): 115 """Reboot device and check if mobile data is available. 116 117 Args: 118 ad: An AndroidDevice object. 119 """ 120 ad.log.info("Reboot device to make changes take effect.") 121 ad.reboot() 122 ad.unlock_screen(password=None) 123 if not int(ad.adb.shell("settings get global mobile_data")) == 1: 124 set_mobile_data(ad, True) 125 utils.sync_device_time(ad) 126 127 128def enable_gnss_verbose_logging(ad): 129 """Enable GNSS VERBOSE Logging and persistent logcat. 130 131 Args: 132 ad: An AndroidDevice object. 133 """ 134 remount_device(ad) 135 ad.log.info("Enable GNSS VERBOSE Logging and persistent logcat.") 136 if check_chipset_vendor_by_qualcomm(ad): 137 ad.adb.shell("echo -e '\nDEBUG_LEVEL = 5' >> /vendor/etc/gps.conf") 138 else: 139 ad.adb.shell("echo LogEnabled=true >> /data/vendor/gps/libgps.conf") 140 ad.adb.shell("chown gps.system /data/vendor/gps/libgps.conf") 141 ad.adb.shell("echo %r >> /data/local.prop" % LOCAL_PROP_FILE_CONTENTS) 142 ad.adb.shell("chmod 644 /data/local.prop") 143 ad.adb.shell("setprop persist.logd.logpersistd.size 20000") 144 ad.adb.shell("setprop persist.logd.size 16777216") 145 ad.adb.shell("setprop persist.vendor.radio.adb_log_on 1") 146 ad.adb.shell("setprop persist.logd.logpersistd logcatd") 147 ad.adb.shell("setprop log.tag.copresGcore VERBOSE") 148 ad.adb.shell("sync") 149 150 151def get_am_flags(value): 152 """Returns the (value, type) flags for a given python value.""" 153 if type(value) is bool: 154 return str(value).lower(), 'boolean' 155 elif type(value) is str: 156 return value, 'string' 157 raise ValueError("%s should be either 'boolean' or 'string'" % value) 158 159 160def enable_compact_and_particle_fusion_log(ad): 161 """Enable CompactLog, FLP particle fusion log and disable gms 162 location-based quake monitoring. 163 164 Args: 165 ad: An AndroidDevice object. 166 """ 167 ad.root_adb() 168 ad.log.info("Enable FLP flags and Disable GMS location-based quake " 169 "monitoring.") 170 overrides = { 171 'compact_log_enabled': True, 172 'flp_use_particle_fusion': True, 173 'flp_particle_fusion_extended_bug_report': True, 174 'flp_event_log_size': '86400', 175 'proks_config': '28', 176 'flp_particle_fusion_bug_report_window_sec': '86400', 177 'flp_particle_fusion_bug_report_max_buffer_size': '86400', 178 'seismic_data_collection': False, 179 'Ealert__enable': False, 180 } 181 for flag, python_value in overrides.items(): 182 value, type = get_am_flags(python_value) 183 cmd = ("am broadcast -a com.google.android.gms.phenotype.FLAG_OVERRIDE " 184 "--es package com.google.android.location --es user \* " 185 "--esa flags %s --esa values %s --esa types %s " 186 "com.google.android.gms" % (flag, value, type)) 187 ad.adb.shell(cmd) 188 ad.adb.shell("am force-stop com.google.android.gms") 189 ad.adb.shell("am broadcast -a com.google.android.gms.INITIALIZE") 190 191 192def disable_xtra_throttle(ad): 193 """Disable XTRA throttle will have no limit to download XTRA data. 194 195 Args: 196 ad: An AndroidDevice object. 197 """ 198 remount_device(ad) 199 ad.log.info("Disable XTRA Throttle.") 200 ad.adb.shell("echo -e '\nXTRA_TEST_ENABLED=1' >> /vendor/etc/gps.conf") 201 ad.adb.shell("echo -e '\nXTRA_THROTTLE_ENABLED=0' >> /vendor/etc/gps.conf") 202 203 204def enable_supl_mode(ad): 205 """Enable SUPL back on for next test item. 206 207 Args: 208 ad: An AndroidDevice object. 209 """ 210 remount_device(ad) 211 ad.log.info("Enable SUPL mode.") 212 ad.adb.shell("echo -e '\nSUPL_MODE=1' >> /etc/gps_debug.conf") 213 if not check_chipset_vendor_by_qualcomm(ad): 214 lto_mode(ad, True) 215 else: 216 reboot(ad) 217 218 219def disable_supl_mode(ad): 220 """Kill SUPL to test XTRA/LTO only test item. 221 222 Args: 223 ad: An AndroidDevice object. 224 """ 225 remount_device(ad) 226 ad.log.info("Disable SUPL mode.") 227 ad.adb.shell("echo -e '\nSUPL_MODE=0' >> /etc/gps_debug.conf") 228 if not check_chipset_vendor_by_qualcomm(ad): 229 lto_mode(ad, True) 230 else: 231 reboot(ad) 232 233 234def kill_xtra_daemon(ad): 235 """Kill XTRA daemon to test SUPL only test item. 236 237 Args: 238 ad: An AndroidDevice object. 239 """ 240 ad.root_adb() 241 if check_chipset_vendor_by_qualcomm(ad): 242 ad.log.info("Disable XTRA-daemon until next reboot.") 243 ad.adb.shell("killall xtra-daemon", ignore_status=True) 244 else: 245 lto_mode(ad, False) 246 247 248def disable_private_dns_mode(ad): 249 """Due to b/118365122, it's better to disable private DNS mode while 250 testing. 8.8.8.8 private dns sever is unstable now, sometimes server 251 will not response dns query suddenly. 252 253 Args: 254 ad: An AndroidDevice object. 255 """ 256 tutils.get_operator_name(ad.log, ad, subId=None) 257 if ad.adb.shell("settings get global private_dns_mode") != "off": 258 ad.log.info("Disable Private DNS mode.") 259 ad.adb.shell("settings put global private_dns_mode off") 260 261 262def _init_device(ad): 263 """Init GNSS test devices. 264 265 Args: 266 ad: An AndroidDevice object. 267 """ 268 enable_gnss_verbose_logging(ad) 269 enable_compact_and_particle_fusion_log(ad) 270 if check_chipset_vendor_by_qualcomm(ad): 271 disable_xtra_throttle(ad) 272 enable_supl_mode(ad) 273 ad.adb.shell("settings put system screen_off_timeout 1800000") 274 wutils.wifi_toggle_state(ad, False) 275 ad.log.info("Setting Bluetooth state to False") 276 ad.droid.bluetoothToggleState(False) 277 check_location_service(ad) 278 set_wifi_and_bt_scanning(ad, True) 279 disable_private_dns_mode(ad) 280 reboot(ad) 281 init_gtw_gpstool(ad) 282 283 284def connect_to_wifi_network(ad, network): 285 """Connection logic for open and psk wifi networks. 286 287 Args: 288 ad: An AndroidDevice object. 289 network: Dictionary with network info. 290 """ 291 SSID = network[WifiEnums.SSID_KEY] 292 ad.ed.clear_all_events() 293 wutils.reset_wifi(ad) 294 wutils.start_wifi_connection_scan_and_ensure_network_found(ad, SSID) 295 wutils.wifi_connect(ad, network, num_of_tries=5) 296 297 298def set_wifi_and_bt_scanning(ad, state=True): 299 """Set Wi-Fi and Bluetooth scanning on/off in Settings -> Location 300 301 Args: 302 ad: An AndroidDevice object. 303 state: True to turn on "Wi-Fi and Bluetooth scanning". 304 False to turn off "Wi-Fi and Bluetooth scanning". 305 """ 306 ad.root_adb() 307 if state: 308 ad.adb.shell("settings put global wifi_scan_always_enabled 1") 309 ad.adb.shell("settings put global ble_scan_always_enabled 1") 310 ad.log.info("Wi-Fi and Bluetooth scanning are enabled") 311 else: 312 ad.adb.shell("settings put global wifi_scan_always_enabled 0") 313 ad.adb.shell("settings put global ble_scan_always_enabled 0") 314 ad.log.info("Wi-Fi and Bluetooth scanning are disabled") 315 316 317def check_location_service(ad): 318 """Set location service on. 319 Verify if location service is available. 320 321 Args: 322 ad: An AndroidDevice object. 323 """ 324 remount_device(ad) 325 utils.set_location_service(ad, True) 326 location_mode = int(ad.adb.shell("settings get secure location_mode")) 327 ad.log.info("Current Location Mode >> %d" % location_mode) 328 if location_mode != 3: 329 raise signals.TestError("Failed to turn Location on") 330 331 332def clear_logd_gnss_qxdm_log(ad): 333 """Clear /data/misc/logd, 334 /storage/emulated/0/Android/data/com.android.gpstool/files and 335 /data/vendor/radio/diag_logs/logs from previous test item then reboot. 336 337 Args: 338 ad: An AndroidDevice object. 339 """ 340 remount_device(ad) 341 ad.log.info("Clear Logd, GNSS and PixelLogger Log from previous test item.") 342 ad.adb.shell("rm -rf /data/misc/logd", ignore_status=True) 343 ad.adb.shell( 344 'find %s -name "*.txt" -type f -delete' % GNSSSTATUS_LOG_PATH, 345 ignore_status=True) 346 if check_chipset_vendor_by_qualcomm(ad): 347 diag_logs = ( 348 "/sdcard/Android/data/com.android.pixellogger/files/logs/diag_logs") 349 ad.adb.shell("rm -rf %s" % diag_logs, ignore_status=True) 350 output_path = posixpath.join(DEFAULT_QXDM_LOG_PATH, "logs") 351 else: 352 output_path = ("/sdcard/Android/data/com.android.pixellogger/files" 353 "/logs/gps/") 354 ad.adb.shell("rm -rf %s" % output_path, ignore_status=True) 355 reboot(ad) 356 357 358def get_gnss_qxdm_log(ad, qdb_path): 359 """Get /storage/emulated/0/Android/data/com.android.gpstool/files and 360 /data/vendor/radio/diag_logs/logs for test item. 361 362 Args: 363 ad: An AndroidDevice object. 364 qdb_path: The path of qdsp6m.qdb on different projects. 365 """ 366 log_path = ad.device_log_path 367 os.makedirs(log_path, exist_ok=True) 368 gnss_log_name = "gnssstatus_log_%s_%s" % (ad.model, ad.serial) 369 gnss_log_path = posixpath.join(log_path, gnss_log_name) 370 os.makedirs(gnss_log_path, exist_ok=True) 371 ad.log.info("Pull GnssStatus Log to %s" % gnss_log_path) 372 ad.adb.pull("%s %s" % (GNSSSTATUS_LOG_PATH+".", gnss_log_path), 373 timeout=PULL_TIMEOUT, ignore_status=True) 374 shutil.make_archive(gnss_log_path, "zip", gnss_log_path) 375 shutil.rmtree(gnss_log_path) 376 if check_chipset_vendor_by_qualcomm(ad): 377 output_path = ( 378 "/sdcard/Android/data/com.android.pixellogger/files/logs/diag_logs") 379 else: 380 output_path = ( 381 "/sdcard/Android/data/com.android.pixellogger/files/logs/gps/") 382 qxdm_log_name = "PixelLogger_%s_%s" % (ad.model, ad.serial) 383 qxdm_log_path = posixpath.join(log_path, qxdm_log_name) 384 os.makedirs(qxdm_log_path, exist_ok=True) 385 ad.log.info("Pull PixelLogger Log %s to %s" % (output_path, 386 qxdm_log_path)) 387 ad.adb.pull("%s %s" % (output_path, qxdm_log_path), 388 timeout=PULL_TIMEOUT, ignore_status=True) 389 if check_chipset_vendor_by_qualcomm(ad): 390 for path in qdb_path: 391 output = ad.adb.pull("%s %s" % (path, qxdm_log_path), 392 timeout=PULL_TIMEOUT, ignore_status=True) 393 if "No such file or directory" in output: 394 continue 395 break 396 shutil.make_archive(qxdm_log_path, "zip", qxdm_log_path) 397 shutil.rmtree(qxdm_log_path) 398 399 400def set_mobile_data(ad, state): 401 """Set mobile data on or off and check mobile data state. 402 403 Args: 404 ad: An AndroidDevice object. 405 state: True to enable mobile data. False to disable mobile data. 406 """ 407 ad.root_adb() 408 if state: 409 ad.log.info("Enable mobile data.") 410 ad.adb.shell("svc data enable") 411 else: 412 ad.log.info("Disable mobile data.") 413 ad.adb.shell("svc data disable") 414 time.sleep(5) 415 out = int(ad.adb.shell("settings get global mobile_data")) 416 if state and out == 1: 417 ad.log.info("Mobile data is enabled and set to %d" % out) 418 elif not state and out == 0: 419 ad.log.info("Mobile data is disabled and set to %d" % out) 420 else: 421 ad.log.error("Mobile data is at unknown state and set to %d" % out) 422 423 424def gnss_trigger_modem_ssr_by_adb(ad, dwelltime=60): 425 """Trigger modem SSR crash by adb and verify if modem crash and recover 426 successfully. 427 428 Args: 429 ad: An AndroidDevice object. 430 dwelltime: Waiting time for modem reset. Default is 60 seconds. 431 432 Returns: 433 True if success. 434 False if failed. 435 """ 436 begin_time = get_current_epoch_time() 437 ad.root_adb() 438 cmds = ("echo restart > /sys/kernel/debug/msm_subsys/modem", 439 r"echo 'at+cfun=1,1\r' > /dev/at_mdm0") 440 for cmd in cmds: 441 ad.log.info("Triggering modem SSR crash by %s" % cmd) 442 output = ad.adb.shell(cmd, ignore_status=True) 443 if "No such file or directory" in output: 444 continue 445 break 446 time.sleep(dwelltime) 447 ad.send_keycode("HOME") 448 logcat_results = ad.search_logcat("SSRObserver", begin_time) 449 if logcat_results: 450 for ssr in logcat_results: 451 if "mSubsystem='modem', mCrashReason" in ssr["log_message"]: 452 ad.log.debug(ssr["log_message"]) 453 ad.log.info("Triggering modem SSR crash successfully.") 454 return True 455 raise signals.TestError("Failed to trigger modem SSR crash") 456 raise signals.TestError("No SSRObserver found in logcat") 457 458 459def gnss_trigger_modem_ssr_by_mds(ad, dwelltime=60): 460 """Trigger modem SSR crash by mds tool and verify if modem crash and recover 461 successfully. 462 463 Args: 464 ad: An AndroidDevice object. 465 dwelltime: Waiting time for modem reset. Default is 60 seconds. 466 """ 467 mds_check = ad.adb.shell("pm path com.google.mdstest") 468 if not mds_check: 469 raise signals.TestError("MDS Tool is not properly installed.") 470 ad.root_adb() 471 cmd = ('am instrument -w -e request "4b 25 03 00" ' 472 '"com.google.mdstest/com.google.mdstest.instrument' 473 '.ModemCommandInstrumentation"') 474 ad.log.info("Triggering modem SSR crash by MDS") 475 output = ad.adb.shell(cmd, ignore_status=True) 476 ad.log.debug(output) 477 time.sleep(dwelltime) 478 ad.send_keycode("HOME") 479 if "SUCCESS" in output: 480 ad.log.info("Triggering modem SSR crash by MDS successfully.") 481 else: 482 raise signals.TestError( 483 "Failed to trigger modem SSR crash by MDS. \n%s" % output) 484 485 486def check_xtra_download(ad, begin_time): 487 """Verify XTRA download success log message in logcat. 488 489 Args: 490 ad: An AndroidDevice object. 491 begin_time: test begin time 492 493 Returns: 494 True: xtra_download if XTRA downloaded and injected successfully 495 otherwise return False. 496 """ 497 ad.send_keycode("HOME") 498 if check_chipset_vendor_by_qualcomm(ad): 499 xtra_results = ad.search_logcat("XTRA download success. " 500 "inject data into modem", begin_time) 501 if xtra_results: 502 ad.log.debug("%s" % xtra_results[-1]["log_message"]) 503 ad.log.info("XTRA downloaded and injected successfully.") 504 return True 505 ad.log.error("XTRA downloaded FAIL.") 506 else: 507 lto_results = ad.search_logcat("GnssPsdsAidl: injectPsdsData: " 508 "psdsType: 1", begin_time) 509 if lto_results: 510 ad.log.debug("%s" % lto_results[-1]["log_message"]) 511 ad.log.info("LTO downloaded and injected successfully.") 512 return True 513 ad.log.error("LTO downloaded and inject FAIL.") 514 return False 515 516 517def pull_package_apk(ad, package_name): 518 """Pull apk of given package_name from device. 519 520 Args: 521 ad: An AndroidDevice object. 522 package_name: Package name of apk to pull. 523 524 Returns: 525 The temp path of pulled apk. 526 """ 527 apk_path = None 528 out = ad.adb.shell("pm path %s" % package_name) 529 result = re.search(r"package:(.*)", out) 530 if not result: 531 tutils.abort_all_tests(ad.log, "Couldn't find apk of %s" % package_name) 532 else: 533 apk_source = result.group(1) 534 ad.log.info("Get apk of %s from %s" % (package_name, apk_source)) 535 apk_path = tempfile.mkdtemp() 536 ad.pull_files([apk_source], apk_path) 537 return apk_path 538 539 540def pull_gnss_cfg_file(ad, file): 541 """Pull given gnss cfg file from device. 542 543 Args: 544 ad: An AndroidDevice object. 545 file: CFG file in device to pull. 546 547 Returns: 548 The temp path of pulled gnss cfg file in host. 549 """ 550 ad.root_adb() 551 host_dest = tempfile.mkdtemp() 552 ad.pull_files(file, host_dest) 553 for path_key in os.listdir(host_dest): 554 if fnmatch.fnmatch(path_key, "*.cfg"): 555 gnss_cfg_file = os.path.join(host_dest, path_key) 556 break 557 else: 558 raise signals.TestError("No cfg file is found in %s" % host_dest) 559 return gnss_cfg_file 560 561 562def reinstall_package_apk(ad, package_name, apk_path): 563 """Reinstall apk of given package_name. 564 565 Args: 566 ad: An AndroidDevice object. 567 package_name: Package name of apk. 568 apk_path: The temp path of pulled apk. 569 """ 570 for path_key in os.listdir(apk_path): 571 if fnmatch.fnmatch(path_key, "*.apk"): 572 apk_path = os.path.join(apk_path, path_key) 573 break 574 else: 575 raise signals.TestError("No apk is found in %s" % apk_path) 576 ad.log.info("Re-install %s with path: %s" % (package_name, apk_path)) 577 ad.adb.shell("settings put global verifier_verify_adb_installs 0") 578 ad.adb.install("-r -d -g --user 0 %s" % apk_path) 579 package_check = ad.adb.shell("pm path %s" % package_name) 580 if not package_check: 581 tutils.abort_all_tests( 582 ad.log, "%s is not properly re-installed." % package_name) 583 ad.log.info("%s is re-installed successfully." % package_name) 584 585 586def init_gtw_gpstool(ad): 587 """Init GTW_GPSTool apk. 588 589 Args: 590 ad: An AndroidDevice object. 591 """ 592 remount_device(ad) 593 gpstool_path = pull_package_apk(ad, "com.android.gpstool") 594 reinstall_package_apk(ad, "com.android.gpstool", gpstool_path) 595 596 597def fastboot_factory_reset(ad): 598 """Factory reset the device in fastboot mode. 599 Pull sl4a apk from device. Terminate all sl4a sessions, 600 Reboot the device to bootloader, 601 factory reset the device by fastboot. 602 Reboot the device. wait for device to complete booting 603 Re-install and start an sl4a session. 604 605 Args: 606 ad: An AndroidDevice object. 607 608 Returns: 609 True if factory reset process complete. 610 """ 611 status = True 612 skip_setup_wizard = True 613 gnss_cfg_path = "/vendor/etc/mdlog" 614 default_gnss_cfg = "/vendor/etc/mdlog/DEFAULT+SECURITY+FULLDPL+GPS.cfg" 615 sl4a_path = pull_package_apk(ad, SL4A_APK_NAME) 616 gpstool_path = pull_package_apk(ad, "com.android.gpstool") 617 mds_path = pull_package_apk(ad, "com.google.mdstest") 618 if check_chipset_vendor_by_qualcomm(ad): 619 gnss_cfg_file = pull_gnss_cfg_file(ad, default_gnss_cfg) 620 stop_pixel_logger(ad) 621 ad.stop_services() 622 attempts = 3 623 for i in range(1, attempts + 1): 624 try: 625 if ad.serial in list_adb_devices(): 626 ad.log.info("Reboot to bootloader") 627 ad.adb.reboot("bootloader", ignore_status=True) 628 time.sleep(10) 629 if ad.serial in list_fastboot_devices(): 630 ad.log.info("Factory reset in fastboot") 631 ad.fastboot._w(timeout=300, ignore_status=True) 632 time.sleep(30) 633 ad.log.info("Reboot in fastboot") 634 ad.fastboot.reboot() 635 ad.wait_for_boot_completion() 636 ad.root_adb() 637 if ad.skip_sl4a: 638 break 639 if ad.is_sl4a_installed(): 640 break 641 reinstall_package_apk(ad, SL4A_APK_NAME, sl4a_path) 642 reinstall_package_apk(ad, "com.android.gpstool", gpstool_path) 643 reinstall_package_apk(ad, "com.google.mdstest", mds_path) 644 if check_chipset_vendor_by_qualcomm(ad): 645 ad.push_system_file(gnss_cfg_file, gnss_cfg_path) 646 time.sleep(10) 647 break 648 except Exception as e: 649 ad.log.error(e) 650 if i == attempts: 651 tutils.abort_all_tests(ad.log, str(e)) 652 time.sleep(5) 653 try: 654 ad.start_adb_logcat() 655 except Exception as e: 656 ad.log.error(e) 657 if skip_setup_wizard: 658 ad.exit_setup_wizard() 659 if ad.skip_sl4a: 660 return status 661 tutils.bring_up_sl4a(ad) 662 return status 663 664 665def clear_aiding_data_by_gtw_gpstool(ad): 666 """Launch GTW GPSTool and Clear all GNSS aiding data. 667 Wait 5 seconds for GTW GPStool to clear all GNSS aiding 668 data properly. 669 670 Args: 671 ad: An AndroidDevice object. 672 """ 673 if not check_chipset_vendor_by_qualcomm(ad): 674 delete_lto_file(ad) 675 ad.log.info("Launch GTW GPSTool and Clear all GNSS aiding data") 676 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode clear") 677 time.sleep(10) 678 679 680def start_gnss_by_gtw_gpstool(ad, 681 state, 682 type="gnss", 683 bgdisplay=False, 684 freq=0, 685 lowpower=False, 686 meas=False): 687 """Start or stop GNSS on GTW_GPSTool. 688 689 Args: 690 ad: An AndroidDevice object. 691 state: True to start GNSS. False to Stop GNSS. 692 type: Different API for location fix. Use gnss/flp/nmea 693 bgdisplay: true to run GTW when Display off. false to not run GTW when 694 Display off. 695 freq: An integer to set location update frequency. 696 meas: A Boolean to set GNSS measurement registration. 697 lowpower: A boolean to set GNSS LowPowerMode. 698 """ 699 cmd = "am start -S -n com.android.gpstool/.GPSTool --es mode gps" 700 if not state: 701 ad.log.info("Stop %s on GTW_GPSTool." % type) 702 cmd = "am broadcast -a com.android.gpstool.stop_gps_action" 703 else: 704 options = ("--es type {} --ei freq {} --ez BG {} --ez meas {} --ez " 705 "lowpower {}").format(type, freq, bgdisplay, meas, lowpower) 706 cmd = cmd + " " + options 707 ad.adb.shell(cmd) 708 time.sleep(3) 709 710 711def process_gnss_by_gtw_gpstool(ad, 712 criteria, 713 type="gnss", 714 clear_data=True, 715 meas_flag=False): 716 """Launch GTW GPSTool and Clear all GNSS aiding data 717 Start GNSS tracking on GTW_GPSTool. 718 719 Args: 720 ad: An AndroidDevice object. 721 criteria: Criteria for current test item. 722 type: Different API for location fix. Use gnss/flp/nmea 723 clear_data: True to clear GNSS aiding data. False is not to. Default 724 set to True. 725 meas_flag: True to enable GnssMeasurement. False is not to. Default 726 set to False. 727 728 Returns: 729 True: First fix TTFF are within criteria. 730 False: First fix TTFF exceed criteria. 731 """ 732 retries = 3 733 for i in range(retries): 734 if not ad.is_adb_logcat_on: 735 ad.start_adb_logcat() 736 check_adblog_functionality(ad) 737 check_location_runtime_permissions( 738 ad, GNSSTOOL_PACKAGE_NAME, GNSSTOOL_PERMISSIONS) 739 begin_time = get_current_epoch_time() 740 if clear_data: 741 clear_aiding_data_by_gtw_gpstool(ad) 742 ad.log.info("Start %s on GTW_GPSTool - attempt %d" % (type.upper(), 743 i+1)) 744 start_gnss_by_gtw_gpstool(ad, state=True, type=type, meas=meas_flag) 745 for _ in range(10 + criteria): 746 logcat_results = ad.search_logcat("First fixed", begin_time) 747 if logcat_results: 748 ad.log.debug(logcat_results[-1]["log_message"]) 749 first_fixed = int(logcat_results[-1]["log_message"].split()[-1]) 750 ad.log.info("%s First fixed = %.3f seconds" % 751 (type.upper(), first_fixed/1000)) 752 if (first_fixed/1000) <= criteria: 753 return True 754 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 755 raise signals.TestFailure("Fail to get %s location fixed " 756 "within %d seconds criteria." 757 % (type.upper(), criteria)) 758 time.sleep(1) 759 check_current_focus_app(ad) 760 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 761 raise signals.TestFailure("Fail to get %s location fixed within %d " 762 "attempts." % (type.upper(), retries)) 763 764def start_ttff_by_gtw_gpstool(ad, ttff_mode, iteration, aid_data=False): 765 """Identify which TTFF mode for different test items. 766 767 Args: 768 ad: An AndroidDevice object. 769 ttff_mode: TTFF Test mode for current test item. 770 iteration: Iteration of TTFF cycles. 771 aid_data: Boolean for identify aid_data existed or not 772 """ 773 begin_time = get_current_epoch_time() 774 if (ttff_mode == "hs" or ttff_mode == "ws") and not aid_data: 775 ad.log.info("Wait 5 minutes to start TTFF %s..." % ttff_mode.upper()) 776 time.sleep(300) 777 if ttff_mode == "cs": 778 ad.log.info("Start TTFF Cold Start...") 779 time.sleep(3) 780 for i in range(1, 4): 781 ad.adb.shell("am broadcast -a com.android.gpstool.ttff_action " 782 "--es ttff %s --es cycle %d" % (ttff_mode, iteration)) 783 time.sleep(1) 784 if ad.search_logcat("act=com.android.gpstool.start_test_action", 785 begin_time): 786 ad.log.info("Send TTFF start_test_action successfully.") 787 break 788 else: 789 check_current_focus_app(ad) 790 raise signals.TestError("Fail to send TTFF start_test_action.") 791 792 793def gnss_tracking_via_gtw_gpstool(ad, 794 criteria, 795 type="gnss", 796 testtime=60, 797 meas_flag=False): 798 """Start GNSS/FLP tracking tests for input testtime on GTW_GPSTool. 799 800 Args: 801 ad: An AndroidDevice object. 802 criteria: Criteria for current TTFF. 803 type: Different API for location fix. Use gnss/flp/nmea 804 testtime: Tracking test time for minutes. Default set to 60 minutes. 805 meas_flag: True to enable GnssMeasurement. False is not to. Default 806 set to False. 807 """ 808 gnss_crash_list = [".*Fatal signal.*gnss", 809 ".*Fatal signal.*xtra", 810 ".*F DEBUG.*gnss"] 811 process_gnss_by_gtw_gpstool( 812 ad, criteria=criteria, type=type, meas_flag=meas_flag) 813 ad.log.info("Start %s tracking test for %d minutes" % (type.upper(), 814 testtime)) 815 begin_time = get_current_epoch_time() 816 while get_current_epoch_time() - begin_time < testtime * 60 * 1000: 817 if not ad.is_adb_logcat_on: 818 ad.start_adb_logcat() 819 for attr in gnss_crash_list: 820 gnss_crash_result = ad.adb.shell( 821 "logcat -d | grep -E -i '%s'" % attr) 822 if gnss_crash_result: 823 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 824 raise signals.TestFailure( 825 "Test failed due to GNSS HAL crashed. \n%s" % 826 gnss_crash_result) 827 gpstool_crash_result = ad.search_logcat("Force finishing activity " 828 "com.android.gpstool/.GPSTool", 829 begin_time) 830 if gpstool_crash_result: 831 raise signals.TestError("GPSTool crashed. Abort test.") 832 ad.log.info("Successfully tested for %d minutes" % testtime) 833 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 834 835 836def parse_gtw_gpstool_log(ad, true_position, type="gnss"): 837 """Process GNSS/FLP API logs from GTW GPSTool and output track_data to 838 test_run_info for ACTS plugin to parse and display on MobileHarness as 839 Property. 840 841 Args: 842 ad: An AndroidDevice object. 843 true_position: Coordinate as [latitude, longitude] to calculate 844 position error. 845 type: Different API for location fix. Use gnss/flp/nmea 846 """ 847 test_logfile = {} 848 track_data = {} 849 ant_top4_cn = 0 850 ant_cn = 0 851 base_top4_cn = 0 852 base_cn = 0 853 track_lat = 0 854 track_long = 0 855 l5flag = "false" 856 file_count = int(ad.adb.shell("find %s -type f -iname *.txt | wc -l" 857 % GNSSSTATUS_LOG_PATH)) 858 if file_count != 1: 859 ad.log.error("%d API logs exist." % file_count) 860 dir_file = ad.adb.shell("ls %s" % GNSSSTATUS_LOG_PATH).split() 861 for path_key in dir_file: 862 if fnmatch.fnmatch(path_key, "*.txt"): 863 logpath = posixpath.join(GNSSSTATUS_LOG_PATH, path_key) 864 out = ad.adb.shell("wc -c %s" % logpath) 865 file_size = int(out.split(" ")[0]) 866 if file_size < 2000: 867 ad.log.info("Skip log %s due to log size %d bytes" % 868 (path_key, file_size)) 869 continue 870 test_logfile = logpath 871 if not test_logfile: 872 raise signals.TestError("Failed to get test log file in device.") 873 lines = ad.adb.shell("cat %s" % test_logfile).split("\n") 874 for line in lines: 875 if "Antenna_History Avg Top4" in line: 876 ant_top4_cn = float(line.split(":")[-1].strip()) 877 elif "Antenna_History Avg" in line: 878 ant_cn = float(line.split(":")[-1].strip()) 879 elif "Baseband_History Avg Top4" in line: 880 base_top4_cn = float(line.split(":")[-1].strip()) 881 elif "Baseband_History Avg" in line: 882 base_cn = float(line.split(":")[-1].strip()) 883 elif "L5 used in fix" in line: 884 l5flag = line.split(":")[-1].strip() 885 elif "Latitude" in line: 886 track_lat = float(line.split(":")[-1].strip()) 887 elif "Longitude" in line: 888 track_long = float(line.split(":")[-1].strip()) 889 elif "Time" in line: 890 track_utc = line.split("Time:")[-1].strip() 891 if track_utc in track_data.keys(): 892 continue 893 pe = calculate_position_error(track_lat, track_long, true_position) 894 track_data[track_utc] = TRACK_REPORT(l5flag=l5flag, 895 pe=pe, 896 ant_top4cn=ant_top4_cn, 897 ant_cn=ant_cn, 898 base_top4cn=base_top4_cn, 899 base_cn=base_cn) 900 ad.log.debug(track_data) 901 prop_basename = "TestResult %s_tracking_" % type.upper() 902 time_list = sorted(track_data.keys()) 903 l5flag_list = [track_data[key].l5flag for key in time_list] 904 pe_list = [float(track_data[key].pe) for key in time_list] 905 ant_top4cn_list = [float(track_data[key].ant_top4cn) for key in time_list] 906 ant_cn_list = [float(track_data[key].ant_cn) for key in time_list] 907 base_top4cn_list = [float(track_data[key].base_top4cn) for key in time_list] 908 base_cn_list = [float(track_data[key].base_cn) for key in time_list] 909 ad.log.info(prop_basename+"StartTime %s" % time_list[0].replace(" ", "-")) 910 ad.log.info(prop_basename+"EndTime %s" % time_list[-1].replace(" ", "-")) 911 ad.log.info(prop_basename+"TotalFixPoints %d" % len(time_list)) 912 ad.log.info(prop_basename+"L5FixRate "+'{percent:.2%}'.format( 913 percent=l5flag_list.count("true")/len(l5flag_list))) 914 ad.log.info(prop_basename+"AvgDis %.1f" % (sum(pe_list)/len(pe_list))) 915 ad.log.info(prop_basename+"MaxDis %.1f" % max(pe_list)) 916 ad.log.info(prop_basename+"Ant_AvgTop4Signal %.1f" % ant_top4cn_list[-1]) 917 ad.log.info(prop_basename+"Ant_AvgSignal %.1f" % ant_cn_list[-1]) 918 ad.log.info(prop_basename+"Base_AvgTop4Signal %.1f" % base_top4cn_list[-1]) 919 ad.log.info(prop_basename+"Base_AvgSignal %.1f" % base_cn_list[-1]) 920 921 922def process_ttff_by_gtw_gpstool(ad, begin_time, true_position, type="gnss"): 923 """Process TTFF and record results in ttff_data. 924 925 Args: 926 ad: An AndroidDevice object. 927 begin_time: test begin time. 928 true_position: Coordinate as [latitude, longitude] to calculate 929 position error. 930 type: Different API for location fix. Use gnss/flp/nmea 931 932 Returns: 933 ttff_data: A dict of all TTFF data. 934 """ 935 ttff_lat = 0 936 ttff_lon = 0 937 utc_time = epoch_to_human_time(get_current_epoch_time()) 938 ttff_data = {} 939 ttff_loop_time = get_current_epoch_time() 940 while True: 941 if get_current_epoch_time() - ttff_loop_time >= 120000: 942 raise signals.TestError("Fail to search specific GPSService " 943 "message in logcat. Abort test.") 944 if not ad.is_adb_logcat_on: 945 ad.start_adb_logcat() 946 logcat_results = ad.search_logcat("write TTFF log", ttff_loop_time) 947 if logcat_results: 948 ttff_loop_time = get_current_epoch_time() 949 ttff_log = logcat_results[-1]["log_message"].split() 950 ttff_loop = int(ttff_log[8].split(":")[-1]) 951 ttff_sec = float(ttff_log[11]) 952 if ttff_sec != 0.0: 953 ttff_ant_cn = float(ttff_log[18].strip("]")) 954 ttff_base_cn = float(ttff_log[25].strip("]")) 955 if type == "gnss": 956 gnss_results = ad.search_logcat("GPSService: Check item", 957 begin_time) 958 if gnss_results: 959 ad.log.debug(gnss_results[-1]["log_message"]) 960 gnss_location_log = \ 961 gnss_results[-1]["log_message"].split() 962 ttff_lat = float( 963 gnss_location_log[8].split("=")[-1].strip(",")) 964 ttff_lon = float( 965 gnss_location_log[9].split("=")[-1].strip(",")) 966 loc_time = int( 967 gnss_location_log[10].split("=")[-1].strip(",")) 968 utc_time = epoch_to_human_time(loc_time) 969 elif type == "flp": 970 flp_results = ad.search_logcat("GPSService: FLP Location", 971 begin_time) 972 if flp_results: 973 ad.log.debug(flp_results[-1]["log_message"]) 974 flp_location_log = flp_results[-1][ 975 "log_message"].split() 976 ttff_lat = float(flp_location_log[8].split(",")[0]) 977 ttff_lon = float(flp_location_log[8].split(",")[1]) 978 utc_time = epoch_to_human_time(get_current_epoch_time()) 979 else: 980 ttff_ant_cn = float(ttff_log[19].strip("]")) 981 ttff_base_cn = float(ttff_log[26].strip("]")) 982 ttff_lat = 0 983 ttff_lon = 0 984 utc_time = epoch_to_human_time(get_current_epoch_time()) 985 ad.log.debug("TTFF Loop %d - (Lat, Lon) = (%s, %s)" % (ttff_loop, 986 ttff_lat, 987 ttff_lon)) 988 ttff_pe = calculate_position_error( 989 ttff_lat, ttff_lon, true_position) 990 ttff_data[ttff_loop] = TTFF_REPORT(utc_time=utc_time, 991 ttff_loop=ttff_loop, 992 ttff_sec=ttff_sec, 993 ttff_pe=ttff_pe, 994 ttff_ant_cn=ttff_ant_cn, 995 ttff_base_cn=ttff_base_cn) 996 ad.log.info("UTC Time = %s, Loop %d = %.1f seconds, " 997 "Position Error = %.1f meters, " 998 "Antenna Average Signal = %.1f dbHz, " 999 "Baseband Average Signal = %.1f dbHz" % (utc_time, 1000 ttff_loop, 1001 ttff_sec, 1002 ttff_pe, 1003 ttff_ant_cn, 1004 ttff_base_cn)) 1005 stop_gps_results = ad.search_logcat("stop gps test", begin_time) 1006 if stop_gps_results: 1007 ad.send_keycode("HOME") 1008 break 1009 crash_result = ad.search_logcat("Force finishing activity " 1010 "com.android.gpstool/.GPSTool", 1011 begin_time) 1012 if crash_result: 1013 raise signals.TestError("GPSTool crashed. Abort test.") 1014 # wait 5 seconds to avoid logs not writing into logcat yet 1015 time.sleep(5) 1016 return ttff_data 1017 1018 1019def check_ttff_data(ad, ttff_data, ttff_mode, criteria): 1020 """Verify all TTFF results from ttff_data. 1021 1022 Args: 1023 ad: An AndroidDevice object. 1024 ttff_data: TTFF data of secs, position error and signal strength. 1025 ttff_mode: TTFF Test mode for current test item. 1026 criteria: Criteria for current test item. 1027 1028 Returns: 1029 True: All TTFF results are within criteria. 1030 False: One or more TTFF results exceed criteria or Timeout. 1031 """ 1032 ad.log.info("%d iterations of TTFF %s tests finished." 1033 % (len(ttff_data.keys()), ttff_mode)) 1034 ad.log.info("%s PASS criteria is %d seconds" % (ttff_mode, criteria)) 1035 ad.log.debug("%s TTFF data: %s" % (ttff_mode, ttff_data)) 1036 ttff_property_key_and_value(ad, ttff_data, ttff_mode) 1037 if len(ttff_data.keys()) == 0: 1038 ad.log.error("GTW_GPSTool didn't process TTFF properly.") 1039 return False 1040 elif any(float(ttff_data[key].ttff_sec) == 0.0 for key in ttff_data.keys()): 1041 ad.log.error("One or more TTFF %s Timeout" % ttff_mode) 1042 return False 1043 elif any(float(ttff_data[key].ttff_sec) >= criteria for key in 1044 ttff_data.keys()): 1045 ad.log.error("One or more TTFF %s are over test criteria %d seconds" 1046 % (ttff_mode, criteria)) 1047 return False 1048 ad.log.info("All TTFF %s are within test criteria %d seconds." 1049 % (ttff_mode, criteria)) 1050 return True 1051 1052 1053def ttff_property_key_and_value(ad, ttff_data, ttff_mode): 1054 """Output ttff_data to test_run_info for ACTS plugin to parse and display 1055 on MobileHarness as Property. 1056 1057 Args: 1058 ad: An AndroidDevice object. 1059 ttff_data: TTFF data of secs, position error and signal strength. 1060 ttff_mode: TTFF Test mode for current test item. 1061 """ 1062 prop_basename = "TestResult "+ttff_mode.replace(" ", "_")+"_TTFF_" 1063 sec_list = [float(ttff_data[key].ttff_sec) for key in ttff_data.keys()] 1064 pe_list = [float(ttff_data[key].ttff_pe) for key in ttff_data.keys()] 1065 ant_cn_list = [float(ttff_data[key].ttff_ant_cn) for key in 1066 ttff_data.keys()] 1067 base_cn_list = [float(ttff_data[key].ttff_base_cn) for key in 1068 ttff_data.keys()] 1069 timeoutcount = sec_list.count(0.0) 1070 if len(sec_list) == timeoutcount: 1071 avgttff = 9527 1072 else: 1073 avgttff = sum(sec_list)/(len(sec_list) - timeoutcount) 1074 if timeoutcount != 0: 1075 maxttff = 9527 1076 else: 1077 maxttff = max(sec_list) 1078 avgdis = sum(pe_list)/len(pe_list) 1079 maxdis = max(pe_list) 1080 ant_avgcn = sum(ant_cn_list)/len(ant_cn_list) 1081 base_avgcn = sum(base_cn_list)/len(base_cn_list) 1082 ad.log.info(prop_basename+"AvgTime %.1f" % avgttff) 1083 ad.log.info(prop_basename+"MaxTime %.1f" % maxttff) 1084 ad.log.info(prop_basename+"TimeoutCount %d" % timeoutcount) 1085 ad.log.info(prop_basename+"AvgDis %.1f" % avgdis) 1086 ad.log.info(prop_basename+"MaxDis %.1f" % maxdis) 1087 ad.log.info(prop_basename+"Ant_AvgSignal %.1f" % ant_avgcn) 1088 ad.log.info(prop_basename+"Base_AvgSignal %.1f" % base_avgcn) 1089 1090 1091def calculate_position_error(latitude, longitude, true_position): 1092 """Use haversine formula to calculate position error base on true location 1093 coordinate. 1094 1095 Args: 1096 latitude: latitude of location fixed in the present. 1097 longitude: longitude of location fixed in the present. 1098 true_position: [latitude, longitude] of true location coordinate. 1099 1100 Returns: 1101 position_error of location fixed in the present. 1102 """ 1103 radius = 6371009 1104 dlat = math.radians(latitude - true_position[0]) 1105 dlon = math.radians(longitude - true_position[1]) 1106 a = math.sin(dlat/2) * math.sin(dlat/2) + \ 1107 math.cos(math.radians(true_position[0])) * \ 1108 math.cos(math.radians(latitude)) * math.sin(dlon/2) * math.sin(dlon/2) 1109 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) 1110 return radius * c 1111 1112 1113def launch_google_map(ad): 1114 """Launch Google Map via intent. 1115 1116 Args: 1117 ad: An AndroidDevice object. 1118 """ 1119 ad.log.info("Launch Google Map.") 1120 try: 1121 ad.adb.shell("am start -S -n com.google.android.apps.maps/" 1122 "com.google.android.maps.MapsActivity") 1123 ad.send_keycode("BACK") 1124 ad.force_stop_apk("com.google.android.apps.maps") 1125 ad.adb.shell("am start -S -n com.google.android.apps.maps/" 1126 "com.google.android.maps.MapsActivity") 1127 except Exception as e: 1128 ad.log.error(e) 1129 raise signals.TestError("Failed to launch google map.") 1130 check_current_focus_app(ad) 1131 1132 1133def check_current_focus_app(ad): 1134 """Check to see current focused window and app. 1135 1136 Args: 1137 ad: An AndroidDevice object. 1138 """ 1139 time.sleep(1) 1140 current = ad.adb.shell( 1141 "dumpsys window | grep -E 'mCurrentFocus|mFocusedApp'") 1142 ad.log.debug("\n"+current) 1143 1144 1145def check_location_api(ad, retries): 1146 """Verify if GnssLocationProvider API reports location. 1147 1148 Args: 1149 ad: An AndroidDevice object. 1150 retries: Retry time. 1151 1152 Returns: 1153 True: GnssLocationProvider API reports location. 1154 otherwise return False. 1155 """ 1156 for i in range(retries): 1157 begin_time = get_current_epoch_time() 1158 ad.log.info("Try to get location report from GnssLocationProvider API " 1159 "- attempt %d" % (i+1)) 1160 while get_current_epoch_time() - begin_time <= 30000: 1161 logcat_results = ad.search_logcat("REPORT_LOCATION", begin_time) 1162 if logcat_results: 1163 ad.log.info("%s" % logcat_results[-1]["log_message"]) 1164 ad.log.info("GnssLocationProvider reports location " 1165 "successfully.") 1166 return True 1167 if not ad.is_adb_logcat_on: 1168 ad.start_adb_logcat() 1169 ad.log.error("GnssLocationProvider is unable to report location.") 1170 return False 1171 1172def check_network_location(ad, retries, location_type, criteria=30): 1173 """Verify if NLP reports location after requesting via GPSTool. 1174 1175 Args: 1176 ad: An AndroidDevice object. 1177 retries: Retry time. 1178 location_type: cell or wifi. 1179 criteria: expected nlp return time, default 30 seconds 1180 1181 Returns: 1182 True: NLP reports location. 1183 otherwise return False. 1184 """ 1185 criteria = criteria * 1000 1186 search_pattern = ("GPSTool : networkLocationType = %s" % location_type) 1187 for i in range(retries): 1188 begin_time = get_current_epoch_time() 1189 ad.log.info("Try to get NLP status - attempt %d" % (i+1)) 1190 ad.adb.shell( 1191 "am start -S -n com.android.gpstool/.GPSTool --es mode nlp") 1192 while get_current_epoch_time() - begin_time <= criteria: 1193 # Search pattern in 1 second interval 1194 time.sleep(1) 1195 result = ad.search_logcat(search_pattern, begin_time) 1196 if result: 1197 ad.log.info("Pattern Found: %s." % result[-1]["log_message"]) 1198 ad.send_keycode("BACK") 1199 return True 1200 if not ad.is_adb_logcat_on: 1201 ad.start_adb_logcat() 1202 ad.send_keycode("BACK") 1203 ad.log.error("Unable to report network location \"%s\"." % location_type) 1204 return False 1205 1206 1207def set_attenuator_gnss_signal(ad, attenuator, atten_value): 1208 """Set attenuation value for different GNSS signal. 1209 1210 Args: 1211 ad: An AndroidDevice object. 1212 attenuator: The attenuator object. 1213 atten_value: attenuation value 1214 """ 1215 try: 1216 ad.log.info( 1217 "Set attenuation value to \"%d\" for GNSS signal." % atten_value) 1218 attenuator[0].set_atten(atten_value) 1219 except Exception as e: 1220 ad.log.error(e) 1221 1222 1223def set_battery_saver_mode(ad, state): 1224 """Enable or disable battery saver mode via adb. 1225 1226 Args: 1227 ad: An AndroidDevice object. 1228 state: True is enable Battery Saver mode. False is disable. 1229 """ 1230 ad.root_adb() 1231 if state: 1232 ad.log.info("Enable Battery Saver mode.") 1233 ad.adb.shell("cmd battery unplug") 1234 ad.adb.shell("settings put global low_power 1") 1235 else: 1236 ad.log.info("Disable Battery Saver mode.") 1237 ad.adb.shell("settings put global low_power 0") 1238 ad.adb.shell("cmd battery reset") 1239 1240 1241def set_gnss_qxdm_mask(ad, masks): 1242 """Find defined gnss qxdm mask and set as default logging mask. 1243 1244 Args: 1245 ad: An AndroidDevice object. 1246 masks: Defined gnss qxdm mask. 1247 """ 1248 try: 1249 for mask in masks: 1250 if not tutils.find_qxdm_log_mask(ad, mask): 1251 continue 1252 tutils.set_qxdm_logger_command(ad, mask) 1253 break 1254 except Exception as e: 1255 ad.log.error(e) 1256 raise signals.TestError("Failed to set any QXDM masks.") 1257 1258 1259def start_youtube_video(ad, url=None, retries=0): 1260 """Start youtube video and verify if audio is in music state. 1261 1262 Args: 1263 ad: An AndroidDevice object. 1264 url: Youtube video url. 1265 retries: Retry times if audio is not in music state. 1266 1267 Returns: 1268 True if youtube video is playing normally. 1269 False if youtube video is not playing properly. 1270 """ 1271 for i in range(retries): 1272 ad.log.info("Open an youtube video - attempt %d" % (i+1)) 1273 cmd = ("am start -n com.google.android.youtube/" 1274 "com.google.android.youtube.UrlActivity -d \"%s\"" % url) 1275 ad.adb.shell(cmd) 1276 time.sleep(2) 1277 out = ad.adb.shell( 1278 "dumpsys activity | grep NewVersionAvailableActivity") 1279 if out: 1280 ad.log.info("Skip Youtube New Version Update.") 1281 ad.send_keycode("BACK") 1282 if tutils.wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1): 1283 ad.log.info("Started a video in youtube, audio is in MUSIC state") 1284 return True 1285 ad.log.info("Force-Stop youtube and reopen youtube again.") 1286 ad.force_stop_apk("com.google.android.youtube") 1287 check_current_focus_app(ad) 1288 raise signals.TestError("Started a video in youtube, " 1289 "but audio is not in MUSIC state") 1290 1291 1292def get_baseband_and_gms_version(ad, extra_msg=""): 1293 """Get current radio baseband and GMSCore version of AndroidDevice object. 1294 1295 Args: 1296 ad: An AndroidDevice object. 1297 extra_msg: Extra message before or after the change. 1298 """ 1299 try: 1300 build_version = ad.adb.getprop("ro.build.id") 1301 baseband_version = ad.adb.getprop("gsm.version.baseband") 1302 gms_version = ad.adb.shell( 1303 "dumpsys package com.google.android.gms | grep versionName" 1304 ).split("\n")[0].split("=")[1] 1305 mpss_version = ad.adb.shell("cat /sys/devices/soc0/images | grep MPSS " 1306 "| cut -d ':' -f 3") 1307 if not extra_msg: 1308 ad.log.info("TestResult Build_Version %s" % build_version) 1309 ad.log.info("TestResult Baseband_Version %s" % baseband_version) 1310 ad.log.info( 1311 "TestResult GMS_Version %s" % gms_version.replace(" ", "")) 1312 ad.log.info("TestResult MPSS_Version %s" % mpss_version) 1313 else: 1314 ad.log.info( 1315 "%s, Baseband_Version = %s" % (extra_msg, baseband_version)) 1316 except Exception as e: 1317 ad.log.error(e) 1318 1319 1320def start_toggle_gnss_by_gtw_gpstool(ad, iteration): 1321 """Send toggle gnss off/on start_test_action 1322 1323 Args: 1324 ad: An AndroidDevice object. 1325 iteration: Iteration of toggle gnss off/on cycles. 1326 """ 1327 msg_list = [] 1328 begin_time = get_current_epoch_time() 1329 try: 1330 for i in range(1, 4): 1331 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool " 1332 "--es mode toggle --es cycle %d" % iteration) 1333 time.sleep(1) 1334 if ad.search_logcat("cmp=com.android.gpstool/.ToggleGPS", 1335 begin_time): 1336 ad.log.info("Send ToggleGPS start_test_action successfully.") 1337 break 1338 else: 1339 check_current_focus_app(ad) 1340 raise signals.TestError("Fail to send ToggleGPS " 1341 "start_test_action within 3 attempts.") 1342 time.sleep(2) 1343 test_start = ad.search_logcat("GPSTool_ToggleGPS: startService", 1344 begin_time) 1345 if test_start: 1346 ad.log.info(test_start[-1]["log_message"].split(":")[-1].strip()) 1347 else: 1348 raise signals.TestError("Fail to start toggle GPS off/on test.") 1349 # Every iteration is expected to finish within 4 minutes. 1350 while get_current_epoch_time() - begin_time <= iteration * 240000: 1351 crash_end = ad.search_logcat("Force finishing activity " 1352 "com.android.gpstool/.GPSTool", 1353 begin_time) 1354 if crash_end: 1355 raise signals.TestError("GPSTool crashed. Abort test.") 1356 toggle_results = ad.search_logcat("GPSTool : msg", begin_time) 1357 if toggle_results: 1358 for toggle_result in toggle_results: 1359 msg = toggle_result["log_message"] 1360 if not msg in msg_list: 1361 ad.log.info(msg.split(":")[-1].strip()) 1362 msg_list.append(msg) 1363 if "timeout" in msg: 1364 raise signals.TestFailure("Fail to get location fixed " 1365 "within 60 seconds.") 1366 if "Test end" in msg: 1367 raise signals.TestPass("Completed quick toggle GNSS " 1368 "off/on test.") 1369 raise signals.TestFailure("Fail to finish toggle GPS off/on test " 1370 "within %d minutes" % (iteration * 4)) 1371 finally: 1372 ad.send_keycode("HOME") 1373 1374 1375def grant_location_permission(ad, option): 1376 """Grant or revoke location related permission. 1377 1378 Args: 1379 ad: An AndroidDevice object. 1380 option: Boolean to grant or revoke location related permissions. 1381 """ 1382 action = "grant" if option else "revoke" 1383 for permission in LOCATION_PERMISSIONS: 1384 ad.log.info( 1385 "%s permission:%s on %s" % (action, permission, TEST_PACKAGE_NAME)) 1386 ad.adb.shell("pm %s %s %s" % (action, TEST_PACKAGE_NAME, permission)) 1387 1388 1389def check_location_runtime_permissions(ad, package, permissions): 1390 """Check if runtime permissions are granted on selected package. 1391 1392 Args: 1393 ad: An AndroidDevice object. 1394 package: Apk package name to check. 1395 permissions: A list of permissions to be granted. 1396 """ 1397 for _ in range(3): 1398 location_runtime_permission = ad.adb.shell( 1399 "dumpsys package %s | grep ACCESS_FINE_LOCATION" % package) 1400 if "true" not in location_runtime_permission: 1401 ad.log.info("ACCESS_FINE_LOCATION is NOT granted on %s" % package) 1402 for permission in permissions: 1403 ad.log.debug("Grant %s on %s" % (permission, package)) 1404 ad.adb.shell("pm grant %s %s" % (package, permission)) 1405 else: 1406 ad.log.info("ACCESS_FINE_LOCATION is granted on %s" % package) 1407 break 1408 else: 1409 raise signals.TestError( 1410 "Fail to grant ACCESS_FINE_LOCATION on %s" % package) 1411 1412 1413def install_mdstest_app(ad, mdsapp): 1414 """ 1415 Install MDS test app in DUT 1416 1417 Args: 1418 ad: An Android Device Object 1419 mdsapp: Installation path of MDSTest app 1420 """ 1421 if not ad.is_apk_installed("com.google.mdstest"): 1422 ad.adb.install("-r %s" % mdsapp, timeout=300, ignore_status=True) 1423 1424 1425def write_modemconfig(ad, mdsapp, nvitem_dict, modemparfile): 1426 """ 1427 Modify the NV items using modem_tool.par 1428 Note: modem_tool.par 1429 1430 Args: 1431 ad: An Android Device Object 1432 mdsapp: Installation path of MDSTest app 1433 nvitem_dict: dictionary of NV items and values. 1434 modemparfile: modem_tool.par path. 1435 """ 1436 ad.log.info("Verify MDSTest app installed in DUT") 1437 install_mdstest_app(ad, mdsapp) 1438 os.system("chmod 777 %s" % modemparfile) 1439 for key, value in nvitem_dict.items(): 1440 if key.isdigit(): 1441 op_name = "WriteEFS" 1442 else: 1443 op_name = "WriteNV" 1444 ad.log.info("Modifying the NV{!r} using {}".format(key, op_name)) 1445 job.run("{} --op {} --item {} --data '{}'". 1446 format(modemparfile, op_name, key, value)) 1447 time.sleep(2) 1448 1449 1450def verify_modemconfig(ad, nvitem_dict, modemparfile): 1451 """ 1452 Verify the NV items using modem_tool.par 1453 Note: modem_tool.par 1454 1455 Args: 1456 ad: An Android Device Object 1457 nvitem_dict: dictionary of NV items and values 1458 modemparfile: modem_tool.par path. 1459 """ 1460 os.system("chmod 777 %s" % modemparfile) 1461 for key, value in nvitem_dict.items(): 1462 if key.isdigit(): 1463 op_name = "ReadEFS" 1464 else: 1465 op_name = "ReadNV" 1466 # Sleeptime to avoid Modem communication error 1467 time.sleep(5) 1468 result = job.run( 1469 "{} --op {} --item {}".format(modemparfile, op_name, key)) 1470 output = str(result.stdout) 1471 ad.log.info("Actual Value for NV{!r} is {!r}".format(key, output)) 1472 if not value.casefold() in output: 1473 ad.log.error("NV Value is wrong {!r} in {!r}".format(value, result)) 1474 raise ValueError( 1475 "could not find {!r} in {!r}".format(value, result)) 1476 1477 1478def check_ttff_pe(ad, ttff_data, ttff_mode, pe_criteria): 1479 """Verify all TTFF results from ttff_data. 1480 1481 Args: 1482 ad: An AndroidDevice object. 1483 ttff_data: TTFF data of secs, position error and signal strength. 1484 ttff_mode: TTFF Test mode for current test item. 1485 pe_criteria: Criteria for current test item. 1486 1487 """ 1488 ad.log.info("%d iterations of TTFF %s tests finished.", 1489 (len(ttff_data.keys()), ttff_mode)) 1490 ad.log.info("%s PASS criteria is %f meters", (ttff_mode, pe_criteria)) 1491 ad.log.debug("%s TTFF data: %s", (ttff_mode, ttff_data)) 1492 1493 if len(ttff_data.keys()) == 0: 1494 ad.log.error("GTW_GPSTool didn't process TTFF properly.") 1495 raise signals.TestFailure("GTW_GPSTool didn't process TTFF properly.") 1496 1497 elif any(float(ttff_data[key].ttff_pe) >= pe_criteria for key in 1498 ttff_data.keys()): 1499 ad.log.error("One or more TTFF %s are over test criteria %f meters", 1500 (ttff_mode, pe_criteria)) 1501 raise signals.TestFailure("GTW_GPSTool didn't process TTFF properly.") 1502 ad.log.info("All TTFF %s are within test criteria %f meters.", 1503 (ttff_mode, pe_criteria)) 1504 1505 1506def check_adblog_functionality(ad): 1507 """Restart adb logcat if system can't write logs into file after checking 1508 adblog file size. 1509 1510 Args: 1511 ad: An AndroidDevice object. 1512 """ 1513 logcat_path = os.path.join(ad.device_log_path, "adblog_%s_debug.txt" % 1514 ad.serial) 1515 if not os.path.exists(logcat_path): 1516 raise signals.TestError("Logcat file %s does not exist." % logcat_path) 1517 original_log_size = os.path.getsize(logcat_path) 1518 ad.log.debug("Original adblog size is %d" % original_log_size) 1519 time.sleep(.5) 1520 current_log_size = os.path.getsize(logcat_path) 1521 ad.log.debug("Current adblog size is %d" % current_log_size) 1522 if current_log_size == original_log_size: 1523 ad.log.warn("System can't write logs into file. Restart adb " 1524 "logcat process now.") 1525 ad.stop_adb_logcat() 1526 ad.start_adb_logcat() 1527 1528 1529def build_instrumentation_call(package, 1530 runner, 1531 test_methods=None, 1532 options=None): 1533 """Build an instrumentation call for the tests 1534 1535 Args: 1536 package: A string to identify test package. 1537 runner: A string to identify test runner. 1538 test_methods: A dictionary contains {class_name, test_method}. 1539 options: A dictionary constant {key, value} param for test. 1540 1541 Returns: 1542 An instrumentation call command. 1543 """ 1544 if test_methods is None: 1545 test_methods = {} 1546 cmd_builder = InstrumentationCommandBuilder() 1547 else: 1548 cmd_builder = InstrumentationTestCommandBuilder() 1549 if options is None: 1550 options = {} 1551 cmd_builder.set_manifest_package(package) 1552 cmd_builder.set_runner(runner) 1553 cmd_builder.add_flag("-w") 1554 for class_name, test_method in test_methods.items(): 1555 cmd_builder.add_test_method(class_name, test_method) 1556 for option_key, option_value in options.items(): 1557 cmd_builder.add_key_value_param(option_key, option_value) 1558 return cmd_builder.build() 1559 1560 1561def check_chipset_vendor_by_qualcomm(ad): 1562 """Check if cipset vendor is by Qualcomm. 1563 1564 Args: 1565 ad: An AndroidDevice object. 1566 1567 Returns: 1568 True if it's by Qualcomm. False irf not. 1569 """ 1570 ad.root_adb() 1571 soc = str(ad.adb.shell("getprop gsm.version.ril-impl")) 1572 ad.log.debug("SOC = %s" % soc) 1573 return "Qualcomm" in soc 1574 1575 1576def delete_lto_file(ad): 1577 """Delete downloaded LTO files. 1578 1579 Args: 1580 ad: An AndroidDevice object. 1581 """ 1582 remount_device(ad) 1583 status = ad.adb.shell("rm -rf /data/vendor/gps/lto*") 1584 ad.log.info("Delete downloaded LTO files.\n%s" % status) 1585 1586 1587def lto_mode(ad, state): 1588 """Enable or Disable LTO mode. 1589 1590 Args: 1591 ad: An AndroidDevice object. 1592 state: True to enable. False to disable. 1593 """ 1594 server_list = ["LONGTERM_PSDS_SERVER_1", 1595 "LONGTERM_PSDS_SERVER_2", 1596 "LONGTERM_PSDS_SERVER_3", 1597 "NORMAL_PSDS_SERVER", 1598 "REALTIME_PSDS_SERVER"] 1599 delete_lto_file(ad) 1600 tmp_path = tempfile.mkdtemp() 1601 ad.pull_files("/etc/gps_debug.conf", tmp_path) 1602 gps_conf_path = os.path.join(tmp_path, "gps_debug.conf") 1603 gps_conf_file = open(gps_conf_path, "r") 1604 lines = gps_conf_file.readlines() 1605 gps_conf_file.close() 1606 fout = open(gps_conf_path, "w") 1607 if state: 1608 for line in lines: 1609 for server in server_list: 1610 if server in line: 1611 line = line.replace(line, "") 1612 fout.write(line) 1613 fout.close() 1614 ad.push_system_file(gps_conf_path, "/etc/gps_debug.conf") 1615 ad.log.info("Push back modified gps_debug.conf") 1616 ad.log.info("LTO/RTO/RTI enabled") 1617 else: 1618 ad.adb.shell("echo %r >> /etc/gps_debug.conf" % 1619 DISABLE_LTO_FILE_CONTENTS) 1620 ad.log.info("LTO/RTO/RTI disabled") 1621 reboot(ad) 1622 1623 1624def start_pixel_logger(ad, max_log_size_mb=100, max_number_of_files=500): 1625 """adb to start pixel logger for GNSS logging. 1626 1627 Args: 1628 ad: An AndroidDevice object. 1629 max_log_size_mb: Determines when to create a new log file if current 1630 one reaches the size limit. 1631 max_number_of_files: Determines how many log files can be saved on DUT. 1632 """ 1633 retries = 3 1634 start_timeout_sec = 60 1635 default_gnss_cfg = "/vendor/etc/mdlog/DEFAULT+SECURITY+FULLDPL+GPS.cfg" 1636 if check_chipset_vendor_by_qualcomm(ad): 1637 start_cmd = ("am start-foreground-service -a com.android.pixellogger" 1638 ".service.logging.LoggingService.ACTION_START_LOGGING " 1639 "-e intent_key_cfg_path '%s' " 1640 "--ei intent_key_max_log_size_mb %d " 1641 "--ei intent_key_max_number_of_files %d" % ( 1642 default_gnss_cfg, max_log_size_mb, max_number_of_files)) 1643 else: 1644 start_cmd = ("am startservice -a com.android.pixellogger." 1645 "service.logging.LoggingService.ACTION_START_LOGGING " 1646 "-e intent_logger brcm_gps") 1647 for attempt in range(retries): 1648 begin_time = get_current_epoch_time() 1649 ad.log.info("Start Pixel Logger. - Attempt %d" % (attempt + 1)) 1650 ad.adb.shell(start_cmd) 1651 while get_current_epoch_time() - begin_time <= start_timeout_sec * 1000: 1652 if not ad.is_adb_logcat_on: 1653 ad.start_adb_logcat() 1654 if check_chipset_vendor_by_qualcomm(ad): 1655 start_result = ad.search_logcat("Start logging", begin_time) 1656 else: 1657 start_result = ad.search_logcat("startRecording", begin_time) 1658 if start_result: 1659 ad.log.info("Pixel Logger starts recording successfully.") 1660 return True 1661 ad.force_stop_apk("com.android.pixellogger") 1662 else: 1663 ad.log.warn("Pixel Logger fails to start recording in %d seconds " 1664 "within %d attempts." % (start_timeout_sec, retries)) 1665 1666 1667def stop_pixel_logger(ad): 1668 """adb to stop pixel logger for GNSS logging. 1669 1670 Args: 1671 ad: An AndroidDevice object. 1672 """ 1673 retries = 3 1674 stop_timeout_sec = 300 1675 if check_chipset_vendor_by_qualcomm(ad): 1676 stop_cmd = ("am start-foreground-service -a com.android.pixellogger" 1677 ".service.logging.LoggingService.ACTION_STOP_LOGGING") 1678 else: 1679 stop_cmd = ("am startservice -a com.android.pixellogger." 1680 "service.logging.LoggingService.ACTION_STOP_LOGGING " 1681 "-e intent_logger brcm_gps") 1682 for attempt in range(retries): 1683 begin_time = get_current_epoch_time() 1684 ad.log.info("Stop Pixel Logger. - Attempt %d" % (attempt + 1)) 1685 ad.adb.shell(stop_cmd) 1686 while get_current_epoch_time() - begin_time <= stop_timeout_sec * 1000: 1687 if not ad.is_adb_logcat_on: 1688 ad.start_adb_logcat() 1689 stop_result = ad.search_logcat( 1690 "LoggingService: Stopping service", begin_time) 1691 if stop_result: 1692 ad.log.info("Pixel Logger stops successfully.") 1693 return True 1694 ad.force_stop_apk("com.android.pixellogger") 1695 else: 1696 ad.log.warn("Pixel Logger fails to stop in %d seconds within %d " 1697 "attempts." % (stop_timeout_sec, retries)) 1698 1699 1700def launch_eecoexer(ad): 1701 """adb to stop pixel logger for GNSS logging. 1702 1703 Args: 1704 ad: An AndroidDevice object. 1705 """ 1706 launch_cmd = ("am start -a android.intent.action.MAIN -n" 1707 "com.google.eecoexer" 1708 "/.MainActivity") 1709 ad.adb.shell(launch_cmd) 1710 try: 1711 ad.log.info("Launch EEcoexer.") 1712 except Exception as e: 1713 ad.log.error(e) 1714 raise signals.TestError("Failed to launch EEcoexer.") 1715 1716 1717def excute_eecoexer_function(ad, eecoexer_args): 1718 """adb to stop pixel logger for GNSS logging. 1719 1720 Args: 1721 ad: An AndroidDevice object. 1722 eecoexer_args: EEcoexer function arguments 1723 """ 1724 enqueue_cmd = ("am broadcast -a com.google.eecoexer.action.LISTENER" 1725 " --es sms_body ENQUEUE,{}".format(eecoexer_args)) 1726 exe_cmd = ("am broadcast -a com.google.eecoexer.action.LISTENER" 1727 " --es sms_body EXECUTE") 1728 ad.log.info("EEcoexer Add Enqueue: {}".format(eecoexer_args)) 1729 ad.adb.shell(enqueue_cmd) 1730 ad.log.info("EEcoexer Excute.") 1731 ad.adb.shell(exe_cmd) 1732 1733 1734def restart_gps_daemons(ad): 1735 """Restart GPS daemons by killing services of gpsd, lhd and scd. 1736 1737 Args: 1738 ad: An AndroidDevice object. 1739 """ 1740 gps_daemons_list = ["gpsd", "lhd", "scd"] 1741 ad.root_adb() 1742 for service in gps_daemons_list: 1743 begin_time = get_current_epoch_time() 1744 time.sleep(3) 1745 ad.log.info("Kill GPS daemon \"%s\"" % service) 1746 ad.adb.shell("killall %s" % service) 1747 # Wait 3 seconds for daemons and services to start. 1748 time.sleep(3) 1749 restart_services = ad.search_logcat("starting service", begin_time) 1750 for restart_service in restart_services: 1751 if service in restart_service["log_message"]: 1752 ad.log.info(restart_service["log_message"]) 1753 ad.log.info( 1754 "GPS daemon \"%s\" restarts successfully." % service) 1755 break 1756 else: 1757 raise signals.TestError("Unable to restart \"%s\"" % service) 1758