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

Commit 504164fe authored by Treehugger Robot's avatar Treehugger Robot Committed by Gerrit Code Review
Browse files

Merge "bta::jv::bta_jv_start_discovery_cback Fix memory leak" into main

parents e7837f07 bdce728e
Loading
Loading
Loading
Loading
+71 −0
Original line number Diff line number Diff line
@@ -451,6 +451,7 @@ cc_test {
        "BluetoothGeneratedDumpsysDataSchema_h",
    ],
    srcs: [
        ":BluetoothLogRedactionSources",
        ":TestCommonMockFunctions",
        ":TestFakeOsi",
        ":TestMockBtaSys",
@@ -1299,3 +1300,73 @@ cc_test {
    },
    cflags: ["-Wno-unused-parameter"],
}

cc_test {
    name: "net_test_bta_jv",
    test_suites: ["general-tests"],
    defaults: [
        "fluoride_bta_defaults",
        "mts_defaults",
    ],
    host_supported: true,
    isolated: false,
    include_dirs: [
        "packages/modules/Bluetooth/system",
        "packages/modules/Bluetooth/system/bta/include",
        "packages/modules/Bluetooth/system/bta/test/common",
        "packages/modules/Bluetooth/system/stack/include",
    ],
    srcs: [
        ":BtaDmSources",
        ":TestCommonMainHandler",
        ":TestCommonMockFunctions",
        ":TestFakeOsi",
        ":TestMockBtaGatt",
        ":TestMockBtaLeAudio",
        ":TestMockBtaScn",
        ":TestMockBtaSdp",
        ":TestMockBtaSys",
        ":TestMockBtif",
        ":TestMockDevice",
        ":TestMockMainShim",
        ":TestMockMainShimEntry",
        ":TestMockStack",
        "jv/bta_jv_act.cc",
        "test/bta_jv_test.cc",
    ],
    shared_libs: [
        "libbase",
        "libcrypto",
        "liblog",
        "server_configurable_flags",
    ],
    static_libs: [
        "libbluetooth-types",
        "libbluetooth_crypto_toolbox",
        "libbluetooth_gd",
        "libbluetooth_hci_pdl",
        "libbluetooth_log",
        "libbt-common",
        "libbt-platform-protos-lite",
        "libbt_shim_bridge",
        "libbt_shim_ffi",
        "libchrome",
        "libcom.android.sysprop.bluetooth.wrapped",
        "libevent",
        "libgmock",
        "libosi",
    ],
    generated_headers: [
        "BluetoothGeneratedDumpsysDataSchema_h",
    ],
    sanitize: {
        cfi: true,
        scs: true,
        address: true,
        all_undefined: true,
        integer_overflow: true,
        diag: {
            undefined: true,
        },
    },
}
+120 −46
Original line number Diff line number Diff line
@@ -37,6 +37,7 @@
#include "bta/sys/bta_sys.h"
#include "internal_include/bt_target.h"
#include "internal_include/bt_trace.h"
#include "os/logging/log_adapter.h"
#include "osi/include/allocator.h"
#include "osi/include/osi.h"  // UNUSED_ATTR
#include "osi/include/properties.h"
@@ -633,11 +634,13 @@ bool bta_jv_check_psm(uint16_t psm) {

/* Initialises the JAVA I/F */
void bta_jv_enable(tBTA_JV_DM_CBACK* p_cback) {
  tBTA_JV_STATUS status = BTA_JV_SUCCESS;
  bta_jv_cb.p_dm_cback = p_cback;
  tBTA_JV bta_jv;
  bta_jv.status = status;
  if (bta_jv_cb.p_dm_cback) {
    tBTA_JV bta_jv = {
        .status = BTA_JV_SUCCESS,
    };
    bta_jv_cb.p_dm_cback(BTA_JV_ENABLE_EVT, &bta_jv, 0);
  }
  memset(bta_jv_cb.free_psm_list, 0, sizeof(bta_jv_cb.free_psm_list));
  memset(bta_jv_cb.scn_in_use, 0, sizeof(bta_jv_cb.scn_in_use));
  bta_jv_cb.scn_search_index = 1;
@@ -794,89 +797,151 @@ void bta_jv_free_scn(int32_t type /* One of BTA_JV_CONN_TYPE_ */,
static void bta_jv_start_discovery_cback(UNUSED_ATTR const RawAddress& bd_addr,
                                         tSDP_RESULT result,
                                         const void* user_data) {
  tBTA_JV_STATUS status;
  uint32_t* p_rfcomm_slot_id =
      static_cast<uint32_t*>(const_cast<void*>(user_data));

  log::verbose("res={}", loghex(static_cast<uint16_t>(result)));
  if (!bta_jv_cb.sdp_cb.sdp_active) {
    log::warn(
        "Received unexpected service discovery callback bd_addr:{} result:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), sdp_result_text(result),
        bta_jv_cb.sdp_cb.sdp_active);
  }
  if (bta_jv_cb.sdp_cb.bd_addr != bta_jv_cb.sdp_cb.bd_addr) {
    log::warn(
        "Received incorrect service discovery callback expected_bd_addr:{} "
        "actual_bd_addr:{} result:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bta_jv_cb.sdp_cb.bd_addr),
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), sdp_result_text(result),
        bta_jv_cb.sdp_cb.sdp_active);
  }

  bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
  if (bta_jv_cb.p_dm_cback) {
    tBTA_JV_DISCOVERY_COMP dcomp;
    dcomp.scn = 0;
    status = BTA_JV_FAILURE;
    const uint32_t rfcomm_slot_id = *static_cast<const uint32_t*>(user_data);
    tBTA_JV bta_jv = {
        .disc_comp =
            {
                .status = BTA_JV_FAILURE,
                .scn = 0,
            },
    };
    if (result == SDP_SUCCESS || result == SDP_DB_FULL) {
      tSDP_DISC_REC* p_sdp_rec = NULL;
      log::info(
          "Received service discovery callback success bd_addr:{} result:{}",
          ADDRESS_TO_LOGGABLE_CSTR(bd_addr), sdp_result_text(result));
      tSDP_PROTOCOL_ELEM pe;
      log::verbose("bta_jv_cb.uuid={}", bta_jv_cb.uuid);
      tSDP_DISC_REC* p_sdp_rec = NULL;
      p_sdp_rec = get_legacy_stack_sdp_api()->db.SDP_FindServiceUUIDInDb(
          p_bta_jv_cfg->p_sdp_db, bta_jv_cb.uuid, p_sdp_rec);
      log::verbose("p_sdp_rec={}", fmt::ptr(p_sdp_rec));
          p_bta_jv_cfg->p_sdp_db, bta_jv_cb.sdp_cb.uuid, p_sdp_rec);
      log::verbose("bta_jv_cb.uuid={} p_sdp_rec={}", bta_jv_cb.sdp_cb.uuid,
                   fmt::ptr(p_sdp_rec));
      if (p_sdp_rec &&
          get_legacy_stack_sdp_api()->record.SDP_FindProtocolListElemInRec(
              p_sdp_rec, UUID_PROTOCOL_RFCOMM, &pe)) {
        dcomp.scn = (uint8_t)pe.params[0];
        status = BTA_JV_SUCCESS;
      }
        bta_jv = {
            .disc_comp =
                {
                    .status = BTA_JV_SUCCESS,
                    .scn = (uint8_t)pe.params[0],
                },
        };
      }

    dcomp.status = status;
    tBTA_JV bta_jv;
    bta_jv.disc_comp = dcomp;
    bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, *p_rfcomm_slot_id);
    osi_free(p_rfcomm_slot_id);
    } else {
      log::warn(
          "Received service discovery callback failed bd_addr:{} result:{}",
          ADDRESS_TO_LOGGABLE_CSTR(bd_addr), sdp_result_text(result));
    }
    log::info(
        "Issuing service discovery complete callback bd_addr:{} result:{} "
        "status:{} scn:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), sdp_result_text(result),
        bta_jv.disc_comp.status, bta_jv.disc_comp.scn);
    bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id);
  } else {
    log::warn(
        "Received service discovery callback when disabled bd_addr:{} "
        "result:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), sdp_result_text(result));
  }
  // User data memory is allocated in `bta_jv_start_discovery`
  osi_free(const_cast<void*>(user_data));
  bta_jv_cb.sdp_cb = {};
}

