1#!/usr/bin/env python3
2#
3#   Copyright 2019 - 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 re
19import time
20
21from acts import asserts
22from acts.test_utils.bt.BtSarBaseTest import BtSarBaseTest
23
24
25class BtSarSanityTest(BtSarBaseTest):
26    """Class to run sanity checks on BT SAR mechanisms.
27
28    This class defines sanity test cases on BT SAR. The tests include
29    a software state sanity check and a software power sanity check.
30    """
31    def __init__(self, controllers):
32        super().__init__(controllers)
33
34    def test_bt_sar_sanity_check_state(self):
35        """ Test for BT SAR State Sanity
36
37        BT SAR Software Sanity Test to ensure that the correct signal state
38        gets propagated to the firmware. This is done by comparing expected
39        device state with that read from device's logcat
40        """
41        #Iterating through the BT SAR scenarios
42        for scenario in range(0, self.bt_sar_df.shape[0]):
43            # Reading BT SAR table row into dict
44            read_scenario = self.bt_sar_df.loc[scenario].to_dict()
45
46            start_time = self.dut.adb.shell('date +%s.%m')
47            time.sleep(1)
48
49            #Setting SAR state to the read BT SAR row
50            enforced_state = self.set_sar_state(self.dut, read_scenario,
51                                                self.country_code)
52
53            #Reading device state from logcat after forcing SAR State
54            device_state = self.get_current_device_state(self.dut, start_time)
55
56            #Comparing read device state to expected device state
57            for key in enforced_state.keys():
58                key_regex = r'{}:\s*(\d)'.format(key)
59                try:
60                    propagated_value = int(
61                        re.findall(key_regex, device_state)[0])
62                except IndexError:
63                    propagated_value = 'NA'
64
65                if enforced_state[key] == propagated_value:
66                    self.log.info(
67                        'scenario: {}, state : {}, forced_value: {}, value:{}'.
68                        format(scenario, key, enforced_state[key],
69                               propagated_value))
70                else:
71                    self.log.error(
72                        'scenario:{}, state : {}, forced_value: {}, value:{}'.
73                        format(scenario, key, enforced_state[key],
74                               propagated_value))
75
76    def test_bt_sar_sanity_check_power(self):
77        """ Test for BT SAR Power Cap Sanity
78
79        BT SAR Power Cap Sanity Test to ensure that the correct SAR power
80        cap corresponding to the forced SAR state gets propagated to the
81        firmware. This is done by comparing expected power cap read from
82        the BT SAR file to the power cap read from logcat
83        """
84
85        sar_df = self.bt_sar_df
86        sar_df['BDR_power_cap'] = -128
87        sar_df['EDR_power_cap'] = -128
88        sar_df['BLE_power_cap'] = -128
89
90        if self.sar_version_2:
91            power_column_dict = {
92                'BDR': 'BluetoothBDRPower',
93                'EDR': 'BluetoothEDRPower',
94                'BLE': 'BluetoothLEPower'
95            }
96        else:
97            power_column_dict = {'EDR': self.power_column}
98
99        power_cap_error = False
100
101        for type, column_name in power_column_dict.items():
102
103            self.log.info("Performing sanity test on {}".format(type))
104            #Iterating through the BT SAR scenarios
105            for scenario in range(0, self.bt_sar_df.shape[0]):
106
107                # Reading BT SAR table row into dict
108                read_scenario = sar_df.loc[scenario].to_dict()
109                start_time = self.dut.adb.shell('date +%s.%m')
110                time.sleep(1)
111
112                #Setting SAR state to the read BT SAR row
113                self.set_sar_state(self.dut, read_scenario, self.country_code)
114
115                #Reading device power cap from logcat after forcing SAR State
116                scenario_power_cap = self.get_current_power_cap(self.dut,
117                                                                start_time,
118                                                                type=type)
119                sar_df.loc[scenario,
120                           '{}_power_cap'.format(type)] = scenario_power_cap
121                self.log.info('scenario: {}, '
122                              'sar_power: {}, power_cap:{}'.format(
123                                  scenario, sar_df.loc[scenario, column_name],
124                                  sar_df.loc[scenario,
125                                             '{}_power_cap'.format(type)]))
126
127        if not sar_df['{}_power_cap'.format(type)].equals(sar_df[column_name]):
128            power_cap_error = True
129
130        results_file_path = os.path.join(
131            self.log_path, '{}.csv'.format(self.current_test_name))
132        sar_df.to_csv(results_file_path)
133
134        # Comparing read device power cap to expected device power cap
135        if power_cap_error:
136            asserts.fail("Power Caps didn't match powers in the SAR table")
137        else:
138            asserts.explicit_pass('Power Caps were set according to the table')
139
140    def test_bt_sar_sanity_country_code(self):
141        """ Test for BT SAR Country Code Sanity
142
143        BT SAR Country Code Sanity Test to ensure that the correct SAR
144        regulatory domain corresponding to the forced SAR country code gets
145        propagated to the firmware. This is done by comparing forced regulatory
146        domain to regulatory domain read from logcat.
147        """
148
149        error_flag = 0
150        for country_code_tuple in self.REG_DOMAIN_DICT.keys():
151            for country_code in country_code_tuple:
152                start_time = self.dut.adb.shell('date +%s.%m')
153
154                #Force country code using adb command
155                self.set_country_code(self.dut, country_code)
156
157                #Read regulatory code from logcat
158                set_regulatory_domain = self.get_country_code(
159                    self.dut, start_time)
160
161                if set_regulatory_domain != self.REG_DOMAIN_DICT[
162                        country_code_tuple]:
163                    error_flag = 1
164                    self.log.error(
165                        'Country Code: {} set to regulatory domain: {}'.format(
166                            country_code, set_regulatory_domain))
167                else:
168                    self.log.info(
169                        'Country Code: {} set to regulatory domain: {}'.format(
170                            country_code, set_regulatory_domain))
171
172        if error_flag:
173            asserts.fail(
174                'Regulatory domains not set according to country code')
175        else:
176            asserts.explicit_pass(
177                'Regulatory domains set according to country code')
178