Loading system/bta/Android.bp +71 −0 Original line number Diff line number Diff line Loading @@ -451,6 +451,7 @@ cc_test { "BluetoothGeneratedDumpsysDataSchema_h", ], srcs: [ ":BluetoothLogRedactionSources", ":TestCommonMockFunctions", ":TestFakeOsi", ":TestMockBtaSys", Loading Loading @@ -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, }, }, } system/bta/jv/bta_jv_act.cc +120 −46 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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 system/bta/jv/bta_jv_int.h +8 −9 Original line number Diff line number Diff line Loading @@ -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. */ Loading @@ -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 */ Loading system/bta/test/bta_jv_test.cc 0 → 100644 +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); } system/test/mock/mock_stack_gatt_main.cc +1 −3 Original line number Diff line number Diff line Loading @@ -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__); } Loading
system/bta/Android.bp +71 −0 Original line number Diff line number Diff line Loading @@ -451,6 +451,7 @@ cc_test { "BluetoothGeneratedDumpsysDataSchema_h", ], srcs: [ ":BluetoothLogRedactionSources", ":TestCommonMockFunctions", ":TestFakeOsi", ":TestMockBtaSys", Loading Loading @@ -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, }, }, }
system/bta/jv/bta_jv_act.cc +120 −46 Original line number Diff line number Diff line Loading @@ -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" Loading Loading @@ -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; Loading Loading @@ -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 */ Loading Loading @@ -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
system/bta/jv/bta_jv_int.h +8 −9 Original line number Diff line number Diff line Loading @@ -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. */ Loading @@ -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 */ Loading
system/bta/test/bta_jv_test.cc 0 → 100644 +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); }
system/test/mock/mock_stack_gatt_main.cc +1 −3 Original line number Diff line number Diff line Loading @@ -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__); }