/* Discovers services on a remote device */
void bta_jv_start_discovery(const RawAddress& bd_addr, uint16_t num_uuid,
                            bluetooth::Uuid* uuid_list,
                            uint32_t rfcomm_slot_id) {
  tBTA_JV_STATUS status = BTA_JV_FAILURE;
  log::verbose("in, sdp_active={}", bta_jv_cb.sdp_active);
  if (bta_jv_cb.sdp_active != BTA_JV_SDP_ACT_NONE) {
    /* SDP is still in progress */
    status = BTA_JV_BUSY;
  ASSERT(uuid_list != nullptr);
  if (bta_jv_cb.sdp_cb.sdp_active) {
    log::warn(
        "Unable to start discovery as already in progress active_bd_addr{} "
        "request_bd_addr:{} "
        "num:uuid:{} rfcomm_slot_id:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bta_jv_cb.sdp_cb.bd_addr),
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), num_uuid, rfcomm_slot_id);
    if (bta_jv_cb.p_dm_cback) {
      tBTA_JV bta_jv;
      bta_jv.status = status;
      tBTA_JV bta_jv = {
          .status = BTA_JV_BUSY,
      };
      bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id);
    } else {
      log::warn(
          "bta::jv module DISABLED so unable to inform caller service "
          "discovery is "
          "unavailable");
    }
    return;
  }

  /* init the database/set up the filter */
  log::verbose("call SDP_InitDiscoveryDb, num_uuid={}", num_uuid);
  get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
      p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size, num_uuid, uuid_list, 0,
      NULL);
  if (!get_legacy_stack_sdp_api()->service.SDP_InitDiscoveryDb(
          p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size, num_uuid,
          uuid_list, 0, NULL)) {
    log::warn(
        "Unable to initialize service discovery db bd_addr:{} num:uuid:{} "
        "rfcomm_slot_id:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), num_uuid, rfcomm_slot_id);
  }

  /* tell SDP to keep the raw data */
  p_bta_jv_cfg->p_sdp_db->raw_data = p_bta_jv_cfg->p_sdp_raw_data;
  p_bta_jv_cfg->p_sdp_db->raw_size = p_bta_jv_cfg->sdp_raw_size;

  bta_jv_cb.p_sel_raw_data = 0;
  bta_jv_cb.uuid = uuid_list[0];

  bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_YES;
  // Optimistically set this as active
  bta_jv_cb.sdp_cb = {
      .sdp_active = true,
      .bd_addr = bd_addr,
      .uuid = uuid_list[0],
  };

  // NOTE: This gets freed on the callback or when discovery failed to start
  uint32_t* rfcomm_slot_id_copy = (uint32_t*)osi_malloc(sizeof(uint32_t));
  *rfcomm_slot_id_copy = rfcomm_slot_id;

  // user_data memory is freed in `bta_jv_start_discovery_cback` callback
  if (!get_legacy_stack_sdp_api()->service.SDP_ServiceSearchAttributeRequest2(
          bd_addr, p_bta_jv_cfg->p_sdp_db, bta_jv_start_discovery_cback,
          (void*)rfcomm_slot_id_copy)) {
    bta_jv_cb.sdp_active = BTA_JV_SDP_ACT_NONE;
          (const void*)rfcomm_slot_id_copy)) {
    bta_jv_cb.sdp_cb = {};
    osi_free(rfcomm_slot_id_copy);
    log::warn(
        "Unable to original service discovery bd_addr:{} num:uuid:{} "
        "rfcomm_slot_id:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), num_uuid, rfcomm_slot_id);
    /* failed to start SDP. report the failure right away */
    if (bta_jv_cb.p_dm_cback) {
      tBTA_JV bta_jv;
      bta_jv.status = status;
      tBTA_JV bta_jv = {
          .status = BTA_JV_FAILURE,
      };
      bta_jv_cb.p_dm_cback(BTA_JV_DISCOVERY_COMP_EVT, &bta_jv, rfcomm_slot_id);
    } else {
      log::warn("No callback set for discovery complete event");
    }
  } else {
    log::info(
        "Started service discovery bd_addr:{} num_uuid:{} "
        "rfcomm_slot_id:{}",
        ADDRESS_TO_LOGGABLE_CSTR(bd_addr), num_uuid, rfcomm_slot_id);
  }
  /*
  else report the result when the cback is called
  */
}

