1 /*
2 * Copyright 2022 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 "hci/acl_manager/classic_acl_connection.h"
18
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21
22 #include <chrono>
23 #include <cstdint>
24 #include <future>
25 #include <list>
26 #include <memory>
27 #include <mutex>
28 #include <queue>
29 #include <vector>
30
31 #include "hci/acl_connection_interface.h"
32 #include "hci/acl_manager/connection_management_callbacks.h"
33 #include "hci/address.h"
34 #include "hci/hci_packets.h"
35 #include "os/handler.h"
36 #include "os/log.h"
37 #include "os/thread.h"
38
39 using namespace bluetooth;
40 using namespace std::chrono_literals;
41
42 namespace {
43 constexpr char kAddress[] = "00:11:22:33:44:55";
44 constexpr uint16_t kConnectionHandle = 123;
45 constexpr size_t kQueueSize = 10;
46
47 std::vector<hci::DisconnectReason> disconnect_reason_vector = {
48 hci::DisconnectReason::AUTHENTICATION_FAILURE,
49 hci::DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION,
50 hci::DisconnectReason::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES,
51 hci::DisconnectReason::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF,
52 hci::DisconnectReason::UNSUPPORTED_REMOTE_FEATURE,
53 hci::DisconnectReason::PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED,
54 hci::DisconnectReason::UNACCEPTABLE_CONNECTION_PARAMETERS,
55 };
56
57 std::vector<hci::ErrorCode> error_code_vector = {
58 hci::ErrorCode::SUCCESS,
59 hci::ErrorCode::UNKNOWN_HCI_COMMAND,
60 hci::ErrorCode::UNKNOWN_CONNECTION,
61 hci::ErrorCode::HARDWARE_FAILURE,
62 hci::ErrorCode::PAGE_TIMEOUT,
63 hci::ErrorCode::AUTHENTICATION_FAILURE,
64 hci::ErrorCode::PIN_OR_KEY_MISSING,
65 hci::ErrorCode::MEMORY_CAPACITY_EXCEEDED,
66 hci::ErrorCode::CONNECTION_TIMEOUT,
67 hci::ErrorCode::CONNECTION_LIMIT_EXCEEDED,
68 hci::ErrorCode::SYNCHRONOUS_CONNECTION_LIMIT_EXCEEDED,
69 hci::ErrorCode::CONNECTION_ALREADY_EXISTS,
70 hci::ErrorCode::COMMAND_DISALLOWED,
71 hci::ErrorCode::CONNECTION_REJECTED_LIMITED_RESOURCES,
72 hci::ErrorCode::CONNECTION_REJECTED_SECURITY_REASONS,
73 hci::ErrorCode::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR,
74 hci::ErrorCode::CONNECTION_ACCEPT_TIMEOUT,
75 hci::ErrorCode::UNSUPPORTED_FEATURE_OR_PARAMETER_VALUE,
76 hci::ErrorCode::INVALID_HCI_COMMAND_PARAMETERS,
77 hci::ErrorCode::REMOTE_USER_TERMINATED_CONNECTION,
78 hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_LOW_RESOURCES,
79 hci::ErrorCode::REMOTE_DEVICE_TERMINATED_CONNECTION_POWER_OFF,
80 hci::ErrorCode::CONNECTION_TERMINATED_BY_LOCAL_HOST,
81 hci::ErrorCode::REPEATED_ATTEMPTS,
82 hci::ErrorCode::PAIRING_NOT_ALLOWED,
83 hci::ErrorCode::UNKNOWN_LMP_PDU,
84 hci::ErrorCode::UNSUPPORTED_REMOTE_OR_LMP_FEATURE,
85 hci::ErrorCode::SCO_OFFSET_REJECTED,
86 hci::ErrorCode::SCO_INTERVAL_REJECTED,
87 hci::ErrorCode::SCO_AIR_MODE_REJECTED,
88 hci::ErrorCode::INVALID_LMP_OR_LL_PARAMETERS,
89 hci::ErrorCode::UNSPECIFIED_ERROR,
90 hci::ErrorCode::UNSUPPORTED_LMP_OR_LL_PARAMETER,
91 hci::ErrorCode::ROLE_CHANGE_NOT_ALLOWED,
92 hci::ErrorCode::TRANSACTION_RESPONSE_TIMEOUT,
93 hci::ErrorCode::LINK_LAYER_COLLISION,
94 hci::ErrorCode::ENCRYPTION_MODE_NOT_ACCEPTABLE,
95 hci::ErrorCode::ROLE_SWITCH_FAILED,
96 hci::ErrorCode::CONTROLLER_BUSY,
97 hci::ErrorCode::ADVERTISING_TIMEOUT,
98 hci::ErrorCode::CONNECTION_FAILED_ESTABLISHMENT,
99 hci::ErrorCode::LIMIT_REACHED,
100 hci::ErrorCode::STATUS_UNKNOWN,
101 };
102
103 // Generic template for all commands
104 template <typename T, typename U>
CreateCommand(U)105 T CreateCommand(U /* u */) {
106 T command;
107 return command;
108 }
109
110 template <>
CreateCommand(std::shared_ptr<std::vector<uint8_t>> bytes)111 hci::DisconnectView CreateCommand(std::shared_ptr<std::vector<uint8_t>> bytes) {
112 return hci::DisconnectView::Create(
113 hci::AclCommandView::Create(hci::CommandView::Create(hci::PacketView<hci::kLittleEndian>(bytes))));
114 }
115
116 } // namespace
117
118 class TestAclConnectionInterface : public hci::AclConnectionInterface {
119 private:
EnqueueCommand(std::unique_ptr<hci::AclCommandBuilder> command,common::ContextualOnceCallback<void (hci::CommandStatusView)> on_status)120 void EnqueueCommand(
121 std::unique_ptr<hci::AclCommandBuilder> command,
122 common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) override {
123 const std::lock_guard<std::mutex> lock(command_queue_mutex_);
124 command_queue_.push(std::move(command));
125 command_status_callbacks.push_back(std::move(on_status));
126 if (command_promise_ != nullptr) {
127 std::promise<void>* prom = command_promise_.release();
128 prom->set_value();
129 delete prom;
130 }
131 }
132
EnqueueCommand(std::unique_ptr<hci::AclCommandBuilder> command,common::ContextualOnceCallback<void (hci::CommandCompleteView)> on_complete)133 void EnqueueCommand(
134 std::unique_ptr<hci::AclCommandBuilder> command,
135 common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) override {
136 const std::lock_guard<std::mutex> lock(command_queue_mutex_);
137 command_queue_.push(std::move(command));
138 command_complete_callbacks.push_back(std::move(on_complete));
139 if (command_promise_ != nullptr) {
140 std::promise<void>* prom = command_promise_.release();
141 prom->set_value();
142 delete prom;
143 }
144 }
145
146 public:
147 virtual ~TestAclConnectionInterface() = default;
148
DequeueCommand()149 std::unique_ptr<hci::CommandBuilder> DequeueCommand() {
150 const std::lock_guard<std::mutex> lock(command_queue_mutex_);
151 auto packet = std::move(command_queue_.front());
152 command_queue_.pop();
153 return packet;
154 }
155
DequeueCommandBytes()156 std::shared_ptr<std::vector<uint8_t>> DequeueCommandBytes() {
157 auto command = DequeueCommand();
158 auto bytes = std::make_shared<std::vector<uint8_t>>();
159 packet::BitInserter bi(*bytes);
160 command->Serialize(bi);
161 return bytes;
162 }
163
IsPacketQueueEmpty() const164 bool IsPacketQueueEmpty() const {
165 const std::lock_guard<std::mutex> lock(command_queue_mutex_);
166 return command_queue_.empty();
167 }
168
NumberOfQueuedCommands() const169 size_t NumberOfQueuedCommands() const {
170 const std::lock_guard<std::mutex> lock(command_queue_mutex_);
171 return command_queue_.size();
172 }
173
174 private:
175 std::list<common::ContextualOnceCallback<void(hci::CommandCompleteView)>> command_complete_callbacks;
176 std::list<common::ContextualOnceCallback<void(hci::CommandStatusView)>> command_status_callbacks;
177 std::queue<std::unique_ptr<hci::CommandBuilder>> command_queue_;
178 mutable std::mutex command_queue_mutex_;
179 std::unique_ptr<std::promise<void>> command_promise_;
180 std::unique_ptr<std::future<void>> command_future_;
181 };
182
183 class TestConnectionManagementCallbacks : public hci::acl_manager::ConnectionManagementCallbacks {
184 public:
185 ~TestConnectionManagementCallbacks() = default;
OnConnectionPacketTypeChanged(uint16_t)186 void OnConnectionPacketTypeChanged(uint16_t /* packet_type */) override {}
OnAuthenticationComplete(hci::ErrorCode)187 void OnAuthenticationComplete(hci::ErrorCode /* hci_status */) override {}
OnEncryptionChange(hci::EncryptionEnabled)188 void OnEncryptionChange(hci::EncryptionEnabled /* enabled */) override {}
OnChangeConnectionLinkKeyComplete()189 void OnChangeConnectionLinkKeyComplete() override {}
OnReadClockOffsetComplete(uint16_t)190 void OnReadClockOffsetComplete(uint16_t /* clock_offset */) override {}
OnModeChange(hci::ErrorCode,hci::Mode,uint16_t)191 void OnModeChange(
192 hci::ErrorCode /* status */, hci::Mode /* current_mode */, uint16_t /* interval */) override {
193 }
OnSniffSubrating(hci::ErrorCode,uint16_t,uint16_t,uint16_t,uint16_t)194 void OnSniffSubrating(
195 hci::ErrorCode /* hci_status */,
196 uint16_t /* maximum_transmit_latency */,
197 uint16_t /* maximum_receive_latency */,
198 uint16_t /* minimum_remote_timeout */,
199 uint16_t /* minimum_local_timeout */) override {}
OnQosSetupComplete(hci::ServiceType,uint32_t,uint32_t,uint32_t,uint32_t)200 void OnQosSetupComplete(
201 hci::ServiceType /* service_type */,
202 uint32_t /* token_rate */,
203 uint32_t /* peak_bandwidth */,
204 uint32_t /* latency */,
205 uint32_t /* delay_variation */) override {}
OnFlowSpecificationComplete(hci::FlowDirection,hci::ServiceType,uint32_t,uint32_t,uint32_t,uint32_t)206 void OnFlowSpecificationComplete(
207 hci::FlowDirection /* flow_direction */,
208 hci::ServiceType /* service_type */,
209 uint32_t /* token_rate */,
210 uint32_t /* token_bucket_size */,
211 uint32_t /* peak_bandwidth */,
212 uint32_t /* access_latency */) override {}
OnFlushOccurred()213 void OnFlushOccurred() override {}
OnRoleDiscoveryComplete(hci::Role)214 void OnRoleDiscoveryComplete(hci::Role /* current_role */) override {}
OnReadLinkPolicySettingsComplete(uint16_t)215 void OnReadLinkPolicySettingsComplete(uint16_t /* link_policy_settings */) override {}
OnReadAutomaticFlushTimeoutComplete(uint16_t)216 void OnReadAutomaticFlushTimeoutComplete(uint16_t /* flush_timeout */) override {}
OnReadTransmitPowerLevelComplete(uint8_t)217 void OnReadTransmitPowerLevelComplete(uint8_t /* transmit_power_level */) override {}
OnReadLinkSupervisionTimeoutComplete(uint16_t)218 void OnReadLinkSupervisionTimeoutComplete(uint16_t /* link_supervision_timeout */) override {}
OnReadFailedContactCounterComplete(uint16_t)219 void OnReadFailedContactCounterComplete(uint16_t /* failed_contact_counter */) override {}
OnReadLinkQualityComplete(uint8_t)220 void OnReadLinkQualityComplete(uint8_t /* link_quality */) override {}
OnReadAfhChannelMapComplete(hci::AfhMode,std::array<uint8_t,10>)221 void OnReadAfhChannelMapComplete(
222 hci::AfhMode /* afh_mode */, std::array<uint8_t, 10> /* afh_channel_map */) override {}
OnReadRssiComplete(uint8_t)223 void OnReadRssiComplete(uint8_t /* rssi */) override {}
OnReadClockComplete(uint32_t,uint16_t)224 void OnReadClockComplete(uint32_t /* clock */, uint16_t /* accuracy */) override {}
OnCentralLinkKeyComplete(hci::KeyFlag)225 void OnCentralLinkKeyComplete(hci::KeyFlag /* key_flag */) override {}
OnRoleChange(hci::ErrorCode,hci::Role)226 void OnRoleChange(hci::ErrorCode /* hci_status */, hci::Role /* new_role */) override {}
OnDisconnection(hci::ErrorCode reason)227 void OnDisconnection(hci::ErrorCode reason) override {
228 on_disconnection_error_code_queue_.push(reason);
229 }
OnReadRemoteVersionInformationComplete(hci::ErrorCode,uint8_t,uint16_t,uint16_t)230 void OnReadRemoteVersionInformationComplete(
231 hci::ErrorCode /* hci_status */,
232 uint8_t /* lmp_version */,
233 uint16_t /* manufacturer_name */,
234 uint16_t /* sub_version */) override {}
OnReadRemoteSupportedFeaturesComplete(uint64_t)235 void OnReadRemoteSupportedFeaturesComplete(uint64_t /* features */) override {}
OnReadRemoteExtendedFeaturesComplete(uint8_t,uint8_t,uint64_t)236 void OnReadRemoteExtendedFeaturesComplete(
237 uint8_t /* page_number */, uint8_t /* max_page_number */, uint64_t /* features */) override {}
238
239 std::queue<hci::ErrorCode> on_disconnection_error_code_queue_;
240 };
241
242 namespace bluetooth {
243 namespace hci {
244 namespace acl_manager {
245
246 class ClassicAclConnectionTest : public ::testing::Test {
247 protected:
SetUp()248 void SetUp() override {
249 ASSERT_TRUE(hci::Address::FromString(kAddress, address_));
250 thread_ = new os::Thread("thread", os::Thread::Priority::NORMAL);
251 handler_ = new os::Handler(thread_);
252 queue_ = std::make_shared<hci::acl_manager::AclConnection::Queue>(kQueueSize);
253 sync_handler();
254 }
255
TearDown()256 void TearDown() override {
257 handler_->Clear();
258 delete handler_;
259 delete thread_;
260 }
261
sync_handler()262 void sync_handler() {
263 log::assert_that(thread_ != nullptr, "assert failed: thread_ != nullptr");
264 log::assert_that(
265 thread_->GetReactor()->WaitForIdle(2s),
266 "assert failed: thread_->GetReactor()->WaitForIdle(2s)");
267 }
268
269 Address address_;
270 os::Handler* handler_{nullptr};
271 os::Thread* thread_{nullptr};
272 std::shared_ptr<hci::acl_manager::AclConnection::Queue> queue_;
273
274 TestAclConnectionInterface acl_connection_interface_;
275 TestConnectionManagementCallbacks callbacks_;
276 };
277
TEST_F(ClassicAclConnectionTest,simple)278 TEST_F(ClassicAclConnectionTest, simple) {
279 AclConnectionInterface* acl_connection_interface = nullptr;
280 ClassicAclConnection* connection =
281 new ClassicAclConnection(queue_, acl_connection_interface, kConnectionHandle, address_);
282 connection->RegisterCallbacks(&callbacks_, handler_);
283
284 delete connection;
285 }
286
287 class ClassicAclConnectionWithCallbacksTest : public ClassicAclConnectionTest {
288 protected:
SetUp()289 void SetUp() override {
290 ClassicAclConnectionTest::SetUp();
291 connection_ =
292 std::make_unique<ClassicAclConnection>(queue_, &acl_connection_interface_, kConnectionHandle, address_);
293 connection_->RegisterCallbacks(&callbacks_, handler_);
294 is_callbacks_registered_ = true;
295 connection_management_callbacks_ = connection_->GetEventCallbacks(
296 [this](uint16_t /* hci_handle */) { is_callbacks_invalidated_ = true; });
297 is_callbacks_invalidated_ = false;
298 }
299
TearDown()300 void TearDown() override {
301 connection_.reset();
302 ASSERT_TRUE(is_callbacks_invalidated_);
303 ClassicAclConnectionTest::TearDown();
304 }
305
306 protected:
307 std::unique_ptr<ClassicAclConnection> connection_;
308 ConnectionManagementCallbacks* connection_management_callbacks_;
309 bool is_callbacks_registered_{false};
310 bool is_callbacks_invalidated_{false};
311 };
312
TEST_F(ClassicAclConnectionWithCallbacksTest,Disconnect)313 TEST_F(ClassicAclConnectionWithCallbacksTest, Disconnect) {
314 for (const auto& reason : disconnect_reason_vector) {
315 ASSERT_TRUE(connection_->Disconnect(reason));
316 }
317
318 for (const auto& reason : disconnect_reason_vector) {
319 ASSERT_FALSE(acl_connection_interface_.IsPacketQueueEmpty());
320 auto command = CreateCommand<DisconnectView>(acl_connection_interface_.DequeueCommandBytes());
321 ASSERT_TRUE(command.IsValid());
322 ASSERT_EQ(reason, command.GetReason());
323 ASSERT_EQ(kConnectionHandle, command.GetConnectionHandle());
324 }
325 ASSERT_TRUE(acl_connection_interface_.IsPacketQueueEmpty());
326 }
327
TEST_F(ClassicAclConnectionWithCallbacksTest,OnDisconnection)328 TEST_F(ClassicAclConnectionWithCallbacksTest, OnDisconnection) {
329 for (const auto& error_code : error_code_vector) {
330 connection_management_callbacks_->OnDisconnection(error_code);
331 }
332
333 sync_handler();
334 ASSERT_TRUE(!callbacks_.on_disconnection_error_code_queue_.empty());
335
336 for (const auto& error_code : error_code_vector) {
337 ASSERT_EQ(error_code, callbacks_.on_disconnection_error_code_queue_.front());
338 callbacks_.on_disconnection_error_code_queue_.pop();
339 }
340 }
341
342 } // namespace acl_manager
343 } // namespace hci
344 } // namespace bluetooth
345