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 25import zipfile 26from collections import namedtuple 27from datetime import datetime 28from xml.etree import ElementTree 29 30from acts import utils 31from acts import asserts 32from acts import signals 33from acts.libs.proc import job 34from acts.controllers.android_device import list_adb_devices 35from acts.controllers.android_device import list_fastboot_devices 36from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH 37from acts.controllers.android_device import SL4A_APK_NAME 38from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 39from acts_contrib.test_utils.tel import tel_logging_utils as tlutils 40from acts_contrib.test_utils.tel import tel_test_utils as tutils 41from acts_contrib.test_utils.instrumentation.device.command.instrumentation_command_builder import InstrumentationCommandBuilder 42from acts_contrib.test_utils.instrumentation.device.command.instrumentation_command_builder import InstrumentationTestCommandBuilder 43from acts.utils import get_current_epoch_time 44from acts.utils import epoch_to_human_time 45from acts_contrib.test_utils.gnss.gnss_defines import BCM_GPS_XML_PATH 46from acts_contrib.test_utils.gnss.gnss_defines import BCM_NVME_STO_PATH 47 48WifiEnums = wutils.WifiEnums 49PULL_TIMEOUT = 300 50GNSSSTATUS_LOG_PATH = ( 51 "/storage/emulated/0/Android/data/com.android.gpstool/files/") 52QXDM_MASKS = ["GPS.cfg", "GPS-general.cfg", "default.cfg"] 53TTFF_REPORT = namedtuple( 54 "TTFF_REPORT", "utc_time ttff_loop ttff_sec ttff_pe ttff_ant_cn " 55 "ttff_base_cn ttff_haccu") 56TRACK_REPORT = namedtuple( 57 "TRACK_REPORT", "l5flag pe ant_top4cn ant_cn base_top4cn base_cn") 58LOCAL_PROP_FILE_CONTENTS = """\ 59log.tag.LocationManagerService=VERBOSE 60log.tag.GnssLocationProvider=VERBOSE 61log.tag.GnssMeasurementsProvider=VERBOSE 62log.tag.GpsNetInitiatedHandler=VERBOSE 63log.tag.GnssNetInitiatedHandler=VERBOSE 64log.tag.GnssNetworkConnectivityHandler=VERBOSE 65log.tag.ConnectivityService=VERBOSE 66log.tag.ConnectivityManager=VERBOSE 67log.tag.GnssVisibilityControl=VERBOSE 68log.tag.NtpTimeHelper=VERBOSE 69log.tag.NtpTrustedTime=VERBOSE 70log.tag.GnssPsdsDownloader=VERBOSE 71log.tag.Gnss=VERBOSE 72log.tag.GnssConfiguration=VERBOSE""" 73TEST_PACKAGE_NAME = "com.google.android.apps.maps" 74LOCATION_PERMISSIONS = [ 75 "android.permission.ACCESS_FINE_LOCATION", 76 "android.permission.ACCESS_COARSE_LOCATION" 77] 78GNSSTOOL_PACKAGE_NAME = "com.android.gpstool" 79GNSSTOOL_PERMISSIONS = [ 80 "android.permission.ACCESS_FINE_LOCATION", 81 "android.permission.READ_EXTERNAL_STORAGE", 82 "android.permission.ACCESS_COARSE_LOCATION", 83 "android.permission.CALL_PHONE", 84 "android.permission.WRITE_CONTACTS", 85 "android.permission.CAMERA", 86 "android.permission.WRITE_EXTERNAL_STORAGE", 87 "android.permission.READ_CONTACTS", 88 "android.permission.ACCESS_BACKGROUND_LOCATION" 89] 90DISABLE_LTO_FILE_CONTENTS = """\ 91LONGTERM_PSDS_SERVER_1="http://" 92LONGTERM_PSDS_SERVER_2="http://" 93LONGTERM_PSDS_SERVER_3="http://" 94NORMAL_PSDS_SERVER="http://" 95REALTIME_PSDS_SERVER="http://" 96""" 97DISABLE_LTO_FILE_CONTENTS_R = """\ 98XTRA_SERVER_1="http://" 99XTRA_SERVER_2="http://" 100XTRA_SERVER_3="http://" 101""" 102 103 104class GnssTestUtilsError(Exception): 105 pass 106 107 108def remount_device(ad): 109 """Remount device file system to read and write. 110 111 Args: 112 ad: An AndroidDevice object. 113 """ 114 for retries in range(5): 115 ad.root_adb() 116 if ad.adb.getprop("ro.boot.veritymode") == "enforcing": 117 ad.adb.disable_verity() 118 reboot(ad) 119 remount_result = ad.adb.remount() 120 ad.log.info("Attempt %d - %s" % (retries + 1, remount_result)) 121 if "remount succeeded" in remount_result: 122 break 123 124 125def reboot(ad): 126 """Reboot device and check if mobile data is available. 127 128 Args: 129 ad: An AndroidDevice object. 130 """ 131 ad.log.info("Reboot device to make changes take effect.") 132 ad.reboot() 133 ad.unlock_screen(password=None) 134 if not is_mobile_data_on(ad): 135 set_mobile_data(ad, True) 136 utils.sync_device_time(ad) 137 138 139def enable_gnss_verbose_logging(ad): 140 """Enable GNSS VERBOSE Logging and persistent logcat. 141 142 Args: 143 ad: An AndroidDevice object. 144 """ 145 remount_device(ad) 146 ad.log.info("Enable GNSS VERBOSE Logging and persistent logcat.") 147 if check_chipset_vendor_by_qualcomm(ad): 148 ad.adb.shell("echo -e '\nDEBUG_LEVEL = 5' >> /vendor/etc/gps.conf") 149 else: 150 ad.adb.shell("echo LogEnabled=true >> /data/vendor/gps/libgps.conf") 151 ad.adb.shell("chown gps.system /data/vendor/gps/libgps.conf") 152 ad.adb.shell("echo %r >> /data/local.prop" % LOCAL_PROP_FILE_CONTENTS) 153 ad.adb.shell("chmod 644 /data/local.prop") 154 ad.adb.shell("setprop persist.logd.logpersistd.size 20000") 155 ad.adb.shell("setprop persist.logd.size 16777216") 156 ad.adb.shell("setprop persist.vendor.radio.adb_log_on 1") 157 ad.adb.shell("setprop persist.logd.logpersistd logcatd") 158 ad.adb.shell("setprop log.tag.copresGcore VERBOSE") 159 ad.adb.shell("sync") 160 161 162def get_am_flags(value): 163 """Returns the (value, type) flags for a given python value.""" 164 if type(value) is bool: 165 return str(value).lower(), 'boolean' 166 elif type(value) is str: 167 return value, 'string' 168 raise ValueError("%s should be either 'boolean' or 'string'" % value) 169 170 171def enable_compact_and_particle_fusion_log(ad): 172 """Enable CompactLog, FLP particle fusion log and disable gms 173 location-based quake monitoring. 174 175 Args: 176 ad: An AndroidDevice object. 177 """ 178 ad.root_adb() 179 ad.log.info("Enable FLP flags and Disable GMS location-based quake " 180 "monitoring.") 181 overrides = { 182 'compact_log_enabled': True, 183 'flp_use_particle_fusion': True, 184 'flp_particle_fusion_extended_bug_report': True, 185 'flp_event_log_size': '86400', 186 'proks_config': '28', 187 'flp_particle_fusion_bug_report_window_sec': '86400', 188 'flp_particle_fusion_bug_report_max_buffer_size': '86400', 189 'seismic_data_collection': False, 190 'Ealert__enable': False, 191 } 192 for flag, python_value in overrides.items(): 193 value, type = get_am_flags(python_value) 194 cmd = ("am broadcast -a com.google.android.gms.phenotype.FLAG_OVERRIDE " 195 "--es package com.google.android.location --es user \* " 196 "--esa flags %s --esa values %s --esa types %s " 197 "com.google.android.gms" % (flag, value, type)) 198 ad.adb.shell(cmd, ignore_status=True) 199 ad.adb.shell("am force-stop com.google.android.gms") 200 ad.adb.shell("am broadcast -a com.google.android.gms.INITIALIZE") 201 202 203def disable_xtra_throttle(ad): 204 """Disable XTRA throttle will have no limit to download XTRA data. 205 206 Args: 207 ad: An AndroidDevice object. 208 """ 209 remount_device(ad) 210 ad.log.info("Disable XTRA Throttle.") 211 ad.adb.shell("echo -e '\nXTRA_TEST_ENABLED=1' >> /vendor/etc/gps.conf") 212 ad.adb.shell("echo -e '\nXTRA_THROTTLE_ENABLED=0' >> /vendor/etc/gps.conf") 213 214 215def enable_supl_mode(ad): 216 """Enable SUPL back on for next test item. 217 218 Args: 219 ad: An AndroidDevice object. 220 """ 221 remount_device(ad) 222 ad.log.info("Enable SUPL mode.") 223 ad.adb.shell("echo -e '\nSUPL_MODE=1' >> /etc/gps_debug.conf") 224 if is_device_wearable(ad): 225 lto_mode_wearable(ad, True) 226 elif not check_chipset_vendor_by_qualcomm(ad): 227 lto_mode(ad, True) 228 else: 229 reboot(ad) 230 231 232def disable_supl_mode(ad): 233 """Kill SUPL to test XTRA/LTO only test item. 234 235 Args: 236 ad: An AndroidDevice object. 237 """ 238 remount_device(ad) 239 ad.log.info("Disable SUPL mode.") 240 ad.adb.shell("echo -e '\nSUPL_MODE=0' >> /etc/gps_debug.conf") 241 if is_device_wearable(ad): 242 lto_mode_wearable(ad, True) 243 elif not check_chipset_vendor_by_qualcomm(ad): 244 lto_mode(ad, True) 245 else: 246 reboot(ad) 247 248 249def kill_xtra_daemon(ad): 250 """Kill XTRA daemon to test SUPL only test item. 251 252 Args: 253 ad: An AndroidDevice object. 254 """ 255 ad.root_adb() 256 if is_device_wearable(ad): 257 lto_mode_wearable(ad, False) 258 elif check_chipset_vendor_by_qualcomm(ad): 259 ad.log.info("Disable XTRA-daemon until next reboot.") 260 ad.adb.shell("killall xtra-daemon", ignore_status=True) 261 else: 262 lto_mode(ad, False) 263 264 265def disable_private_dns_mode(ad): 266 """Due to b/118365122, it's better to disable private DNS mode while 267 testing. 8.8.8.8 private dns sever is unstable now, sometimes server 268 will not response dns query suddenly. 269 270 Args: 271 ad: An AndroidDevice object. 272 """ 273 tutils.get_operator_name(ad.log, ad, subId=None) 274 if ad.adb.shell("settings get global private_dns_mode") != "off": 275 ad.log.info("Disable Private DNS mode.") 276 ad.adb.shell("settings put global private_dns_mode off") 277 278 279def _init_device(ad): 280 """Init GNSS test devices. 281 282 Args: 283 ad: An AndroidDevice object. 284 """ 285 enable_gnss_verbose_logging(ad) 286 enable_compact_and_particle_fusion_log(ad) 287 prepare_gps_overlay(ad) 288 if check_chipset_vendor_by_qualcomm(ad): 289 disable_xtra_throttle(ad) 290 enable_supl_mode(ad) 291 if is_device_wearable(ad): 292 ad.adb.shell("settings put global stay_on_while_plugged_in 7") 293 else: 294 ad.adb.shell("settings put system screen_off_timeout 1800000") 295 wutils.wifi_toggle_state(ad, False) 296 ad.log.info("Setting Bluetooth state to False") 297 ad.droid.bluetoothToggleState(False) 298 check_location_service(ad) 299 set_wifi_and_bt_scanning(ad, True) 300 disable_private_dns_mode(ad) 301 reboot(ad) 302 init_gtw_gpstool(ad) 303 if not is_mobile_data_on(ad): 304 set_mobile_data(ad, True) 305 306 307def prepare_gps_overlay(ad): 308 """Set pixellogger gps log mask to 309 resolve gps logs unreplayable from brcm vendor 310 """ 311 if not check_chipset_vendor_by_qualcomm(ad): 312 overlay_file = "/data/vendor/gps/overlay/gps_overlay.xml" 313 xml_file = generate_gps_overlay_xml(ad) 314 try: 315 ad.log.info("Push gps_overlay to device") 316 ad.adb.push(xml_file, overlay_file) 317 ad.adb.shell(f"chmod 777 {overlay_file}") 318 finally: 319 xml_folder = os.path.abspath(os.path.join(xml_file, os.pardir)) 320 shutil.rmtree(xml_folder) 321 322 323def generate_gps_overlay_xml(ad): 324 """For r11 devices, the overlay setting is 'Replayable default' 325 For other brcm devices, the setting is 'Replayable debug' 326 327 Returns: 328 path to the xml file 329 """ 330 root_attrib = { 331 "xmlns": "http://www.glpals.com/", 332 "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance", 333 "xsi:schemaLocation": "http://www.glpals.com/ glconfig.xsd", 334 } 335 sub_attrib = {"EnableOnChipStopNotification": "true"} 336 if not is_device_wearable(ad): 337 sub_attrib["LogPriMask"] = "LOG_DEBUG" 338 sub_attrib["LogFacMask"] = "LOG_GLLIO | LOG_GLLAPI | LOG_NMEA | LOG_RAWDATA" 339 sub_attrib["OnChipLogPriMask"] = "LOG_DEBUG" 340 sub_attrib["OnChipLogFacMask"] = "LOG_GLLIO | LOG_GLLAPI | LOG_NMEA | LOG_RAWDATA" 341 342 temp_path = tempfile.mkdtemp() 343 xml_file = os.path.join(temp_path, "gps_overlay.xml") 344 345 root = ElementTree.Element('glgps') 346 for key, value in root_attrib.items(): 347 root.attrib[key] = value 348 349 ad.log.debug("Sub attrib is %s", sub_attrib) 350 351 sub = ElementTree.SubElement(root, 'gll') 352 for key, value in sub_attrib.items(): 353 sub.attrib[key] = value 354 355 xml = ElementTree.ElementTree(root) 356 xml.write(xml_file, xml_declaration=True, encoding="utf-8", method="xml") 357 return xml_file 358 359 360def connect_to_wifi_network(ad, network): 361 """Connection logic for open and psk wifi networks. 362 363 Args: 364 ad: An AndroidDevice object. 365 network: Dictionary with network info. 366 """ 367 SSID = network[WifiEnums.SSID_KEY] 368 ad.ed.clear_all_events() 369 wutils.reset_wifi(ad) 370 wutils.start_wifi_connection_scan_and_ensure_network_found(ad, SSID) 371 wutils.wifi_connect(ad, network, num_of_tries=5) 372 373 374def set_wifi_and_bt_scanning(ad, state=True): 375 """Set Wi-Fi and Bluetooth scanning on/off in Settings -> Location 376 377 Args: 378 ad: An AndroidDevice object. 379 state: True to turn on "Wi-Fi and Bluetooth scanning". 380 False to turn off "Wi-Fi and Bluetooth scanning". 381 """ 382 ad.root_adb() 383 if state: 384 ad.adb.shell("settings put global wifi_scan_always_enabled 1") 385 ad.adb.shell("settings put global ble_scan_always_enabled 1") 386 ad.log.info("Wi-Fi and Bluetooth scanning are enabled") 387 else: 388 ad.adb.shell("settings put global wifi_scan_always_enabled 0") 389 ad.adb.shell("settings put global ble_scan_always_enabled 0") 390 ad.log.info("Wi-Fi and Bluetooth scanning are disabled") 391 392 393def check_location_service(ad): 394 """Set location service on. 395 Verify if location service is available. 396 397 Args: 398 ad: An AndroidDevice object. 399 """ 400 remount_device(ad) 401 utils.set_location_service(ad, True) 402 ad.adb.shell("cmd location set-location-enabled true") 403 location_mode = int(ad.adb.shell("settings get secure location_mode")) 404 ad.log.info("Current Location Mode >> %d" % location_mode) 405 if location_mode != 3: 406 raise signals.TestError("Failed to turn Location on") 407 408 409def clear_logd_gnss_qxdm_log(ad): 410 """Clear /data/misc/logd, 411 /storage/emulated/0/Android/data/com.android.gpstool/files and 412 /data/vendor/radio/diag_logs/logs from previous test item then reboot. 413 414 Args: 415 ad: An AndroidDevice object. 416 """ 417 remount_device(ad) 418 ad.log.info("Clear Logd, GNSS and PixelLogger Log from previous test item.") 419 ad.adb.shell("rm -rf /data/misc/logd", ignore_status=True) 420 ad.adb.shell( 421 'find %s -name "*.txt" -type f -delete' % GNSSSTATUS_LOG_PATH, 422 ignore_status=True) 423 if check_chipset_vendor_by_qualcomm(ad): 424 diag_logs = ( 425 "/sdcard/Android/data/com.android.pixellogger/files/logs/diag_logs") 426 ad.adb.shell("rm -rf %s" % diag_logs, ignore_status=True) 427 output_path = posixpath.join(DEFAULT_QXDM_LOG_PATH, "logs") 428 else: 429 output_path = ("/sdcard/Android/data/com.android.pixellogger/files" 430 "/logs/gps/") 431 ad.adb.shell("rm -rf %s" % output_path, ignore_status=True) 432 reboot(ad) 433 434 435def get_gnss_qxdm_log(ad, qdb_path=None): 436 """Get /storage/emulated/0/Android/data/com.android.gpstool/files and 437 /data/vendor/radio/diag_logs/logs for test item. 438 439 Args: 440 ad: An AndroidDevice object. 441 qdb_path: The path of qdsp6m.qdb on different projects. 442 """ 443 log_path = ad.device_log_path 444 os.makedirs(log_path, exist_ok=True) 445 gnss_log_name = "gnssstatus_log_%s_%s" % (ad.model, ad.serial) 446 gnss_log_path = posixpath.join(log_path, gnss_log_name) 447 os.makedirs(gnss_log_path, exist_ok=True) 448 ad.log.info("Pull GnssStatus Log to %s" % gnss_log_path) 449 ad.adb.pull("%s %s" % (GNSSSTATUS_LOG_PATH + ".", gnss_log_path), 450 timeout=PULL_TIMEOUT, ignore_status=True) 451 shutil.make_archive(gnss_log_path, "zip", gnss_log_path) 452 shutil.rmtree(gnss_log_path, ignore_errors=True) 453 if check_chipset_vendor_by_qualcomm(ad): 454 output_path = ( 455 "/sdcard/Android/data/com.android.pixellogger/files/logs/" 456 "diag_logs/.") 457 else: 458 output_path = ( 459 "/sdcard/Android/data/com.android.pixellogger/files/logs/gps/.") 460 qxdm_log_name = "PixelLogger_%s_%s" % (ad.model, ad.serial) 461 qxdm_log_path = posixpath.join(log_path, qxdm_log_name) 462 os.makedirs(qxdm_log_path, exist_ok=True) 463 ad.log.info("Pull PixelLogger Log %s to %s" % (output_path, 464 qxdm_log_path)) 465 ad.adb.pull("%s %s" % (output_path, qxdm_log_path), 466 timeout=PULL_TIMEOUT, ignore_status=True) 467 if check_chipset_vendor_by_qualcomm(ad): 468 for path in qdb_path: 469 output = ad.adb.pull("%s %s" % (path, qxdm_log_path), 470 timeout=PULL_TIMEOUT, ignore_status=True) 471 if "No such file or directory" in output: 472 continue 473 break 474 shutil.make_archive(qxdm_log_path, "zip", qxdm_log_path) 475 shutil.rmtree(qxdm_log_path, ignore_errors=True) 476 477 478def set_mobile_data(ad, state): 479 """Set mobile data on or off and check mobile data state. 480 481 Args: 482 ad: An AndroidDevice object. 483 state: True to enable mobile data. False to disable mobile data. 484 """ 485 ad.root_adb() 486 if state: 487 if is_device_wearable(ad): 488 ad.log.info("Enable wearable mobile data.") 489 ad.adb.shell("settings put global cell_on 1") 490 else: 491 ad.log.info("Enable mobile data via RPC call.") 492 ad.droid.telephonyToggleDataConnection(True) 493 else: 494 if is_device_wearable(ad): 495 ad.log.info("Disable wearable mobile data.") 496 ad.adb.shell("settings put global cell_on 0") 497 else: 498 ad.log.info("Disable mobile data via RPC call.") 499 ad.droid.telephonyToggleDataConnection(False) 500 time.sleep(5) 501 ret_val = is_mobile_data_on(ad) 502 if state and ret_val: 503 ad.log.info("Mobile data is enabled and set to %s" % ret_val) 504 elif not state and not ret_val: 505 ad.log.info("Mobile data is disabled and set to %s" % ret_val) 506 else: 507 ad.log.error("Mobile data is at unknown state and set to %s" % ret_val) 508 509 510def gnss_trigger_modem_ssr_by_adb(ad, dwelltime=60): 511 """Trigger modem SSR crash by adb and verify if modem crash and recover 512 successfully. 513 514 Args: 515 ad: An AndroidDevice object. 516 dwelltime: Waiting time for modem reset. Default is 60 seconds. 517 518 Returns: 519 True if success. 520 False if failed. 521 """ 522 begin_time = get_current_epoch_time() 523 ad.root_adb() 524 cmds = ("echo restart > /sys/kernel/debug/msm_subsys/modem", 525 r"echo 'at+cfun=1,1\r' > /dev/at_mdm0") 526 for cmd in cmds: 527 ad.log.info("Triggering modem SSR crash by %s" % cmd) 528 output = ad.adb.shell(cmd, ignore_status=True) 529 if "No such file or directory" in output: 530 continue 531 break 532 time.sleep(dwelltime) 533 ad.send_keycode("HOME") 534 logcat_results = ad.search_logcat("SSRObserver", begin_time) 535 if logcat_results: 536 for ssr in logcat_results: 537 if "mSubsystem='modem', mCrashReason" in ssr["log_message"]: 538 ad.log.debug(ssr["log_message"]) 539 ad.log.info("Triggering modem SSR crash successfully.") 540 return True 541 raise signals.TestError("Failed to trigger modem SSR crash") 542 raise signals.TestError("No SSRObserver found in logcat") 543 544 545def gnss_trigger_modem_ssr_by_mds(ad, dwelltime=60): 546 """Trigger modem SSR crash by mds tool and verify if modem crash and recover 547 successfully. 548 549 Args: 550 ad: An AndroidDevice object. 551 dwelltime: Waiting time for modem reset. Default is 60 seconds. 552 """ 553 mds_check = ad.adb.shell("pm path com.google.mdstest") 554 if not mds_check: 555 raise signals.TestError("MDS Tool is not properly installed.") 556 ad.root_adb() 557 cmd = ('am instrument -w -e request "4b 25 03 00" ' 558 '"com.google.mdstest/com.google.mdstest.instrument' 559 '.ModemCommandInstrumentation"') 560 ad.log.info("Triggering modem SSR crash by MDS") 561 output = ad.adb.shell(cmd, ignore_status=True) 562 ad.log.debug(output) 563 time.sleep(dwelltime) 564 ad.send_keycode("HOME") 565 if "SUCCESS" in output: 566 ad.log.info("Triggering modem SSR crash by MDS successfully.") 567 else: 568 raise signals.TestError( 569 "Failed to trigger modem SSR crash by MDS. \n%s" % output) 570 571 572def check_xtra_download(ad, begin_time): 573 """Verify XTRA download success log message in logcat. 574 575 Args: 576 ad: An AndroidDevice object. 577 begin_time: test begin time 578 579 Returns: 580 True: xtra_download if XTRA downloaded and injected successfully 581 otherwise return False. 582 """ 583 ad.send_keycode("HOME") 584 if check_chipset_vendor_by_qualcomm(ad): 585 xtra_results = ad.search_logcat("XTRA download success. " 586 "inject data into modem", begin_time) 587 if xtra_results: 588 ad.log.debug("%s" % xtra_results[-1]["log_message"]) 589 ad.log.info("XTRA downloaded and injected successfully.") 590 return True 591 ad.log.error("XTRA downloaded FAIL.") 592 elif is_device_wearable(ad): 593 lto_results = ad.adb.shell("ls -al /data/vendor/gps/lto*") 594 if "lto2.dat" in lto_results: 595 ad.log.info("LTO downloaded and injected successfully.") 596 return True 597 else: 598 lto_results = ad.search_logcat("GnssPsdsAidl: injectPsdsData: " 599 "psdsType: 1", begin_time) 600 if lto_results: 601 ad.log.debug("%s" % lto_results[-1]["log_message"]) 602 ad.log.info("LTO downloaded and injected successfully.") 603 return True 604 ad.log.error("LTO downloaded and inject FAIL.") 605 return False 606 607 608def pull_package_apk(ad, package_name): 609 """Pull apk of given package_name from device. 610 611 Args: 612 ad: An AndroidDevice object. 613 package_name: Package name of apk to pull. 614 615 Returns: 616 The temp path of pulled apk. 617 """ 618 out = ad.adb.shell("pm path %s" % package_name) 619 result = re.search(r"package:(.*)", out) 620 if not result: 621 raise signals.TestError("Couldn't find apk of %s" % package_name) 622 else: 623 apk_source = result.group(1) 624 ad.log.info("Get apk of %s from %s" % (package_name, apk_source)) 625 apk_path = tempfile.mkdtemp() 626 ad.pull_files([apk_source], apk_path) 627 return apk_path 628 629 630def pull_gnss_cfg_file(ad, file): 631 """Pull given gnss cfg file from device. 632 633 Args: 634 ad: An AndroidDevice object. 635 file: CFG file in device to pull. 636 637 Returns: 638 The temp path of pulled gnss cfg file in host. 639 """ 640 ad.root_adb() 641 host_dest = tempfile.mkdtemp() 642 ad.pull_files(file, host_dest) 643 for path_key in os.listdir(host_dest): 644 if fnmatch.fnmatch(path_key, "*.cfg"): 645 gnss_cfg_file = os.path.join(host_dest, path_key) 646 break 647 else: 648 raise signals.TestError("No cfg file is found in %s" % host_dest) 649 return gnss_cfg_file 650 651 652def reinstall_package_apk(ad, package_name, apk_path): 653 """Reinstall apk of given package_name. 654 655 Args: 656 ad: An AndroidDevice object. 657 package_name: Package name of apk. 658 apk_path: The temp path of pulled apk. 659 """ 660 for path_key in os.listdir(apk_path): 661 if fnmatch.fnmatch(path_key, "*.apk"): 662 apk_path = os.path.join(apk_path, path_key) 663 break 664 else: 665 raise signals.TestError("No apk is found in %s" % apk_path) 666 ad.log.info("Re-install %s with path: %s" % (package_name, apk_path)) 667 ad.adb.shell("settings put global verifier_verify_adb_installs 0") 668 ad.adb.install("-r -d -g --user 0 %s" % apk_path) 669 package_check = ad.adb.shell("pm path %s" % package_name) 670 if not package_check: 671 tutils.abort_all_tests( 672 ad.log, "%s is not properly re-installed." % package_name) 673 ad.log.info("%s is re-installed successfully." % package_name) 674 675 676def init_gtw_gpstool(ad): 677 """Init GTW_GPSTool apk. 678 679 Args: 680 ad: An AndroidDevice object. 681 """ 682 remount_device(ad) 683 gpstool_path = pull_package_apk(ad, "com.android.gpstool") 684 reinstall_package_apk(ad, "com.android.gpstool", gpstool_path) 685 shutil.rmtree(gpstool_path, ignore_errors=True) 686 687 688def fastboot_factory_reset(ad, state=True): 689 """Factory reset the device in fastboot mode. 690 Pull sl4a apk from device. Terminate all sl4a sessions, 691 Reboot the device to bootloader, 692 factory reset the device by fastboot. 693 Reboot the device. wait for device to complete booting 694 Re-install and start an sl4a session. 695 696 Args: 697 ad: An AndroidDevice object. 698 State: True for exit_setup_wizard, False for not exit_setup_wizard. 699 700 Returns: 701 True if factory reset process complete. 702 """ 703 status = True 704 mds_path = "" 705 gnss_cfg_file = "" 706 gnss_cfg_path = "/vendor/etc/mdlog" 707 default_gnss_cfg = "/vendor/etc/mdlog/DEFAULT+SECURITY+FULLDPL+GPS.cfg" 708 sl4a_path = pull_package_apk(ad, SL4A_APK_NAME) 709 gpstool_path = pull_package_apk(ad, "com.android.gpstool") 710 if check_chipset_vendor_by_qualcomm(ad): 711 mds_path = pull_package_apk(ad, "com.google.mdstest") 712 gnss_cfg_file = pull_gnss_cfg_file(ad, default_gnss_cfg) 713 stop_pixel_logger(ad) 714 ad.stop_services() 715 for i in range(1, 4): 716 try: 717 if ad.serial in list_adb_devices(): 718 ad.log.info("Reboot to bootloader") 719 ad.adb.reboot("bootloader", ignore_status=True) 720 time.sleep(10) 721 if ad.serial in list_fastboot_devices(): 722 ad.log.info("Factory reset in fastboot") 723 ad.fastboot._w(timeout=300, ignore_status=True) 724 time.sleep(30) 725 ad.log.info("Reboot in fastboot") 726 ad.fastboot.reboot() 727 ad.wait_for_boot_completion() 728 ad.root_adb() 729 if ad.skip_sl4a: 730 break 731 if ad.is_sl4a_installed(): 732 break 733 if is_device_wearable(ad): 734 ad.log.info("Wait 5 mins for wearable projects system busy time.") 735 time.sleep(300) 736 reinstall_package_apk(ad, SL4A_APK_NAME, sl4a_path) 737 reinstall_package_apk(ad, "com.android.gpstool", gpstool_path) 738 if check_chipset_vendor_by_qualcomm(ad): 739 reinstall_package_apk(ad, "com.google.mdstest", mds_path) 740 ad.push_system_file(gnss_cfg_file, gnss_cfg_path) 741 time.sleep(10) 742 break 743 except Exception as e: 744 ad.log.error(e) 745 if i == attempts: 746 tutils.abort_all_tests(ad.log, str(e)) 747 time.sleep(5) 748 try: 749 ad.start_adb_logcat() 750 except Exception as e: 751 ad.log.error(e) 752 if state: 753 ad.exit_setup_wizard() 754 if ad.skip_sl4a: 755 return status 756 tutils.bring_up_sl4a(ad) 757 for path in [sl4a_path, gpstool_path, mds_path, gnss_cfg_file]: 758 shutil.rmtree(path, ignore_errors=True) 759 return status 760 761 762def clear_aiding_data_by_gtw_gpstool(ad): 763 """Launch GTW GPSTool and Clear all GNSS aiding data. 764 Wait 5 seconds for GTW GPStool to clear all GNSS aiding 765 data properly. 766 767 Args: 768 ad: An AndroidDevice object. 769 """ 770 if not check_chipset_vendor_by_qualcomm(ad): 771 delete_lto_file(ad) 772 ad.log.info("Launch GTW GPSTool and Clear all GNSS aiding data") 773 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode clear") 774 time.sleep(10) 775 776 777def start_gnss_by_gtw_gpstool(ad, 778 state, 779 type="gnss", 780 bgdisplay=False, 781 freq=0, 782 lowpower=False, 783 meas=False): 784 """Start or stop GNSS on GTW_GPSTool. 785 786 Args: 787 ad: An AndroidDevice object. 788 state: True to start GNSS. False to Stop GNSS. 789 type: Different API for location fix. Use gnss/flp/nmea 790 bgdisplay: true to run GTW when Display off. false to not run GTW when 791 Display off. 792 freq: An integer to set location update frequency. 793 meas: A Boolean to set GNSS measurement registration. 794 lowpower: A boolean to set GNSS LowPowerMode. 795 """ 796 cmd = "am start -S -n com.android.gpstool/.GPSTool --es mode gps" 797 if not state: 798 ad.log.info("Stop %s on GTW_GPSTool." % type) 799 cmd = "am broadcast -a com.android.gpstool.stop_gps_action" 800 else: 801 options = ("--es type {} --ei freq {} --ez BG {} --ez meas {} --ez " 802 "lowpower {}").format(type, freq, bgdisplay, meas, lowpower) 803 cmd = cmd + " " + options 804 ad.adb.shell(cmd) 805 time.sleep(3) 806 807 808def process_gnss_by_gtw_gpstool(ad, 809 criteria, 810 type="gnss", 811 clear_data=True, 812 meas_flag=False): 813 """Launch GTW GPSTool and Clear all GNSS aiding data 814 Start GNSS tracking on GTW_GPSTool. 815 816 Args: 817 ad: An AndroidDevice object. 818 criteria: Criteria for current test item. 819 type: Different API for location fix. Use gnss/flp/nmea 820 clear_data: True to clear GNSS aiding data. False is not to. Default 821 set to True. 822 meas_flag: True to enable GnssMeasurement. False is not to. Default 823 set to False. 824 825 Returns: 826 True: First fix TTFF are within criteria. 827 False: First fix TTFF exceed criteria. 828 """ 829 retries = 3 830 for i in range(retries): 831 if not ad.is_adb_logcat_on: 832 ad.start_adb_logcat() 833 check_adblog_functionality(ad) 834 check_location_runtime_permissions( 835 ad, GNSSTOOL_PACKAGE_NAME, GNSSTOOL_PERMISSIONS) 836 begin_time = get_current_epoch_time() 837 if clear_data: 838 clear_aiding_data_by_gtw_gpstool(ad) 839 ad.log.info("Start %s on GTW_GPSTool - attempt %d" % (type.upper(), 840 i+1)) 841 start_gnss_by_gtw_gpstool(ad, state=True, type=type, meas=meas_flag) 842 for _ in range(10 + criteria): 843 logcat_results = ad.search_logcat("First fixed", begin_time) 844 if logcat_results: 845 ad.log.debug(logcat_results[-1]["log_message"]) 846 first_fixed = int(logcat_results[-1]["log_message"].split()[-1]) 847 ad.log.info("%s First fixed = %.3f seconds" % 848 (type.upper(), first_fixed/1000)) 849 if (first_fixed/1000) <= criteria: 850 return True 851 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 852 raise signals.TestFailure("Fail to get %s location fixed " 853 "within %d seconds criteria." 854 % (type.upper(), criteria)) 855 time.sleep(1) 856 check_current_focus_app(ad) 857 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 858 raise signals.TestFailure("Fail to get %s location fixed within %d " 859 "attempts." % (type.upper(), retries)) 860 861 862def start_ttff_by_gtw_gpstool(ad, 863 ttff_mode, 864 iteration, 865 aid_data=False, 866 raninterval=False, 867 mininterval=10, 868 maxinterval=40, 869 hot_warm_sleep=300): 870 """Identify which TTFF mode for different test items. 871 872 Args: 873 ad: An AndroidDevice object. 874 ttff_mode: TTFF Test mode for current test item. 875 iteration: Iteration of TTFF cycles. 876 aid_data: Boolean for identify aid_data existed or not 877 raninterval: Boolean for identify random interval of TTFF in enable or not. 878 mininterval: Minimum value of random interval pool. The unit is second. 879 maxinterval: Maximum value of random interval pool. The unit is second. 880 hot_warm_sleep: Wait time for acquiring Almanac. 881 """ 882 begin_time = get_current_epoch_time() 883 if (ttff_mode == "hs" or ttff_mode == "ws") and not aid_data: 884 ad.log.info("Wait {} seconds to start TTFF {}...".format( 885 hot_warm_sleep, ttff_mode.upper())) 886 time.sleep(hot_warm_sleep) 887 if ttff_mode == "cs": 888 ad.log.info("Start TTFF Cold Start...") 889 time.sleep(3) 890 elif ttff_mode == "csa": 891 ad.log.info("Start TTFF CSWith Assist...") 892 time.sleep(3) 893 for i in range(1, 4): 894 ad.adb.shell("am broadcast -a com.android.gpstool.ttff_action " 895 "--es ttff {} --es cycle {} --ez raninterval {} " 896 "--ei mininterval {} --ei maxinterval {}".format( 897 ttff_mode, iteration, raninterval, mininterval, 898 maxinterval)) 899 time.sleep(1) 900 if ad.search_logcat("act=com.android.gpstool.start_test_action", 901 begin_time): 902 ad.log.info("Send TTFF start_test_action successfully.") 903 break 904 else: 905 check_current_focus_app(ad) 906 raise signals.TestError("Fail to send TTFF start_test_action.") 907 908 909def gnss_tracking_via_gtw_gpstool(ad, 910 criteria, 911 type="gnss", 912 testtime=60, 913 meas_flag=False): 914 """Start GNSS/FLP tracking tests for input testtime on GTW_GPSTool. 915 916 Args: 917 ad: An AndroidDevice object. 918 criteria: Criteria for current TTFF. 919 type: Different API for location fix. Use gnss/flp/nmea 920 testtime: Tracking test time for minutes. Default set to 60 minutes. 921 meas_flag: True to enable GnssMeasurement. False is not to. Default 922 set to False. 923 """ 924 process_gnss_by_gtw_gpstool( 925 ad, criteria=criteria, type=type, meas_flag=meas_flag) 926 ad.log.info("Start %s tracking test for %d minutes" % (type.upper(), 927 testtime)) 928 begin_time = get_current_epoch_time() 929 while get_current_epoch_time() - begin_time < testtime * 60 * 1000: 930 detect_crash_during_tracking(ad, begin_time, type) 931 ad.log.info("Successfully tested for %d minutes" % testtime) 932 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 933 934 935def parse_gtw_gpstool_log(ad, true_position, type="gnss"): 936 """Process GNSS/FLP API logs from GTW GPSTool and output track_data to 937 test_run_info for ACTS plugin to parse and display on MobileHarness as 938 Property. 939 940 Args: 941 ad: An AndroidDevice object. 942 true_position: Coordinate as [latitude, longitude] to calculate 943 position error. 944 type: Different API for location fix. Use gnss/flp/nmea 945 """ 946 test_logfile = {} 947 track_data = {} 948 ant_top4_cn = 0 949 ant_cn = 0 950 base_top4_cn = 0 951 base_cn = 0 952 track_lat = 0 953 track_long = 0 954 l5flag = "false" 955 file_count = int(ad.adb.shell("find %s -type f -iname *.txt | wc -l" 956 % GNSSSTATUS_LOG_PATH)) 957 if file_count != 1: 958 ad.log.error("%d API logs exist." % file_count) 959 dir_file = ad.adb.shell("ls %s" % GNSSSTATUS_LOG_PATH).split() 960 for path_key in dir_file: 961 if fnmatch.fnmatch(path_key, "*.txt"): 962 logpath = posixpath.join(GNSSSTATUS_LOG_PATH, path_key) 963 out = ad.adb.shell("wc -c %s" % logpath) 964 file_size = int(out.split(" ")[0]) 965 if file_size < 2000: 966 ad.log.info("Skip log %s due to log size %d bytes" % 967 (path_key, file_size)) 968 continue 969 test_logfile = logpath 970 if not test_logfile: 971 raise signals.TestError("Failed to get test log file in device.") 972 lines = ad.adb.shell("cat %s" % test_logfile).split("\n") 973 for line in lines: 974 if "Antenna_History Avg Top4" in line: 975 ant_top4_cn = float(line.split(":")[-1].strip()) 976 elif "Antenna_History Avg" in line: 977 ant_cn = float(line.split(":")[-1].strip()) 978 elif "Baseband_History Avg Top4" in line: 979 base_top4_cn = float(line.split(":")[-1].strip()) 980 elif "Baseband_History Avg" in line: 981 base_cn = float(line.split(":")[-1].strip()) 982 elif "L5 used in fix" in line: 983 l5flag = line.split(":")[-1].strip() 984 elif "Latitude" in line: 985 track_lat = float(line.split(":")[-1].strip()) 986 elif "Longitude" in line: 987 track_long = float(line.split(":")[-1].strip()) 988 elif "Time" in line: 989 track_utc = line.split("Time:")[-1].strip() 990 if track_utc in track_data.keys(): 991 continue 992 pe = calculate_position_error(track_lat, track_long, true_position) 993 track_data[track_utc] = TRACK_REPORT(l5flag=l5flag, 994 pe=pe, 995 ant_top4cn=ant_top4_cn, 996 ant_cn=ant_cn, 997 base_top4cn=base_top4_cn, 998 base_cn=base_cn) 999 ad.log.debug(track_data) 1000 prop_basename = "TestResult %s_tracking_" % type.upper() 1001 time_list = sorted(track_data.keys()) 1002 l5flag_list = [track_data[key].l5flag for key in time_list] 1003 pe_list = [float(track_data[key].pe) for key in time_list] 1004 ant_top4cn_list = [float(track_data[key].ant_top4cn) for key in time_list] 1005 ant_cn_list = [float(track_data[key].ant_cn) for key in time_list] 1006 base_top4cn_list = [float(track_data[key].base_top4cn) for key in time_list] 1007 base_cn_list = [float(track_data[key].base_cn) for key in time_list] 1008 ad.log.info(prop_basename+"StartTime %s" % time_list[0].replace(" ", "-")) 1009 ad.log.info(prop_basename+"EndTime %s" % time_list[-1].replace(" ", "-")) 1010 ad.log.info(prop_basename+"TotalFixPoints %d" % len(time_list)) 1011 ad.log.info(prop_basename+"L5FixRate "+'{percent:.2%}'.format( 1012 percent=l5flag_list.count("true")/len(l5flag_list))) 1013 ad.log.info(prop_basename+"AvgDis %.1f" % (sum(pe_list)/len(pe_list))) 1014 ad.log.info(prop_basename+"MaxDis %.1f" % max(pe_list)) 1015 ad.log.info(prop_basename+"Ant_AvgTop4Signal %.1f" % ant_top4cn_list[-1]) 1016 ad.log.info(prop_basename+"Ant_AvgSignal %.1f" % ant_cn_list[-1]) 1017 ad.log.info(prop_basename+"Base_AvgTop4Signal %.1f" % base_top4cn_list[-1]) 1018 ad.log.info(prop_basename+"Base_AvgSignal %.1f" % base_cn_list[-1]) 1019 1020 1021def process_ttff_by_gtw_gpstool(ad, begin_time, true_position, type="gnss"): 1022 """Process TTFF and record results in ttff_data. 1023 1024 Args: 1025 ad: An AndroidDevice object. 1026 begin_time: test begin time. 1027 true_position: Coordinate as [latitude, longitude] to calculate 1028 position error. 1029 type: Different API for location fix. Use gnss/flp/nmea 1030 1031 Returns: 1032 ttff_data: A dict of all TTFF data. 1033 """ 1034 ttff_lat = 0 1035 ttff_lon = 0 1036 utc_time = epoch_to_human_time(get_current_epoch_time()) 1037 ttff_data = {} 1038 ttff_loop_time = get_current_epoch_time() 1039 while True: 1040 if get_current_epoch_time() - ttff_loop_time >= 120000: 1041 raise signals.TestError("Fail to search specific GPSService " 1042 "message in logcat. Abort test.") 1043 if not ad.is_adb_logcat_on: 1044 ad.start_adb_logcat() 1045 logcat_results = ad.search_logcat("write TTFF log", ttff_loop_time) 1046 if logcat_results: 1047 ttff_loop_time = get_current_epoch_time() 1048 ttff_log = logcat_results[-1]["log_message"].split() 1049 ttff_loop = int(ttff_log[8].split(":")[-1]) 1050 ttff_sec = float(ttff_log[11]) 1051 if ttff_sec != 0.0: 1052 ttff_ant_cn = float(ttff_log[18].strip("]")) 1053 ttff_base_cn = float(ttff_log[25].strip("]")) 1054 if type == "gnss": 1055 gnss_results = ad.search_logcat("GPSService: Check item", 1056 begin_time) 1057 if gnss_results: 1058 ad.log.debug(gnss_results[-1]["log_message"]) 1059 gnss_location_log = \ 1060 gnss_results[-1]["log_message"].split() 1061 ttff_lat = float( 1062 gnss_location_log[8].split("=")[-1].strip(",")) 1063 ttff_lon = float( 1064 gnss_location_log[9].split("=")[-1].strip(",")) 1065 loc_time = int( 1066 gnss_location_log[10].split("=")[-1].strip(",")) 1067 utc_time = epoch_to_human_time(loc_time) 1068 ttff_haccu = float( 1069 gnss_location_log[11].split("=")[-1].strip(",")) 1070 elif type == "flp": 1071 flp_results = ad.search_logcat("GPSService: FLP Location", 1072 begin_time) 1073 if flp_results: 1074 ad.log.debug(flp_results[-1]["log_message"]) 1075 flp_location_log = flp_results[-1][ 1076 "log_message"].split() 1077 ttff_lat = float(flp_location_log[8].split(",")[0]) 1078 ttff_lon = float(flp_location_log[8].split(",")[1]) 1079 ttff_haccu = float(flp_location_log[9].split("=")[1]) 1080 utc_time = epoch_to_human_time(get_current_epoch_time()) 1081 else: 1082 ttff_ant_cn = float(ttff_log[19].strip("]")) 1083 ttff_base_cn = float(ttff_log[26].strip("]")) 1084 ttff_lat = 0 1085 ttff_lon = 0 1086 ttff_haccu = 0 1087 utc_time = epoch_to_human_time(get_current_epoch_time()) 1088 ad.log.debug("TTFF Loop %d - (Lat, Lon) = (%s, %s)" % (ttff_loop, 1089 ttff_lat, 1090 ttff_lon)) 1091 ttff_pe = calculate_position_error( 1092 ttff_lat, ttff_lon, true_position) 1093 ttff_data[ttff_loop] = TTFF_REPORT(utc_time=utc_time, 1094 ttff_loop=ttff_loop, 1095 ttff_sec=ttff_sec, 1096 ttff_pe=ttff_pe, 1097 ttff_ant_cn=ttff_ant_cn, 1098 ttff_base_cn=ttff_base_cn, 1099 ttff_haccu=ttff_haccu) 1100 ad.log.info("UTC Time = %s, Loop %d = %.1f seconds, " 1101 "Position Error = %.1f meters, " 1102 "Antenna Average Signal = %.1f dbHz, " 1103 "Baseband Average Signal = %.1f dbHz, " 1104 "Horizontal Accuracy = %.1f meters" % (utc_time, 1105 ttff_loop, 1106 ttff_sec, 1107 ttff_pe, 1108 ttff_ant_cn, 1109 ttff_base_cn, 1110 ttff_haccu)) 1111 stop_gps_results = ad.search_logcat("stop gps test", begin_time) 1112 if stop_gps_results: 1113 ad.send_keycode("HOME") 1114 break 1115 crash_result = ad.search_logcat("Force finishing activity " 1116 "com.android.gpstool/.GPSTool", 1117 begin_time) 1118 if crash_result: 1119 raise signals.TestError("GPSTool crashed. Abort test.") 1120 # wait 5 seconds to avoid logs not writing into logcat yet 1121 time.sleep(5) 1122 return ttff_data 1123 1124 1125def check_ttff_data(ad, ttff_data, ttff_mode, criteria): 1126 """Verify all TTFF results from ttff_data. 1127 1128 Args: 1129 ad: An AndroidDevice object. 1130 ttff_data: TTFF data of secs, position error and signal strength. 1131 ttff_mode: TTFF Test mode for current test item. 1132 criteria: Criteria for current test item. 1133 1134 Returns: 1135 True: All TTFF results are within criteria. 1136 False: One or more TTFF results exceed criteria or Timeout. 1137 """ 1138 ad.log.info("%d iterations of TTFF %s tests finished." 1139 % (len(ttff_data.keys()), ttff_mode)) 1140 ad.log.info("%s PASS criteria is %d seconds" % (ttff_mode, criteria)) 1141 ad.log.debug("%s TTFF data: %s" % (ttff_mode, ttff_data)) 1142 ttff_property_key_and_value(ad, ttff_data, ttff_mode) 1143 if len(ttff_data.keys()) == 0: 1144 ad.log.error("GTW_GPSTool didn't process TTFF properly.") 1145 return False 1146 elif any(float(ttff_data[key].ttff_sec) == 0.0 for key in ttff_data.keys()): 1147 ad.log.error("One or more TTFF %s Timeout" % ttff_mode) 1148 return False 1149 elif any(float(ttff_data[key].ttff_sec) >= criteria for key in 1150 ttff_data.keys()): 1151 ad.log.error("One or more TTFF %s are over test criteria %d seconds" 1152 % (ttff_mode, criteria)) 1153 return False 1154 ad.log.info("All TTFF %s are within test criteria %d seconds." 1155 % (ttff_mode, criteria)) 1156 return True 1157 1158 1159def ttff_property_key_and_value(ad, ttff_data, ttff_mode): 1160 """Output ttff_data to test_run_info for ACTS plugin to parse and display 1161 on MobileHarness as Property. 1162 1163 Args: 1164 ad: An AndroidDevice object. 1165 ttff_data: TTFF data of secs, position error and signal strength. 1166 ttff_mode: TTFF Test mode for current test item. 1167 """ 1168 prop_basename = "TestResult "+ttff_mode.replace(" ", "_")+"_TTFF_" 1169 sec_list = [float(ttff_data[key].ttff_sec) for key in ttff_data.keys()] 1170 pe_list = [float(ttff_data[key].ttff_pe) for key in ttff_data.keys()] 1171 ant_cn_list = [float(ttff_data[key].ttff_ant_cn) for key in 1172 ttff_data.keys()] 1173 base_cn_list = [float(ttff_data[key].ttff_base_cn) for key in 1174 ttff_data.keys()] 1175 haccu_list = [float(ttff_data[key].ttff_haccu) for key in 1176 ttff_data.keys()] 1177 timeoutcount = sec_list.count(0.0) 1178 if len(sec_list) == timeoutcount: 1179 avgttff = 9527 1180 else: 1181 avgttff = sum(sec_list)/(len(sec_list) - timeoutcount) 1182 if timeoutcount != 0: 1183 maxttff = 9527 1184 else: 1185 maxttff = max(sec_list) 1186 avgdis = sum(pe_list)/len(pe_list) 1187 maxdis = max(pe_list) 1188 ant_avgcn = sum(ant_cn_list)/len(ant_cn_list) 1189 base_avgcn = sum(base_cn_list)/len(base_cn_list) 1190 avg_haccu = sum(haccu_list)/len(haccu_list) 1191 ad.log.info(prop_basename+"AvgTime %.1f" % avgttff) 1192 ad.log.info(prop_basename+"MaxTime %.1f" % maxttff) 1193 ad.log.info(prop_basename+"TimeoutCount %d" % timeoutcount) 1194 ad.log.info(prop_basename+"AvgDis %.1f" % avgdis) 1195 ad.log.info(prop_basename+"MaxDis %.1f" % maxdis) 1196 ad.log.info(prop_basename+"Ant_AvgSignal %.1f" % ant_avgcn) 1197 ad.log.info(prop_basename+"Base_AvgSignal %.1f" % base_avgcn) 1198 ad.log.info(prop_basename+"Avg_Horizontal_Accuracy %.1f" % avg_haccu) 1199 1200 1201def calculate_position_error(latitude, longitude, true_position): 1202 """Use haversine formula to calculate position error base on true location 1203 coordinate. 1204 1205 Args: 1206 latitude: latitude of location fixed in the present. 1207 longitude: longitude of location fixed in the present. 1208 true_position: [latitude, longitude] of true location coordinate. 1209 1210 Returns: 1211 position_error of location fixed in the present. 1212 """ 1213 radius = 6371009 1214 dlat = math.radians(latitude - true_position[0]) 1215 dlon = math.radians(longitude - true_position[1]) 1216 a = math.sin(dlat/2) * math.sin(dlat/2) + \ 1217 math.cos(math.radians(true_position[0])) * \ 1218 math.cos(math.radians(latitude)) * math.sin(dlon/2) * math.sin(dlon/2) 1219 c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a)) 1220 return radius * c 1221 1222 1223def launch_google_map(ad): 1224 """Launch Google Map via intent. 1225 1226 Args: 1227 ad: An AndroidDevice object. 1228 """ 1229 ad.log.info("Launch Google Map.") 1230 try: 1231 if is_device_wearable(ad): 1232 cmd = ("am start -S -n com.google.android.apps.maps/" 1233 "com.google.android.apps.gmmwearable.MainActivity") 1234 else: 1235 cmd = ("am start -S -n com.google.android.apps.maps/" 1236 "com.google.android.maps.MapsActivity") 1237 ad.adb.shell(cmd) 1238 ad.send_keycode("BACK") 1239 ad.force_stop_apk("com.google.android.apps.maps") 1240 ad.adb.shell(cmd) 1241 except Exception as e: 1242 ad.log.error(e) 1243 raise signals.TestError("Failed to launch google map.") 1244 check_current_focus_app(ad) 1245 1246 1247def check_current_focus_app(ad): 1248 """Check to see current focused window and app. 1249 1250 Args: 1251 ad: An AndroidDevice object. 1252 """ 1253 time.sleep(1) 1254 current = ad.adb.shell( 1255 "dumpsys window | grep -E 'mCurrentFocus|mFocusedApp'") 1256 ad.log.debug("\n"+current) 1257 1258 1259def check_location_api(ad, retries): 1260 """Verify if GnssLocationProvider API reports location. 1261 1262 Args: 1263 ad: An AndroidDevice object. 1264 retries: Retry time. 1265 1266 Returns: 1267 True: GnssLocationProvider API reports location. 1268 otherwise return False. 1269 """ 1270 for i in range(retries): 1271 begin_time = get_current_epoch_time() 1272 ad.log.info("Try to get location report from GnssLocationProvider API " 1273 "- attempt %d" % (i+1)) 1274 while get_current_epoch_time() - begin_time <= 30000: 1275 logcat_results = ad.search_logcat("reportLocation", begin_time) 1276 if logcat_results: 1277 ad.log.info("%s" % logcat_results[-1]["log_message"]) 1278 ad.log.info("GnssLocationProvider reports location " 1279 "successfully.") 1280 return True 1281 if not ad.is_adb_logcat_on: 1282 ad.start_adb_logcat() 1283 ad.log.error("GnssLocationProvider is unable to report location.") 1284 return False 1285 1286 1287def check_network_location(ad, retries, location_type, criteria=30): 1288 """Verify if NLP reports location after requesting via GPSTool. 1289 1290 Args: 1291 ad: An AndroidDevice object. 1292 retries: Retry time. 1293 location_type: cell or wifi. 1294 criteria: expected nlp return time, default 30 seconds 1295 1296 Returns: 1297 True: NLP reports location. 1298 otherwise return False. 1299 """ 1300 criteria = criteria * 1000 1301 search_pattern = ("GPSTool : networkLocationType = %s" % location_type) 1302 for i in range(retries): 1303 begin_time = get_current_epoch_time() 1304 ad.log.info("Try to get NLP status - attempt %d" % (i+1)) 1305 ad.adb.shell( 1306 "am start -S -n com.android.gpstool/.GPSTool --es mode nlp") 1307 while get_current_epoch_time() - begin_time <= criteria: 1308 # Search pattern in 1 second interval 1309 time.sleep(1) 1310 result = ad.search_logcat(search_pattern, begin_time) 1311 if result: 1312 ad.log.info("Pattern Found: %s." % result[-1]["log_message"]) 1313 ad.send_keycode("BACK") 1314 return True 1315 if not ad.is_adb_logcat_on: 1316 ad.start_adb_logcat() 1317 ad.send_keycode("BACK") 1318 ad.log.error("Unable to report network location \"%s\"." % location_type) 1319 return False 1320 1321 1322def set_attenuator_gnss_signal(ad, attenuator, atten_value): 1323 """Set attenuation value for different GNSS signal. 1324 1325 Args: 1326 ad: An AndroidDevice object. 1327 attenuator: The attenuator object. 1328 atten_value: attenuation value 1329 """ 1330 try: 1331 ad.log.info( 1332 "Set attenuation value to \"%d\" for GNSS signal." % atten_value) 1333 attenuator[0].set_atten(atten_value) 1334 except Exception as e: 1335 ad.log.error(e) 1336 1337 1338def set_battery_saver_mode(ad, state): 1339 """Enable or disable battery saver mode via adb. 1340 1341 Args: 1342 ad: An AndroidDevice object. 1343 state: True is enable Battery Saver mode. False is disable. 1344 """ 1345 ad.root_adb() 1346 if state: 1347 ad.log.info("Enable Battery Saver mode.") 1348 ad.adb.shell("cmd battery unplug") 1349 ad.adb.shell("settings put global low_power 1") 1350 else: 1351 ad.log.info("Disable Battery Saver mode.") 1352 ad.adb.shell("settings put global low_power 0") 1353 ad.adb.shell("cmd battery reset") 1354 1355 1356def set_gnss_qxdm_mask(ad, masks): 1357 """Find defined gnss qxdm mask and set as default logging mask. 1358 1359 Args: 1360 ad: An AndroidDevice object. 1361 masks: Defined gnss qxdm mask. 1362 """ 1363 try: 1364 for mask in masks: 1365 if not tlutils.find_qxdm_log_mask(ad, mask): 1366 continue 1367 tlutils.set_qxdm_logger_command(ad, mask) 1368 break 1369 except Exception as e: 1370 ad.log.error(e) 1371 raise signals.TestError("Failed to set any QXDM masks.") 1372 1373 1374def start_youtube_video(ad, url=None, retries=0): 1375 """Start youtube video and verify if audio is in music state. 1376 1377 Args: 1378 ad: An AndroidDevice object. 1379 url: Youtube video url. 1380 retries: Retry times if audio is not in music state. 1381 1382 Returns: 1383 True if youtube video is playing normally. 1384 False if youtube video is not playing properly. 1385 """ 1386 for i in range(retries): 1387 ad.log.info("Open an youtube video - attempt %d" % (i+1)) 1388 cmd = ("am start -n com.google.android.youtube/" 1389 "com.google.android.youtube.UrlActivity -d \"%s\"" % url) 1390 ad.adb.shell(cmd) 1391 time.sleep(2) 1392 out = ad.adb.shell( 1393 "dumpsys activity | grep NewVersionAvailableActivity") 1394 if out: 1395 ad.log.info("Skip Youtube New Version Update.") 1396 ad.send_keycode("BACK") 1397 if tutils.wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1): 1398 ad.log.info("Started a video in youtube, audio is in MUSIC state") 1399 return True 1400 ad.log.info("Force-Stop youtube and reopen youtube again.") 1401 ad.force_stop_apk("com.google.android.youtube") 1402 check_current_focus_app(ad) 1403 raise signals.TestError("Started a video in youtube, " 1404 "but audio is not in MUSIC state") 1405 1406 1407def get_baseband_and_gms_version(ad, extra_msg=""): 1408 """Get current radio baseband and GMSCore version of AndroidDevice object. 1409 1410 Args: 1411 ad: An AndroidDevice object. 1412 extra_msg: Extra message before or after the change. 1413 """ 1414 mpss_version = "" 1415 brcm_gps_version = "" 1416 brcm_sensorhub_version = "" 1417 try: 1418 build_version = ad.adb.getprop("ro.build.id") 1419 baseband_version = ad.adb.getprop("gsm.version.baseband") 1420 gms_version = ad.adb.shell( 1421 "dumpsys package com.google.android.gms | grep versionName" 1422 ).split("\n")[0].split("=")[1] 1423 if check_chipset_vendor_by_qualcomm(ad): 1424 mpss_version = ad.adb.shell( 1425 "cat /sys/devices/soc0/images | grep MPSS | cut -d ':' -f 3") 1426 else: 1427 brcm_gps_version = ad.adb.shell("cat /data/vendor/gps/chip.info") 1428 sensorhub_version = ad.adb.shell( 1429 "cat /vendor/firmware/SensorHub.patch | grep ChangeList") 1430 brcm_sensorhub_version = re.compile( 1431 r'<ChangeList=(\w+)>').search(sensorhub_version).group(1) 1432 if not extra_msg: 1433 ad.log.info("TestResult Build_Version %s" % build_version) 1434 ad.log.info("TestResult Baseband_Version %s" % baseband_version) 1435 ad.log.info( 1436 "TestResult GMS_Version %s" % gms_version.replace(" ", "")) 1437 if check_chipset_vendor_by_qualcomm(ad): 1438 ad.log.info("TestResult MPSS_Version %s" % mpss_version) 1439 else: 1440 ad.log.info("TestResult GPS_Version %s" % brcm_gps_version) 1441 ad.log.info( 1442 "TestResult SensorHub_Version %s" % brcm_sensorhub_version) 1443 else: 1444 ad.log.info( 1445 "%s, Baseband_Version = %s" % (extra_msg, baseband_version)) 1446 except Exception as e: 1447 ad.log.error(e) 1448 1449 1450def start_toggle_gnss_by_gtw_gpstool(ad, iteration): 1451 """Send toggle gnss off/on start_test_action 1452 1453 Args: 1454 ad: An AndroidDevice object. 1455 iteration: Iteration of toggle gnss off/on cycles. 1456 """ 1457 msg_list = [] 1458 begin_time = get_current_epoch_time() 1459 try: 1460 for i in range(1, 4): 1461 ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool " 1462 "--es mode toggle --es cycle %d" % iteration) 1463 time.sleep(1) 1464 if is_device_wearable(ad): 1465 # Wait 20 seconds for Wearable low performance time. 1466 time.sleep(20) 1467 if ad.search_logcat("ToggleGPS onResume", 1468 begin_time): 1469 ad.log.info("Send ToggleGPS start_test_action successfully.") 1470 break 1471 elif ad.search_logcat("cmp=com.android.gpstool/.ToggleGPS", 1472 begin_time): 1473 ad.log.info("Send ToggleGPS start_test_action successfully.") 1474 break 1475 else: 1476 check_current_focus_app(ad) 1477 raise signals.TestError("Fail to send ToggleGPS " 1478 "start_test_action within 3 attempts.") 1479 time.sleep(2) 1480 if is_device_wearable(ad): 1481 test_start = ad.search_logcat("GPSService: create toggle GPS log", 1482 begin_time) 1483 else: 1484 test_start = ad.search_logcat("GPSTool_ToggleGPS: startService", 1485 begin_time) 1486 if test_start: 1487 ad.log.info(test_start[-1]["log_message"].split(":")[-1].strip()) 1488 else: 1489 raise signals.TestError("Fail to start toggle GPS off/on test.") 1490 # Every iteration is expected to finish within 4 minutes. 1491 while get_current_epoch_time() - begin_time <= iteration * 240000: 1492 crash_end = ad.search_logcat("Force finishing activity " 1493 "com.android.gpstool/.GPSTool", 1494 begin_time) 1495 if crash_end: 1496 raise signals.TestError("GPSTool crashed. Abort test.") 1497 toggle_results = ad.search_logcat("GPSTool : msg", begin_time) 1498 if toggle_results: 1499 for toggle_result in toggle_results: 1500 msg = toggle_result["log_message"] 1501 if not msg in msg_list: 1502 ad.log.info(msg.split(":")[-1].strip()) 1503 msg_list.append(msg) 1504 if "timeout" in msg: 1505 raise signals.TestFailure("Fail to get location fixed " 1506 "within 60 seconds.") 1507 if "Test end" in msg: 1508 raise signals.TestPass("Completed quick toggle GNSS " 1509 "off/on test.") 1510 raise signals.TestFailure("Fail to finish toggle GPS off/on test " 1511 "within %d minutes" % (iteration * 4)) 1512 finally: 1513 ad.send_keycode("HOME") 1514 1515 1516def grant_location_permission(ad, option): 1517 """Grant or revoke location related permission. 1518 1519 Args: 1520 ad: An AndroidDevice object. 1521 option: Boolean to grant or revoke location related permissions. 1522 """ 1523 action = "grant" if option else "revoke" 1524 for permission in LOCATION_PERMISSIONS: 1525 ad.log.info( 1526 "%s permission:%s on %s" % (action, permission, TEST_PACKAGE_NAME)) 1527 ad.adb.shell("pm %s %s %s" % (action, TEST_PACKAGE_NAME, permission)) 1528 1529 1530def check_location_runtime_permissions(ad, package, permissions): 1531 """Check if runtime permissions are granted on selected package. 1532 1533 Args: 1534 ad: An AndroidDevice object. 1535 package: Apk package name to check. 1536 permissions: A list of permissions to be granted. 1537 """ 1538 for _ in range(3): 1539 location_runtime_permission = ad.adb.shell( 1540 "dumpsys package %s | grep ACCESS_FINE_LOCATION" % package) 1541 if "true" not in location_runtime_permission: 1542 ad.log.info("ACCESS_FINE_LOCATION is NOT granted on %s" % package) 1543 for permission in permissions: 1544 ad.log.debug("Grant %s on %s" % (permission, package)) 1545 ad.adb.shell("pm grant %s %s" % (package, permission)) 1546 else: 1547 ad.log.info("ACCESS_FINE_LOCATION is granted on %s" % package) 1548 break 1549 else: 1550 raise signals.TestError( 1551 "Fail to grant ACCESS_FINE_LOCATION on %s" % package) 1552 1553 1554def install_mdstest_app(ad, mdsapp): 1555 """ 1556 Install MDS test app in DUT 1557 1558 Args: 1559 ad: An Android Device Object 1560 mdsapp: Installation path of MDSTest app 1561 """ 1562 if not ad.is_apk_installed("com.google.mdstest"): 1563 ad.adb.install("-r %s" % mdsapp, timeout=300, ignore_status=True) 1564 1565 1566def write_modemconfig(ad, mdsapp, nvitem_dict, modemparfile): 1567 """ 1568 Modify the NV items using modem_tool.par 1569 Note: modem_tool.par 1570 1571 Args: 1572 ad: An Android Device Object 1573 mdsapp: Installation path of MDSTest app 1574 nvitem_dict: dictionary of NV items and values. 1575 modemparfile: modem_tool.par path. 1576 """ 1577 ad.log.info("Verify MDSTest app installed in DUT") 1578 install_mdstest_app(ad, mdsapp) 1579 os.system("chmod 777 %s" % modemparfile) 1580 for key, value in nvitem_dict.items(): 1581 if key.isdigit(): 1582 op_name = "WriteEFS" 1583 else: 1584 op_name = "WriteNV" 1585 ad.log.info("Modifying the NV{!r} using {}".format(key, op_name)) 1586 job.run("{} --op {} --item {} --data '{}'". 1587 format(modemparfile, op_name, key, value)) 1588 time.sleep(2) 1589 1590 1591def verify_modemconfig(ad, nvitem_dict, modemparfile): 1592 """ 1593 Verify the NV items using modem_tool.par 1594 Note: modem_tool.par 1595 1596 Args: 1597 ad: An Android Device Object 1598 nvitem_dict: dictionary of NV items and values 1599 modemparfile: modem_tool.par path. 1600 """ 1601 os.system("chmod 777 %s" % modemparfile) 1602 for key, value in nvitem_dict.items(): 1603 if key.isdigit(): 1604 op_name = "ReadEFS" 1605 else: 1606 op_name = "ReadNV" 1607 # Sleeptime to avoid Modem communication error 1608 time.sleep(5) 1609 result = job.run( 1610 "{} --op {} --item {}".format(modemparfile, op_name, key)) 1611 output = str(result.stdout) 1612 ad.log.info("Actual Value for NV{!r} is {!r}".format(key, output)) 1613 if not value.casefold() in output: 1614 ad.log.error("NV Value is wrong {!r} in {!r}".format(value, result)) 1615 raise ValueError( 1616 "could not find {!r} in {!r}".format(value, result)) 1617 1618 1619def check_ttff_pe(ad, ttff_data, ttff_mode, pe_criteria): 1620 """Verify all TTFF results from ttff_data. 1621 1622 Args: 1623 ad: An AndroidDevice object. 1624 ttff_data: TTFF data of secs, position error and signal strength. 1625 ttff_mode: TTFF Test mode for current test item. 1626 pe_criteria: Criteria for current test item. 1627 1628 """ 1629 ad.log.info("%d iterations of TTFF %s tests finished." 1630 % (len(ttff_data.keys()), ttff_mode)) 1631 ad.log.info("%s PASS criteria is %f meters" % (ttff_mode, pe_criteria)) 1632 ad.log.debug("%s TTFF data: %s" % (ttff_mode, ttff_data)) 1633 1634 if len(ttff_data.keys()) == 0: 1635 ad.log.error("GTW_GPSTool didn't process TTFF properly.") 1636 raise signals.TestFailure("GTW_GPSTool didn't process TTFF properly.") 1637 1638 elif any(float(ttff_data[key].ttff_pe) >= pe_criteria for key in 1639 ttff_data.keys()): 1640 ad.log.error("One or more TTFF %s are over test criteria %f meters" 1641 % (ttff_mode, pe_criteria)) 1642 raise signals.TestFailure("GTW_GPSTool didn't process TTFF properly.") 1643 else: 1644 ad.log.info("All TTFF %s are within test criteria %f meters." % ( 1645 ttff_mode, pe_criteria)) 1646 return True 1647 1648 1649def check_adblog_functionality(ad): 1650 """Restart adb logcat if system can't write logs into file after checking 1651 adblog file size. 1652 1653 Args: 1654 ad: An AndroidDevice object. 1655 """ 1656 logcat_path = os.path.join(ad.device_log_path, "adblog_%s_debug.txt" % 1657 ad.serial) 1658 if not os.path.exists(logcat_path): 1659 raise signals.TestError("Logcat file %s does not exist." % logcat_path) 1660 original_log_size = os.path.getsize(logcat_path) 1661 ad.log.debug("Original adblog size is %d" % original_log_size) 1662 time.sleep(.5) 1663 current_log_size = os.path.getsize(logcat_path) 1664 ad.log.debug("Current adblog size is %d" % current_log_size) 1665 if current_log_size == original_log_size: 1666 ad.log.warn("System can't write logs into file. Restart adb " 1667 "logcat process now.") 1668 ad.stop_adb_logcat() 1669 ad.start_adb_logcat() 1670 1671 1672def build_instrumentation_call(package, 1673 runner, 1674 test_methods=None, 1675 options=None): 1676 """Build an instrumentation call for the tests 1677 1678 Args: 1679 package: A string to identify test package. 1680 runner: A string to identify test runner. 1681 test_methods: A dictionary contains {class_name, test_method}. 1682 options: A dictionary constant {key, value} param for test. 1683 1684 Returns: 1685 An instrumentation call command. 1686 """ 1687 if test_methods is None: 1688 test_methods = {} 1689 cmd_builder = InstrumentationCommandBuilder() 1690 else: 1691 cmd_builder = InstrumentationTestCommandBuilder() 1692 if options is None: 1693 options = {} 1694 cmd_builder.set_manifest_package(package) 1695 cmd_builder.set_runner(runner) 1696 cmd_builder.add_flag("-w") 1697 for class_name, test_method in test_methods.items(): 1698 cmd_builder.add_test_method(class_name, test_method) 1699 for option_key, option_value in options.items(): 1700 cmd_builder.add_key_value_param(option_key, option_value) 1701 return cmd_builder.build() 1702 1703 1704def check_chipset_vendor_by_qualcomm(ad): 1705 """Check if chipset vendor is by Qualcomm. 1706 1707 Args: 1708 ad: An AndroidDevice object. 1709 1710 Returns: 1711 True if it's by Qualcomm. False irf not. 1712 """ 1713 ad.root_adb() 1714 soc = str(ad.adb.shell("getprop gsm.version.ril-impl")) 1715 ad.log.debug("SOC = %s" % soc) 1716 return "Qualcomm" in soc 1717 1718 1719def delete_lto_file(ad): 1720 """Delete downloaded LTO files. 1721 1722 Args: 1723 ad: An AndroidDevice object. 1724 """ 1725 remount_device(ad) 1726 status = ad.adb.shell("rm -rf /data/vendor/gps/lto*") 1727 ad.log.info("Delete downloaded LTO files.\n%s" % status) 1728 1729 1730def lto_mode(ad, state): 1731 """Enable or Disable LTO mode. 1732 1733 Args: 1734 ad: An AndroidDevice object. 1735 state: True to enable. False to disable. 1736 """ 1737 server_list = ["LONGTERM_PSDS_SERVER_1", 1738 "LONGTERM_PSDS_SERVER_2", 1739 "LONGTERM_PSDS_SERVER_3", 1740 "NORMAL_PSDS_SERVER", 1741 "REALTIME_PSDS_SERVER"] 1742 delete_lto_file(ad) 1743 if state: 1744 tmp_path = tempfile.mkdtemp() 1745 ad.pull_files("/etc/gps_debug.conf", tmp_path) 1746 gps_conf_path = os.path.join(tmp_path, "gps_debug.conf") 1747 gps_conf_file = open(gps_conf_path, "r") 1748 lines = gps_conf_file.readlines() 1749 gps_conf_file.close() 1750 fout = open(gps_conf_path, "w") 1751 for line in lines: 1752 for server in server_list: 1753 if server in line: 1754 line = line.replace(line, "") 1755 fout.write(line) 1756 fout.close() 1757 ad.push_system_file(gps_conf_path, "/etc/gps_debug.conf") 1758 ad.log.info("Push back modified gps_debug.conf") 1759 ad.log.info("LTO/RTO/RTI enabled") 1760 shutil.rmtree(tmp_path, ignore_errors=True) 1761 else: 1762 ad.adb.shell("echo %r >> /etc/gps_debug.conf" % 1763 DISABLE_LTO_FILE_CONTENTS) 1764 ad.log.info("LTO/RTO/RTI disabled") 1765 reboot(ad) 1766 1767 1768def lto_mode_wearable(ad, state): 1769 """Enable or Disable LTO mode for wearable in Android R release. 1770 1771 Args: 1772 ad: An AndroidDevice object. 1773 state: True to enable. False to disable. 1774 """ 1775 rto_enable = ' RtoEnable="true"\n' 1776 rto_disable = ' RtoEnable="false"\n' 1777 rti_enable = ' RtiEnable="true"\n' 1778 rti_disable = ' RtiEnable="false"\n' 1779 sync_lto_enable = ' HttpDirectSyncLto="true"\n' 1780 sync_lto_disable = ' HttpDirectSyncLto="false"\n' 1781 server_list = ["XTRA_SERVER_1", "XTRA_SERVER_2", "XTRA_SERVER_3"] 1782 delete_lto_file(ad) 1783 tmp_path = tempfile.mkdtemp() 1784 ad.pull_files("/vendor/etc/gnss/gps.xml", tmp_path) 1785 gps_xml_path = os.path.join(tmp_path, "gps.xml") 1786 gps_xml_file = open(gps_xml_path, "r") 1787 lines = gps_xml_file.readlines() 1788 gps_xml_file.close() 1789 fout = open(gps_xml_path, "w") 1790 for line in lines: 1791 if state: 1792 if rto_disable in line: 1793 line = line.replace(line, rto_enable) 1794 ad.log.info("RTO enabled") 1795 elif rti_disable in line: 1796 line = line.replace(line, rti_enable) 1797 ad.log.info("RTI enabled") 1798 elif sync_lto_disable in line: 1799 line = line.replace(line, sync_lto_enable) 1800 ad.log.info("LTO sync enabled") 1801 else: 1802 if rto_enable in line: 1803 line = line.replace(line, rto_disable) 1804 ad.log.info("RTO disabled") 1805 elif rti_enable in line: 1806 line = line.replace(line, rti_disable) 1807 ad.log.info("RTI disabled") 1808 elif sync_lto_enable in line: 1809 line = line.replace(line, sync_lto_disable) 1810 ad.log.info("LTO sync disabled") 1811 fout.write(line) 1812 fout.close() 1813 ad.push_system_file(gps_xml_path, "/vendor/etc/gnss/gps.xml") 1814 ad.log.info("Push back modified gps.xml") 1815 shutil.rmtree(tmp_path, ignore_errors=True) 1816 if state: 1817 xtra_tmp_path = tempfile.mkdtemp() 1818 ad.pull_files("/etc/gps_debug.conf", xtra_tmp_path) 1819 gps_conf_path = os.path.join(xtra_tmp_path, "gps_debug.conf") 1820 gps_conf_file = open(gps_conf_path, "r") 1821 lines = gps_conf_file.readlines() 1822 gps_conf_file.close() 1823 fout = open(gps_conf_path, "w") 1824 for line in lines: 1825 for server in server_list: 1826 if server in line: 1827 line = line.replace(line, "") 1828 fout.write(line) 1829 fout.close() 1830 ad.push_system_file(gps_conf_path, "/etc/gps_debug.conf") 1831 ad.log.info("Push back modified gps_debug.conf") 1832 ad.log.info("LTO/RTO/RTI enabled") 1833 shutil.rmtree(xtra_tmp_path, ignore_errors=True) 1834 else: 1835 ad.adb.shell( 1836 "echo %r >> /etc/gps_debug.conf" % DISABLE_LTO_FILE_CONTENTS_R) 1837 ad.log.info("LTO/RTO/RTI disabled") 1838 1839 1840def start_pixel_logger(ad, max_log_size_mb=100, max_number_of_files=500): 1841 """adb to start pixel logger for GNSS logging. 1842 1843 Args: 1844 ad: An AndroidDevice object. 1845 max_log_size_mb: Determines when to create a new log file if current 1846 one reaches the size limit. 1847 max_number_of_files: Determines how many log files can be saved on DUT. 1848 """ 1849 retries = 3 1850 start_timeout_sec = 60 1851 default_gnss_cfg = "/vendor/etc/mdlog/DEFAULT+SECURITY+FULLDPL+GPS.cfg" 1852 if check_chipset_vendor_by_qualcomm(ad): 1853 start_cmd = ("am startservice -a com.android.pixellogger." 1854 "service.logging.LoggingService.ACTION_START_LOGGING " 1855 "-e intent_key_cfg_path '%s' " 1856 "--ei intent_key_max_log_size_mb %d " 1857 "--ei intent_key_max_number_of_files %d" % 1858 (default_gnss_cfg, max_log_size_mb, max_number_of_files)) 1859 else: 1860 start_cmd = ("am startservice -a com.android.pixellogger." 1861 "service.logging.LoggingService.ACTION_START_LOGGING " 1862 "-e intent_logger brcm_gps " 1863 "--ei intent_key_max_log_size_mb %d " 1864 "--ei intent_key_max_number_of_files %d" % 1865 (max_log_size_mb, max_number_of_files)) 1866 for attempt in range(retries): 1867 begin_time = get_current_epoch_time() - 3000 1868 ad.log.info("Start Pixel Logger - Attempt %d" % (attempt + 1)) 1869 ad.adb.shell(start_cmd) 1870 while get_current_epoch_time() - begin_time <= start_timeout_sec * 1000: 1871 if not ad.is_adb_logcat_on: 1872 ad.start_adb_logcat() 1873 if check_chipset_vendor_by_qualcomm(ad): 1874 start_result = ad.search_logcat( 1875 "ModemLogger: Start logging", begin_time) 1876 else: 1877 start_result = ad.search_logcat("startRecording", begin_time) 1878 if start_result: 1879 ad.log.info("Pixel Logger starts recording successfully.") 1880 return True 1881 stop_pixel_logger(ad) 1882 else: 1883 ad.log.warn("Pixel Logger fails to start recording in %d seconds " 1884 "within %d attempts." % (start_timeout_sec, retries)) 1885 1886 1887def stop_pixel_logger(ad): 1888 """adb to stop pixel logger for GNSS logging. 1889 1890 Args: 1891 ad: An AndroidDevice object. 1892 """ 1893 retries = 3 1894 stop_timeout_sec = 60 1895 zip_timeout_sec = 30 1896 if check_chipset_vendor_by_qualcomm(ad): 1897 stop_cmd = ("am startservice -a com.android.pixellogger." 1898 "service.logging.LoggingService.ACTION_STOP_LOGGING") 1899 else: 1900 stop_cmd = ("am startservice -a com.android.pixellogger." 1901 "service.logging.LoggingService.ACTION_STOP_LOGGING " 1902 "-e intent_logger brcm_gps") 1903 for attempt in range(retries): 1904 begin_time = get_current_epoch_time() - 3000 1905 ad.log.info("Stop Pixel Logger - Attempt %d" % (attempt + 1)) 1906 ad.adb.shell(stop_cmd) 1907 while get_current_epoch_time() - begin_time <= stop_timeout_sec * 1000: 1908 if not ad.is_adb_logcat_on: 1909 ad.start_adb_logcat() 1910 stop_result = ad.search_logcat( 1911 "LoggingService: Stopping service", begin_time) 1912 if stop_result: 1913 ad.log.info("Pixel Logger stops successfully.") 1914 zip_end_time = time.time() + zip_timeout_sec 1915 while time.time() < zip_end_time: 1916 zip_file_created = ad.search_logcat( 1917 "FileUtil: Zip file has been created", begin_time) 1918 if zip_file_created: 1919 ad.log.info("Pixel Logger created zip file " 1920 "successfully.") 1921 return True 1922 else: 1923 ad.log.warn("Pixel Logger failed to create zip file.") 1924 return False 1925 ad.force_stop_apk("com.android.pixellogger") 1926 else: 1927 ad.log.warn("Pixel Logger fails to stop in %d seconds within %d " 1928 "attempts." % (stop_timeout_sec, retries)) 1929 1930 1931def launch_eecoexer(ad): 1932 """Launch EEcoexer. 1933 1934 Args: 1935 ad: An AndroidDevice object. 1936 Raise: 1937 signals.TestError if DUT fails to launch EEcoexer 1938 """ 1939 launch_cmd = ("am start -a android.intent.action.MAIN -n" 1940 "com.google.eecoexer" 1941 "/.MainActivity") 1942 ad.adb.shell(launch_cmd) 1943 try: 1944 ad.log.info("Launch EEcoexer.") 1945 except Exception as e: 1946 ad.log.error(e) 1947 raise signals.TestError("Failed to launch EEcoexer.") 1948 1949 1950def excute_eecoexer_function(ad, eecoexer_args): 1951 """Execute EEcoexer commands. 1952 1953 Args: 1954 ad: An AndroidDevice object. 1955 eecoexer_args: EEcoexer function arguments 1956 """ 1957 cat_index = eecoexer_args.split(',')[:2] 1958 cat_index = ','.join(cat_index) 1959 enqueue_cmd = ("am broadcast -a com.google.eecoexer.action.LISTENER" 1960 " --es sms_body ENQUEUE,{}".format(eecoexer_args)) 1961 exe_cmd = ("am broadcast -a com.google.eecoexer.action.LISTENER" 1962 " --es sms_body EXECUTE") 1963 wait_for_cmd = ("am broadcast -a com.google.eecoexer.action.LISTENER" 1964 " --es sms_body WAIT_FOR_COMPLETE,{}".format(cat_index)) 1965 ad.log.info("EEcoexer Add Enqueue: {}".format(eecoexer_args)) 1966 ad.adb.shell(enqueue_cmd) 1967 ad.log.info("EEcoexer Excute.") 1968 ad.adb.shell(exe_cmd) 1969 ad.log.info("Wait EEcoexer for complete") 1970 ad.adb.shell(wait_for_cmd) 1971 1972 1973def restart_gps_daemons(ad): 1974 """Restart GPS daemons by killing services of gpsd, lhd and scd. 1975 1976 Args: 1977 ad: An AndroidDevice object. 1978 """ 1979 gps_daemons_list = ["gpsd", "lhd", "scd"] 1980 ad.root_adb() 1981 for service in gps_daemons_list: 1982 begin_time = get_current_epoch_time() 1983 time.sleep(3) 1984 ad.log.info("Kill GPS daemon \"%s\"" % service) 1985 ad.adb.shell("killall %s" % service) 1986 # Wait 3 seconds for daemons and services to start. 1987 time.sleep(3) 1988 restart_services = ad.search_logcat("starting service", begin_time) 1989 for restart_service in restart_services: 1990 if service in restart_service["log_message"]: 1991 ad.log.info(restart_service["log_message"]) 1992 ad.log.info( 1993 "GPS daemon \"%s\" restarts successfully." % service) 1994 break 1995 else: 1996 raise signals.TestError("Unable to restart \"%s\"" % service) 1997 1998 1999def is_device_wearable(ad): 2000 """Check device is wearable project or not. 2001 2002 Args: 2003 ad: An AndroidDevice object. 2004 """ 2005 package = ad.adb.getprop("ro.cw.home_package_names") 2006 ad.log.debug("[ro.cw.home_package_names]: [%s]" % package) 2007 return "wearable" in package 2008 2009 2010def is_mobile_data_on(ad): 2011 """Check if mobile data of device is on. 2012 2013 Args: 2014 ad: An AndroidDevice object. 2015 """ 2016 if is_device_wearable(ad): 2017 cell_on = ad.adb.shell("settings get global cell_on") 2018 ad.log.debug("Current mobile status is %s" % cell_on) 2019 return "1" in cell_on 2020 else: 2021 return ad.droid.telephonyIsDataEnabled() 2022 2023 2024def human_to_epoch_time(human_time): 2025 """Convert human readable time to epoch time. 2026 2027 Args: 2028 human_time: Human readable time. (Ex: 2020-08-04 13:24:28.900) 2029 2030 Returns: 2031 epoch: Epoch time in milliseconds. 2032 """ 2033 if "/" in human_time: 2034 human_time.replace("/", "-") 2035 try: 2036 epoch_start = datetime.utcfromtimestamp(0) 2037 if "." in human_time: 2038 epoch_time = datetime.strptime(human_time, "%Y-%m-%d %H:%M:%S.%f") 2039 else: 2040 epoch_time = datetime.strptime(human_time, "%Y-%m-%d %H:%M:%S") 2041 epoch = int((epoch_time - epoch_start).total_seconds() * 1000) 2042 return epoch 2043 except ValueError: 2044 return None 2045 2046 2047def check_dpo_rate_via_gnss_meas(ad, begin_time, dpo_threshold): 2048 """Check DPO engage rate through "HardwareClockDiscontinuityCount" in 2049 GnssMeasurement callback. 2050 2051 Args: 2052 ad: An AndroidDevice object. 2053 begin_time: test begin time. 2054 dpo_threshold: The value to set threshold. (Ex: dpo_threshold = 60) 2055 """ 2056 time_regex = r'(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}.\d{3})' 2057 dpo_results = ad.search_logcat("HardwareClockDiscontinuityCount", 2058 begin_time) 2059 if not dpo_results: 2060 raise signals.TestError( 2061 "No \"HardwareClockDiscontinuityCount\" is found in logs.") 2062 ad.log.info(dpo_results[0]["log_message"]) 2063 ad.log.info(dpo_results[-1]["log_message"]) 2064 start_time = re.compile( 2065 time_regex).search(dpo_results[0]["log_message"]).group(1) 2066 end_time = re.compile( 2067 time_regex).search(dpo_results[-1]["log_message"]).group(1) 2068 gnss_start_epoch = human_to_epoch_time(start_time) 2069 gnss_stop_epoch = human_to_epoch_time(end_time) 2070 test_time_in_sec = round((gnss_stop_epoch - gnss_start_epoch) / 1000) + 1 2071 first_dpo_count = int(dpo_results[0]["log_message"].split()[-1]) 2072 final_dpo_count = int(dpo_results[-1]["log_message"].split()[-1]) 2073 dpo_rate = ((final_dpo_count - first_dpo_count)/test_time_in_sec) 2074 dpo_engage_rate = "{percent:.2%}".format(percent=dpo_rate) 2075 ad.log.info("DPO is ON for %d seconds during %d seconds test." % ( 2076 final_dpo_count - first_dpo_count, test_time_in_sec)) 2077 ad.log.info("TestResult DPO_Engage_Rate " + dpo_engage_rate) 2078 threshold = "{percent:.0%}".format(percent=dpo_threshold / 100) 2079 asserts.assert_true(dpo_rate * 100 > dpo_threshold, 2080 "DPO only engaged %s in %d seconds test with " 2081 "threshold %s." % (dpo_engage_rate, 2082 test_time_in_sec, 2083 threshold)) 2084 2085 2086def parse_brcm_nmea_log(ad, nmea_pattern, brcm_error_log_allowlist): 2087 """Parse specific NMEA pattern out of BRCM NMEA log. 2088 2089 Args: 2090 ad: An AndroidDevice object. 2091 nmea_pattern: Specific NMEA pattern to parse. 2092 brcm_error_log_allowlist: Benign error logs to exclude. 2093 2094 Returns: 2095 brcm_log_list: A list of specific NMEA pattern logs. 2096 """ 2097 brcm_log_list = [] 2098 brcm_log_error_pattern = ["lhd: FS: Start Failsafe dump", "E slog"] 2099 brcm_error_log_list = [] 2100 stop_pixel_logger(ad) 2101 pixellogger_path = ( 2102 "/sdcard/Android/data/com.android.pixellogger/files/logs/gps/.") 2103 tmp_log_path = tempfile.mkdtemp() 2104 ad.pull_files(pixellogger_path, tmp_log_path) 2105 for path_key in os.listdir(tmp_log_path): 2106 zip_path = posixpath.join(tmp_log_path, path_key) 2107 if path_key.endswith(".zip"): 2108 ad.log.info("Processing zip file: {}".format(zip_path)) 2109 with zipfile.ZipFile(zip_path, "r") as zip_file: 2110 zip_file.extractall(tmp_log_path) 2111 gl_logs = zip_file.namelist() 2112 # b/214145973 check if hidden exists in pixel logger zip file 2113 tmp_file = [name for name in gl_logs if 'tmp' in name] 2114 if tmp_file: 2115 ad.log.warn(f"Hidden file {tmp_file} exists in pixel logger zip file") 2116 break 2117 elif os.path.isdir(zip_path): 2118 ad.log.info("BRCM logs didn't zip properly. Log path is directory.") 2119 tmp_log_path = zip_path 2120 gl_logs = os.listdir(tmp_log_path) 2121 ad.log.info("Processing BRCM log files: {}".format(gl_logs)) 2122 break 2123 else: 2124 raise signals.TestError( 2125 "No BRCM logs found in {}".format(os.listdir(tmp_log_path))) 2126 gl_logs = [log for log in gl_logs 2127 if log.startswith("gl") and log.endswith(".log")] 2128 for file in gl_logs: 2129 nmea_log_path = posixpath.join(tmp_log_path, file) 2130 ad.log.info("Parsing log pattern of \"%s\" in %s" % (nmea_pattern, 2131 nmea_log_path)) 2132 brcm_log = open(nmea_log_path, "r", encoding="UTF-8", errors="ignore") 2133 lines = brcm_log.readlines() 2134 for line in lines: 2135 if nmea_pattern in line: 2136 brcm_log_list.append(line) 2137 for attr in brcm_log_error_pattern: 2138 if attr in line: 2139 benign_log = False 2140 for allow_log in brcm_error_log_allowlist: 2141 if allow_log in line: 2142 benign_log = True 2143 ad.log.info("\"%s\" is in allow-list and removed " 2144 "from error." % allow_log) 2145 if not benign_log: 2146 brcm_error_log_list.append(line) 2147 brcm_error_log = "".join(brcm_error_log_list) 2148 shutil.rmtree(tmp_log_path, ignore_errors=True) 2149 return brcm_log_list, brcm_error_log 2150 2151 2152def check_dpo_rate_via_brcm_log(ad, dpo_threshold, brcm_error_log_allowlist): 2153 """Check DPO engage rate through "$PGLOR,11,STA" in BRCM Log. 2154 D - Disabled, Always full power. 2155 F - Enabled, now in full power mode. 2156 S - Enabled, now in power save mode. 2157 H - Host off load mode. 2158 2159 Args: 2160 ad: An AndroidDevice object. 2161 dpo_threshold: The value to set threshold. (Ex: dpo_threshold = 60) 2162 brcm_error_log_allowlist: Benign error logs to exclude. 2163 """ 2164 always_full_power_count = 0 2165 full_power_count = 0 2166 power_save_count = 0 2167 pglor_list, brcm_error_log = parse_brcm_nmea_log( 2168 ad, "$PGLOR,11,STA", brcm_error_log_allowlist) 2169 if not pglor_list: 2170 raise signals.TestFailure("Fail to get DPO logs from pixel logger") 2171 2172 for pglor in pglor_list: 2173 power_res = re.compile(r',P,(\w),').search(pglor).group(1) 2174 if power_res == "D": 2175 always_full_power_count += 1 2176 elif power_res == "F": 2177 full_power_count += 1 2178 elif power_res == "S": 2179 power_save_count += 1 2180 ad.log.info(sorted(pglor_list)[0]) 2181 ad.log.info(sorted(pglor_list)[-1]) 2182 ad.log.info("TestResult Total_Count %d" % len(pglor_list)) 2183 ad.log.info("TestResult Always_Full_Power_Count %d" % 2184 always_full_power_count) 2185 ad.log.info("TestResult Full_Power_Mode_Count %d" % full_power_count) 2186 ad.log.info("TestResult Power_Save_Mode_Count %d" % power_save_count) 2187 dpo_rate = (power_save_count / len(pglor_list)) 2188 dpo_engage_rate = "{percent:.2%}".format(percent=dpo_rate) 2189 ad.log.info("Power Save Mode is ON for %d seconds during %d seconds test." 2190 % (power_save_count, len(pglor_list))) 2191 ad.log.info("TestResult DPO_Engage_Rate " + dpo_engage_rate) 2192 threshold = "{percent:.0%}".format(percent=dpo_threshold / 100) 2193 asserts.assert_true((dpo_rate * 100 > dpo_threshold) and not brcm_error_log, 2194 "Power Save Mode only engaged %s in %d seconds test " 2195 "with threshold %s.\nAbnormal behavior found as below." 2196 "\n%s" % (dpo_engage_rate, 2197 len(pglor_list), 2198 threshold, 2199 brcm_error_log)) 2200 2201 2202def pair_to_wearable(ad, ad1): 2203 """Pair phone to watch via Bluetooth. 2204 2205 Args: 2206 ad: A pixel phone. 2207 ad1: A wearable project. 2208 """ 2209 check_location_service(ad1) 2210 utils.sync_device_time(ad1) 2211 bt_model_name = ad.adb.getprop("ro.product.model") 2212 bt_sn_name = ad.adb.getprop("ro.serialno") 2213 bluetooth_name = bt_model_name +" " + bt_sn_name[10:] 2214 fastboot_factory_reset(ad, False) 2215 ad.log.info("Wait 1 min for wearable system busy time.") 2216 time.sleep(60) 2217 ad.adb.shell("input keyevent 4") 2218 # Clear Denali paired data in phone. 2219 ad1.adb.shell("pm clear com.google.android.gms") 2220 ad1.adb.shell("pm clear com.google.android.apps.wear.companion") 2221 ad1.adb.shell("am start -S -n com.google.android.apps.wear.companion/" 2222 "com.google.android.apps.wear.companion.application.RootActivity") 2223 uia_click(ad1, "Next") 2224 uia_click(ad1, "I agree") 2225 uia_click(ad1, bluetooth_name) 2226 uia_click(ad1, "Pair") 2227 uia_click(ad1, "Skip") 2228 uia_click(ad1, "Skip") 2229 uia_click(ad1, "Finish") 2230 ad.log.info("Wait 3 mins for complete pairing process.") 2231 time.sleep(180) 2232 ad.adb.shell("settings put global stay_on_while_plugged_in 7") 2233 check_location_service(ad) 2234 enable_gnss_verbose_logging(ad) 2235 if is_bluetooth_connected(ad, ad1): 2236 ad.log.info("Pairing successfully.") 2237 else: 2238 raise signals.TestFailure("Fail to pair watch and phone successfully.") 2239 2240 2241def is_bluetooth_connected(ad, ad1): 2242 """Check if device's Bluetooth status is connected or not. 2243 2244 Args: 2245 ad: A wearable project 2246 ad1: A pixel phone. 2247 """ 2248 return ad.droid.bluetoothIsDeviceConnected(ad1.droid.bluetoothGetLocalAddress()) 2249 2250 2251def detect_crash_during_tracking(ad, begin_time, type): 2252 """Check if GNSS or GPSTool crash happened druing GNSS Tracking. 2253 2254 Args: 2255 ad: An AndroidDevice object. 2256 begin_time: Start Time to check if crash happened in logs. 2257 type: Using GNSS or FLP reading method in GNSS tracking. 2258 """ 2259 gnss_crash_list = [".*Fatal signal.*gnss", 2260 ".*Fatal signal.*xtra", 2261 ".*F DEBUG.*gnss", 2262 ".*Fatal signal.*gpsd"] 2263 if not ad.is_adb_logcat_on: 2264 ad.start_adb_logcat() 2265 for attr in gnss_crash_list: 2266 gnss_crash_result = ad.adb.shell( 2267 "logcat -d | grep -E -i '%s'" % attr) 2268 if gnss_crash_result: 2269 start_gnss_by_gtw_gpstool(ad, state=False, type=type) 2270 raise signals.TestFailure( 2271 "Test failed due to GNSS HAL crashed. \n%s" % 2272 gnss_crash_result) 2273 gpstool_crash_result = ad.search_logcat("Force finishing activity " 2274 "com.android.gpstool/.GPSTool", 2275 begin_time) 2276 if gpstool_crash_result: 2277 raise signals.TestError("GPSTool crashed. Abort test.") 2278 2279 2280def is_wearable_btwifi(ad): 2281 """Check device is wearable btwifi sku or not. 2282 2283 Args: 2284 ad: An AndroidDevice object. 2285 """ 2286 package = ad.adb.getprop("ro.product.product.name") 2287 ad.log.debug("[ro.product.product.name]: [%s]" % package) 2288 return "btwifi" in package 2289 2290 2291def compare_watch_phone_location(ad,watch_file, phone_file): 2292 """Compare watch and phone's FLP location to see if the same or not. 2293 2294 Args: 2295 ad: An AndroidDevice object. 2296 watch_file: watch's FLP locations 2297 phone_file: phone's FLP locations 2298 """ 2299 not_match_location_counts = 0 2300 not_match_location = [] 2301 for watch_key, watch_value in watch_file.items(): 2302 if phone_file.get(watch_key): 2303 lat_ads = abs(float(watch_value[0]) - float(phone_file[watch_key][0])) 2304 lon_ads = abs(float(watch_value[1]) - float(phone_file[watch_key][1])) 2305 if lat_ads > 0.000002 or lon_ads > 0.000002: 2306 not_match_location_counts += 1 2307 not_match_location += (watch_key, watch_value, phone_file[watch_key]) 2308 if not_match_location_counts > 0: 2309 ad.log.info("There are %s not match locations: %s" %(not_match_location_counts, not_match_location)) 2310 ad.log.info("Watch's locations are not using Phone's locations.") 2311 return False 2312 else: 2313 ad.log.info("Watch's locations are using Phone's location.") 2314 return True 2315 2316 2317def check_tracking_file(ad): 2318 """Check tracking file in device and save "Latitude", "Longitude", and "Time" information. 2319 2320 Args: 2321 ad: An AndroidDevice object. 2322 2323 Returns: 2324 location_reports: A dict with [latitude, longitude] 2325 """ 2326 location_reports = dict() 2327 test_logfile = {} 2328 file_count = int(ad.adb.shell("find %s -type f -iname *.txt | wc -l" 2329 % GNSSSTATUS_LOG_PATH)) 2330 if file_count != 1: 2331 ad.log.error("%d API logs exist." % file_count) 2332 dir_file = ad.adb.shell("ls %s" % GNSSSTATUS_LOG_PATH).split() 2333 for path_key in dir_file: 2334 if fnmatch.fnmatch(path_key, "*.txt"): 2335 logpath = posixpath.join(GNSSSTATUS_LOG_PATH, path_key) 2336 out = ad.adb.shell("wc -c %s" % logpath) 2337 file_size = int(out.split(" ")[0]) 2338 if file_size < 10: 2339 ad.log.info("Skip log %s due to log size %d bytes" % 2340 (path_key, file_size)) 2341 continue 2342 test_logfile = logpath 2343 if not test_logfile: 2344 raise signals.TestError("Failed to get test log file in device.") 2345 lines = ad.adb.shell("cat %s" % test_logfile).split("\n") 2346 for file_data in lines: 2347 if "Latitude:" in file_data: 2348 file_lat = ("%.6f" %float(file_data[9:])) 2349 elif "Longitude:" in file_data: 2350 file_long = ("%.6f" %float(file_data[11:])) 2351 elif "Time:" in file_data: 2352 file_time = (file_data[17:25]) 2353 location_reports[file_time] = [file_lat, file_long] 2354 return location_reports 2355 2356 2357def uia_click(ad, matching_text): 2358 """Use uiautomator to click objects. 2359 2360 Args: 2361 ad: An AndroidDevice object. 2362 matching_text: Text of the target object to click 2363 """ 2364 if ad.uia(textMatches=matching_text).wait.exists(timeout=60000): 2365 2366 ad.uia(textMatches=matching_text).click() 2367 ad.log.info("Click button %s" % matching_text) 2368 else: 2369 ad.log.error("No button named %s" % matching_text) 2370 2371 2372def delete_bcm_nvmem_sto_file(ad): 2373 """Delete BCM's NVMEM ephemeris gldata.sto. 2374 2375 Args: 2376 ad: An AndroidDevice object. 2377 """ 2378 remount_device(ad) 2379 rm_cmd = "rm -rf {}".format(BCM_NVME_STO_PATH) 2380 status = ad.adb.shell(rm_cmd) 2381 ad.log.info("Delete BCM's NVMEM ephemeris files.\n%s" % status) 2382 2383 2384def bcm_gps_xml_add_option(ad, 2385 search_line=None, 2386 append_txt=None, 2387 gps_xml_path=BCM_GPS_XML_PATH): 2388 """Append parameter setting in gps.xml for BCM solution 2389 2390 Args: 2391 ad: An AndroidDevice object. 2392 search_line: Pattern matching of target 2393 line for appending new line data. 2394 append_txt: New line that will be appended after the search_line. 2395 gps_xml_path: gps.xml file location of DUT 2396 """ 2397 remount_device(ad) 2398 #Update gps.xml 2399 if not search_line or not append_txt: 2400 ad.log.info("Nothing for update.") 2401 else: 2402 tmp_log_path = tempfile.mkdtemp() 2403 ad.pull_files(gps_xml_path, tmp_log_path) 2404 gps_xml_tmp_path = os.path.join(tmp_log_path, "gps.xml") 2405 gps_xml_file = open(gps_xml_tmp_path, "r") 2406 lines = gps_xml_file.readlines() 2407 gps_xml_file.close() 2408 fout = open(gps_xml_tmp_path, "w") 2409 append_txt_tag = append_txt.strip() 2410 for line in lines: 2411 if append_txt_tag in line: 2412 ad.log.info('{} is already in the file. Skip'.format(append_txt)) 2413 continue 2414 fout.write(line) 2415 if search_line in line: 2416 fout.write(append_txt) 2417 ad.log.info("Update new line: '{}' in gps.xml.".format(append_txt)) 2418 fout.close() 2419 2420 # Update gps.xml with gps_new.xml 2421 ad.push_system_file(gps_xml_tmp_path, gps_xml_path) 2422 2423 # remove temp folder 2424 shutil.rmtree(tmp_log_path, ignore_errors=True) 2425 2426 2427def bcm_gps_ignore_rom_alm(ad): 2428 """ Update BCM gps.xml with ignoreRomAlm="True" 2429 Args: 2430 ad: An AndroidDevice object. 2431 """ 2432 search_line_tag = '<gll\n' 2433 append_line_str = ' IgnoreRomAlm=\"true\"\n' 2434 bcm_gps_xml_add_option(ad, search_line_tag, append_line_str) 2435 2436 2437def check_inject_time(ad): 2438 """Check if watch could get the UTC time. 2439 2440 Args: 2441 ad: An AndroidDevice object. 2442 """ 2443 for i in range(1, 6): 2444 time.sleep(10) 2445 inject_time_results = ad.search_logcat("GPSIC.OUT.gps_inject_time") 2446 ad.log.info("Check time injected - attempt %s" % i) 2447 if inject_time_results: 2448 ad.log.info("Time is injected successfully.") 2449 return True 2450 raise signals.TestFailure("Fail to get time injected within %s attempts." % i) 2451 2452 2453def enable_framework_log(ad): 2454 """Enable framework log for wearable to check UTC time download. 2455 2456 Args: 2457 ad: An AndroidDevice object. 2458 """ 2459 remount_device(ad) 2460 time.sleep(3) 2461 ad.log.info("Start to enable framwork log for wearable.") 2462 ad.adb.shell("echo 'log.tag.LocationManagerService=VERBOSE' >> /data/local.prop") 2463 ad.adb.shell("echo 'log.tag.GnssLocationProvider=VERBOSE' >> /data/local.prop") 2464 ad.adb.shell("echo 'log.tag.GpsNetInitiatedHandler=VERBOSE' >> /data/local.prop") 2465 ad.adb.shell("echo 'log.tag.GnssNetInitiatedHandler=VERBOSE' >> /data/local.prop") 2466 ad.adb.shell("echo 'log.tag.GnssNetworkConnectivityHandler=VERBOSE' >> /data/local.prop") 2467 ad.adb.shell("echo 'log.tag.NtpTimeHelper=VERBOSE' >> /data/local.prop") 2468 ad.adb.shell("echo 'log.tag.ConnectivityService=VERBOSE' >> /data/local.prop") 2469 ad.adb.shell("echo 'log.tag.GnssPsdsDownloader=VERBOSE' >> /data/local.prop") 2470 ad.adb.shell("echo 'log.tag.GnssVisibilityControl=VERBOSE' >> /data/local.prop") 2471 ad.adb.shell("echo 'log.tag.Gnss=VERBOSE' >> /data/local.prop") 2472 ad.adb.shell("echo 'log.tag.GnssConfiguration=VERBOSE' >> /data/local.prop") 2473 ad.adb.shell("echo 'log.tag.ImsPhone=VERBOSE' >> /data/local.prop") 2474 ad.adb.shell("echo 'log.tag.GsmCdmaPhone=VERBOSE' >> /data/local.prop") 2475 ad.adb.shell("echo 'log.tag.Phone=VERBOSE' >> /data/local.prop") 2476 ad.adb.shell("echo 'log.tag.GCoreFlp=VERBOSE' >> /data/local.prop") 2477 ad.adb.shell("chmod 644 /data/local.prop") 2478 ad.adb.shell("echo 'LogEnabled=true' > /data/vendor/gps/libgps.conf") 2479 ad.adb.shell("chown gps.system /data/vendor/gps/libgps.conf") 2480 ad.adb.shell("sync") 2481 reboot(ad) 2482 ad.log.info("Wait 2 mins for Wearable booting system busy") 2483 time.sleep(120) 2484