/* Create an SDP record with the given attributes */
@@ -1914,3 +1979,12 @@ static void bta_jv_reset_sniff_timer(tBTA_JV_PM_CB* p_cb) {
  }
}
/******************************************************************************/

namespace bluetooth::legacy::testing {

void bta_jv_start_discovery_cback(const RawAddress& bd_addr, tSDP_RESULT result,
                                  const void* user_data) {
  ::bta_jv_start_discovery_cback(bd_addr, result, user_data);
}

}  // namespace bluetooth::legacy::testing
+8 −9
Original line number Diff line number Diff line
@@ -110,7 +110,7 @@ typedef struct {
} tBTA_JV_RFC_CB;

/* JV control block */
typedef struct {
struct tBTA_JV_CB {
  /* the SDP handle reported to JV user is the (index + 1) to sdp_handle[].
   * if sdp_handle[i]==0, it's not used.
   * otherwise sdp_handle[i] is the stack SDP handle. */
@@ -127,17 +127,16 @@ typedef struct {
  bool scn_in_use[RFCOMM_MAX_SCN];
  uint8_t scn_search_index; /* used to search for free scns */

  uint8_t sdp_active;                          /* see BTA_JV_SDP_ACT_* */
  bluetooth::Uuid uuid;                   /* current uuid of sdp discovery*/
  struct sdp_cb {
    bool sdp_active{false};
    RawAddress bd_addr{RawAddress::kEmpty};  // current bd_addr of sdp discovery
    bluetooth::Uuid uuid{
        bluetooth::Uuid::kEmpty};  // current uuid of sdp discovery
  } sdp_cb;

  tBTA_JV_PM_CB pm_cb[BTA_JV_PM_MAX_NUM]; /* PM on a per JV handle bases */

  uint16_t dyn_psm; /* Next dynamic PSM value to try to assign */
} tBTA_JV_CB;

enum {
  BTA_JV_SDP_ACT_NONE = 0,
  BTA_JV_SDP_ACT_YES,   /* waiting for SDP result */
  BTA_JV_SDP_ACT_CANCEL /* waiting for cancel complete */
};

/* JV control block */
+350 −0
Original line number Diff line number Diff line
/*
 * Copyright 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <gtest/gtest.h>

#include <memory>

#include "bta/jv/bta_jv_int.h"
#include "bta_jv_api.h"
#include "osi/include/allocator.h"
#include "stack/include/sdp_status.h"
#include "test/common/mock_functions.h"
#include "test/fake/fake_osi.h"
#include "test/mock/mock_stack_sdp_legacy_api.h"
#include "types/bluetooth/uuid.h"
#include "types/raw_address.h"

namespace {
const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
const RawAddress kRawAddress2 =
    RawAddress({0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc});
const bluetooth::Uuid kUuid = bluetooth::Uuid::From16Bit(0x1234);
const bluetooth::Uuid kUuid2 = bluetooth::Uuid::From16Bit(0x789a);

constexpr uint32_t kSlotId = 0x1234568;
constexpr uint8_t kScn = 123;

}  // namespace

namespace bluetooth::legacy::testing {

void bta_jv_start_discovery_cback(const RawAddress& bd_addr, tSDP_RESULT result,
                                  const void* user_data);

}  // namespace bluetooth::legacy::testing

class FakeSdp {
 public:
  FakeSdp() {
    test::mock::stack_sdp_legacy::api_ = {
        .service = {
            .SDP_InitDiscoveryDb = [](tSDP_DISCOVERY_DB*, uint32_t, uint16_t,
                                      const bluetooth::Uuid*, uint16_t,
                                      const uint16_t*) -> bool { return true; },
            .SDP_CancelServiceSearch = nullptr,
            .SDP_ServiceSearchRequest = nullptr,
            .SDP_ServiceSearchAttributeRequest = nullptr,
            .SDP_ServiceSearchAttributeRequest2 =
                [](const RawAddress& /* p_bd_addr */,
                   tSDP_DISCOVERY_DB* /* p_db */,
                   tSDP_DISC_CMPL_CB2* /* p_cb2 */, const void* user_data) {
                  if (user_data) osi_free((void*)user_data);
                  return true;
                },
        },
        .db =
            {
                .SDP_FindServiceInDb = nullptr,
                .SDP_FindServiceUUIDInDb =
                    [](const tSDP_DISCOVERY_DB* /* p_db */,
                       const bluetooth::Uuid& /* uuid */,
                       tSDP_DISC_REC* /* p_start_rec */) -> tSDP_DISC_REC* {
                  return nullptr;
                },
                .SDP_FindServiceInDb_128bit = nullptr,
            },
        .record =
            {
                .SDP_FindAttributeInRec = nullptr,
                .SDP_FindServiceUUIDInRec_128bit = nullptr,
                .SDP_FindProtocolListElemInRec =
                    [](const tSDP_DISC_REC* /* p_rec */,
                       uint16_t /* layer_uuid */,
                       tSDP_PROTOCOL_ELEM* /* p_elem */) -> bool {
                  return false;
                },
                .SDP_FindProfileVersionInRec = nullptr,
                .SDP_FindServiceUUIDInRec = nullptr,
            },
        .handle =
            {
                .SDP_CreateRecord = nullptr,
                .SDP_DeleteRecord = nullptr,
                .SDP_AddAttribute = nullptr,
                .SDP_AddSequence = nullptr,
                .SDP_AddUuidSequence = nullptr,
                .SDP_AddProtocolList = nullptr,
                .SDP_AddAdditionProtoLists = nullptr,
                .SDP_AddProfileDescriptorList = nullptr,
                .SDP_AddLanguageBaseAttrIDList = nullptr,
                .SDP_AddServiceClassIdList = nullptr,
            },
        .device_id =
            {
                .SDP_SetLocalDiRecord = nullptr,
                .SDP_DiDiscover = nullptr,
                .SDP_GetNumDiRecords = nullptr,
                .SDP_GetDiRecord = nullptr,
            },
    };
  }

  ~FakeSdp() { test::mock::stack_sdp_legacy::api_ = {}; }
};

