Beispiel #1
0
 def connect_over_bredr(self):
     """Perform GATT connection over BREDR"""
     self.bluetooth_gatt, self.gatt_callback = setup_gatt_connection(
         self.dut,
         self.target_mac_addr,
         False,
         transport=gatt_transport['bredr'])
Beispiel #2
0
 def connect_over_le(self, autoconnect):
     """Perform GATT connection over LE"""
     self.bluetooth_gatt, self.gatt_callback = setup_gatt_connection(
         self.dut,
         self.mac_addr,
         autoconnect,
         transport=gatt_transport['le'])
     self.discovered_services_index = None
    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 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_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 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 test_concurrent_gatt_connections(self):
        """Test max concurrent GATT connections

        Connect to all peripherals.

        Steps:
        1. Scan
        2. Save addresses
        3. Connect all addresses of the peripherals

        Expected Result:
        All connections successful.

        Returns:
          Pass if True
          Fail if False

        TAGS: Bluetooth, GATT
        Priority: 2
        """

        address_list = self.obtain_address_list_from_scan()
        if address_list is None:
            return False

        # Connect to all addresses
        for address_tuple in address_list:
            address = address_tuple[1]
            try:
                autoconnect = False
                bluetooth_gatt, gatt_callback = setup_gatt_connection(
                    self.pri_dut, address, autoconnect)
                self.log.info("Successfully connected to {}".format(address))
            except Exception as err:
                self.log.error(
                    "Failed to establish connection to {}".format(address))
                return False
        if (len(
                self.pri_dut.droid.bluetoothGetConnectedLeDevices(
                    bt_profile_constants['gatt_server'])) !=
                self.max_connections):
            self.log.error("Did not reach max connection count.")
            return False

        return True
Beispiel #8
0
    def connect_over_le_based_off_name(self, autoconnect, name):
        """Perform GATT connection over LE"""
        self.dut.droid.bleSetScanSettingsScanMode(
            ble_scan_settings_modes['low_latency'])
        filter_list = self.dut.droid.bleGenFilterList()
        scan_settings = self.dut.droid.bleBuildScanSetting()
        scan_callback = self.dut.droid.bleGenScanCallback()
        event_name = scan_result.format(scan_callback)
        self.dut.droid.bleSetScanFilterDeviceName("BLE Rect")
        self.dut.droid.bleBuildScanFilter(filter_list)
        self.dut.droid.bleStartBleScan(filter_list, scan_settings,
                                       scan_callback)

        try:
            event = self.dut.ed.pop_event(event_name, 10)
            self.log.info("Found scan result: {}".format(event))
        except Exception:
            self.log.info("Didn't find any scan results.")
        mac_addr = event['data']['Result']['deviceInfo']['address']
        self.bluetooth_gatt, self.gatt_callback = setup_gatt_connection(
            self.dut, mac_addr, autoconnect, transport=gatt_transport['le'])
        self.dut.droid.bleStopBleScan(scan_callback)
        self.discovered_services_index = None
