1# Lint as: python2, python3 2# Copyright 2022 The Chromium OS Authors. All rights reserved. 3# Use of this source code is governed by a BSD-style license that can be 4# found in the LICENSE file. 5""" Bluetooth test that tests the Fast Pair scenarios.""" 6 7from __future__ import absolute_import 8from __future__ import division 9from __future__ import print_function 10 11from base64 import b64decode 12import logging 13 14from autotest_lib.client.common_lib import error 15from autotest_lib.server.cros.bluetooth.bluetooth_adapter_quick_tests import ( 16 BluetoothAdapterQuickTests) 17from autotest_lib.server.cros.bluetooth.bluetooth_adapter_tests import ( 18 UNSUPPORTED_BT_HW_FILTERING_CHIPSETS) 19from autotest_lib.server import autotest 20 21imported_password_util = True 22 23try: 24 # Importing this private util fails on public boards (e.g amd64-generic) 25 from autotest_lib.client.common_lib.cros import password_util 26except ImportError: 27 imported_password_util = False 28 logging.error('Failed to import password_util from autotest-private') 29 30test_wrapper = BluetoothAdapterQuickTests.quick_test_test_decorator 31batch_wrapper = BluetoothAdapterQuickTests.quick_test_batch_decorator 32 33 34class bluetooth_FastPair(BluetoothAdapterQuickTests): 35 """Fast Pair tests""" 36 37 UI_TEST = 'bluetooth_FastPairUI' 38 39 KEY_PEM_ARG_KEY = 'fast_pair_antispoofing_key_pem' 40 ACCOUNT_KEY_ARG_KEY = 'fast_pair_account_key' 41 USERNAME_ARG_KEY = 'fast_pair_username' 42 PASSWORD_ARG_KEY = 'fast_pair_password' 43 44 _key_pem = None 45 _account_key = None 46 _username = None 47 _password = None 48 49 def run_ui_test(self): 50 """Runs the UI client test, which clicks through the Fast Pair UI""" 51 client_at = autotest.Autotest(self.host) 52 client_at.run_test(self.UI_TEST, 53 username=self._username, 54 password=self._password) 55 client_at._check_client_test_result(self.host, self.UI_TEST) 56 57 @test_wrapper('Fast Pair Initial Pairing', 58 devices={'BLE_FAST_PAIR': 1}, 59 skip_chipsets=UNSUPPORTED_BT_HW_FILTERING_CHIPSETS) 60 def fast_pair_initial_pairing_test(self): 61 """Test the Fast Pair initial pairing scenario""" 62 try: 63 # Setup the Fast Pair device. 64 device = self.devices['BLE_FAST_PAIR'][0] 65 device.SetAntispoofingKeyPem(self._key_pem) 66 67 # Toggling discoverable here ensures the device starts 68 # advertising during this test. 69 device.SetDiscoverable(False) 70 device.SetDiscoverable(True) 71 72 # Run UI test, which clicks through the pairing UI flow. 73 self.run_ui_test() 74 # Verify device is paired. 75 return self.bluetooth_facade.device_is_paired(device.address) 76 except Exception as e: 77 logging.error('exception in fast_pair_initial_pairing_test %s', 78 str(e)) 79 return False 80 81 @test_wrapper('Fast Pair Subsequent Pairing', 82 devices={'BLE_FAST_PAIR': 1}, 83 skip_chipsets=UNSUPPORTED_BT_HW_FILTERING_CHIPSETS) 84 def fast_pair_subsequent_pairing_test(self): 85 """Test the Fast Pair subsequent pairing scenario""" 86 try: 87 # Setup the Fast Pair device. 88 device = self.devices['BLE_FAST_PAIR'][0] 89 device.SetAntispoofingKeyPem(None) 90 device.AddAccountKey(self._account_key) 91 92 # Toggling discoverable here ensures the device starts 93 # advertising during this test. 94 device.SetDiscoverable(False) 95 device.SetDiscoverable(True) 96 97 # Run UI test, which clicks through the pairing UI flow. 98 self.run_ui_test() 99 100 # Verify device is paired. 101 return self.bluetooth_facade.device_is_paired(device.address) 102 except Exception as e: 103 logging.error('exception in fast_pair_subsequent_pairing_test %s', 104 str(e)) 105 return False 106 107 def set_key_pem(self, args_dict): 108 if imported_password_util: 109 self._key_pem = b64decode( 110 password_util.get_fast_pair_anti_spoofing_key()) 111 112 elif args_dict is not None and self.KEY_PEM_ARG_KEY in args_dict: 113 self._key_pem = b64decode(args_dict[self.KEY_PEM_ARG_KEY]) 114 115 if self._key_pem is None: 116 raise error.TestError('Valid %s arg is missing' % 117 self.KEY_PEM_ARG_KEY) 118 119 def set_account_key(self, args_dict): 120 if imported_password_util: 121 self._account_key = b64decode( 122 password_util.get_fast_pair_account_key()) 123 124 elif args_dict is not None and self.ACCOUNT_KEY_ARG_KEY in args_dict: 125 self._account_key = b64decode(args_dict[self.ACCOUNT_KEY_ARG_KEY]) 126 127 if self._account_key is None: 128 raise error.TestError('Valid %s arg is missing' % 129 self.ACCOUNT_KEY_ARG_KEY) 130 131 def set_username(self, args_dict): 132 if imported_password_util: 133 self._username = ( 134 password_util.get_fast_pair_user_credentials().username) 135 136 elif args_dict is not None and self.USERNAME_ARG_KEY in args_dict: 137 self._username = args_dict[self.USERNAME_ARG_KEY] 138 139 if self._username is None: 140 raise error.TestError('Valid %s arg is missing' % 141 self.USERNAME_ARG_KEY) 142 143 def set_password(self, args_dict): 144 if imported_password_util: 145 self._password = ( 146 password_util.get_fast_pair_user_credentials().password) 147 148 elif args_dict is not None and self.PASSWORD_ARG_KEY in args_dict: 149 self._password = args_dict[self.PASSWORD_ARG_KEY] 150 151 if self._password is None: 152 raise error.TestError('Valid %s arg is missing' % 153 self.PASSWORD_ARG_KEY) 154 155 @batch_wrapper('Fast Pair') 156 def fast_pair_batch_run(self, num_iterations=1, test_name=None): 157 """ Batch of Fair Pair tests """ 158 self.fast_pair_initial_pairing_test() 159 self.fast_pair_subsequent_pairing_test() 160 161 def run_once(self, 162 host, 163 num_iterations=1, 164 args_dict=None, 165 test_name=None, 166 flag='Quick Health'): 167 """Running Fast Pair tests. 168 169 @param host: the DUT, usually a chromebook 170 @param num_iterations: the number of times to execute the test 171 @param test_name: the test to run or None for all tests 172 @param flag: run tests with this flag (default: Quick Health) 173 174 """ 175 176 # First set required args 177 self.set_key_pem(args_dict) 178 self.set_account_key(args_dict) 179 self.set_username(args_dict) 180 self.set_password(args_dict) 181 182 # Initialize and run the test batch or the requested specific test 183 self.quick_test_init(host, 184 use_btpeer=True, 185 flag=flag, 186 args_dict=args_dict) 187 self.fast_pair_batch_run(num_iterations, test_name) 188 self.quick_test_cleanup() 189