class BtaJvMockAndFakeTest : public ::testing::Test {
 protected:
  void SetUp() override {
    reset_mock_function_count_map();
    fake_osi_ = std::make_unique<test::fake::FakeOsi>();
    fake_sdp_ = std::make_unique<FakeSdp>();
  }

  void TearDown() override {}

  std::unique_ptr<test::fake::FakeOsi> fake_osi_;
  std::unique_ptr<FakeSdp> fake_sdp_;
};

class BtaJvTest : public BtaJvMockAndFakeTest {
 protected:
  void SetUp() override {
    BtaJvMockAndFakeTest::SetUp();
    bta_jv_cb.sdp_cb = {};
  }

  void TearDown() override {
    bta_jv_cb.sdp_cb = {};
    BtaJvMockAndFakeTest::TearDown();
  }
};

TEST_F(BtaJvTest, bta_jv_start_discovery_cback__no_callback) {
  uint32_t* user_data = (uint32_t*)osi_malloc(sizeof(uint32_t));
  *user_data = 0x12345678;

  bta_jv_enable(nullptr);
  bluetooth::legacy::testing::bta_jv_start_discovery_cback(
      kRawAddress, SDP_SUCCESS, (const void*)user_data);
}

TEST_F(BtaJvTest,
       bta_jv_start_discovery_cback__with_callback_success_no_record) {
  uint32_t* user_data = (uint32_t*)osi_malloc(sizeof(uint32_t));
  *user_data = kSlotId;

  // Ensure that there was an sdp active
  bta_jv_cb.sdp_cb = {
      .sdp_active = true,
      .bd_addr = kRawAddress,
      .uuid = kUuid,
  };
  bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
    switch (event) {
      case BTA_JV_DISCOVERY_COMP_EVT:
        ASSERT_EQ(p_data->disc_comp.status, BTA_JV_FAILURE);
        ASSERT_EQ(kSlotId, id);
        break;

      case BTA_JV_ENABLE_EVT:
        ASSERT_EQ(p_data->disc_comp.status, BTA_JV_SUCCESS);
        ASSERT_EQ(0U, id);
        break;

      default:
        FAIL();
    }
  });
  bluetooth::legacy::testing::bta_jv_start_discovery_cback(
      kRawAddress, SDP_SUCCESS, (const void*)user_data);
}

