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

Commit 3609373c authored by Jakub Pawłowski's avatar Jakub Pawłowski Committed by Gerrit Code Review
Browse files

Merge "bta_dm_discovery_both implementation" into main

parents 6601e54b 63da6808
Loading
Loading
Loading
Loading
+75 −24
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@
#include "main/shim/dumpsys.h"
#include "os/logging/log_adapter.h"
#include "osi/include/allocator.h"
#include "stack/btm/btm_dev.h"
#include "stack/include/bt_name.h"
#include "stack/include/bt_uuid16.h"
#include "stack/include/btm_client_interface.h"
@@ -72,6 +73,17 @@ base::RepeatingCallback<void(tBTA_DM_SDP_STATE*)> sdp_performer =
    default_sdp_performer;
base::RepeatingCallback<void(const RawAddress&)> gatt_performer =
    default_gatt_performer;

static bool is_same_device(const RawAddress& a, const RawAddress& b) {
  if (a == b) return true;

  auto devA = btm_find_dev(a);
  if (devA != nullptr && devA == btm_find_dev(b)) {
    return true;
  }

  return false;
}
}  // namespace

static void bta_dm_disc_sm_execute(tBTA_DM_DISC_EVT event,
@@ -284,8 +296,10 @@ static void bta_dm_read_dis_cmpl(const RawAddress& addr,
        p_dis_value->pnp_id.product_id, p_dis_value->pnp_id.product_version);
  }

  if (!bta_dm_discovery_cb.transports) {
    bta_dm_execute_queued_discovery_request();
  }
}
#endif

/*******************************************************************************
@@ -303,6 +317,8 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) {

  /* if any BR/EDR service discovery has been done, report the event */
  if (!disc_result.is_gatt_over_ble) {
    bta_dm_discovery_cb.transports &= ~BT_TRANSPORT_BR_EDR;

    auto& r = disc_result;
    if (!r.gatt_uuids.empty()) {
      log::info("Sending GATT services discovered using SDP");
@@ -313,6 +329,7 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) {
    bta_dm_discovery_cb.service_search_cbacks.on_service_discovery_results(
        r.bd_addr, r.uuids, r.result);
  } else {
    bta_dm_discovery_cb.transports &= ~BT_TRANSPORT_LE;
    GAP_BleReadPeerPrefConnParams(bta_dm_discovery_cb.peer_bdaddr);

    bta_dm_discovery_cb.service_search_cbacks.on_gatt_results(
@@ -320,7 +337,9 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) {
        /* transport_le */ true);
  }

  if (!bta_dm_discovery_cb.transports) {
    bta_dm_discovery_set_state(BTA_DM_DISCOVER_IDLE);
  }

#if TARGET_FLOSS
  if (bta_dm_discovery_cb.conn_id != GATT_INVALID_CONN_ID &&
@@ -330,8 +349,10 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) {
  }
#endif

  if (!bta_dm_discovery_cb.transports) {
    bta_dm_execute_queued_discovery_request();
  }
}

/*******************************************************************************
 *
@@ -343,8 +364,8 @@ static void bta_dm_disc_result(tBTA_DM_SVC_RES& disc_result) {
 *
 ******************************************************************************/
static void bta_dm_queue_disc(tBTA_DM_API_DISCOVER& discovery) {
  log::info("bta_dm_discovery: queuing service discovery to {}",
            discovery.bd_addr);
  log::info("bta_dm_discovery: queuing service discovery to {} [{}]",
            discovery.bd_addr, bt_transport_text(discovery.transport));
  bta_dm_discovery_cb.pending_discovery_queue.push(discovery);
}

