• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/hci_layer_fake.h"
18 
19 #include <gmock/gmock.h>
20 #include <gtest/gtest.h>
21 
22 #include <algorithm>
23 #include <chrono>
24 
25 namespace bluetooth {
26 namespace hci {
27 
28 using common::BidiQueue;
29 using common::BidiQueueEnd;
30 using packet::kLittleEndian;
31 using packet::PacketView;
32 using packet::RawBuilder;
33 
GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet)34 PacketView<packet::kLittleEndian> GetPacketView(std::unique_ptr<packet::BasePacketBuilder> packet) {
35   auto bytes = std::make_shared<std::vector<uint8_t>>();
36   BitInserter i(*bytes);
37   bytes->reserve(packet->size());
38   packet->Serialize(i);
39   return packet::PacketView<packet::kLittleEndian>(bytes);
40 }
41 
NextPayload(uint16_t handle)42 std::unique_ptr<BasePacketBuilder> NextPayload(uint16_t handle) {
43   static uint32_t packet_number = 1;
44   auto payload = std::make_unique<RawBuilder>();
45   payload->AddOctets2(6);  // L2CAP PDU size
46   payload->AddOctets2(2);  // L2CAP CID
47   payload->AddOctets2(handle);
48   payload->AddOctets4(packet_number++);
49   return std::move(payload);
50 }
51 
NextAclPacket(uint16_t handle)52 static std::unique_ptr<AclBuilder> NextAclPacket(uint16_t handle) {
53   PacketBoundaryFlag packet_boundary_flag = PacketBoundaryFlag::FIRST_AUTOMATICALLY_FLUSHABLE;
54   BroadcastFlag broadcast_flag = BroadcastFlag::POINT_TO_POINT;
55   return AclBuilder::Create(handle, packet_boundary_flag, broadcast_flag, NextPayload(handle));
56 }
57 
EnqueueCommand(std::unique_ptr<CommandBuilder> command,common::ContextualOnceCallback<void (CommandStatusView)> on_status)58 void TestHciLayer::EnqueueCommand(
59     std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandStatusView)> on_status) {
60   std::lock_guard<std::mutex> lock(mutex_);
61 
62   command_queue_.push(std::move(command));
63   command_status_callbacks.push_back(std::move(on_status));
64 
65   if (command_queue_.size() == 1) {
66     // since GetCommand may replace this promise, we have to do this inside the lock
67     command_promise_.set_value();
68   }
69 }
70 
EnqueueCommand(std::unique_ptr<CommandBuilder> command,common::ContextualOnceCallback<void (CommandCompleteView)> on_complete)71 void TestHciLayer::EnqueueCommand(
72     std::unique_ptr<CommandBuilder> command, common::ContextualOnceCallback<void(CommandCompleteView)> on_complete) {
73   std::lock_guard<std::mutex> lock(mutex_);
74 
75   command_queue_.push(std::move(command));
76   command_complete_callbacks.push_back(std::move(on_complete));
77 
78   if (command_queue_.size() == 1) {
79     // since GetCommand may replace this promise, we have to do this inside the lock
80     command_promise_.set_value();
81   }
82 }
83 
GetCommand()84 CommandView TestHciLayer::GetCommand() {
85   EXPECT_EQ(command_future_.wait_for(std::chrono::milliseconds(1000)), std::future_status::ready);
86 
87   std::lock_guard<std::mutex> lock(mutex_);
88 
89   if (command_queue_.empty()) {
90     LOG_ERROR("Command queue is empty");
91     return empty_command_view_;
92   }
93 
94   auto last = std::move(command_queue_.front());
95   command_queue_.pop();
96 
97   if (command_queue_.empty()) {
98     command_promise_ = {};
99     command_future_ = command_promise_.get_future();
100   }
101 
102   CommandView command_packet_view = CommandView::Create(GetPacketView(std::move(last)));
103   ASSERT_LOG(command_packet_view.IsValid(), "Got invalid command");
104   return command_packet_view;
105 }
106 
RegisterEventHandler(EventCode event_code,common::ContextualCallback<void (EventView)> event_handler)107 void TestHciLayer::RegisterEventHandler(
108     EventCode event_code, common::ContextualCallback<void(EventView)> event_handler) {
109   registered_events_[event_code] = event_handler;
110 }
111 
UnregisterEventHandler(EventCode event_code)112 void TestHciLayer::UnregisterEventHandler(EventCode event_code) {
113   registered_events_.erase(event_code);
114 }
115 
RegisterLeEventHandler(SubeventCode subevent_code,common::ContextualCallback<void (LeMetaEventView)> event_handler)116 void TestHciLayer::RegisterLeEventHandler(
117     SubeventCode subevent_code, common::ContextualCallback<void(LeMetaEventView)> event_handler) {
118   registered_le_events_[subevent_code] = event_handler;
119 }
120 
UnregisterLeEventHandler(SubeventCode subevent_code)121 void TestHciLayer::UnregisterLeEventHandler(SubeventCode subevent_code) {
122   registered_le_events_.erase(subevent_code);
123 }
124 
IncomingEvent(std::unique_ptr<EventBuilder> event_builder)125 void TestHciLayer::IncomingEvent(std::unique_ptr<EventBuilder> event_builder) {
126   auto packet = GetPacketView(std::move(event_builder));
127   EventView event = EventView::Create(packet);
128   ASSERT_TRUE(event.IsValid());
129   EventCode event_code = event.GetEventCode();
130   if (event_code == EventCode::COMMAND_COMPLETE) {
131     CommandCompleteCallback(event);
132   } else if (event_code == EventCode::COMMAND_STATUS) {
133     CommandStatusCallback(event);
134   } else {
135     ASSERT_NE(registered_events_.find(event_code), registered_events_.end()) << EventCodeText(event_code);
136     registered_events_[event_code].Invoke(event);
137   }
138 }
139 
IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder)140 void TestHciLayer::IncomingLeMetaEvent(std::unique_ptr<LeMetaEventBuilder> event_builder) {
141   auto packet = GetPacketView(std::move(event_builder));
142   EventView event = EventView::Create(packet);
143   LeMetaEventView meta_event_view = LeMetaEventView::Create(event);
144   ASSERT_TRUE(meta_event_view.IsValid());
145   SubeventCode subevent_code = meta_event_view.GetSubeventCode();
146   ASSERT_TRUE(registered_le_events_.find(subevent_code) != registered_le_events_.end());
147   registered_le_events_[subevent_code].Invoke(meta_event_view);
148 }
149 
CommandCompleteCallback(EventView event)150 void TestHciLayer::CommandCompleteCallback(EventView event) {
151   CommandCompleteView complete_view = CommandCompleteView::Create(event);
152   ASSERT_TRUE(complete_view.IsValid());
153   std::move(command_complete_callbacks.front()).Invoke(complete_view);
154   command_complete_callbacks.pop_front();
155 }
156 
CommandStatusCallback(EventView event)157 void TestHciLayer::CommandStatusCallback(EventView event) {
158   CommandStatusView status_view = CommandStatusView::Create(event);
159   ASSERT_TRUE(status_view.IsValid());
160   std::move(command_status_callbacks.front()).Invoke(status_view);
161   command_status_callbacks.pop_front();
162 }
163 
InitEmptyCommand()164 void TestHciLayer::InitEmptyCommand() {
165   auto payload = std::make_unique<bluetooth::packet::RawBuilder>();
166   auto command_builder = CommandBuilder::Create(OpCode::NONE, std::move(payload));
167   empty_command_view_ = CommandView::Create(GetPacketView(std::move(command_builder)));
168   ASSERT_TRUE(empty_command_view_.IsValid());
169 }
170 
IncomingAclData(uint16_t handle)171 void TestHciLayer::IncomingAclData(uint16_t handle) {
172   os::Handler* hci_handler = GetHandler();
173   auto* queue_end = acl_queue_.GetDownEnd();
174   std::promise<void> promise;
175   auto future = promise.get_future();
176   queue_end->RegisterEnqueue(
177       hci_handler,
178       common::Bind(
179           [](decltype(queue_end) queue_end, uint16_t handle, std::promise<void> promise) {
180             auto packet = GetPacketView(NextAclPacket(handle));
181             AclView acl2 = AclView::Create(packet);
182             queue_end->UnregisterEnqueue();
183             promise.set_value();
184             return std::make_unique<AclView>(acl2);
185           },
186           queue_end,
187           handle,
188           common::Passed(std::move(promise))));
189   auto status = future.wait_for(std::chrono::milliseconds(1000));
190   ASSERT_EQ(status, std::future_status::ready);
191 }
192 
AssertNoOutgoingAclData()193 void TestHciLayer::AssertNoOutgoingAclData() {
194   auto queue_end = acl_queue_.GetDownEnd();
195   EXPECT_EQ(queue_end->TryDequeue(), nullptr);
196 }
197 
OutgoingAclData()198 PacketView<kLittleEndian> TestHciLayer::OutgoingAclData() {
199   auto queue_end = acl_queue_.GetDownEnd();
200   std::unique_ptr<AclBuilder> received;
201   do {
202     received = queue_end->TryDequeue();
203   } while (received == nullptr);
204 
205   return GetPacketView(std::move(received));
206 }
207 
GetAclQueueEnd()208 BidiQueueEnd<AclBuilder, AclView>* TestHciLayer::GetAclQueueEnd() {
209   return acl_queue_.GetUpEnd();
210 }
211 
Disconnect(uint16_t handle,ErrorCode reason)212 void TestHciLayer::Disconnect(uint16_t handle, ErrorCode reason) {
213   GetHandler()->Post(
214       common::BindOnce(&TestHciLayer::do_disconnect, common::Unretained(this), handle, reason));
215 }
216 
do_disconnect(uint16_t handle,ErrorCode reason)217 void TestHciLayer::do_disconnect(uint16_t handle, ErrorCode reason) {
218   HciLayer::Disconnect(handle, reason);
219 }
220 
ListDependencies(ModuleList * list) const221 void TestHciLayer::ListDependencies(ModuleList* list) const {}
Start()222 void TestHciLayer::Start() {
223   std::lock_guard<std::mutex> lock(mutex_);
224   InitEmptyCommand();
225 }
Stop()226 void TestHciLayer::Stop() {}
227 
228 }  // namespace hci
229 }  // namespace bluetooth