TEST_F(BtaJvTest,
       bta_jv_start_discovery_cback__with_callback_success_with_record) {
  uint32_t* user_data = (uint32_t*)osi_malloc(sizeof(uint32_t));
  *user_data = kSlotId;

  static tSDP_DISC_REC sdp_disc_rec = {
      .p_first_attr = nullptr,
      .p_next_rec = nullptr,
      .time_read = 1,
      .remote_bd_addr = RawAddress::kAny,
  };

  test::mock::stack_sdp_legacy::api_.db.SDP_FindServiceUUIDInDb =
      [](const tSDP_DISCOVERY_DB* /* p_db */, const bluetooth::Uuid& /* uuid */,
         tSDP_DISC_REC* /* p_start_rec */) -> tSDP_DISC_REC* {
    return &sdp_disc_rec;
  };

  test::mock::stack_sdp_legacy::api_.record.SDP_FindProtocolListElemInRec =
      [](const tSDP_DISC_REC* /* p_rec */, uint16_t /* layer_uuid */,
         tSDP_PROTOCOL_ELEM* p_elem) -> bool {
    p_elem->params[0] = (uint16_t)kScn;
    return true;
  };

  // Ensure that there was an sdp active
  bta_jv_cb.sdp_cb = {
      .sdp_active = true,
      .bd_addr = kRawAddress,
      .uuid = kUuid,
  };
  bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
    switch (event) {
      case BTA_JV_DISCOVERY_COMP_EVT:
        ASSERT_EQ(BTA_JV_SUCCESS, p_data->disc_comp.status);
        ASSERT_EQ(kScn, p_data->disc_comp.scn);
        ASSERT_EQ(kSlotId, id);
        break;

      case BTA_JV_ENABLE_EVT:
        ASSERT_EQ(BTA_JV_SUCCESS, p_data->disc_comp.status);
        ASSERT_EQ(0U, id);
        break;

      default:
        FAIL();
    }
  });
  bluetooth::legacy::testing::bta_jv_start_discovery_cback(
      kRawAddress, SDP_SUCCESS, (const void*)user_data);
}