@@ -358,7 +379,8 @@ static void bta_dm_execute_queued_discovery_request() {
  tBTA_DM_API_DISCOVER pending_discovery =
      bta_dm_discovery_cb.pending_discovery_queue.front();
  bta_dm_discovery_cb.pending_discovery_queue.pop();
  log::info("Start pending discovery");
  log::info("Start pending discovery {} [{}]", pending_discovery.bd_addr,
            pending_discovery.transport);
  post_disc_evt(
      BTA_DM_API_DISCOVER_EVT,
      std::make_unique<tBTA_DM_MSG>(tBTA_DM_API_DISCOVER{pending_discovery}));
@@ -428,14 +450,25 @@ static void bta_dm_discover_services(tBTA_DM_API_DISCOVER& discover) {
      base::StringPrintf("Transport:%s", bt_transport_text(transport).c_str()));

  if (transport == BT_TRANSPORT_LE) {
    if (bta_dm_discovery_cb.transports & BT_TRANSPORT_LE) {
      log::info("won't start GATT discovery - already started {}", bd_addr);
      return;
    } else {
      log::info("starting GATT discovery on {}", bd_addr);
      /* start GATT for service discovery */
      bta_dm_discovery_cb.transports |= BT_TRANSPORT_LE;
      gatt_performer.Run(bd_addr);
      return;
    }
  // transport == BT_TRANSPORT_BR_EDR
  }

  // transport == BT_TRANSPORT_BR_EDR
  if (bta_dm_discovery_cb.transports & BT_TRANSPORT_BR_EDR) {
    log::info("won't start SDP - already started {}", bd_addr);
  } else {
    log::info("starting SDP discovery on {}", bd_addr);
    bta_dm_discovery_cb.transports |= BT_TRANSPORT_BR_EDR;

    bta_dm_discovery_cb.sdp_state =
        std::make_unique<tBTA_DM_SDP_STATE>(tBTA_DM_SDP_STATE{
            .bd_addr = bd_addr,
@@ -443,9 +476,9 @@ static void bta_dm_discover_services(tBTA_DM_API_DISCOVER& discover) {
            .services_found = 0,
            .service_index = 0,
        });

    sdp_performer.Run(bta_dm_discovery_cb.sdp_state.get());
  }
}

void bta_dm_disc_override_sdp_performer_for_testing(
    base::RepeatingCallback<void(tBTA_DM_SDP_STATE*)> test_sdp_performer) {
@@ -527,7 +560,19 @@ void bta_dm_gatt_finished(RawAddress bda, tBTA_STATUS result,
 *
 ******************************************************************************/
static void bta_dm_gatt_disc_complete(uint16_t conn_id, tGATT_STATUS status) {
  log::verbose("conn_id = {}", conn_id);
  bool sdp_pending = bta_dm_discovery_cb.transports & BT_TRANSPORT_BR_EDR;
  bool le_pending = bta_dm_discovery_cb.transports & BT_TRANSPORT_LE;

  log::verbose("conn_id = {}, status = {}, sdp_pending = {}, le_pending = {}",
               conn_id, status, sdp_pending, le_pending);

  if (com::android::bluetooth::flags::bta_dm_discover_both() && sdp_pending &&
      !le_pending) {
    /* LE Service discovery finished, and services were reported, but SDP is not
     * finished yet. gatt_close_timer closed the connection, and we received
     * this callback because of disconnnection */
    return;
  }

  std::vector<Uuid> gatt_services;

@@ -806,12 +851,18 @@ static void bta_dm_disc_sm_execute(tBTA_DM_DISC_EVT event,

          bta_dm_disc_result(std::get<tBTA_DM_SVC_RES>(*msg));
          break;
        case BTA_DM_API_DISCOVER_EVT:
        case BTA_DM_API_DISCOVER_EVT: {
          log::assert_that(std::holds_alternative<tBTA_DM_API_DISCOVER>(*msg),
                           "bad message type: {}", msg->index());

          auto req = std::get<tBTA_DM_API_DISCOVER>(*msg);
          if (com::android::bluetooth::flags::bta_dm_discover_both() &&
              is_same_device(req.bd_addr, bta_dm_discovery_cb.peer_bdaddr)) {
            bta_dm_discover_services(std::get<tBTA_DM_API_DISCOVER>(*msg));
          } else {
            bta_dm_queue_disc(std::get<tBTA_DM_API_DISCOVER>(*msg));
          break;
          }
        } break;
        case BTA_DM_DISC_CLOSE_TOUT_EVT:
          bta_dm_close_gatt_conn();
          break;
+1 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@ typedef struct {
  std::queue<tBTA_DM_API_DISCOVER> pending_discovery_queue;

  RawAddress peer_bdaddr;
  uint8_t transports;
  /* This covers service discovery state - callers of BTA_DmDiscover. That is
   * initial service discovery after bonding and
   * BluetoothDevice.fetchUuidsWithSdp(). Responsible for LE GATT Service
+130 −0
Original line number Diff line number Diff line
@@ -14,8 +14,11 @@
 * limitations under the License.
 */

#define LOG_TAG "bt_bta_dm_test"

#include <base/strings/stringprintf.h>
#include <base/test/bind_test_util.h>
#include <bluetooth/log.h>
#include <com_android_bluetooth_flags.h>
#include <flag_macros.h>
#include <gmock/gmock.h>
@@ -35,6 +38,8 @@

#define TEST_BT com::android::bluetooth::flags

using namespace bluetooth;

namespace {
const RawAddress kRawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
}
@@ -255,6 +260,131 @@ TEST_F_WITH_FLAGS(BtaInitializedTest,
  bta_dm_disc_override_gatt_performer_for_testing({});
}

// must be global, as capturing lambda can't be treated as function
int service_cb_both_call_cnt = 0;
int gatt_service_cb_both_call_cnt = 0;

/* This test exercises the usual service discovery flow when bonding to
 * dual-mode, CTKD capable device on LE transport.
 */
TEST_F_WITH_FLAGS(
    BtaInitializedTest, bta_dm_disc_both_transports_flag_disabled,
    REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT,
                                        separate_service_and_device_discovery)),
    REQUIRES_FLAGS_DISABLED(ACONFIG_FLAG(TEST_BT, bta_dm_discover_both))) {
  bta_dm_disc_start(true);

  std::promise<void> gatt_triggered;
  int gatt_call_cnt = 0;
  base::RepeatingCallback<void(const RawAddress&)> gatt_performer =
      base::BindLambdaForTesting([&](const RawAddress& bd_addr) {
        gatt_call_cnt++;
        gatt_triggered.set_value();
      });
  bta_dm_disc_override_gatt_performer_for_testing(gatt_performer);

  int sdp_call_cnt = 0;
  base::RepeatingCallback<void(tBTA_DM_SDP_STATE*)> sdp_performer =
      base::BindLambdaForTesting(
          [&](tBTA_DM_SDP_STATE* sdp_state) { sdp_call_cnt++; });
  bta_dm_disc_override_sdp_performer_for_testing(sdp_performer);

  gatt_service_cb_both_call_cnt = 0;
  service_cb_both_call_cnt = 0;

  bta_dm_disc_start_service_discovery(
      {[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, bool) {}, nullptr,
       nullptr,
       [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) {
         service_cb_both_call_cnt++;
       }},
      kRawAddress, BT_TRANSPORT_BR_EDR);
  EXPECT_EQ(sdp_call_cnt, 1);

  bta_dm_disc_start_service_discovery(
      {[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, bool) {
         gatt_service_cb_both_call_cnt++;
       },
       nullptr, nullptr,
       [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) {
       }},
      kRawAddress, BT_TRANSPORT_LE);

  // GATT discovery is queued, until SDP finishes
  EXPECT_EQ(gatt_call_cnt, 0);

  bta_dm_sdp_finished(kRawAddress, BTA_SUCCESS, {}, {});
  EXPECT_EQ(service_cb_both_call_cnt, 1);

  // SDP finished, wait until GATT is triggered.
  EXPECT_EQ(std::future_status::ready,
            gatt_triggered.get_future().wait_for(std::chrono::seconds(1)));
  bta_dm_gatt_finished(kRawAddress, BTA_SUCCESS);
  EXPECT_EQ(gatt_service_cb_both_call_cnt, 1);

  bta_dm_disc_override_sdp_performer_for_testing({});
  bta_dm_disc_override_gatt_performer_for_testing({});
}

/* This test exercises the usual service discovery flow when bonding to
 * dual-mode, CTKD capable device on LE transport.
 */
TEST_F_WITH_FLAGS(BtaInitializedTest, bta_dm_disc_both_transports_flag_enabled,
                  REQUIRES_FLAGS_ENABLED(ACONFIG_FLAG(TEST_BT,
                                                      bta_dm_discover_both))) {
  bta_dm_disc_start(true);

  int gatt_call_cnt = 0;
  base::RepeatingCallback<void(const RawAddress&)> gatt_performer =
      base::BindLambdaForTesting(
          [&](const RawAddress& bd_addr) { gatt_call_cnt++; });
  bta_dm_disc_override_gatt_performer_for_testing(gatt_performer);

  int sdp_call_cnt = 0;
  base::RepeatingCallback<void(tBTA_DM_SDP_STATE*)> sdp_performer =
      base::BindLambdaForTesting(
          [&](tBTA_DM_SDP_STATE* sdp_state) { sdp_call_cnt++; });
  bta_dm_disc_override_sdp_performer_for_testing(sdp_performer);

  gatt_service_cb_both_call_cnt = 0;
  service_cb_both_call_cnt = 0;

  bta_dm_disc_start_service_discovery(
      {[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, bool) {
         gatt_service_cb_both_call_cnt++;
       },
       nullptr, nullptr,
       [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) {
         service_cb_both_call_cnt++;
       }},
      kRawAddress, BT_TRANSPORT_BR_EDR);
  EXPECT_EQ(sdp_call_cnt, 1);

  bta_dm_disc_start_service_discovery(
      {[](RawAddress, BD_NAME, std::vector<bluetooth::Uuid>&, bool) {
         gatt_service_cb_both_call_cnt++;
       },
       nullptr, nullptr,
       [](RawAddress addr, const std::vector<bluetooth::Uuid>&, tBTA_STATUS) {
         service_cb_both_call_cnt++;
       }},
      kRawAddress, BT_TRANSPORT_LE);

  // GATT discovery on same device is immediately started
  EXPECT_EQ(gatt_call_cnt, 1);

  // GATT finished first
  bta_dm_gatt_finished(kRawAddress, BTA_SUCCESS);
  EXPECT_EQ(gatt_service_cb_both_call_cnt, 1);

  // SDP finishes too
  bta_dm_sdp_finished(kRawAddress, BTA_SUCCESS, {}, {});
  EXPECT_EQ(service_cb_both_call_cnt, 1);

  bta_dm_disc_override_sdp_performer_for_testing({});
  bta_dm_disc_override_gatt_performer_for_testing({});
}

TEST_F(BtaInitializedTest, init_bta_dm_search_cb__conn_id) {
  // Set the global search block target field to some non-reset value
  tBTA_DM_SEARCH_CB& search_cb =
+39 −10
Original line number Diff line number Diff line
@@ -1745,8 +1745,26 @@ static void btif_on_service_discovery_results(
    }

    Uuid existing_uuids[BT_MAX_NUM_UUIDS] = {};
    btif_get_existing_uuids(&bd_addr, existing_uuids);
    bt_status_t existing_lookup_result =
        btif_get_existing_uuids(&pairing_cb.bd_addr, existing_uuids);

    if (existing_lookup_result != BT_STATUS_FAIL) {
      for (int i = 0; i < BT_MAX_NUM_UUIDS; i++) {
        Uuid uuid = existing_uuids[i];
        if (btif_should_ignore_uuid(uuid)) {
          continue;
        }
        if (btif_is_interesting_le_service(uuid)) {
          log::info("interesting le service {} insert", uuid.ToString());
          uuids.insert(uuid);
        }
      }
    }

    existing_lookup_result =
        btif_get_existing_uuids(&pairing_cb.static_bdaddr, existing_uuids);

    if (existing_lookup_result != BT_STATUS_FAIL) {
      for (int i = 0; i < BT_MAX_NUM_UUIDS; i++) {
        Uuid uuid = existing_uuids[i];
        if (btif_should_ignore_uuid(uuid)) {
@@ -1757,6 +1775,8 @@ static void btif_on_service_discovery_results(
          uuids.insert(uuid);
        }
      }
    }

    for (auto& uuid : uuids) {
      auto uuid_128bit = uuid.To128BitBE();
      property_value.insert(property_value.end(), uuid_128bit.begin(),
@@ -2005,10 +2025,19 @@ void btif_on_gatt_results(RawAddress bd_addr, BD_NAME bd_name,
    num_properties++;
  }

  if (!transport_le) {
    /* If services were returned as part of SDP discovery, we will immediately
     * send them with rest of SDP results in on_service_discovery_results */
  if (!transport_le) {
    return;
  } else {
    if (pairing_cb.sdp_over_classic ==
            btif_dm_pairing_cb_t::ServiceDiscoveryState::SCHEDULED &&
        com::android::bluetooth::flags::bta_dm_discover_both()) {
      /* Don't report services yet, they will be reported together once SDP
       * finishes. */
      log::info("will report services later, with SDP results {}", bd_addr);
      return;
    }
  }

  /* Send the event to the BTIF */