def _orchestrate_gatt_disconnection(self, bluetooth_gatt, gatt_callback): """Disconnect gatt connection between two devices. Args: bluetooth_gatt: Index of the BluetoothGatt object gatt_callback: Index of gatt callback object. Steps: 1. Disconnect gatt connection. 2. Close bluetooth gatt object. Returns: True if successful, False otherwise. """ self.log.info("Disconnecting from peripheral device.") try: disconnect_gatt_connection(self.pri_ad, bluetooth_gatt, gatt_callback) close_gatt_client(self.pri_ad, bluetooth_gatt) 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 return True
def _orchestrate_gatt_disconnection(self, bluetooth_gatt, gatt_callback): self.log.info("Disconnecting from peripheral device.") try: disconnect_gatt_connection(self.cen_ad, bluetooth_gatt, gatt_callback) except GattTestUtilsError as err: self.log.error(err) return False return True
def test_gatt_connect_iterate_uuids(self): """Test the discovery of uuids of a peripheral This test will prompt the user to press "Enter" when the peripheral is in a connecable advertisement state. Once the user presses enter, this script connects an Android device to the periphal and attempt to discover all services, characteristics, and descriptors. Steps: 1. Wait for user input to confirm peripheral is advertising. 2. Perform GATT connection to peripheral 3. Upon successful connection, iterate through all services, characteristics, and descriptors. 5. Disconnect from peripheral Expected Result: Device services, characteristics, and descriptors should all be read. Returns: Pass if True Fail if False TAGS: LE, GATT Priority: 2 """ try: bluetooth_gatt, gatt_callback = (setup_gatt_connection( self.cen_ad, self.ble_mac_address, self.AUTOCONNECT, gatt_transport['le'])) except GattTestUtilsError as err: self.log.error(err) return False if self.cen_ad.droid.gattClientDiscoverServices(bluetooth_gatt): expected_event = gatt_cb_strings['gatt_serv_disc'].format( gatt_callback) try: event = self.cen_ad.ed.pop_event(expected_event, self.DEFAULT_TIMEOUT) discovered_services_index = event['data']['ServicesIndex'] except Empty: self.log.error( gatt_cb_err['gatt_serv_disc'].format(expected_event)) return False log_gatt_server_uuids(self.cen_ad, discovered_services_index) try: disconnect_gatt_connection(self.cen_ad, bluetooth_gatt, gatt_callback) self.cen_ad.droid.gattClientClose(bluetooth_gatt) except GattTestUtilsError as err: self.log.error(err) return False self.cen_ad.droid.gattClientClose(bluetooth_gatt) return True
def disconnect(self): """Perform GATT disconnect""" try: disconnect_gatt_connection(self.dut, self.bluetooth_gatt, self.gatt_callback) except Exception as err: self.log.info("Cmd {} failed with {}".format(cmd, err)) try: self.dut.droid.gattClientClose(self.bluetooth_gatt) except Exception as err: self.log.info("Cmd failed with {}".format(err))
def test_gatt_connect_stress(self): """Test the round trip speed of connecting to a peripheral many times This test will prompt the user to press "Enter" when the peripheral is in a connecable advertisement state. Once the user presses enter, this script will measure the amount of time it takes to establish a GATT connection to the peripheral. The test will then disconnect. It will attempt to repeat this process multiple times. Steps: 1. Wait for user input to confirm peripheral is advertising. 2. Start timer 3. Perform GATT connection to peripheral 4. Upon successful connection, stop timer 5. Disconnect from peripheral 6. Repeat steps 2-5 1000 times. Expected Result: Test should measure 1000 iterations of connect/disconnect cycles. Returns: Pass if True Fail if False TAGS: LE, GATT Priority: 2 """ filter_list, scan_settings, scan_callback = generate_ble_scan_objects( self.cen_ad.droid) self.cen_ad.droid.bleStartBleScan(filter_list, scan_settings, scan_callback) self.AUTOCONNECT = False iterations = 1000 n = 0 while n < iterations: self.start_timer() try: bluetooth_gatt, gatt_callback = (setup_gatt_connection( self.cen_ad, self.ble_mac_address, self.AUTOCONNECT, gatt_transport['le'])) except GattTestUtilsError as err: self.log.error(err) return False self.log.info("Total time (ms): {}".format(self.end_timer())) try: disconnect_gatt_connection(self.cen_ad, bluetooth_gatt, gatt_callback) self.cen_ad.droid.gattClientClose(bluetooth_gatt) except GattTestUtilsError as err: self.log.error(err) return False n += 1 return True
def test_gatt_connect_without_scanning(self): """Test the round trip speed of connecting to a peripheral This test will prompt the user to press "Enter" when the peripheral is in a connecable advertisement state. Once the user presses enter, this script will measure the amount of time it takes to establish a GATT connection to the peripheral. The test will then disconnect Steps: 1. Wait for user input to confirm peripheral is advertising. 2. Start timer 3. Perform GATT connection to peripheral 4. Upon successful connection, stop timer 5. Disconnect from peripheral Expected Result: Device should be connected successfully Returns: Pass if True Fail if False TAGS: LE, GATT Priority: 1 """ self.AUTOCONNECT = False start_time = self._get_time_in_milliseconds() try: bluetooth_gatt, gatt_callback = (setup_gatt_connection( self.cen_ad, self.ble_mac_address, self.AUTOCONNECT, gatt_transport['le'])) except GattTestUtilsError as err: self.log.error(err) return False end_time = self._get_time_in_milliseconds() self.log.info("Total time (ms): {}".format(end_time - start_time)) try: disconnect_gatt_connection(self.cen_ad, bluetooth_gatt, gatt_callback) self.cen_ad.droid.gattClientClose(bluetooth_gatt) except GattTestUtilsError as err: self.log.error(err) return False self.cen_ad.droid.gattClientClose(bluetooth_gatt)
def ble_gatt_disconnection(client_ad, bluetooth_gatt, gatt_callback): """Function to disconnect GATT connection between client and server. Args: client_ad: the Android device performing the connection. bluetooth_gatt: GATT object gatt_callback:the gatt connection call back object Returns: ble_rssi: RSSI value of the remote BLE device """ logging.info("Disconnecting from peripheral device.") try: disconnect_gatt_connection(client_ad, bluetooth_gatt, gatt_callback) close_gatt_client(client_ad, bluetooth_gatt) except GattTestUtilsError as err: logging.error(err) return False return True
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