• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python3.5
2#
3#   Copyright 2019 - Google
4#
5#   Licensed under the Apache License, Version 2.0 (the "License");
6#   you may not use this file except in compliance with the License.
7#   You may obtain a copy of the License at
8#
9#       http://www.apache.org/licenses/LICENSE-2.0
10#
11#   Unless required by applicable law or agreed to in writing, software
12#   distributed under the License is distributed on an "AS IS" BASIS,
13#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14#   See the License for the specific language governing permissions and
15#   limitations under the License.
16
17import time
18import re
19import os
20import logging
21
22from acts import utils
23from acts import signals
24from acts.controllers.android_device import list_adb_devices
25from acts.controllers.android_device import list_fastboot_devices
26from acts.controllers.android_device import DEFAULT_QXDM_LOG_PATH
27from acts.controllers.android_device import SL4A_APK_NAME
28from acts.test_utils.wifi import wifi_test_utils as wutils
29from acts.test_utils.tel import tel_test_utils as tutils
30from acts.utils import get_current_epoch_time
31
32WifiEnums = wutils.WifiEnums
33PULL_TIMEOUT = 300
34GNSSSTATUS_LOG_PATH = "/storage/emulated/0/Android/data/com.android.gpstool/files"
35QXDM_MASKS = ["GPS-general.cfg", "GPS.cfg", "default.cfg"]
36
37
38class GnssTestUtilsError(Exception):
39    pass
40
41def remount_device(ad):
42    """Remount device file system to read and write.
43
44    Args:
45        ad: An AndroidDevice object.
46    """
47    remount_flag = 0
48    for retries in range(2):
49        ad.root_adb()
50        remount_result = ad.adb.remount()
51        ad.log.info("Attempt %d - %s" % (retries + 1, remount_result))
52        if "remount succeeded" in remount_result or remount_flag == 1:
53            break
54        if ad.adb.getprop("ro.boot.veritymode") == "enforcing":
55            remount_flag = 1
56            disable_verity_result = ad.adb.disable_verity()
57            ad.log.info("%s" % disable_verity_result)
58            ad.reboot()
59            ad.unlock_screen(password=None)
60
61def enable_gnss_verbose_logging(ad):
62    """Enable GNSS VERBOSE Logging and logd.
63
64    Args:
65        ad: An AndroidDevice object.
66    """
67    remount_device(ad)
68    ad.log.info("Enable GNSS VERBOSE Logging and logd.")
69    ad.adb.shell("echo DEBUG_LEVEL = 5 >> /vendor/etc/gps.conf")
70    ad.adb.shell("echo log.tag.LocationManagerService=VERBOSE >> /data/local.prop")
71    ad.adb.shell("echo log.tag.GnssLocationProvider=VERBOSE >> /data/local.prop")
72    ad.adb.shell("echo log.tag.GnssMeasurementsProvider=VERBOSE >> /data/local.prop")
73    ad.adb.shell("chmod 644 /data/local.prop")
74    ad.adb.shell("setprop persist.logd.logpersistd logcatd")
75    ad.adb.shell("setprop persist.vendor.radio.adb_log_on 1")
76    ad.adb.shell("setprop log.tag.copresGcore VERBOSE")
77    ad.adb.shell("sync")
78
79def disable_xtra_throttle(ad):
80    """Disable XTRA throttle will have no limit to download XTRA data.
81
82    Args:
83        ad: An AndroidDevice object.
84    """
85    remount_device(ad)
86    ad.log.info("Disable XTRA Throttle.")
87    ad.adb.shell("echo XTRA_TEST_ENABLED=1 >> /vendor/etc/gps.conf")
88    ad.adb.shell("echo XTRA_THROTTLE_ENABLED=0 >> /vendor/etc/gps.conf")
89
90def enable_supl_mode(ad):
91    """Enable SUPL back on for next test item.
92
93    Args:
94        ad: An AndroidDevice object.
95    """
96    remount_device(ad)
97    ad.log.info("Enable SUPL mode.")
98    ad.adb.shell("echo SUPL_MODE=1 >> /etc/gps_debug.conf")
99
100def disable_supl_mode(ad):
101    """Kill SUPL to test XTRA only test item.
102
103    Args:
104        ad: An AndroidDevice object.
105    """
106    remount_device(ad)
107    ad.log.info("Disable SUPL mode.")
108    ad.adb.shell("echo SUPL_MODE=0 >> /etc/gps_debug.conf")
109    ad.log.info("Reboot device to make changes take effect.")
110    ad.reboot()
111    ad.unlock_screen(password=None)
112
113def kill_xtra_daemon(ad):
114    """Kill XTRA daemon to test SUPL only test item.
115
116    Args:
117        ad: An AndroidDevice object.
118    """
119    ad.root_adb()
120    ad.log.info("Disable XTRA-daemon until next reboot.")
121    ad.adb.shell("killall xtra-daemon")
122
123def disable_private_dns_mode(ad):
124    """Due to b/118365122, it's better to disable private DNS mode while
125       testing. 8.8.8.8 private dns sever is unstable now, sometimes server
126       will not response dns query suddenly.
127
128    Args:
129        ad: An AndroidDevice object.
130    """
131    tutils.get_operator_name(ad.log, ad, subId=None)
132    if ad.adb.shell("settings get global private_dns_mode") != "off":
133        ad.log.info("Disable Private DNS mode.")
134        ad.adb.shell("settings put global private_dns_mode off")
135
136def _init_device(ad):
137    """Init GNSS test devices.
138
139    Args:
140        ad: An AndroidDevice object.
141    """
142    set_mobile_data(ad, True)
143    disable_private_dns_mode(ad)
144    tutils.synchronize_device_time(ad)
145    enable_gnss_verbose_logging(ad)
146    disable_xtra_throttle(ad)
147    enable_supl_mode(ad)
148    ad.adb.shell("svc power stayon true")
149    ad.adb.shell("settings put system screen_off_timeout 1800000")
150    wutils.wifi_toggle_state(ad, False)
151    ad.log.info("Setting Bluetooth state to False")
152    ad.droid.bluetoothToggleState(False)
153    set_gnss_qxdm_mask(ad, QXDM_MASKS)
154    check_location_service(ad)
155    set_wifi_and_bt_scanning(ad, True)
156    ad.reboot()
157    ad.unlock_screen(password=None)
158
159def connect_to_wifi_network(ad, network):
160    """Connection logic for open and psk wifi networks.
161
162    Args:
163        ad: An AndroidDevice object.
164        network: Dictionary with network info.
165    """
166    SSID = network[WifiEnums.SSID_KEY]
167    ad.ed.clear_all_events()
168    wutils.start_wifi_connection_scan(ad)
169    scan_results = ad.droid.wifiGetScanResults()
170    wutils.assert_network_in_list({WifiEnums.SSID_KEY: SSID}, scan_results)
171    wutils.wifi_connect(ad, network, num_of_tries=5)
172
173def set_wifi_and_bt_scanning(ad, state=True):
174    """Set Wi-Fi and Bluetooth scanning on/off in Settings -> Location
175
176    Args:
177        ad: An AndroidDevice object.
178        state: State for "Wi-Fi and Bluetooth scanning".
179        If state is True, turn on "Wi-Fi and Bluetooth scanning".
180        If state is False, turn off "Wi-Fi and Bluetooth scanning".
181    """
182    ad.root_adb()
183    if state:
184        ad.adb.shell("settings put global wifi_scan_always_enabled 1")
185        ad.adb.shell("settings put global ble_scan_always_enabled 1")
186        ad.log.info("Wi-Fi and Bluetooth scanning are enabled")
187    else:
188        ad.adb.shell("settings put global wifi_scan_always_enabled 0")
189        ad.adb.shell("settings put global ble_scan_always_enabled 0")
190        ad.log.info("Wi-Fi and Bluetooth scanning are disabled")
191
192def check_location_service(ad):
193    """Set location service on.
194       Verify if location service is available.
195
196    Args:
197        ad: An AndroidDevice object.
198
199    Return:
200        True : location service is on.
201        False : location service is off.
202    """
203    utils.set_location_service(ad, True)
204    out = ad.adb.shell("settings get secure location_providers_allowed")
205    ad.log.info("Current Location Provider >> %s" % out)
206    if "gps,network" in out:
207        return True
208    return False
209
210def clear_logd_gnss_qxdm_log(ad):
211    """Clear /data/misc/logd,
212    /storage/emulated/0/Android/data/com.android.gpstool/files and
213    /data/vendor/radio/diag_logs/logs from previous test item then reboot.
214
215    Args:
216        ad: An AndroidDevice object.
217    """
218    remount_device(ad)
219    ad.log.info("Clear Logd, GNSS and QXDM Log from previous test item.")
220    ad.adb.shell("rm -rf /data/misc/logd", ignore_status=True)
221    ad.adb.shell("rm -rf %s" % GNSSSTATUS_LOG_PATH, ignore_status=True)
222    output_path = os.path.join(DEFAULT_QXDM_LOG_PATH, "logs")
223    ad.adb.shell("rm -rf %s" % output_path, ignore_status=True)
224    ad.reboot()
225    ad.unlock_screen(password=None)
226
227def get_gnss_qxdm_log(ad, test_name=""):
228    """Get /storage/emulated/0/Android/data/com.android.gpstool/files and
229    /data/vendor/radio/diag_logs/logs for failed test item.
230
231    Args:
232        ad: An AndroidDevice object.
233    """
234    log_path_base = getattr(logging, "log_path", "/tmp/logs")
235    log_path = os.path.join(log_path_base, "AndroidDevice%s" % ad.serial)
236    utils.create_dir(log_path)
237    gnss_log_path = os.path.join(log_path, test_name, "gnssstatus_log_%s_%s"
238                                 % (ad.model, ad.serial))
239    utils.create_dir(gnss_log_path)
240    ad.log.info("Pull GnssStatus Log to %s" % gnss_log_path)
241    ad.adb.pull("%s %s" % (GNSSSTATUS_LOG_PATH, gnss_log_path),
242                timeout=PULL_TIMEOUT, ignore_status=True)
243    output_path = os.path.join(DEFAULT_QXDM_LOG_PATH, "logs")
244    file_count = ad.adb.shell("find %s -type f -iname *.qmdl | wc -l" % output_path)
245    if not int(file_count) == 0:
246        qxdm_log_path = os.path.join(log_path, test_name, "QXDM_%s_%s"
247                                     % (ad.model, ad.serial))
248        utils.create_dir(qxdm_log_path)
249        ad.log.info("Pull QXDM Log %s to %s" % (output_path, qxdm_log_path))
250        ad.adb.pull("%s %s" % (output_path, qxdm_log_path),
251                    timeout=PULL_TIMEOUT, ignore_status=True)
252        if ad.model == "sailfish" or ad.model == "marlin":
253            ad.adb.pull("/firmware/radio/qdsp6m.qdb %s" % qxdm_log_path,
254                        timeout=PULL_TIMEOUT, ignore_status=True)
255        elif ad.model == "walleye":
256            ad.adb.pull("/firmware/image/qdsp6m.qdb %s" % qxdm_log_path,
257                        timeout=PULL_TIMEOUT, ignore_status=True)
258        else:
259            ad.adb.pull("/vendor/firmware_mnt/image/qdsp6m.qdb %s"
260                        % qxdm_log_path, timeout=PULL_TIMEOUT, ignore_status=True)
261    else:
262        ad.log.error("QXDM file count is %d. There is no QXDM log on device."
263                     % int(file_count))
264
265def start_youtube_video(ad, url=None, retries=0):
266    """Start youtube video and verify if audio is in music state.
267
268    Args:
269        ad: An AndroidDevice object.
270        url: Website for youtube video
271        retries: Retry times if audio is not in music state.
272
273    Returns:
274        True if youtube video is playing normally.
275        False if youtube video is not playing properly.
276    """
277    ad.droid.setMediaVolume(25)
278    for i in range(retries):
279        ad.log.info("Open an youtube video - attempt %d" % (i+1))
280        ad.adb.shell("am start -a android.intent.action.VIEW -d \"%s\"" % url)
281        time.sleep(1)
282        out = ad.adb.shell("dumpsys activity | grep \"NewVersionAvailableActivity\"")
283        if out:
284            ad.log.info("Skip Youtube New Version Update.")
285            ad.send_keycode("BACK")
286        if tutils.wait_for_state(ad.droid.audioIsMusicActive, True, 15, 1):
287            ad.log.info("Started a video in youtube, audio is in MUSIC state")
288            return True
289        ad.log.info("Force-Stop youtube and reopen youtube again.")
290        ad.force_stop_apk("com.google.android.youtube")
291        time.sleep(1)
292    ad.log.error("Started a video in youtube, but audio is not in MUSIC state")
293    return False
294
295def set_mobile_data(ad, state):
296    """Set mobile data on or off and check mobile data state.
297
298    Args:
299        ad: An AndroidDevice object.
300        state: True to enable mobile data. False to disable mobile data.
301    """
302    ad.root_adb()
303    if state:
304        ad.log.info("Enable mobile data.")
305        ad.adb.shell("svc data enable")
306    else:
307        ad.log.info("Disable mobile data.")
308        ad.adb.shell("svc data disable")
309    time.sleep(5)
310    out = int(ad.adb.shell("settings get global mobile_data"))
311    if state and out == 1:
312        ad.log.info("Mobile data is enabled and set to %d" % out)
313    elif not state and out == 0:
314        ad.log.info("Mobile data is disabled and set to %d" % out)
315    else:
316        ad.log.error("Mobile data is at unknown state and set to %d" % out)
317
318def get_modem_ssr_crash_count(ad):
319    """Check current modem SSR crash count.
320
321    Args:
322        ad: An AndroidDevice object.
323
324    Returns:
325        Times of current modem SSR crash count
326    """
327    crash_count = 0
328    ad.send_keycode("HOME")
329    ad.log.info("Check modem SSR crash count...")
330    total_subsys = ad.adb.shell("ls /sys/bus/msm_subsys/devices/")
331    for i in range(0, len(total_subsys.split())):
332        crash_count = int(ad.adb.shell("cat /sys/bus/msm_subsys/devices/"
333                                       "subsys%d/crash_count" % i))
334        ad.log.info("subsys%d crash_count is %d" % (i, crash_count))
335        if crash_count != 0:
336            return crash_count
337    return crash_count
338
339def check_xtra_download(ad, begin_time):
340    """Verify XTRA download success log message in logcat.
341
342    Args:
343        ad: An AndroidDevice object.
344        begin_time: test begin time
345
346    Returns:
347        True: xtra_download if XTRA downloaded and injected successfully
348        otherwise return False.
349    """
350    ad.send_keycode("HOME")
351    logcat_results = ad.search_logcat("XTRA download success. "
352                                      "inject data into modem", begin_time)
353    if logcat_results:
354        ad.log.info("%s" % logcat_results[-1]["log_message"])
355        ad.log.info("XTRA downloaded and injected successfully.")
356        return True
357    ad.log.error("XTRA downloaded FAIL.")
358    return False
359
360def pull_gtw_gpstool(ad):
361    """Pull GTW_GPSTool apk from device.
362
363    Args:
364        ad: An AndroidDevice object.
365    """
366    out = ad.adb.shell("pm path com.android.gpstool")
367    result = re.search(r"package:(.*)", out)
368    if not result:
369        tutils.abort_all_tests(ad.log, "Couldn't find GTW GPSTool apk")
370    else:
371        GTW_GPSTool_apk = result.group(1)
372        ad.log.info("Get GTW GPSTool apk from %s" % GTW_GPSTool_apk)
373        apkdir = "/tmp/GNSS/"
374        utils.create_dir(apkdir)
375        ad.pull_files([GTW_GPSTool_apk], apkdir)
376
377def reinstall_gtw_gpstool(ad):
378    """Reinstall GTW_GPSTool apk.
379
380    Args:
381        ad: An AndroidDevice object.
382    """
383    ad.log.info("Re-install GTW GPSTool")
384    ad.adb.install("-r -g /tmp/GNSS/base.apk")
385
386def fastboot_factory_reset(ad):
387    """Factory reset the device in fastboot mode.
388       Pull sl4a apk from device. Terminate all sl4a sessions,
389       Reboot the device to bootloader,
390       factory reset the device by fastboot.
391       Reboot the device. wait for device to complete booting
392       Re-install and start an sl4a session.
393
394    Args:
395        ad: An AndroidDevice object.
396
397    Returns:
398        True if factory reset process complete.
399    """
400    status = True
401    skip_setup_wizard = True
402    out = ad.adb.shell("pm path %s" % SL4A_APK_NAME)
403    result = re.search(r"package:(.*)", out)
404    if not result:
405        tutils.abort_all_tests(ad.log, "Couldn't find sl4a apk")
406    else:
407        sl4a_apk = result.group(1)
408        ad.log.info("Get sl4a apk from %s" % sl4a_apk)
409        ad.pull_files([sl4a_apk], "/tmp/")
410    pull_gtw_gpstool(ad)
411    tutils.stop_qxdm_logger(ad)
412    ad.stop_services()
413    attempts = 3
414    for i in range(1, attempts + 1):
415        try:
416            if ad.serial in list_adb_devices():
417                ad.log.info("Reboot to bootloader")
418                ad.adb.reboot("bootloader", ignore_status=True)
419                time.sleep(10)
420            if ad.serial in list_fastboot_devices():
421                ad.log.info("Factory reset in fastboot")
422                ad.fastboot._w(timeout=300, ignore_status=True)
423                time.sleep(30)
424                ad.log.info("Reboot in fastboot")
425                ad.fastboot.reboot()
426            ad.wait_for_boot_completion()
427            ad.root_adb()
428            if ad.skip_sl4a:
429                break
430            if ad.is_sl4a_installed():
431                break
432            ad.log.info("Re-install sl4a")
433            ad.adb.shell("settings put global verifier_verify_adb_installs 0")
434            ad.adb.shell("settings put global package_verifier_enable 0")
435            ad.adb.install("-r -g /tmp/base.apk")
436            reinstall_gtw_gpstool(ad)
437            time.sleep(10)
438            break
439        except Exception as e:
440            ad.log.error(e)
441            if i == attempts:
442                tutils.abort_all_tests(ad.log, str(e))
443            time.sleep(5)
444    try:
445        ad.start_adb_logcat()
446    except Exception as e:
447        ad.log.error(e)
448    if skip_setup_wizard:
449        ad.exit_setup_wizard()
450    if ad.skip_sl4a:
451        return status
452    tutils.bring_up_sl4a(ad)
453    set_gnss_qxdm_mask(ad, QXDM_MASKS)
454    return status
455
456def clear_aiding_data_by_gtw_gpstool(ad):
457    """Launch GTW GPSTool and Clear all GNSS aiding data.
458       Wait 5 seconds for GTW GPStool to clear all GNSS aiding
459       data properly.
460
461    Args:
462        ad: An AndroidDevice object.
463    """
464    ad.log.info("Launch GTW GPSTool and Clear all GNSS aiding data")
465    ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode clear")
466    time.sleep(10)
467
468def start_gnss_by_gtw_gpstool(ad, state):
469    """Start or stop GNSS on GTW_GPSTool.
470
471    Args:
472        ad: An AndroidDevice object.
473        state: True to start GNSS. False to Stop GNSS.
474    """
475    if state:
476        ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode gps")
477    if not state:
478        ad.log.info("Stop GNSS on GTW_GPSTool.")
479        ad.adb.shell("am broadcast -a com.android.gpstool.stop_gps_action")
480    time.sleep(3)
481
482def process_gnss_by_gtw_gpstool(ad, criteria):
483    """Launch GTW GPSTool and Clear all GNSS aiding data
484       Start GNSS tracking on GTW_GPSTool.
485
486    Args:
487        ad: An AndroidDevice object.
488        criteria: Criteria for current test item.
489
490    Returns:
491        True: First fix TTFF are within criteria.
492        False: First fix TTFF exceed criteria.
493    """
494    retries = 3
495    for i in range(retries):
496        begin_time = get_current_epoch_time()
497        clear_aiding_data_by_gtw_gpstool(ad)
498        ad.log.info("Start GNSS on GTW_GPSTool - attempt %d" % (i+1))
499        start_gnss_by_gtw_gpstool(ad, True)
500        for _ in range(10 + criteria):
501            logcat_results = ad.search_logcat("First fixed", begin_time)
502            if logcat_results:
503                first_fixed = int(logcat_results[-1]["log_message"].split()[-1])
504                ad.log.info("GNSS First fixed = %.3f seconds" % (first_fixed / 1000))
505                if (first_fixed / 1000) <= criteria:
506                    return True
507                ad.log.error("DUT takes more than %d seconds to get location "
508                             "fixed. Test Abort and Close GPS for next test "
509                             "item." % criteria)
510                start_gnss_by_gtw_gpstool(ad, False)
511                return False
512            time.sleep(1)
513        start_gnss_by_gtw_gpstool(ad, False)
514        if not ad.is_adb_logcat_on:
515            ad.start_adb_logcat()
516    ad.log.error("Test Abort. DUT can't get location fixed within %d attempts."
517                 % retries)
518    return False
519
520def start_ttff_by_gtw_gpstool(ad, ttff_mode, iteration):
521    """Identify which TTFF mode for different test items.
522
523    Args:
524        ad: An AndroidDevice object.
525        ttff_mode: TTFF Test mode for current test item.
526        iteration: Iteration of TTFF cycles.
527    """
528    if ttff_mode == "ws":
529        ad.log.info("Wait 5 minutes to start TTFF Warm Start...")
530        time.sleep(300)
531    if ttff_mode == "cs":
532        ad.log.info("Start TTFF Cold Start...")
533        time.sleep(3)
534    ad.adb.shell("am broadcast -a com.android.gpstool.ttff_action "
535                 "--es ttff %s --es cycle %d" % (ttff_mode, iteration))
536
537def process_ttff_by_gtw_gpstool(ad, begin_time):
538    """Process and save TTFF results.
539
540    Args:
541        ad: An AndroidDevice object.
542        begin_time: test begin time
543
544    Returns:
545        ttff_result: A list of saved TTFF seconds.
546    """
547    loop = 1
548    ttff_result = []
549    ttff_log_loop = []
550    while True:
551        stop_gps_results = ad.search_logcat("stop gps test()", begin_time)
552        if stop_gps_results:
553            ad.send_keycode("HOME")
554            break
555        crash_result = ad.search_logcat("Force finishing activity "
556                                        "com.android.gpstool/.GPSTool", begin_time)
557        if crash_result:
558            ad.log.error("GPSTool crashed. Abort test.")
559            break
560        logcat_results = ad.search_logcat("write TTFF log", begin_time)
561        if logcat_results:
562            ttff_log = logcat_results[-1]["log_message"].split()
563            if not ttff_log_loop:
564                ttff_log_loop.append(ttff_log[8].split(":")[-1])
565            elif ttff_log[8].split(":")[-1] == ttff_log_loop[loop-1]:
566                continue
567            if ttff_log[11] == "0.0":
568                ad.log.error("Iteration %d = Timeout" % loop)
569            else:
570                ad.log.info("Iteration %d = %s seconds" % (loop, ttff_log[11]))
571            ttff_log_loop.append(ttff_log[8].split(":")[-1])
572            ttff_result.append(float(ttff_log[11]))
573            loop += 1
574        if not ad.is_adb_logcat_on:
575            ad.start_adb_logcat()
576    return ttff_result
577
578def check_ttff_result(ad, ttff_result, ttff_mode, criteria):
579    """Verify all TTFF results.
580
581    Args:
582        ad: An AndroidDevice object.
583        ttff_result: A list of saved TTFF seconds.
584        ttff_mode: TTFF Test mode for current test item.
585        criteria: Criteria for current test item.
586
587    Returns:
588        True: All TTFF results are within criteria.
589        False: One or more TTFF results exceed criteria or Timeout.
590    """
591    ad.log.info("%d iterations of TTFF %s tests finished."
592                % (len(ttff_result), ttff_mode))
593    ad.log.info("%s PASS criteria is %d seconds" % (ttff_mode, criteria))
594    if len(ttff_result) == 0:
595        ad.log.error("GTW_GPSTool didn't process TTFF properly.")
596        return False
597    elif any(float(ttff_result[i]) == 0.0 for i in range(len(ttff_result))):
598        ad.log.error("One or more TTFF %s Timeout" % ttff_mode)
599        return False
600    elif any(float(ttff_result[i]) >= criteria for i in range(len(ttff_result))):
601        ad.log.error("One or more TTFF %s are over test criteria %d seconds"
602                     % (ttff_mode, criteria))
603        return False
604    ad.log.info("All TTFF %s are within test criteria %d seconds."
605                % (ttff_mode, criteria))
606    return True
607
608def launch_google_map(ad):
609    """Launch Google Map via intent.
610
611    Args:
612        ad: An AndroidDevice object.
613    """
614    ad.log.info("Launch Google Map.")
615    try:
616        ad.adb.shell("am start -S -n com.google.android.apps.maps/"
617                     "com.google.android.maps.MapsActivity")
618        ad.send_keycode("BACK")
619        ad.force_stop_apk("com.google.android.apps.maps")
620        ad.adb.shell("am start -S -n com.google.android.apps.maps/"
621                     "com.google.android.maps.MapsActivity")
622    except Exception as e:
623        ad.log.error(e)
624        raise signals.TestFailure("Failed to launch google map.")
625
626def check_location_api(ad, retries):
627    """Verify if GnssLocationProvider API reports location.
628
629    Args:
630        ad: An AndroidDevice object.
631        retries: Retry time.
632
633    Returns:
634        True: GnssLocationProvider API reports location.
635        otherwise return False.
636    """
637    for i in range(retries):
638        begin_time = get_current_epoch_time()
639        ad.log.info("Try to get location report from GnssLocationProvider API "
640                    "- attempt %d" % (i+1))
641        while get_current_epoch_time() - begin_time <= 30000:
642            logcat_results = ad.search_logcat("REPORT_LOCATION", begin_time)
643            if logcat_results:
644                ad.log.info("%s" % logcat_results[-1]["log_message"])
645                ad.log.info("GnssLocationProvider reports location successfully.")
646                return True
647        if not ad.is_adb_logcat_on:
648            ad.start_adb_logcat()
649    ad.log.error("GnssLocationProvider is unable to report location.")
650    return False
651
652def check_network_location(ad, retries, location_type):
653    """Verify if NLP reports location after requesting via GPSTool.
654
655    Args:
656        ad: An AndroidDevice object.
657        retries: Retry time.
658        location_type: neworkLocationType of cell or wifi.
659
660    Returns:
661        True: NLP reports location.
662        otherwise return False.
663    """
664    for i in range(retries):
665        time.sleep(1)
666        begin_time = get_current_epoch_time()
667        ad.log.info("Try to get NLP status - attempt %d" % (i+1))
668        ad.adb.shell("am start -S -n com.android.gpstool/.GPSTool --es mode nlp")
669        while get_current_epoch_time() - begin_time <= 30000:
670            logcat_results = ad.search_logcat(
671                "LocationManagerService: incoming location: Location", begin_time)
672            if logcat_results:
673                for logcat_result in logcat_results:
674                    if location_type in logcat_result["log_message"]:
675                        ad.log.info(logcat_result["log_message"])
676                        ad.send_keycode("BACK")
677                        return True
678        if not ad.is_adb_logcat_on:
679            ad.start_adb_logcat()
680        ad.send_keycode("BACK")
681    ad.log.error("Unable to report network location \"%s\"." % location_type)
682    return False
683
684def set_attenuator_gnss_signal(ad, attenuator, atten_value):
685    """Set attenuation value for different GNSS signal.
686
687    Args:
688        ad: An AndroidDevice object.
689        attenuator: The attenuator object.
690        atten_value: attenuation value
691    """
692    ad.log.info("Set attenuation value to \"%d\" for GNSS signal." % atten_value)
693    try:
694        attenuator[0].set_atten(atten_value)
695        time.sleep(3)
696        atten_val = int(attenuator[0].get_atten())
697        ad.log.info("Current attenuation value is \"%d\"" % atten_val)
698    except Exception as e:
699        ad.log.error(e)
700        raise signals.TestFailure("Failed to set attenuation for gnss signal.")
701
702def set_battery_saver_mode(ad, state):
703    """Enable or diable battery saver mode via adb.
704
705    Args:
706        ad: An AndroidDevice object.
707        state: True is enable Battery Saver mode. False is disable.
708    """
709    ad.root_adb()
710    if state:
711        ad.log.info("Enable Battery Saver mode.")
712        ad.adb.shell("cmd battery unplug")
713        ad.adb.shell("settings put global low_power 1")
714    else:
715        ad.log.info("Disable Battery Saver mode.")
716        ad.adb.shell("settings put global low_power 0")
717        ad.adb.shell("cmd battery reset")
718
719def set_gnss_qxdm_mask(ad, masks):
720    """Find defined gnss qxdm mask and set as default logging mask.
721
722    Args:
723        ad: An AndroidDevice object.
724        masks: Defined gnss qxdm mask.
725    """
726    try:
727        for mask in masks:
728            if not tutils.find_qxdm_log_mask(ad, mask):
729                continue
730            tutils.set_qxdm_logger_command(ad, mask)
731            break
732    except Exception as e:
733        ad.log.error(e)
734        raise signals.TestFailure("Failed to set any QXDM masks.")
735