Beispiel #9
0
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_notification_longev(self):
        """Test GATT characterisitic notifications for long periods of time

        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 aims to set characteristic
        notification to true on the config file's SERVICE_UUID,
        NOTIFIABLE_CHAR_UUID, and CCC_DESC_UUID. This test assumes
        the peripheral will constantly write data to a notifiable
        characteristic.

        Steps:
        1. Wait for user input to confirm peripheral is advertising.
        2. Perform Bluetooth pairing to GATT mac address
        3. Perform a GATT connection to the periheral
        4. Get the discovered service uuid that matches the user's input
        in the config file
        4. Write to the CCC descriptor to enable notifications
        5. Enable notifications on the user's input Characteristic UUID
        6. Continuously wait for Characteristic Changed events which
        equate to recieving notifications for 15 minutes.

        Expected Result:
        There should be no disconnects and we should constantly receive
        Characteristic Changed information. Values should vary upon user
        interaction with the peripheral.

        Returns:
          Pass if True
          Fail if False

        TAGS: LE, GATT
        Priority: 1
        """
        #pair devices
        if not self._pair_with_peripheral():
            return False
        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
        # TODO: in setup save service_cound and discovered_services_index
        # programatically
        services_count = self.cen_ad.droid.gattClientGetDiscoveredServicesCount(
            discovered_services_index)
        test_service_index = None
        for i in range(services_count):
            disc_service_uuid = (
                self.cen_ad.droid.gattClientGetDiscoveredServiceUuid(
                    discovered_services_index, i))
            if disc_service_uuid == self.SERVICE_UUID:
                test_service_index = i
                break
        if not test_service_index:
            self.log.error("Service not found.")
            return False

        self.cen_ad.droid.gattClientDescriptorSetValue(
            bluetooth_gatt, discovered_services_index, test_service_index,
            self.NOTIFIABLE_CHAR_UUID, self.CCC_DESC_UUID,
            gatt_descriptor['enable_notification_value'])

        self.cen_ad.droid.gattClientWriteDescriptor(bluetooth_gatt,
                                                    discovered_services_index,
                                                    test_service_index,
                                                    self.NOTIFIABLE_CHAR_UUID,
                                                    self.CCC_DESC_UUID)

        self.cen_ad.droid.gattClientSetCharacteristicNotification(
            bluetooth_gatt, discovered_services_index, test_service_index,
            self.NOTIFIABLE_CHAR_UUID, True)

        # set 15 minute notification test time
        notification_test_time = 900
        end_time = time.time() + notification_test_time
        expected_event = gatt_cb_strings['char_change'].format(gatt_callback)
        while time.time() < end_time:
            try:
                event = self.cen_ad.ed.pop_event(expected_event,
                                                 self.DEFAULT_TIMEOUT)
                self.log.info(event)
            except Empty as err:
                print(err)
                self.log.error(
                    gatt_cb_err['char_change_err'].format(expected_event))
                return False
        return True
    def test_data_transfer_to_concurrent_gatt_connections(self):
        """Test writing GATT descriptors concurrently to many peripherals.

        Connect to all peripherals and write gatt descriptors concurrently.


        Steps:
        1. Scan the addresses by names
        2. Save mac addresses of the peripherals
        3. Connect all addresses of the peripherals and write gatt descriptors


        Expected Result:
        All connections and data transfers are successful.

        Returns:
          Pass if True
          Fail if False

        TAGS: Bluetooth, GATT
        Priority: 2
        """

        address_list = self.obtain_address_list_from_scan()
        if address_list is None:
            return False

        # Connect to all addresses
        executor = concurrent.futures.ThreadPoolExecutor(max_workers=10)

        for address_tuple in address_list:
            ad, address = address_tuple

            gatts = GattServerLib(log=self.log, dut=ad)
            gatt_server, gatt_server_callback = gatts.setup_gatts_db(
                database=gatt_server_read_descriptor_sample)

            try:
                bluetooth_gatt, gatt_callback = setup_gatt_connection(
                    self.pri_dut, address, autoconnect=False)
                self.log.info("Successfully connected to {}".format(address))

            except Exception as err:
                self.log.error(
                    "Failed to establish connection to {}".format(address))
                return False

            if self.pri_dut.droid.gattClientDiscoverServices(bluetooth_gatt):
                event = self.pri_dut.ed.pop_event(
                    "GattConnect{}onServicesDiscovered".format(bluetooth_gatt),
                    self.bt_default_timeout)
                discovered_services_index = event['data']['ServicesIndex']
            else:
                self.log.info("Failed to discover services.")
                return False
            services_count = self.pri_dut.droid.gattClientGetDiscoveredServicesCount(
                discovered_services_index)

            arguments_list = [
                self.pri_dut.droid, self.pri_dut.ed, ad.droid, ad.ed,
                gatt_server, gatt_server_callback, bluetooth_gatt,
                services_count, discovered_services_index, 100
            ]
            self.list_of_arguments_list.append(arguments_list)

        for arguments_list in self.list_of_arguments_list:
            executor.submit(run_continuous_write_descriptor, *arguments_list)

        executor.shutdown(wait=True)

        if (len(
                self.pri_dut.droid.bluetoothGetConnectedLeDevices(
                    bt_profile_constants['gatt_server'])) !=
                self.max_connections):
            self.log.error("Failed to write concurrently.")
            return False

        return True
Beispiel #13
0
    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