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