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