1#!/usr/bin/env python3 2# 3# Copyright 2020 - The Android Open Source Project 4# 5# Licensed under the Apache License, Version 2.0 (the "License"); 6# you may not use this file except in compliance with the License. 7# You may obtain a copy of the License at 8# 9# http://www.apache.org/licenses/LICENSE-2.0 10# 11# Unless required by applicable law or agreed to in writing, software 12# distributed under the License is distributed on an "AS IS" BASIS, 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14# See the License for the specific language governing permissions and 15# limitations under the License. 16import time 17import statistics 18 19from acts import asserts 20from acts import signals 21from acts.base_test import BaseTestClass 22from acts_contrib.test_utils.gnss.testtracker_util import log_testtracker_uuid 23from acts_contrib.test_utils.gnss import gnss_test_utils as gutils 24from acts_contrib.test_utils.tel import tel_logging_utils as tutils 25from acts_contrib.test_utils.tel.tel_test_utils import verify_internet_connection 26from acts_contrib.test_utils.tel.tel_test_utils import toggle_airplane_mode 27from acts.utils import get_current_epoch_time 28from acts_contrib.test_utils.gnss.gnss_test_utils import delete_lto_file, pair_to_wearable 29from acts_contrib.test_utils.gnss.gnss_test_utils import process_gnss_by_gtw_gpstool 30from acts_contrib.test_utils.gnss.gnss_test_utils import start_gnss_by_gtw_gpstool 31from acts_contrib.test_utils.gnss.gnss_test_utils import check_tracking_file 32from uiautomator import Device 33 34 35class GnssWearableTetherFunctionTest(BaseTestClass): 36 """ GNSS Wearable Tether Function Tests""" 37 def setup_class(self): 38 super().setup_class() 39 self.watch = self.android_devices[0] 40 self.phone = self.android_devices[1] 41 self.phone.uia = Device(self.phone.serial) 42 req_params = ["pixel_lab_network", "standalone_cs_criteria", 43 "flp_ttff_max_threshold", "pixel_lab_location", 44 "flp_ttff_cycle", "default_gnss_signal_attenuation", 45 "flp_waiting_time", "tracking_test_time", 46 "far_start_criteria", "ttff_test_cycle"] 47 self.unpack_userparams(req_param_names=req_params) 48 # create hashmap for SSID 49 self.ssid_map = {} 50 for network in self.pixel_lab_network: 51 SSID = network["SSID"] 52 self.ssid_map[SSID] = network 53 self.ttff_mode = {"cs": "Cold Start", 54 "ws": "Warm Start", 55 "hs": "Hot Start"} 56 gutils._init_device(self.watch) 57 pair_to_wearable(self.watch, self.phone) 58 59 def teardown_class(self): 60 super().teardown_class() 61 gutils.reboot(self.phone) 62 63 def setup_test(self): 64 gutils.log_current_epoch_time(self.watch, "test_start_time") 65 log_testtracker_uuid(self.watch, self.current_test_name) 66 gutils.get_baseband_and_gms_version(self.watch) 67 gutils.clear_logd_gnss_qxdm_log(self.watch) 68 gutils.clear_logd_gnss_qxdm_log(self.phone) 69 gutils.set_attenuator_gnss_signal(self.watch, self.attenuators, 70 self.default_gnss_signal_attenuation) 71 if not verify_internet_connection(self.watch.log, self.watch, retries=5, 72 expected_state=True): 73 time.sleep(60) 74 if not verify_internet_connection(self.watch.log, self.watch, retries=3, 75 expected_state=True): 76 raise signals.TestFailure("Fail to connect to LTE network.") 77 78 def teardown_test(self): 79 gutils.stop_pixel_logger(self.watch) 80 tutils.stop_adb_tcpdump(self.watch) 81 gutils.set_attenuator_gnss_signal(self.watch, self.attenuators, 82 self.default_gnss_signal_attenuation) 83 if self.watch.droid.connectivityCheckAirplaneMode(): 84 self.watch.log.info("Force airplane mode off") 85 toggle_airplane_mode(self.watch.log, self.watch, new_state=False) 86 gutils.log_current_epoch_time(self.watch, "test_end_time") 87 88 def on_fail(self, test_name, begin_time): 89 self.watch.take_bug_report(test_name, begin_time) 90 gutils.get_gnss_qxdm_log(self.watch) 91 tutils.get_tcpdump_log(self.watch, test_name, begin_time) 92 93 def start_qxdm_and_tcpdump_log(self): 94 """Start QXDM and adb tcpdump if collect_logs is True.""" 95 gutils.start_pixel_logger(self.watch) 96 tutils.start_adb_tcpdump(self.watch) 97 98 def flp_ttff(self, mode, criteria, location): 99 self.start_qxdm_and_tcpdump_log() 100 start_gnss_by_gtw_gpstool(self.phone, True, api_type="FLP") 101 time.sleep(self.flp_waiting_time) 102 self.watch.unlock_screen(password=None) 103 begin_time = get_current_epoch_time() 104 process_gnss_by_gtw_gpstool( 105 self.watch, self.standalone_cs_criteria, api_type="flp") 106 gutils.start_ttff_by_gtw_gpstool( 107 self.watch, mode, iteration=self.flp_ttff_cycle) 108 results = gutils.process_ttff_by_gtw_gpstool( 109 self.watch, begin_time, location, api_type="flp") 110 gutils.check_ttff_data(self.watch, results, mode, criteria) 111 self.check_location_from_phone() 112 start_gnss_by_gtw_gpstool(self.phone, False, api_type="FLP") 113 114 def check_location_from_phone(self): 115 watch_file = check_tracking_file(self.watch) 116 phone_file = check_tracking_file(self.phone) 117 return gutils.compare_watch_phone_location(self, watch_file, phone_file) 118 119 def run_ttff_via_gtw_gpstool(self, mode, criteria): 120 """Run GNSS TTFF test with selected mode and parse the results. 121 122 Args: 123 mode: "cs", "ws" or "hs" 124 criteria: Criteria for the TTFF. 125 """ 126 begin_time = get_current_epoch_time() 127 gutils.process_gnss_by_gtw_gpstool(self.watch, self.standalone_cs_criteria, clear_data=False) 128 gutils.start_ttff_by_gtw_gpstool(self.watch, mode, self.ttff_test_cycle) 129 ttff_data = gutils.process_ttff_by_gtw_gpstool( 130 self.watch, begin_time, self.pixel_lab_location) 131 result = gutils.check_ttff_data( 132 self.watch, ttff_data, self.ttff_mode.get(mode), criteria) 133 asserts.assert_true( 134 result, "TTFF %s fails to reach designated criteria of %d " 135 "seconds." % (self.ttff_mode.get(mode), criteria)) 136 137 """ Test Cases """ 138 def test_flp_ttff_cs(self): 139 """Verify FLP TTFF Cold Start while tether with phone. 140 141 Steps: 142 1. Pair with phone via Bluetooth. 143 2. FLP TTFF Cold Start for 10 iteration. 144 3. Check location source is from Phone. 145 146 Expected Results: 147 1. FLP TTFF Cold Start results should be within 148 flp_ttff_max_threshold. 149 2. Watch uses phone's FLP location. 150 """ 151 self.flp_ttff("cs", self.flp_ttff_max_threshold, self.pixel_lab_location) 152 153 def test_flp_ttff_ws(self): 154 """Verify FLP TTFF Warm Start while tether with phone. 155 156 Steps: 157 1. Pair with phone via Bluetooth. 158 2. FLP TTFF Warm Start for 10 iteration. 159 3. Check location source is from Phone. 160 161 Expected Results: 162 1. FLP TTFF Warm Start results should be within 163 flp_ttff_max_threshold. 164 2. Watch uses phone's FLP location. 165 """ 166 self.flp_ttff("ws", self.flp_ttff_max_threshold, self.pixel_lab_location) 167 168 def test_flp_ttff_hs(self): 169 """Verify FLP TTFF Hot Start while tether with phone. 170 171 Steps: 172 1. Pair with phone via Bluetooth. 173 2. FLP TTFF Hot Start for 10 iteration. 174 3. Check location source is from Phone. 175 176 Expected Results: 177 1. FLP TTFF Hot Start results should be within 178 flp_ttff_max_threshold. 179 2. Watch uses phone's FLP location. 180 """ 181 self.flp_ttff("hs", self.flp_ttff_max_threshold, self.pixel_lab_location) 182 183 def test_tracking_during_bt_disconnect_resume(self): 184 """Verify tracking is correct during Bluetooth disconnect and resume. 185 186 Steps: 187 1. Make sure watch Bluetooth is on and in paired status. 188 2. Do 1 min tracking. 189 3. After 1 min tracking, check location source is using phone's FLP. 190 4. Turn off watch Bluetooth, and do 1 min tracking. 191 5. After 1 min tracking, check tracking results. 192 6. Repeat Step 1 to Step 5 for 5 times. 193 194 Expected Results: 195 1. Watch uses phone's FLP location in Bluetooth connect state. 196 2. Tracking results should be within pixel_lab_location criteria. 197 """ 198 self.start_qxdm_and_tcpdump_log() 199 for i in range(1, 4): 200 if not self.watch.droid.bluetoothCheckState(): 201 self.watch.droid.bluetoothToggleState(True) 202 self.watch.log.info("Turn Bluetooth on") 203 self.watch.log.info("Wait 40s for Bluetooth auto re-connect") 204 time.sleep(40) 205 if not gutils.is_bluetooth_connected(self.watch, self.phone): 206 raise signals.TestFailure("Fail to connect to device via Bluetooth.") 207 start_gnss_by_gtw_gpstool(self.phone, True, api_type="FLP") 208 time.sleep(self.flp_waiting_time) 209 start_gnss_by_gtw_gpstool(self.watch, True, api_type="FLP") 210 time.sleep(self.flp_waiting_time) 211 self.watch.log.info("Wait 1 min for tracking") 212 time.sleep(self.tracking_test_time) 213 if not self.check_location_from_phone(): 214 raise signals.TestFailure("Watch is not using phone location") 215 self.watch.droid.bluetoothToggleState(False) 216 self.watch.log.info("Turn off Watch Bluetooth") 217 self.watch.log.info("Wait 1 min for tracking") 218 time.sleep(self.tracking_test_time) 219 if self.check_location_from_phone(): 220 raise signals.TestError("Watch should not use phone location") 221 gutils.parse_gtw_gpstool_log(self.watch, self.pixel_lab_location, api_type="FLP") 222 start_gnss_by_gtw_gpstool(self.phone, False, api_type="FLP") 223 224 def test_oobe_first_fix(self): 225 """Verify first fix after OOBE pairing within the criteria 226 227 Steps: 228 1. Pair watch to phone during OOBE. 229 2. Ensure LTO file download in watch. 230 3. Ensure UTC time inject in watch. 231 4. Enable AirPlane mode to untether to phone. 232 5. Open GPSTool to get first fix in LTO and UTC time injected. 233 6. Repeat Step1 ~ Step5 for 5 times. 234 235 Expected Results: 236 1. First fix should be within far_start_threshold. 237 """ 238 oobe_results_all = [] 239 for i in range(1,4): 240 self.watch.log.info("First fix after OOBE pairing - attempts %s" % i) 241 pair_to_wearable(self.watch, self.phone) 242 self.start_qxdm_and_tcpdump_log() 243 begin_time = get_current_epoch_time() 244 gutils.check_xtra_download(self.watch, begin_time) 245 gutils.check_inject_time(self.watch) 246 self.watch.log.info("Turn airplane mode on") 247 # self.watch.droid.connectivityToggleAirplaneMode(True) 248 toggle_airplane_mode(self.watch.log, self.watch, new_state=True) 249 oobe_results = gutils.process_gnss( 250 self.watch, self.far_start_criteria, clear_data=False) 251 oobe_results_all.append(oobe_results) 252 self.watch.log.info(f"TestResult Max_OOBE_First_Fix {max(oobe_results_all)}") 253 self.watch.log.info(f"TestResult Avg_OOBE_First_Fix {statistics.mean(oobe_results_all)}") 254 # self.watch.droid.connectivityToggleAirplaneMode(False) 255 toggle_airplane_mode(self.watch.log, self.watch, new_state=False) 256 self.watch.log.info("Turn airplane mode off") 257 258 def test_oobe_first_fix_with_network_connection(self): 259 """Verify first fix after OOBE pairing within the criteria 260 261 Steps: 262 1. Pair watch to phone during OOBE. 263 2. Ensure LTO file download in watch. 264 3. Ensure UTC time inject in watch. 265 4. Turn off Bluetooth to untether to phone. 266 5. Open GPSTool to get first fix in LTO and UTC time injected. 267 6. Repeat Step1 ~ Step5 for 5 times. 268 269 Expected Results: 270 1. First fix should be within far_start_threshold. 271 """ 272 oobe_results_all = [] 273 for i in range(1,4): 274 self.watch.log.info("First fix after OOBE pairing - attempts %s" % i) 275 pair_to_wearable(self.watch, self.phone) 276 self.start_qxdm_and_tcpdump_log() 277 begin_time = get_current_epoch_time() 278 gutils.check_xtra_download(self.watch, begin_time) 279 gutils.check_inject_time(self.watch) 280 self.watch.log.info("Turn off Bluetooth to disconnect to phone") 281 self.watch.droid.bluetoothToggleState(False) 282 oobe_results = gutils.process_gnss( 283 self.watch, self.far_start_criteria, clear_data=False) 284 oobe_results_all.append(oobe_results) 285 self.watch.log.info(f"TestResult Max_OOBE_First_Fix {max(oobe_results_all)}") 286 self.watch.log.info(f"TestResult Avg_OOBE_First_Fix {statistics.mean(oobe_results_all)}") 287 288 def test_far_start_ttff(self): 289 """Verify Far Start (Warm Start v4) TTFF within the criteria 290 291 Steps: 292 1. Pair watch to phone during OOBE. 293 2. Ensure LTO file download in watch. 294 3. Ensure UTC time inject in watch. 295 4. Enable AirPlane mode to untether to phone. 296 5. TTFF Warm Start for 10 iteration. 297 298 Expected Results: 299 1. TTFF should be within far_start_threshold. 300 """ 301 pair_to_wearable(self.watch, self.phone) 302 self.start_qxdm_and_tcpdump_log() 303 begin_time = get_current_epoch_time() 304 gutils.check_xtra_download(self.watch, begin_time) 305 gutils.check_inject_time(self.watch) 306 self.watch.log.info("Turn airplane mode on") 307 toggle_airplane_mode(self.watch.log, self.watch, new_state=True) 308 self.run_ttff_via_gtw_gpstool("ws", self.far_start_criteria) 309