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