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. 16 17import os 18import time 19import glob 20import errno 21 22from acts import utils 23from acts import asserts 24from acts import signals 25from acts import base_test 26from pandas import DataFrame 27from collections import namedtuple 28from acts.controllers.spectracom_lib import gsg6 29from acts.test_utils.gnss import dut_log_test_utils as diaglog 30from acts_contrib.test_utils.gnss import gnss_test_utils as gutils 31from acts_contrib.test_utils.gnss import gnss_testlog_utils as glogutils 32 33DEVICE_GPSLOG_FOLDER = '/sdcard/Android/data/com.android.gpstool/files/' 34GPS_PKG_NAME = 'com.android.gpstool' 35 36class LabTtffTest(base_test.BaseTestClass): 37 38 """ LAB TTFF Tests""" 39 GTW_GPSTOOL_APP = 'gtw_gpstool_apk' 40 SPECTRACOM_IP_KEY = 'spectracom_ip' 41 SPECTRACOM_PORT_KEY = 'spectracom_port' 42 SPECTRACOM_FILES_KEY = 'spectracom_files' 43 SPECTRACOM_POWER_KEY = 'spectracom_power_level' 44 SPIRENT_IP_KEY = 'spirent_ip' 45 SPIRENT_SCENARIO = 'sprient_scenario' 46 CUSTOM_FILES_KEY = 'custom_files' 47 CSTTFF_CRITERIA = 'cs_criteria' 48 HSTTFF_CRITERIA = 'hs_criteria' 49 WSTTFF_CRITERIA = 'ws_criteria' 50 CSTTFF_PECRITERIA = 'cs_ttff_pecriteria' 51 HSTTFF_PECRITERIA = 'hs_ttff_pecriteria' 52 WSTTFF_PECRITERIA = 'ws_ttff_pecriteria' 53 TTFF_ITERATION = 'ttff_iteration' 54 SIMULATOR_LOCATION = 'simulator_location' 55 DIAG_OPTION = 'diag_option' 56 57 def __init__(self, controllers): 58 """ Initializes class attributes. """ 59 60 super().__init__(controllers) 61 62 self.dut = None 63 self.spectracom = None 64 65 def setup_class(self): 66 super().setup_class() 67 68 req_params = [ 69 self.SPECTRACOM_IP_KEY, self.SPECTRACOM_PORT_KEY, 70 self.SPECTRACOM_FILES_KEY, self.SPECTRACOM_POWER_KEY, 71 self.CSTTFF_CRITERIA, self.HSTTFF_CRITERIA, 72 self.WSTTFF_CRITERIA, self.TTFF_ITERATION, 73 self.SIMULATOR_LOCATION, self.DIAG_OPTION 74 ] 75 76 for param in req_params: 77 if param not in self.user_params: 78 self.log.error('Required parameter {} is missing in config ' 79 'file.'.format(param)) 80 raise signals.TestAbortClass( 81 'Required parameter {} is missing in config ' 82 'file.'.format(param)) 83 self.dut = self.android_devices[0] 84 self.spectracom_ip = self.user_params[self.SPECTRACOM_IP_KEY] 85 self.spectracom_port = self.user_params[self.SPECTRACOM_PORT_KEY] 86 self.spectracom_file = self.user_params[self.SPECTRACOM_FILES_KEY] 87 self.spectracom_power = self.user_params[self.SPECTRACOM_POWER_KEY] 88 self.gtw_gpstool_app = self.user_params[self.GTW_GPSTOOL_APP] 89 custom_files = self.user_params.get(self.CUSTOM_FILES_KEY, []) 90 self.cs_ttff_criteria = self.user_params.get(self.CSTTFF_CRITERIA, []) 91 self.hs_ttff_criteria = self.user_params.get(self.HSTTFF_CRITERIA, []) 92 self.ws_ttff_criteria = self.user_params.get(self.WSTTFF_CRITERIA, []) 93 self.cs_ttff_pecriteria = self.user_params.get( 94 self.CSTTFF_PECRITERIA, []) 95 self.hs_ttff_pecriteria = self.user_params.get( 96 self.HSTTFF_PECRITERIA, []) 97 self.ws_ttff_pecriteria = self.user_params.get( 98 self.WSTTFF_PECRITERIA, []) 99 self.ttff_iteration = self.user_params.get(self.TTFF_ITERATION, []) 100 self.simulator_location = self.user_params.get( 101 self.SIMULATOR_LOCATION, []) 102 self.diag_option = self.user_params.get(self.DIAG_OPTION, []) 103 104 test_type = namedtuple('Type', ['command', 'criteria']) 105 self.test_types = { 106 'cs': test_type('Cold Start', self.cs_ttff_criteria), 107 'ws': test_type('Warm Start', self.ws_ttff_criteria), 108 'hs': test_type('Hot Start', self.hs_ttff_criteria) 109 } 110 111 # Unpack the rockbottom script or fail class setup if it can't be found 112 for file in custom_files: 113 if 'rockbottom_' + self.dut.model in file: 114 self.rockbottom_script = file 115 break 116 else: 117 raise signals.TestAbortClass( 118 'Required rockbottom script is missing.') 119 120 def setup_test(self): 121 122 self.clear_gps_log() 123 self.spectracom = gsg6.GSG6(self.spectracom_ip, self.spectracom_port) 124 125 self.spectracom.stop_scenario() 126 time.sleep(10) 127 self.spectracom.close() 128 129 self.dut_rockbottom() 130 utils.set_location_service(self.dut, True) 131 gutils.reinstall_package_apk(self.dut, GPS_PKG_NAME, 132 self.gtw_gpstool_app) 133 self.spectracom = gsg6.GSG6(self.spectracom_ip, self.spectracom_port) 134 self.spectracom.connect() 135 136 def dut_rockbottom(self): 137 """ 138 Set the dut to rockbottom state 139 140 """ 141 # The rockbottom script might include a device reboot, so it is 142 # necessary to stop SL4A during its execution. 143 self.dut.stop_services() 144 self.log.info('Executing rockbottom script for ' + self.dut.model) 145 os.chmod(self.rockbottom_script, 0o777) 146 os.system('{} {}'.format(self.rockbottom_script, self.dut.serial)) 147 # Make sure the DUT is in root mode after coming back 148 self.dut.root_adb() 149 # Restart SL4A 150 self.dut.start_services() 151 152 def teardown_class(self): 153 """ Executed after completing all selected test cases.""" 154 self.clear_gps_log() 155 if self.spectracom: 156 self.spectracom.stop_scenario() 157 time.sleep(10) 158 self.spectracom.close() 159 160 def start_and_set_spectracom_power(self): 161 """ 162 Start spectracom secnario and set power level. 163 164 """ 165 166 self.spectracom.start_scenario(self.spectracom_file) 167 time.sleep(25) 168 self.spectracom.set_power(self.spectracom_power) 169 170 def get_and_verify_ttff(self, mode): 171 """Retrieve ttff with designate mode. 172 173 Args: 174 mode: A string for identify gnss test mode. 175 """ 176 if mode not in self.test_types: 177 raise signals.TestError('Unrecognized mode %s' % mode) 178 test_type = self.test_types.get(mode) 179 180 gutils.process_gnss_by_gtw_gpstool(self.dut, 181 self.test_types['cs'].criteria) 182 begin_time = gutils.get_current_epoch_time() 183 gutils.start_ttff_by_gtw_gpstool( 184 self.dut, ttff_mode=mode, 185 iteration=self.ttff_iteration, aid_data=True) 186 ttff_data = gutils.process_ttff_by_gtw_gpstool(self.dut, begin_time, 187 self.simulator_location) 188 189 gps_log_path = os.path.join(self.log_path, 'GPSLogs') 190 self.dut.adb.pull("{} {}".format(DEVICE_GPSLOG_FOLDER, gps_log_path)) 191 192 gps_api_log = glob.glob(gps_log_path + '/GPS_API_*.txt') 193 ttff_loop_log = glob.glob(gps_log_path + '/GPS_{}_*.txt'. 194 format(mode.upper())) 195 196 if not gps_api_log and ttff_loop_log: 197 raise FileNotFoundError(errno.ENOENT, os.strerror(errno.ENOENT), 198 gps_log_path) 199 200 df = DataFrame(glogutils.parse_gpstool_ttfflog_to_df(gps_api_log[0])) 201 202 ttff_dict = {} 203 for i in ttff_data: 204 d = ttff_data[i]._asdict() 205 ttff_dict[i] = dict(d) 206 207 ttff_time =[] 208 ttff_pe = [] 209 for i, k in ttff_dict.items(): 210 ttff_time.append(ttff_dict[i]['ttff_time']) 211 ttff_pe.append(ttff_dict[i]['ttff_pe']) 212 df['ttff_time'] = ttff_time 213 df['ttff_pe'] = ttff_pe 214 df.to_json(gps_log_path + '/gps_log.json', orient='table') 215 result = gutils.check_ttff_data( 216 self.dut, 217 ttff_data, 218 ttff_mode=test_type.command, 219 criteria=test_type.criteria) 220 if not result: 221 raise signals.TestFailure('%s TTFF fails to reach ' 222 'designated criteria' 223 % test_type.command) 224 return ttff_data 225 226 def verify_pe(self, mode): 227 """ 228 Verify ttff Position Error with designate mode. 229 230 Args: 231 mode: A string for identify gnss test mode. 232 """ 233 234 ffpe_type = namedtuple('Type', ['command', 'pecriteria']) 235 ffpe_types = { 236 'cs': ffpe_type('Cold Start', self.cs_ttff_pecriteria), 237 'ws': ffpe_type('Warm Start', self.ws_ttff_pecriteria), 238 'hs': ffpe_type('Hot Start', self.hs_ttff_pecriteria) 239 } 240 241 if mode not in self.test_types: 242 raise signals.TestError('Unrecognized mode %s' % mode) 243 test_type = self.test_types.get(mode) 244 245 ttff_data = self.get_and_verify_ttff(mode) 246 result = gutils.check_ttff_pe( 247 self.dut, 248 ttff_data, 249 ttff_mode=test_type.command, 250 pecriteria=test_type.pecriteria 251 ) 252 if not result: 253 raise signals.TestFailure('%s TTFF fails to reach ' 254 'designated criteria' 255 % test_type.command) 256 return ttff_data 257 258 def clear_gps_log(self): 259 """ 260 Delete the existing GPS GTW Log from DUT. 261 262 """ 263 self.dut.adb.shell("rm -rf {}".format(DEVICE_GPSLOG_FOLDER)) 264 265 def test_gnss_cold_ttff_ffpe(self): 266 267 self.start_and_set_spectracom_power() 268 if self.diag_option is "QCOM": 269 diaglog.start_diagmdlog_background(self.dut, maskfile=self.maskfile) 270 else: 271 #start_tbdlog() yet to add for Broadcom 272 pass 273 self.verify_pe('cs') 274 diaglog.stop_background_diagmdlog(self.dut, self.qxdm_log_path, keep_logs=False) 275 276 def test_gnss_warm_ttff_ffpe(self): 277 278 self.start_and_set_spectracom_power() 279 if self.diag_option is "QCOM": 280 diaglog.start_diagmdlog_background(self.dut, maskfile=self.maskfile) 281 else: 282 #start_tbdlog() yet to add for Broadcom 283 pass 284 self.verify_pe('ws') 285 diaglog.stop_background_diagmdlog(self.dut, self.qxdm_log_path, keep_logs=False) 286 287 def test_gnss_hot_ttff_ffpe(self): 288 289 self.start_and_set_spectracom_power() 290 if self.diag_option is "QCOM": 291 diaglog.start_diagmdlog_background(self.dut, maskfile=self.maskfile) 292 else: 293 #start_tbdlog() yet to add for Broadcom 294 pass 295 self.verify_pe('hs') 296 diaglog.stop_background_diagmdlog(self.dut, self.qxdm_log_path, keep_logs=False) 297 298