1 /*
2  * Copyright 2023 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 <gmock/gmock.h>
18 #include <gtest/gtest.h>
19 #include <sys/socket.h>
20 
21 #include "bta/dm/bta_dm_sec_int.h"
22 #include "bta/test/bta_test_fixtures.h"
23 #include "stack/include/btm_status.h"
24 #include "test/mock/mock_stack_btm_interface.h"
25 #include "test/mock/mock_stack_rnr_interface.h"
26 #include "types/raw_address.h"
27 
28 using ::testing::_;
29 using ::testing::ElementsAre;
30 using ::testing::Return;
31 
32 namespace {
33 const RawAddress kRawAddress({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
34 const RawAddress kRawAddress2({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
35 const DEV_CLASS kDeviceClass = {0x11, 0x22, 0x33};
36 
37 constexpr char kRemoteName[] = "TheRemoteName";
38 
39 }  // namespace
40 
41 // Test hooks
42 namespace bluetooth {
43 namespace legacy {
44 namespace testing {
45 
46 tBTM_STATUS bta_dm_sp_cback(tBTM_SP_EVT event, tBTM_SP_EVT_DATA* p_data);
47 
48 }  // namespace testing
49 }  // namespace legacy
50 }  // namespace bluetooth
51 
52 class BtaSecTest : public BtaWithHwOnTest {
53 protected:
SetUp()54   void SetUp() override {
55     BtaWithHwOnTest::SetUp();
56     bluetooth::testing::stack::rnr::set_interface(&mock_stack_rnr_interface_);
57   }
58 
TearDown()59   void TearDown() override {
60     bluetooth::testing::stack::rnr::reset_interface();
61     BtaWithHwOnTest::TearDown();
62   }
63 
64   bluetooth::testing::stack::rnr::Mock mock_stack_rnr_interface_;
65 };
66 
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithName)67 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithName) {
68   constexpr uint32_t kNumVal = 1234;
69   static bool callback_sent = false;
70 
71   static tBTA_DM_SP_CFM_REQ cfm_req{};
72   bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
73     callback_sent = true;
74     cfm_req = p_data->cfm_req;
75   });
76 
77   tBTM_SP_EVT_DATA data = {
78           .cfm_req =
79                   {
80                           // tBTM_SP_CFM_REQ
81                           .bd_addr = kRawAddress,
82                           .dev_class = {},
83                           .bd_name = {},
84                           .num_val = kNumVal,
85                           .just_works = false,
86                           .loc_auth_req = BTM_AUTH_SP_YES,
87                           .rmt_auth_req = BTM_AUTH_SP_YES,
88                           .loc_io_caps = BTM_IO_CAP_NONE,
89                           .rmt_io_caps = BTM_IO_CAP_NONE,
90                   },
91   };
92   data.cfm_req.dev_class = kDeviceClass;
93   bd_name_from_char_pointer(data.cfm_req.bd_name, kRemoteName);
94 
95   ASSERT_EQ(
96           btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
97           btm_status_text(bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_CFM_REQ_EVT, &data)));
98   ASSERT_EQ(kNumVal, bta_dm_sec_cb.num_val);
99   ASSERT_TRUE(callback_sent);
100 
101   ASSERT_EQ(kRawAddress, cfm_req.bd_addr);
102   ASSERT_THAT(cfm_req.dev_class, ElementsAre(kDeviceClass[0], kDeviceClass[1], kDeviceClass[2]));
103   ASSERT_STREQ(kRemoteName, reinterpret_cast<const char*>(cfm_req.bd_name));
104   ASSERT_EQ(kNumVal, cfm_req.num_val);
105   ASSERT_EQ(false, cfm_req.just_works);
106   ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.loc_auth_req);
107   ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.rmt_auth_req);
108   ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.loc_io_caps);
109   ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.rmt_io_caps);
110 }
111 
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRSuccess)112 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRSuccess) {
113   constexpr uint32_t kNumVal = 1234;
114   static bool callback_sent = false;
115   reset_mock_btm_client_interface();
116 
117   EXPECT_CALL(mock_stack_rnr_interface_, BTM_ReadRemoteDeviceName(_, _, _))
118           .WillOnce(Return(tBTM_STATUS::BTM_CMD_STARTED));
119 
120   static tBTA_DM_SP_CFM_REQ cfm_req{};
121   bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
122     callback_sent = true;
123     cfm_req = p_data->cfm_req;
124   });
125 
126   tBTM_SP_EVT_DATA data = {
127           .cfm_req =
128                   {
129                           // tBTM_SP_CFM_REQ
130                           .bd_addr = kRawAddress,
131                           .dev_class = {},
132                           .bd_name = {0},  // No name available
133                           .num_val = kNumVal,
134                           .just_works = false,
135                           .loc_auth_req = BTM_AUTH_SP_YES,
136                           .rmt_auth_req = BTM_AUTH_SP_YES,
137                           .loc_io_caps = BTM_IO_CAP_NONE,
138                           .rmt_io_caps = BTM_IO_CAP_NONE,
139                   },
140   };
141   data.cfm_req.dev_class = kDeviceClass;
142 
143   ASSERT_EQ(
144           btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
145           btm_status_text(bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_CFM_REQ_EVT, &data)));
146   ASSERT_EQ(kNumVal, bta_dm_sec_cb.num_val);
147   ASSERT_FALSE(callback_sent);
148 }
149 
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRFail)150 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_CFM_REQ_EVT_WithoutName_RNRFail) {
151   constexpr uint32_t kNumVal = 1234;
152   static bool callback_sent = false;
153 
154   EXPECT_CALL(mock_stack_rnr_interface_, BTM_ReadRemoteDeviceName(_, _, _))
155           .WillOnce(Return(tBTM_STATUS::BTM_SUCCESS));
156 
157   static tBTA_DM_SP_CFM_REQ cfm_req{};
158   bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
159     callback_sent = true;
160     cfm_req = p_data->cfm_req;
161   });
162 
163   tBTM_SP_EVT_DATA data = {
164           .cfm_req =
165                   {
166                           // tBTM_SP_CFM_REQ
167                           .bd_addr = kRawAddress,
168                           .dev_class = {},
169                           .bd_name = {0},
170                           .num_val = kNumVal,
171                           .just_works = false,
172                           .loc_auth_req = BTM_AUTH_SP_YES,
173                           .rmt_auth_req = BTM_AUTH_SP_YES,
174                           .loc_io_caps = BTM_IO_CAP_NONE,
175                           .rmt_io_caps = BTM_IO_CAP_NONE,
176                   },
177   };
178   data.cfm_req.dev_class = kDeviceClass;
179 
180   ASSERT_EQ(
181           btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
182           btm_status_text(bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_CFM_REQ_EVT, &data)));
183   ASSERT_EQ(kNumVal, bta_dm_sec_cb.num_val);
184   ASSERT_TRUE(callback_sent);
185 
186   ASSERT_EQ(kRawAddress, cfm_req.bd_addr);
187   ASSERT_THAT(cfm_req.dev_class, ElementsAre(kDeviceClass[0], kDeviceClass[1], kDeviceClass[2]));
188   ASSERT_EQ(kNumVal, cfm_req.num_val);
189   ASSERT_EQ(false, cfm_req.just_works);
190   ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.loc_auth_req);
191   ASSERT_EQ(BTM_AUTH_SP_YES, cfm_req.rmt_auth_req);
192   ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.loc_io_caps);
193   ASSERT_EQ(BTM_IO_CAP_NONE, cfm_req.rmt_io_caps);
194 }
195 
TEST_F(BtaSecTest,bta_dm_sp_cback__BTM_SP_KEY_NOTIF_EVT)196 TEST_F(BtaSecTest, bta_dm_sp_cback__BTM_SP_KEY_NOTIF_EVT) {
197   constexpr uint32_t kPassKey = 1234;
198   static bool callback_sent = false;
199 
200   ON_CALL(mock_stack_rnr_interface_, BTM_ReadRemoteDeviceName(_, _, _))
201           .WillByDefault(Return(tBTM_STATUS::BTM_CMD_STARTED));
202 
203   static tBTA_DM_SP_KEY_NOTIF key_notif{};
204   bta_dm_sec_enable([](tBTA_DM_SEC_EVT /*event*/, tBTA_DM_SEC* p_data) {
205     callback_sent = true;
206     key_notif = p_data->key_notif;
207   });
208 
209   tBTM_SP_EVT_DATA data = {
210           .key_notif =
211                   {
212                           // tBTM_SP_KEY_NOTIF
213                           .bd_addr = kRawAddress,
214                           .dev_class = {},
215                           .bd_name = {},
216                           .passkey = kPassKey,
217                   },
218   };
219   data.key_notif.dev_class = kDeviceClass;
220   bd_name_from_char_pointer(data.key_notif.bd_name, kRemoteName);
221 
222   ASSERT_EQ(btm_status_text(tBTM_STATUS::BTM_CMD_STARTED),
223             btm_status_text(
224                     bluetooth::legacy::testing::bta_dm_sp_cback(BTM_SP_KEY_NOTIF_EVT, &data)));
225   ASSERT_EQ(kPassKey, bta_dm_sec_cb.num_val);
226   ASSERT_TRUE(callback_sent);
227 
228   ASSERT_EQ(kRawAddress, key_notif.bd_addr);
229   ASSERT_THAT(key_notif.dev_class, ElementsAre(kDeviceClass[0], kDeviceClass[1], kDeviceClass[2]));
230   ASSERT_STREQ(kRemoteName, reinterpret_cast<const char*>(key_notif.bd_name));
231   ASSERT_EQ(kPassKey, key_notif.passkey);
232 }
233