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