1 /*
2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <bluetooth/log.h>
18 #include <gmock/gmock.h>
19 #include <gtest/gtest.h>
20 
21 #include <future>
22 
23 #include "common/contextual_callback.h"
24 #include "hci/address.h"
25 #include "hci/class_of_device.h"
26 #include "hci/hci_layer_fake.h"
27 #include "hci/hci_packets.h"
28 #include "stack/btm/btm_int_types.h"
29 #include "stack/include/btm_inq.h"
30 #include "stack/include/btm_status.h"
31 #include "stack/include/hci_error_code.h"
32 #include "stack/include/inq_hci_link_interface.h"
33 #include "stack/include/main_thread.h"
34 #include "stack/test/btm/btm_test_fixtures.h"
35 #include "test/common/mock_functions.h"
36 #include "test/mock/mock_main_shim_entry.h"
37 #include "types/raw_address.h"
38 
39 // TODO(b/369381361) Enfore -Wmissing-prototypes
40 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
41 
42 extern tBTM_CB btm_cb;
43 
44 using bluetooth::common::ContextualCallback;
45 using bluetooth::common::ContextualOnceCallback;
46 using bluetooth::hci::Address;
47 using bluetooth::hci::CommandCompleteView;
48 using bluetooth::hci::CommandStatusView;
49 using bluetooth::hci::EventView;
50 using bluetooth::hci::ExtendedInquiryResultBuilder;
51 using bluetooth::hci::ExtendedInquiryResultView;
52 using bluetooth::hci::InquiryResponse;
53 using bluetooth::hci::InquiryResultBuilder;
54 using bluetooth::hci::InquiryResultView;
55 using bluetooth::hci::InquiryResultWithRssiBuilder;
56 using bluetooth::hci::InquiryResultWithRssiView;
57 using bluetooth::hci::InquiryStatusBuilder;
58 using bluetooth::hci::InquiryView;
59 using bluetooth::hci::OpCode;
60 using bluetooth::hci::EventCode::EXTENDED_INQUIRY_RESULT;
61 using bluetooth::hci::EventCode::INQUIRY_COMPLETE;
62 using bluetooth::hci::EventCode::INQUIRY_RESULT;
63 using bluetooth::hci::EventCode::INQUIRY_RESULT_WITH_RSSI;
64 using testing::_;
65 using testing::A;
66 using testing::Matcher;
67 using testing::NiceMock;
68 using testing::Return;
69 using testing::SaveArg;
70 
71 namespace {
72 const Address kAddress = Address({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
73 const Address kAddress2 = Address({0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc});
74 const RawAddress kRawAddress = RawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
75 const RawAddress kRawAddress2 = RawAddress({0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc});
76 const BD_NAME kBdName = {'A', ' ', 'B', 'd', ' ', 'N', 'a', 'm', 'e', '\0'};
77 const BD_NAME kEmptyName = "";
78 
79 tBTM_REMOTE_DEV_NAME gBTM_REMOTE_DEV_NAME{};
80 bool gBTM_REMOTE_DEV_NAME_sent{false};
81 
82 static constexpr uint8_t kNumCommandPackets = 1;
83 
84 }  // namespace
85 
86 class BtmInqTest : public BtmWithMocksTest {
87 protected:
SetUp()88   void SetUp() override {
89     BtmWithMocksTest::SetUp();
90     btm_cb = {};
91   }
92 
TearDown()93   void TearDown() override { BtmWithMocksTest::TearDown(); }
94 };
95 
96 class BtmInqActiveTest : public BtmInqTest {
97 protected:
SetUp()98   void SetUp() override {
99     BtmInqTest::SetUp();
100     gBTM_REMOTE_DEV_NAME = {};
101     gBTM_REMOTE_DEV_NAME_sent = false;
102 
103     btm_cb.rnr.remname_active = true;
104     btm_cb.rnr.remname_bda = kRawAddress;
105     btm_cb.rnr.remname_dev_type = BT_DEVICE_TYPE_BREDR;
106     btm_cb.rnr.p_remname_cmpl_cb = [](const tBTM_REMOTE_DEV_NAME* name) {
107       gBTM_REMOTE_DEV_NAME = *name;
108       gBTM_REMOTE_DEV_NAME_sent = true;
109     };
110   }
111 
TearDown()112   void TearDown() override { BtmInqTest::TearDown(); }
113 };
114 
115 class BtmInquiryCallbacks {
116 public:
117   virtual ~BtmInquiryCallbacks() = default;
118   virtual void btm_inq_results_cb(tBTM_INQ_RESULTS*, const uint8_t*, uint16_t) = 0;
119   virtual void btm_inq_cmpl_cb(void*) = 0;
120 };
121 
122 class MockBtmInquiryCallbacks : public BtmInquiryCallbacks {
123 public:
124   MOCK_METHOD(void, btm_inq_results_cb,
125               (tBTM_INQ_RESULTS * p_inq_results, const uint8_t* p_eir, uint16_t eir_len),
126               (override));
127   MOCK_METHOD(void, btm_inq_cmpl_cb, (void*), (override));
128 };
129 
130 MockBtmInquiryCallbacks* inquiry_callback_ptr = nullptr;
131 
btm_inq_results_cb(tBTM_INQ_RESULTS * p_inq_results,const uint8_t * p_eir,uint16_t eir_len)132 void btm_inq_results_cb(tBTM_INQ_RESULTS* p_inq_results, const uint8_t* p_eir, uint16_t eir_len) {
133   inquiry_callback_ptr->btm_inq_results_cb(p_inq_results, p_eir, eir_len);
134 }
135 
btm_inq_cmpl_cb(void * p1)136 void btm_inq_cmpl_cb(void* p1) { inquiry_callback_ptr->btm_inq_cmpl_cb(p1); }
137 
138 class BtmDeviceInquiryTest : public BtmInqTest {
139 protected:
SetUp()140   void SetUp() override {
141     BtmInqTest::SetUp();
142     main_thread_start_up();
143     inquiry_callback_ptr = &callbacks_;
144     bluetooth::hci::testing::mock_controller_ = &controller_;
145     ON_CALL(controller_, SupportsBle()).WillByDefault(Return(true));
146     bluetooth::hci::testing::mock_hci_layer_ = &hci_layer_;
147 
148     // Start Inquiry
149     EXPECT_EQ(tBTM_STATUS::BTM_CMD_STARTED, BTM_StartInquiry(btm_inq_results_cb, btm_inq_cmpl_cb));
150     auto view = hci_layer_.GetCommand(OpCode::INQUIRY);
151     hci_layer_.IncomingEvent(
152             InquiryStatusBuilder::Create(bluetooth::hci::ErrorCode::SUCCESS, kNumCommandPackets));
153 
154     // Send one response to synchronize
155     std::promise<void> first_result_promise;
156     auto first_result = first_result_promise.get_future();
157     EXPECT_CALL(*inquiry_callback_ptr, btm_inq_results_cb(_, _, _))
158             .WillOnce([&first_result_promise]() { first_result_promise.set_value(); })
159             .RetiresOnSaturation();
160 
161     InquiryResponse one_device(kAddress, bluetooth::hci::PageScanRepetitionMode::R0,
162                                bluetooth::hci::ClassOfDevice(), 0x1234);
163     hci_layer_.IncomingEvent(InquiryResultBuilder::Create({one_device}));
164 
165     EXPECT_EQ(std::future_status::ready, first_result.wait_for(std::chrono::seconds(1)));
166   }
167 
TearDown()168   void TearDown() override {
169     BTM_CancelInquiry();
170     inquiry_callback_ptr = nullptr;
171     main_thread_shut_down();
172     BtmInqTest::TearDown();
173   }
174 
175   NiceMock<bluetooth::hci::testing::MockControllerInterface> controller_;
176   bluetooth::hci::HciLayerFake hci_layer_;
177   ContextualCallback<void(EventView)> on_exteneded_inq_result_;
178   ContextualCallback<void(EventView)> on_inq_complete_;
179   ContextualCallback<void(EventView)> on_inq_result_;
180   ContextualCallback<void(EventView)> on_inq_result_with_rssi_;
181   MockBtmInquiryCallbacks callbacks_;
182 };
183 
TEST_F(BtmDeviceInquiryTest,bta_dm_disc_device_discovery_single_result)184 TEST_F(BtmDeviceInquiryTest, bta_dm_disc_device_discovery_single_result) {
185   std::promise<void> one_result_promise;
186   auto one_result = one_result_promise.get_future();
187   EXPECT_CALL(*inquiry_callback_ptr, btm_inq_results_cb(_, _, _))
188           .WillOnce([&one_result_promise]() { one_result_promise.set_value(); })
189           .RetiresOnSaturation();
190 
191   InquiryResponse one_device(kAddress2, bluetooth::hci::PageScanRepetitionMode::R0,
192                              bluetooth::hci::ClassOfDevice(), 0x2345);
193   hci_layer_.IncomingEvent(InquiryResultBuilder::Create({one_device}));
194 
195   EXPECT_EQ(std::future_status::ready, one_result.wait_for(std::chrono::seconds(1)));
196 }
197