TEST_F(BtaJvTest, bta_jv_start_discovery_cback__with_callback_failure) {
  tSDP_RESULT result = SDP_CONN_FAILED;
  uint32_t* user_data = (uint32_t*)osi_malloc(sizeof(uint32_t));
  *user_data = kSlotId;

  // Ensure that there was an sdp active
  bta_jv_cb.sdp_cb = {
      .sdp_active = true,
      .bd_addr = kRawAddress,
      .uuid = kUuid,
  };
  bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
    switch (event) {
      case BTA_JV_DISCOVERY_COMP_EVT:
        ASSERT_EQ(BTA_JV_FAILURE, p_data->disc_comp.status);
        ASSERT_EQ(kSlotId, id);
        break;

      case BTA_JV_ENABLE_EVT:
        ASSERT_EQ(BTA_JV_SUCCESS, p_data->disc_comp.status);
        ASSERT_EQ(0U, id);
        break;

      default:
        FAIL();
    }
  });
  bluetooth::legacy::testing::bta_jv_start_discovery_cback(
      kRawAddress, result, (const void*)user_data);
}

TEST_F(BtaJvTest, bta_jv_start_discovery__idle) {
  bluetooth::Uuid uuid_list[1] = {
      kUuid,
  };
  uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));

  bta_jv_start_discovery(kRawAddress, num_uuid, uuid_list, kSlotId);

  ASSERT_EQ(true, bta_jv_cb.sdp_cb.sdp_active);
  ASSERT_EQ(kRawAddress, bta_jv_cb.sdp_cb.bd_addr);
  ASSERT_EQ(kUuid, bta_jv_cb.sdp_cb.uuid);
}

