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