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