Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit eb238cbb authored by Chris Manton's avatar Chris Manton
Browse files

api: GetConnectionState is unsynchronized on main thread

Also provide informative address resolution

Bug: 325333712
Bug: 325333718
Test: atest net_test_btif_stack
Flag: api_get_connection_state_sync_on_main

Change-Id: I08849879e33349acb24337287628a2522efbfea6
parent f73e507b
Loading
Loading
Loading
Loading
+19 −4
Original line number Diff line number Diff line
@@ -266,13 +266,28 @@ void btif_dm_remove_bond(const RawAddress bd_addr);
/*******************************************************************************
 *
 * Function         btif_dm_get_connection_state
 *
 * Description      Returns whether the remote device is currently connected
 *
 * Returns          0 if not connected
 *                  btif_dm_get_connection_state_sync
 *
 * Description      Returns bitmask on remote device connection state indicating
 *                  connection and encryption.  The `_sync` version properly
 *                  synchronizes the state and is the preferred mechanism.
 *                  NOTE: Currently no address resolution is attempted upon
 *                  LE random addresses.
 *
 * Returns          '000 (0x0000) if not connected
 *                  '001 (0x0001) Connected with no encryption to remote
 *                                device on BR/EDR or LE ACL
 *                  '011 (0x0003) Connected with encryption to remote
 *                                device on BR/EDR ACL
 *                  '101 (0x0005) Connected with encruption to remote
 *                                device on LE ACL
 *                  '111 (0x0007) Connected with encruption to remote
 *                                device on both BR/EDR and LE ACLs
 *                  All other values are reserved
 *
 ******************************************************************************/
uint16_t btif_dm_get_connection_state(const RawAddress& bd_addr);
uint16_t btif_dm_get_connection_state_sync(const RawAddress& bd_addr);

/*******************************************************************************
 *
+6 −1
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@

#define LOG_TAG "bt_btif"

#include <android_bluetooth_flags.h>
#include <base/logging.h>
#include <hardware/bluetooth.h>
#include <hardware/bluetooth_headset_interface.h>
@@ -660,8 +661,12 @@ static int get_connection_state(const RawAddress* bd_addr) {

  if (bd_addr == nullptr) return 0;

  if (IS_FLAG_ENABLED(api_get_connection_state_sync_on_main)) {
    return btif_dm_get_connection_state_sync(*bd_addr);
  } else {
    return btif_dm_get_connection_state(*bd_addr);
  }
}

static int pin_reply(const RawAddress* bd_addr, uint8_t accept, uint8_t pin_len,
                     bt_pin_code_t* pin_code) {
+45 −0
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@
#include "stack/include/bt_octets.h"
#include "stack/include/bt_types.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/btm_ble_addr.h"
#include "stack/include/btm_ble_api.h"
#include "stack/include/btm_ble_sec_api.h"
#include "stack/include/btm_ble_sec_api_types.h"
@@ -921,6 +922,50 @@ uint16_t btif_dm_get_connection_state(const RawAddress& bd_addr) {
  return rc;
}

static uint16_t btif_dm_get_resolved_connection_state(
    tBLE_BD_ADDR ble_bd_addr) {
  uint16_t rc = 0;
  if (maybe_resolve_address(&ble_bd_addr.bda, &ble_bd_addr.type)) {
    if (BTA_DmGetConnectionState(ble_bd_addr.bda)) {
      rc = 0x0001;
      if (BTM_IsEncrypted(ble_bd_addr.bda, BT_TRANSPORT_BR_EDR)) {
        rc |= ENCRYPTED_BREDR;
      }
      if (BTM_IsEncrypted(ble_bd_addr.bda, BT_TRANSPORT_LE)) {
        rc |= ENCRYPTED_LE;
      }

      BTM_LogHistory(
          kBtmLogTag, ble_bd_addr.bda, "RESOLVED connection state",
          base::StringPrintf(
              "connected:%c classic_encrypted:%c le_encrypted:%c",
              (rc & 0x0001) ? 'T' : 'F', (rc & ENCRYPTED_BREDR) ? 'T' : 'F',
              (rc & ENCRYPTED_LE) ? 'T' : 'F'));
    }
  }
  return rc;
}

uint16_t btif_dm_get_connection_state_sync(const RawAddress& bd_addr) {
  std::promise<uint16_t> promise;
  std::future future = promise.get_future();

  ASSERT(BT_STATUS_SUCCESS ==
         do_in_main_thread(
             FROM_HERE,
             base::BindOnce(
                 [](const RawAddress bd_addr, std::promise<uint16_t> promise) {
                   // Experiment to try with maybe resolved address
                   btif_dm_get_resolved_connection_state({
                       .type = BLE_ADDR_RANDOM,
                       .bda = bd_addr,
                   });
                   promise.set_value(btif_dm_get_connection_state(bd_addr));
                 },
                 bd_addr, std::move(promise))));
  return future.get();
}

/******************************************************************************
 *
 *  BTIF DM callback events
+18 −0
Original line number Diff line number Diff line
@@ -753,3 +753,21 @@ TEST_F(BtifCoreWithControllerTest,
  ASSERT_EQ(7, btif_dm_get_connection_state(kRawAddress));
  test::mock::stack_btm_sec::BTM_IsEncrypted = {};
}

TEST_F(BtifCoreWithControllerTest, btif_dm_get_connection_state_sync) {
  bta_dm_acl_up(kRawAddress, BT_TRANSPORT_AUTO, 0x123);

  test::mock::stack_btm_sec::BTM_IsEncrypted.body =
      [](const RawAddress& /* bd_addr */, tBT_TRANSPORT transport) {
        switch (transport) {
          case BT_TRANSPORT_BR_EDR:
            return true;
          case BT_TRANSPORT_LE:
            return true;
        }
        return false;
      };
  ASSERT_EQ(7, btif_dm_get_connection_state_sync(kRawAddress));

  test::mock::stack_btm_sec::BTM_IsEncrypted = {};
}