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/le_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_manager/le_connection_management_callbacks_mock.h"
32 #include "hci/address_with_type.h"
33 #include "hci/hci_layer_fake.h"
34 #include "hci/hci_packets.h"
35 #include "hci/le_acl_connection_interface.h"
36 #include "os/handler.h"
37 #include "os/thread.h"
38 
39 using namespace bluetooth;
40 using namespace std::chrono_literals;
41 
42 template <typename T>
CreateCommandView(std::shared_ptr<std::vector<uint8_t>> bytes)43 T CreateCommandView(std::shared_ptr<std::vector<uint8_t>> bytes) {
44   return T::Create(hci::CommandView::Create(hci::PacketView<hci::kLittleEndian>(bytes)));
45 }
46 
47 template <typename T>
CreateAclCommandView(std::shared_ptr<std::vector<uint8_t>> bytes)48 T CreateAclCommandView(std::shared_ptr<std::vector<uint8_t>> bytes) {
49   return T::Create(CreateCommandView<hci::AclCommandView>(bytes));
50 }
51 
52 constexpr uint16_t kConnectionHandle = 123;
53 constexpr size_t kQueueSize = 10;
54 
55 constexpr uint16_t kIntervalMin = 0x20;
56 constexpr uint16_t kIntervalMax = 0x40;
57 constexpr uint16_t kLatency = 0x60;
58 constexpr uint16_t kTimeout = 0x80;
59 constexpr uint16_t kContinuationNumber = 0x32;
60 
61 namespace bluetooth::hci::acl_manager {
62 
63 namespace {
64 class TestLeAclConnectionInterface : public hci::LeAclConnectionInterface {
65 private:
EnqueueCommand(std::unique_ptr<hci::AclCommandBuilder> command,common::ContextualOnceCallback<void (hci::CommandStatusView)> on_status)66   void EnqueueCommand(
67           std::unique_ptr<hci::AclCommandBuilder> command,
68           common::ContextualOnceCallback<void(hci::CommandStatusView)> on_status) override {
69     const std::lock_guard<std::mutex> lock(command_queue_mutex_);
70     command_queue_.push(std::move(command));
71     command_status_callbacks.push_back(std::move(on_status));
72     if (command_promise_ != nullptr) {
73       std::promise<void>* prom = command_promise_.release();
74       prom->set_value();
75       delete prom;
76     }
77   }
78 
EnqueueCommand(std::unique_ptr<hci::AclCommandBuilder> command,common::ContextualOnceCallback<void (hci::CommandCompleteView)> on_complete)79   void EnqueueCommand(
80           std::unique_ptr<hci::AclCommandBuilder> command,
81           common::ContextualOnceCallback<void(hci::CommandCompleteView)> on_complete) override {
82     const std::lock_guard<std::mutex> lock(command_queue_mutex_);
83     command_queue_.push(std::move(command));
84     command_complete_callbacks.push_back(std::move(on_complete));
85     if (command_promise_ != nullptr) {
86       std::promise<void>* prom = command_promise_.release();
87       prom->set_value();
88       delete prom;
89     }
90   }
91 
EnqueueCommand(std::unique_ptr<hci::AclCommandBuilder>,common::ContextualOnceCallback<void (hci::CommandStatusOrCompleteView)>)92   void EnqueueCommand(
93           std::unique_ptr<hci::AclCommandBuilder> /* command */,
94           common::ContextualOnceCallback<
95                   void(hci::CommandStatusOrCompleteView)> /* on_status_or_complete */) override {
96     FAIL();
97   }
98 
99 public:
100   virtual ~TestLeAclConnectionInterface() = default;
101 
DequeueCommand()102   std::unique_ptr<hci::CommandBuilder> DequeueCommand() {
103     const std::lock_guard<std::mutex> lock(command_queue_mutex_);
104     auto packet = std::move(command_queue_.front());
105     command_queue_.pop();
106     return packet;
107   }
108 
DequeueCommandBytes()109   std::shared_ptr<std::vector<uint8_t>> DequeueCommandBytes() {
110     auto command = DequeueCommand();
111     auto bytes = std::make_shared<std::vector<uint8_t>>();
112     packet::BitInserter bi(*bytes);
113     command->Serialize(bi);
114     return bytes;
115   }
116 
DequeueStatusCallback()117   common::ContextualOnceCallback<void(hci::CommandStatusView)> DequeueStatusCallback() {
118     auto on_status = std::move(command_status_callbacks.front());
119     command_status_callbacks.pop_front();
120     return on_status;
121   }
122 
IsPacketQueueEmpty() const123   bool IsPacketQueueEmpty() const {
124     const std::lock_guard<std::mutex> lock(command_queue_mutex_);
125     return command_queue_.empty();
126   }
127 
NumberOfQueuedCommands() const128   size_t NumberOfQueuedCommands() const {
129     const std::lock_guard<std::mutex> lock(command_queue_mutex_);
130     return command_queue_.size();
131   }
132 
133 private:
134   std::list<common::ContextualOnceCallback<void(hci::CommandCompleteView)>>
135           command_complete_callbacks;
136   std::list<common::ContextualOnceCallback<void(hci::CommandStatusView)>> command_status_callbacks;
137   std::queue<std::unique_ptr<hci::CommandBuilder>> command_queue_;
138   mutable std::mutex command_queue_mutex_;
139   std::unique_ptr<std::promise<void>> command_promise_;
140   std::unique_ptr<std::future<void>> command_future_;
141 };
142 
143 class LeAclConnectionTest : public ::testing::Test {
144 protected:
SetUp()145   void SetUp() override {
146     thread_ = new os::Thread("thread", os::Thread::Priority::NORMAL);
147     handler_ = new os::Handler(thread_);
148     queue_ = std::make_shared<LeAclConnection::Queue>(kQueueSize);
149     sync_handler();
150     connection_ = new LeAclConnection(queue_, &le_acl_connection_interface_, kConnectionHandle,
151                                       DataAsCentral{address_1}, address_2);
152     connection_->RegisterCallbacks(&callbacks_, handler_);
153   }
154 
TearDown()155   void TearDown() override {
156     handler_->Clear();
157     delete connection_;
158     delete handler_;
159     delete thread_;
160   }
161 
sync_handler()162   void sync_handler() {
163     log::assert_that(thread_ != nullptr, "assert failed: thread_ != nullptr");
164     log::assert_that(thread_->GetReactor()->WaitForIdle(2s),
165                      "assert failed: thread_->GetReactor()->WaitForIdle(2s)");
166   }
167 
168   AddressWithType address_1 = AddressWithType(Address{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}},
169                                               AddressType::RANDOM_DEVICE_ADDRESS);
170   AddressWithType address_2 = AddressWithType(Address{{0x11, 0x22, 0x33, 0x44, 0x55, 0x66}},
171                                               AddressType::PUBLIC_DEVICE_ADDRESS);
172   os::Handler* handler_{nullptr};
173   os::Thread* thread_{nullptr};
174   std::shared_ptr<LeAclConnection::Queue> queue_;
175 
176   TestLeAclConnectionInterface le_acl_connection_interface_;
177   MockLeConnectionManagementCallbacks callbacks_;
178   LeAclConnection* connection_;
179 };
180 
TEST_F(LeAclConnectionTest,simple)181 TEST_F(LeAclConnectionTest, simple) {
182   // empty
183 }
184 
TEST_F(LeAclConnectionTest,LeSubrateRequest_success)185 TEST_F(LeAclConnectionTest, LeSubrateRequest_success) {
186   connection_->LeSubrateRequest(kIntervalMin, kIntervalMax, kLatency, kContinuationNumber,
187                                 kTimeout);
188 
189   auto command = CreateAclCommandView<LeSubrateRequestView>(
190           le_acl_connection_interface_.DequeueCommandBytes());
191   ASSERT_TRUE(command.IsValid());
192   ASSERT_EQ(kIntervalMin, command.GetSubrateMin());
193   ASSERT_EQ(kIntervalMax, command.GetSubrateMax());
194   ASSERT_EQ(kLatency, command.GetMaxLatency());
195   ASSERT_EQ(kContinuationNumber, command.GetContinuationNumber());
196   ASSERT_EQ(kTimeout, command.GetSupervisionTimeout());
197 
198   EXPECT_CALL(callbacks_, OnLeSubrateChange).Times(0);
199 
200   auto status_builder = LeSubrateRequestStatusBuilder::Create(ErrorCode::SUCCESS, 0x01);
201   hci::EventView event = hci::EventView::Create(GetPacketView(std::move(status_builder)));
202   hci::CommandStatusView command_status = hci::CommandStatusView::Create(event);
203   auto on_status = le_acl_connection_interface_.DequeueStatusCallback();
204   on_status(command_status);
205   sync_handler();
206 }
207 
TEST_F(LeAclConnectionTest,LeSubrateRequest_error)208 TEST_F(LeAclConnectionTest, LeSubrateRequest_error) {
209   EXPECT_CALL(callbacks_, OnLeSubrateChange(ErrorCode::UNKNOWN_HCI_COMMAND, 0, 0, 0, 0));
210 
211   connection_->LeSubrateRequest(kIntervalMin, kIntervalMax, kLatency, kContinuationNumber,
212                                 kTimeout);
213 
214   auto command = CreateAclCommandView<LeSubrateRequestView>(
215           le_acl_connection_interface_.DequeueCommandBytes());
216   ASSERT_TRUE(command.IsValid());
217   ASSERT_EQ(kIntervalMin, command.GetSubrateMin());
218   ASSERT_EQ(kIntervalMax, command.GetSubrateMax());
219   ASSERT_EQ(kLatency, command.GetMaxLatency());
220   ASSERT_EQ(kContinuationNumber, command.GetContinuationNumber());
221   ASSERT_EQ(kTimeout, command.GetSupervisionTimeout());
222 
223   auto status_builder = LeSubrateRequestStatusBuilder::Create(ErrorCode::UNKNOWN_HCI_COMMAND, 0x01);
224   hci::EventView event = hci::EventView::Create(GetPacketView(std::move(status_builder)));
225   hci::CommandStatusView command_status = hci::CommandStatusView::Create(event);
226   auto on_status = le_acl_connection_interface_.DequeueStatusCallback();
227   on_status(std::move(command_status));
228   sync_handler();
229 }
230 
231 }  // namespace
232 }  // namespace bluetooth::hci::acl_manager
233