TEST_F(BtaJvTest, bta_jv_start_discovery__idle_failed_to_start) {
  bluetooth::Uuid uuid_list[1] = {
      kUuid,
  };
  uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));

  test::mock::stack_sdp_legacy::api_.service
      .SDP_ServiceSearchAttributeRequest2 =
      [](const RawAddress& /* p_bd_addr */, tSDP_DISCOVERY_DB* /* p_db */,
         tSDP_DISC_CMPL_CB2* /* p_cb2 */,
         const void* /* user_data */) { return false; };

  bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
    switch (event) {
      case BTA_JV_DISCOVERY_COMP_EVT:
        ASSERT_EQ(BTA_JV_FAILURE, p_data->disc_comp.status);
        ASSERT_EQ(kSlotId, id);
        break;

      case BTA_JV_ENABLE_EVT:
        ASSERT_EQ(BTA_JV_SUCCESS, p_data->disc_comp.status);
        ASSERT_EQ(0U, id);
        break;

      default:
        FAIL();
    }
  });
  bta_jv_start_discovery(kRawAddress2, num_uuid, uuid_list, kSlotId);

  ASSERT_EQ(false, bta_jv_cb.sdp_cb.sdp_active);
  ASSERT_EQ(RawAddress::kEmpty, bta_jv_cb.sdp_cb.bd_addr);
  ASSERT_EQ(bluetooth::Uuid::kEmpty, bta_jv_cb.sdp_cb.uuid);
}

TEST_F(BtaJvTest, bta_jv_start_discovery__already_active) {
  bta_jv_cb.sdp_cb = {
      .sdp_active = true,
      .bd_addr = kRawAddress,
      .uuid = kUuid,
  };

  bluetooth::Uuid uuid_list[1] = {
      kUuid2,
  };
  uint16_t num_uuid = (uint16_t)(sizeof(uuid_list) / sizeof(uuid_list[0]));

  bta_jv_enable([](tBTA_JV_EVT event, tBTA_JV* p_data, uint32_t id) {
    switch (event) {
      case BTA_JV_DISCOVERY_COMP_EVT:
        ASSERT_EQ(BTA_JV_BUSY, p_data->disc_comp.status);
        ASSERT_EQ(kSlotId, id);
        break;

      case BTA_JV_ENABLE_EVT:
        ASSERT_EQ(BTA_JV_SUCCESS, p_data->disc_comp.status);
        ASSERT_EQ(0U, id);
        break;

      default:
        FAIL();
    }
  });
  bta_jv_start_discovery(kRawAddress2, num_uuid, uuid_list, kSlotId);

  ASSERT_EQ(true, bta_jv_cb.sdp_cb.sdp_active);
  ASSERT_EQ(kRawAddress, bta_jv_cb.sdp_cb.bd_addr);
  ASSERT_EQ(kUuid, bta_jv_cb.sdp_cb.uuid);
}
+1 −3
Original line number Diff line number Diff line
@@ -109,6 +109,4 @@ void gatt_update_app_use_link_flag(tGATT_IF /* gatt_if */,
  inc_func_call_count(__func__);
}

void gatt_tcb_dump(int fd) {
  inc_func_call_count(__func__);
}
void gatt_tcb_dump(int /* fd */) { inc_func_call_count(__func__); }