def test_le_pairing(self): """Test LE pairing transport stress This will test LE pairing between two android devices. Steps: 1. Start an LE advertisement on secondary device. 2. Find address from primary device. 3. Discover and bond to LE address. 4. Stop LE advertisement on secondary device. 5. Repeat steps 1-4 100 times Expected Result: LE pairing should pass 100 times. Returns: Pass if True Fail if False TAGS: LE, Scanning, Stress, Pairing Priority: 1 """ iterations = 100 for i in range(iterations): try: target_address, adv_callback, scan_callback = get_mac_address_of_generic_advertisement( self.scn_ad, self.adv_ad) except BtTestUtilsError as err: self.log.error(err) return False self.log.info("Begin interation {}/{}".format(i + 1, iterations)) self.scn_ad.droid.bluetoothStartPairingHelper() self.adv_ad.droid.bluetoothStartPairingHelper() start_time = self.start_timer() self.scn_ad.droid.bluetoothDiscoverAndBond(target_address) if not self._verify_successful_bond(target_address): self.log.error("Failed to bond devices.") return False self.log.info("Total time (ms): {}".format(self.end_timer())) if not self._verify_successful_bond( self.adv_ad.droid.bluetoothGetLocalAddress()): self.log.error("Failed to bond BREDR devices.") return False if not self.scn_ad.droid.bluetoothUnbond(target_address): self.log.error("Failed to unbond device from scanner.") return False time.sleep(2) if not self.adv_ad.droid.bluetoothUnbond( self.scn_ad.droid.bluetoothGetLocalAddress()): self.log.error("Failed to unbond device from advertiser.") return False self.adv_ad.droid.bleStopBleAdvertising(adv_callback) self.scn_ad.droid.bleStopBleScan(scan_callback) # Magic sleep to let unbonding finish time.sleep(2) return True
def test_gatt_connect_in_quick_succession(self): """Test GATT connections multiple times. Test establishing a gatt connection between a GATT server and GATT client with multiple iterations. Steps: 1. Start a generic advertisement. 2. Start a generic scanner. 3. Find the advertisement and extract the mac address. 4. Stop the first scanner. 5. Create a GATT connection between the scanner and advertiser. 6. Disconnect the GATT connection. 7. Repeat steps 5 and 6 twenty times. Expected Result: Verify that a connection was established and then disconnected successfully twenty times. Returns: Pass if True Fail if False TAGS: LE, Advertising, Filtering, Scanning, GATT, Stress Priority: 1 """ gatt_server_cb = self.per_ad.droid.gattServerCreateGattServerCallback() gatt_server = self.per_ad.droid.gattServerOpenGattServer( gatt_server_cb) self.gatt_server_list.append(gatt_server) mac_address, adv_callback = get_mac_address_of_generic_advertisement( self.cen_ad, self.per_ad) autoconnect = False for i in range(1000): self.log.info("Starting connection iteration {}".format(i + 1)) try: bluetooth_gatt, gatt_callback = setup_gatt_connection( self.cen_ad, mac_address, autoconnect) except GattTestUtilsError as err: self.log.error(err) return False test_result = self._orchestrate_gatt_disconnection(bluetooth_gatt, gatt_callback) self.cen_ad.droid.gattClientClose(bluetooth_gatt) if not test_result: self.log.info("Failed to disconnect from peripheral device.") return False self.adv_instances.append(adv_callback) return True
def orchestrate_gatt_connection(cen_ad, per_ad, transport=GattTransport.TRANSPORT_LE.value, mac_address=None, autoconnect=False): adv_callback = None if mac_address is None: if transport == GattTransport.TRANSPORT_LE.value: try: mac_address, adv_callback = ( get_mac_address_of_generic_advertisement(cen_ad, per_ad)) except BtTestUtilsError as err: raise GattTestUtilsError( "Error in getting mac address: {}".format(err)) else: mac_address = per_ad.droid.bluetoothGetLocalAddress() adv_callback = None bluetooth_gatt, gatt_callback = setup_gatt_connection( cen_ad, mac_address, autoconnect, transport) return bluetooth_gatt, gatt_callback, adv_callback
def orchestrate_coc_connection( client_ad, server_ad, is_ble, secured_conn=False, le_connection_interval=0, le_tx_data_length=default_le_data_length, accept_timeout_ms=default_bluetooth_socket_timeout_ms, le_min_ce_len=0, le_max_ce_len=0, gatt_disconnection=True): """Sets up the CoC connection between two Android devices. Args: client_ad: the Android device performing the connection. server_ad: the Android device accepting the connection. is_ble: using LE transport. secured_conn: using secured connection le_connection_interval: LE Connection interval. 0 means use default. le_tx_data_length: LE Data Length used by BT Controller to transmit. accept_timeout_ms: timeout while waiting for incoming connection. gatt_disconnection: LE GATT disconnection, default is True, False will return bluetooth_gatt and gatt_callback Returns: True if connection was successful or false if unsuccessful, client connection ID, and server connection ID """ server_ad.droid.bluetoothStartPairingHelper() client_ad.droid.bluetoothStartPairingHelper() adv_callback = None mac_address = None if is_ble: try: # This will start advertising and scanning. Will fail if it could # not find the advertisements from server_ad client_ad.log.info( "Orchestrate_coc_connection: Start BLE advertisement and" "scanning. Secured Connection={}".format(secured_conn)) mac_address, adv_callback, scan_callback = ( get_mac_address_of_generic_advertisement(client_ad, server_ad)) except BtTestUtilsError as err: raise BtCoCTestUtilsError( "Orchestrate_coc_connection: Error in getting mac address: {}". format(err)) else: mac_address = server_ad.droid.bluetoothGetLocalAddress() adv_callback = None # Adjust the Connection Interval (if necessary) bluetooth_gatt_1 = -1 gatt_callback_1 = -1 gatt_connected = False if is_ble and (le_connection_interval != 0 or le_min_ce_len != 0 or le_max_ce_len != 0): client_ad.log.info( "Adjusting connection interval={}, le_min_ce_len={}, le_max_ce_len={}" .format(le_connection_interval, le_min_ce_len, le_max_ce_len)) try: bluetooth_gatt_1, gatt_callback_1 = setup_gatt_connection( client_ad, mac_address, False, transport=gatt_transport['le'], opportunistic=False) client_ad.droid.bleStopBleScan(scan_callback) except GattTestUtilsError as err: client_ad.log.error(err) if (adv_callback != None): server_ad.droid.bleStopBleAdvertising(adv_callback) return False, None, None client_ad.log.info("setup_gatt_connection returns success") if (le_connection_interval != 0): minInterval = le_connection_interval / le_connection_interval_time_step_ms maxInterval = le_connection_interval / le_connection_interval_time_step_ms else: minInterval = default_le_connection_interval_ms / le_connection_interval_time_step_ms maxInterval = default_le_connection_interval_ms / le_connection_interval_time_step_ms if (le_min_ce_len != 0): le_min_ce_len = le_min_ce_len / le_connection_event_time_step_ms if (le_max_ce_len != 0): le_max_ce_len = le_max_ce_len / le_connection_event_time_step_ms return_status = client_ad.droid.gattClientRequestLeConnectionParameters( bluetooth_gatt_1, minInterval, maxInterval, 0, le_default_supervision_timeout, le_min_ce_len, le_max_ce_len) if not return_status: client_ad.log.error( "gattClientRequestLeConnectionParameters returns failure") if (adv_callback != None): server_ad.droid.bleStopBleAdvertising(adv_callback) return False, None, None client_ad.log.info( "gattClientRequestLeConnectionParameters returns success. Interval={}" .format(minInterval)) gatt_connected = True # For now, we will only test with 1 Mbit Phy. # TODO: Add explicit tests with 2 MBit Phy. client_ad.droid.gattClientSetPreferredPhy( bluetooth_gatt_1, gatt_phy['1m'], gatt_phy['1m'], 0) server_ad.droid.bluetoothSocketConnBeginAcceptThreadPsm( accept_timeout_ms, is_ble, secured_conn) psm_value = server_ad.droid.bluetoothSocketConnGetPsm() client_ad.log.info("Assigned PSM value={}".format(psm_value)) client_ad.droid.bluetoothSocketConnBeginConnectThreadPsm( mac_address, is_ble, psm_value, secured_conn) if (le_tx_data_length != default_le_data_length) and is_ble: client_ad.log.info("orchestrate_coc_connection: call " "bluetoothSocketRequestMaximumTxDataLength") client_ad.droid.bluetoothSocketRequestMaximumTxDataLength() end_time = time.time() + bt_default_timeout test_result = False while time.time() < end_time: if len(server_ad.droid.bluetoothSocketConnActiveConnections()) > 0: server_ad.log.info("CoC Server Connection Active") if len(client_ad.droid.bluetoothSocketConnActiveConnections()) > 0: client_ad.log.info("CoC Client Connection Active") test_result = True break time.sleep(1) if (adv_callback != None): server_ad.droid.bleStopBleAdvertising(adv_callback) if not test_result: client_ad.log.error("Failed to establish an CoC connection") return False, None, None if len(client_ad.droid.bluetoothSocketConnActiveConnections()) > 0: server_ad.log.info( "CoC client_ad Connection Active, num=%d", len(client_ad.droid.bluetoothSocketConnActiveConnections())) else: server_ad.log.info("Error CoC client_ad Connection Inactive") client_ad.log.info("Error CoC client_ad Connection Inactive") # Wait for the client to be ready client_conn_id = None while (client_conn_id == None): client_conn_id = client_ad.droid.bluetoothGetLastConnId() if (client_conn_id != None): break time.sleep(1) # Wait for the server to be ready server_conn_id = None while (server_conn_id == None): server_conn_id = server_ad.droid.bluetoothGetLastConnId() if (server_conn_id != None): break time.sleep(1) client_ad.log.info( "orchestrate_coc_connection: client conn id={}, server conn id={}". format(client_conn_id, server_conn_id)) if gatt_disconnection: if gatt_connected: disconnect_gatt_connection(client_ad, bluetooth_gatt_1, gatt_callback_1) client_ad.droid.gattClientClose(bluetooth_gatt_1) return True, client_conn_id, server_conn_id else: return True, client_conn_id, server_conn_id, bluetooth_gatt_1, gatt_callback_1
def test_gatt_connect_autoconnect(self): """Test GATT connection over LE. Test re-establishing a gat connection using autoconnect set to True in order to test connection whitelist. Steps: 1. Start a generic advertisement. 2. Start a generic scanner. 3. Find the advertisement and extract the mac address. 4. Stop the first scanner. 5. Create a GATT connection between the scanner and advertiser. 6. Disconnect the GATT connection. 7. Create a GATT connection with autoconnect set to True 8. Disconnect the GATT connection. Expected Result: Verify that a connection was re-established and then disconnected successfully. Returns: Pass if True Fail if False TAGS: LE, Advertising, Filtering, Scanning, GATT Priority: 0 """ gatt_server_cb = self.per_ad.droid.gattServerCreateGattServerCallback() gatt_server = self.per_ad.droid.gattServerOpenGattServer( gatt_server_cb) self.gatt_server_list.append(gatt_server) autoconnect = False mac_address, adv_callback = ( get_mac_address_of_generic_advertisement(self.cen_ad, self.per_ad)) try: bluetooth_gatt, gatt_callback = setup_gatt_connection( self.cen_ad, mac_address, autoconnect) self.bluetooth_gatt_list.append(bluetooth_gatt) except GattTestUtilsError as err: self.log.error(err) return False try: disconnect_gatt_connection(self.cen_ad, bluetooth_gatt, gatt_callback) if bluetooth_gatt in self.bluetooth_gatt_list: self.bluetooth_gatt_list.remove(bluetooth_gatt) except GattTestUtilsError as err: self.log.error(err) return False autoconnect = True bluetooth_gatt = self.cen_ad.droid.gattClientConnectGatt( gatt_callback, mac_address, autoconnect, GattTransport.TRANSPORT_AUTO.value) self.bluetooth_gatt_list.append(bluetooth_gatt) expected_event = GattCbStrings.GATT_CONN_CHANGE.value.format( gatt_callback) try: event = self.cen_ad.ed.pop_event(expected_event, self.default_timeout) except Empty: self.log.error( GattCbErr.GATT_CONN_CHANGE_ERR.value.format(expected_event)) test_result = False return True
def test_gatt_connect_opportunistic(self): """Test opportunistic GATT connection over LE. Test establishing a gatt connection between a GATT server and GATT client in opportunistic mode. Steps: 1. Start a generic advertisement. 2. Start a generic scanner. 3. Find the advertisement and extract the mac address. 4. Stop the first scanner. 5. Create GATT connection 1 between the scanner and advertiser normally 6. Create GATT connection 2 between the scanner and advertiser using opportunistic mode 7. Disconnect GATT connection 1 Expected Result: Verify GATT connection 2 automatically disconnects when GATT connection 1 disconnect Returns: Pass if True Fail if False TAGS: LE, Advertising, Filtering, Scanning, GATT Priority: 0 """ gatt_server_cb = self.per_ad.droid.gattServerCreateGattServerCallback() gatt_server = self.per_ad.droid.gattServerOpenGattServer( gatt_server_cb) self.gatt_server_list.append(gatt_server) mac_address, adv_callback = ( get_mac_address_of_generic_advertisement(self.cen_ad, self.per_ad)) # Make GATT connection 1 try: bluetooth_gatt_1, gatt_callback_1 = setup_gatt_connection( self.cen_ad, mac_address, False, transport=gatt_transport['auto'], opportunistic=False) self.bluetooth_gatt_list.append(bluetooth_gatt_1) except GattTestUtilsError as err: self.log.error(err) return False # Make GATT connection 2 try: bluetooth_gatt_2, gatt_callback_2 = setup_gatt_connection( self.cen_ad, mac_address, False, transport=gatt_transport['auto'], opportunistic=True) self.bluetooth_gatt_list.append(bluetooth_gatt_2) except GattTestUtilsError as err: self.log.error(err) return False # Disconnect GATT connection 1 try: disconnect_gatt_connection(self.cen_ad, bluetooth_gatt_1, gatt_callback_1) close_gatt_client(self.cen_ad, bluetooth_gatt_1) if bluetooth_gatt_1 in self.bluetooth_gatt_list: self.bluetooth_gatt_list.remove(bluetooth_gatt_1) except GattTestUtilsError as err: self.log.error(err) return False # Confirm that GATT connection 2 also disconnects wait_for_gatt_disconnect_event(self.cen_ad, gatt_callback_2) close_gatt_client(self.cen_ad, bluetooth_gatt_2) if bluetooth_gatt_2 in self.bluetooth_gatt_list: self.bluetooth_gatt_list.remove(bluetooth_gatt_2) return True