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 17 18from acts import signals 19from acts import utils 20from acts_contrib.test_utils.power.PowerBaseTest import PowerBaseTest 21from acts_contrib.test_utils.gnss import gnss_test_utils as gutils 22from acts_contrib.test_utils.wifi import wifi_test_utils as wutils 23 24DEFAULT_WAIT_TIME = 60 25DPO_NV_VALUE = '15DC' 26MDS_TEST_PACKAGE = 'com.google.mdstest' 27MDS_RUNNER = 'com.google.mdstest.instrument.ModemConfigInstrumentation' 28 29 30class PowerGTWGnssBaseTest(PowerBaseTest): 31 """Power GTW Gnss Base test""" 32 33 def setup_class(self): 34 super().setup_class() 35 self.ad = self.android_devices[0] 36 req_params = [ 37 'wifi_network', 'test_location', 'qdsp6m_path', 38 'calibrate_target', 'interval', 'meas_interval' 39 ] 40 self.unpack_userparams(req_param_names=req_params) 41 self.set_xtra_data() 42 43 def setup_test(self): 44 gutils.log_current_epoch_time(self.ad, "test_start_time") 45 super().setup_test() 46 # Enable DPO 47 self.enable_DPO(True) 48 # Enable GNSS setting for GNSS standalone mode 49 self.ad.adb.shell('settings put secure location_mode 3') 50 # Recover attenuation value to strong CN 51 self.set_attenuation(self.atten_level['strong_signal']) 52 53 def teardown_test(self): 54 begin_time = utils.get_current_epoch_time() 55 self.ad.take_bug_report(self.test_name, begin_time) 56 gutils.get_gnss_qxdm_log(self.ad, self.qdsp6m_path) 57 gutils.log_current_epoch_time(self.ad, "test_end_time") 58 59 def set_xtra_data(self): 60 gutils.disable_xtra_throttle(self.ad) 61 self.turn_on_wifi_connection() 62 gutils.enable_gnss_verbose_logging(self.ad) 63 gutils.start_gnss_by_gtw_gpstool(self.ad, True, 'gnss') 64 time.sleep(30) 65 gutils.start_gnss_by_gtw_gpstool(self.ad, False, 'gnss') 66 67 def turn_on_wifi_connection(self): 68 """Turn on wifi connection.""" 69 wutils.wifi_toggle_state(self.ad, True) 70 gutils.connect_to_wifi_network(self.ad, self.wifi_network) 71 72 def set_cell_only(self): 73 """Turn off wifi connection, enable cell service.""" 74 wutils.wifi_toggle_state(self.ad, False) 75 utils.force_airplane_mode(self.ad, False) 76 77 def baseline_test(self): 78 """Baseline power measurement""" 79 self.ad.droid.goToSleepNow() 80 self.collect_power_data() 81 self.ad.log.info('TestResult AVG_Current %.2f' % self.avg_current) 82 83 def start_gnss_tracking_with_power_data(self, 84 mode='default', 85 is_signal=True, 86 freq=0, 87 lowpower=False, 88 meas=False): 89 """Start GNSS tracking and collect power metrics. 90 91 Args: 92 is_signal: default True, False for no Gnss signal test. 93 freq: an integer to set location update frequency. 94 lowpower: a boolean to set GNSS Low Power Mode. 95 meas: a boolean to set GNSS Measurement registeration. 96 """ 97 c_power, c_tracking, c_acquisition = self.request_power_stat() 98 self.ad.adb.shell('settings put secure location_mode 3') 99 gutils.start_gnss_by_gtw_gpstool(self.ad, True, 'gnss', True, freq, 100 lowpower, meas) 101 self.ad.droid.goToSleepNow() 102 103 self.ad.log.info('Collect SV data for %d seconds.' % DEFAULT_WAIT_TIME) 104 time.sleep(DEFAULT_WAIT_TIME) 105 106 samples = self.collect_power_data() 107 self.ad.log.info('TestResult AVG_Current %.2f' % self.avg_current) 108 self.calibrate_avg_current(samples) 109 self.ad.send_keycode('WAKEUP') 110 111 gutils.start_gnss_by_gtw_gpstool(self.ad, False, 'gnss') 112 n_power, n_tracking, n_acquisition = self.request_power_stat() 113 self.ad.log.info("TestResult Total_power: %.2f" %(n_power - c_power)) 114 self.ad.log.info("TestResult Tracking: %.2f" %(n_tracking - c_tracking)) 115 self.ad.log.info("TestResult Acquisition: %.2f" %(n_acquisition - c_acquisition)) 116 gutils.parse_gtw_gpstool_log(self.ad, self.test_location, type='gnss') 117 118 def calibrate_avg_current(self, samples): 119 """Calibrate average current by filtering AP wake up current with target 120 value. 121 122 Args: 123 samples: a list of tuples where the first element is a timestamp 124 and the second element is a current sample. 125 """ 126 calibrate_results = [ 127 sample[1] * 1000 for sample in samples 128 if sample[1] * 1000 < self.calibrate_target 129 ] 130 avg_current = sum(calibrate_results) / len(calibrate_results) 131 self.ad.log.info('TestResult Calibrate_AVG_Current %.2f' % avg_current) 132 133 def enable_DPO(self, enable): 134 """Enable or disable the DPO option. 135 136 Args: 137 enable: True or False to enable DPO. 138 """ 139 self.ad.log.info('Change DPO to new state: %s.' % enable) 140 val = '02' if enable else '00' 141 options = {'request': 'writeNV', 'item': DPO_NV_VALUE, 'data': val} 142 instrument_cmd = gutils.build_instrumentation_call( 143 MDS_TEST_PACKAGE, MDS_RUNNER, options=options) 144 result = self.ad.adb.shell(instrument_cmd) 145 if 'SUCCESS' not in result: 146 self.ad.log.info(result) 147 raise signals.TestFailure('DPO is not able to Turn: %s' % enable) 148 self.dut_rockbottom() 149 150 def request_power_stat(self): 151 """Request the power state via command. 152 Returns: 153 total_power, tracking, acquisition power consumption. 154 If the device does not support, return 0, 0, 0 155 """ 156 self.ad.adb.shell('cmd location providers send-extra-command gps request_power_stats') 157 time.sleep(1) 158 res = self.ad.adb.shell('dumpsys location | grep -A 10 -i \'power stats\'') 159 if res: 160 for line in res.split("\n"): 161 if "total power" in line: 162 total_power = line.split(" ")[-1].split("mJ")[0] 163 if "single-band tracking" in line: 164 single_tracking = line.split(" ")[-1].split("mJ")[0] 165 self.ad.log.info(single_tracking) 166 if "multi-band tracking" in line: 167 multi_tracking = line.split(" ")[-1].split("mJ")[0] 168 if "single-band acquisition" in line: 169 single_acquisition = line.split(" ")[-1].split("mJ")[0] 170 if "multi-band acquisition" in line: 171 multi_acquisition = line.split(" ")[-1].split("mJ")[0] 172 tracking = float(single_tracking) + float(multi_tracking) 173 acquisition = float(single_acquisition) + float(multi_acquisition) 174 self.ad.log.info("total power: %.2f" %float(total_power)) 175 self.ad.log.info("tracking: %.2f" %tracking) 176 self.ad.log.info("acquisition: %.2f" %acquisition) 177 return float(total_power), tracking, acquisition 178 return 0, 0, 0 179