1 /*
2  * Copyright 2019 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/facade/le_acl_manager_facade.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include <memory>
22 #include <mutex>
23 
24 #include "blueberry/facade/hci/le_acl_manager_facade.grpc.pb.h"
25 #include "blueberry/facade/hci/le_acl_manager_facade.pb.h"
26 #include "common/bind.h"
27 #include "grpc/grpc_event_queue.h"
28 #include "hci/acl_manager.h"
29 #include "hci/hci_packets.h"
30 #include "hci/octets.h"
31 #include "packet/raw_builder.h"
32 
33 using ::grpc::ServerAsyncResponseWriter;
34 using ::grpc::ServerAsyncWriter;
35 using ::grpc::ServerContext;
36 
37 using ::bluetooth::packet::RawBuilder;
38 
39 namespace fmt {
40 template <>
41 struct formatter<blueberry::facade::BluetoothAddressTypeEnum>
42     : enum_formatter<blueberry::facade::BluetoothAddressTypeEnum> {};
43 }  // namespace fmt
44 
45 namespace bluetooth {
46 namespace hci {
47 namespace facade {
48 
49 using acl_manager::LeAclConnection;
50 using acl_manager::LeConnectionCallbacks;
51 using acl_manager::LeConnectionManagementCallbacks;
52 
53 using namespace blueberry::facade::hci;
54 
55 class LeAclManagerFacadeService : public LeAclManagerFacade::Service, public LeConnectionCallbacks {
56  public:
LeAclManagerFacadeService(AclManager * acl_manager,::bluetooth::os::Handler * facade_handler)57   LeAclManagerFacadeService(AclManager* acl_manager, ::bluetooth::os::Handler* facade_handler)
58       : acl_manager_(acl_manager), facade_handler_(facade_handler) {
59     acl_manager_->RegisterLeCallbacks(this, facade_handler_);
60   }
61 
~LeAclManagerFacadeService()62   ~LeAclManagerFacadeService() {
63     std::unique_lock<std::mutex> lock(acl_connections_mutex_);
64     for (auto& conn : acl_connections_) {
65       if (conn.second.connection_ != nullptr) {
66         conn.second.connection_->GetAclQueueEnd()->UnregisterDequeue();
67         conn.second.connection_.reset();
68       }
69     }
70   }
71 
CreateConnection(::grpc::ServerContext * context,const CreateConnectionMsg * request,::grpc::ServerWriter<LeConnectionEvent> * writer)72   ::grpc::Status CreateConnection(
73       ::grpc::ServerContext* context,
74       const CreateConnectionMsg* request,
75       ::grpc::ServerWriter<LeConnectionEvent>* writer) override {
76     log::info(
77         "peer={}, type={}, id_direct={}",
78         request->peer_address().address().address(),
79         request->peer_address().type(),
80         request->is_direct());
81     Address peer_address;
82     log::assert_that(
83         Address::FromString(request->peer_address().address().address(), peer_address),
84         "assert failed: Address::FromString(request->peer_address().address().address(), "
85         "peer_address)");
86     AddressWithType peer(peer_address, static_cast<AddressType>(request->peer_address().type()));
87     bool is_direct = request->is_direct();
88     acl_manager_->CreateLeConnection(peer, is_direct);
89 
90     if (is_direct) {
91       if (direct_connection_events_ != nullptr) {
92         return ::grpc::Status(
93             ::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding direct request is supported");
94       }
95       direct_connection_events_ = std::make_shared<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>(
96           std::string("direct connection attempt ") + peer.ToString());
97       direct_connection_address_ = peer;
98       return direct_connection_events_->RunLoop(context, writer);
99     }
100     per_connection_events_.emplace(
101         peer,
102         std::make_unique<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>(
103             std::string("connection attempt ") + peer.ToString()));
104     return per_connection_events_[peer]->RunLoop(context, writer);
105   }
106 
CancelConnection(::grpc::ServerContext *,const::blueberry::facade::BluetoothAddressWithType * request,google::protobuf::Empty *)107   ::grpc::Status CancelConnection(
108       ::grpc::ServerContext* /* context */,
109       const ::blueberry::facade::BluetoothAddressWithType* request,
110       google::protobuf::Empty* /* response */) override {
111     log::info("peer={}, type={}", request->address().address(), request->type());
112     Address peer_address;
113     log::assert_that(
114         Address::FromString(request->address().address(), peer_address),
115         "assert failed: Address::FromString(request->address().address(), peer_address)");
116     AddressWithType peer(peer_address, static_cast<AddressType>(request->type()));
117     if (peer == direct_connection_address_) {
118       direct_connection_address_ = AddressWithType();
119       direct_connection_events_.reset();
120     } else {
121       if (per_connection_events_.count(peer) == 0) {
122         return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "No matching outstanding connection");
123       }
124     }
125     acl_manager_->CancelLeConnect(peer);
126     return ::grpc::Status::OK;
127   }
128 
Disconnect(::grpc::ServerContext *,const LeHandleMsg * request,::google::protobuf::Empty *)129   ::grpc::Status Disconnect(
130       ::grpc::ServerContext* /* context */,
131       const LeHandleMsg* request,
132       ::google::protobuf::Empty* /* response */) override {
133     log::info("handle={}", request->handle());
134     std::unique_lock<std::mutex> lock(acl_connections_mutex_);
135     auto connection = acl_connections_.find(request->handle());
136     if (connection == acl_connections_.end()) {
137       log::error("Invalid handle");
138       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
139     } else {
140       connection->second.connection_->Disconnect(DisconnectReason::REMOTE_USER_TERMINATED_CONNECTION);
141       return ::grpc::Status::OK;
142     }
143   }
144 
145 #define GET_CONNECTION(view)                                                         \
146   std::map<uint16_t, Connection>::iterator connection;                               \
147   do {                                                                               \
148     if (!view.IsValid()) {                                                           \
149       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle"); \
150     }                                                                                \
151     std::unique_lock<std::mutex> lock(acl_connections_mutex_);                       \
152     connection = acl_connections_.find(view.GetConnectionHandle());                  \
153     if (connection == acl_connections_.end()) {                                      \
154       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle"); \
155     }                                                                                \
156   } while (0)
157 
ConnectionCommand(::grpc::ServerContext *,const LeConnectionCommandMsg * request,::google::protobuf::Empty *)158   ::grpc::Status ConnectionCommand(
159       ::grpc::ServerContext* /* context */,
160       const LeConnectionCommandMsg* request,
161       ::google::protobuf::Empty* /* response */) override {
162     log::info("size={}", request->packet().size());
163     auto command_view =
164         ConnectionManagementCommandView::Create(AclCommandView::Create(CommandView::Create(PacketView<kLittleEndian>(
165             std::make_shared<std::vector<uint8_t>>(request->packet().begin(), request->packet().end())))));
166     if (!command_view.IsValid()) {
167       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
168     }
169     log::info("opcode={}", OpCodeText(command_view.GetOpCode()));
170     switch (command_view.GetOpCode()) {
171       case OpCode::DISCONNECT: {
172         auto view = DisconnectView::Create(command_view);
173         GET_CONNECTION(view);
174         connection->second.connection_->Disconnect(view.GetReason());
175         return ::grpc::Status::OK;
176       }
177       default:
178         return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid command packet");
179     }
180   }
181 #undef GET_CONNECTION
182 
FetchIncomingConnection(::grpc::ServerContext * context,const google::protobuf::Empty *,::grpc::ServerWriter<LeConnectionEvent> * writer)183   ::grpc::Status FetchIncomingConnection(
184       ::grpc::ServerContext* context,
185       const google::protobuf::Empty* /* request */,
186       ::grpc::ServerWriter<LeConnectionEvent>* writer) override {
187     log::info("wait for one incoming connection");
188     if (incoming_connection_events_ != nullptr) {
189       return ::grpc::Status(
190           ::grpc::StatusCode::RESOURCE_EXHAUSTED, "Only one outstanding incoming connection is supported");
191     }
192     incoming_connection_events_ =
193         std::make_unique<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>(std::string("incoming connection "));
194     return incoming_connection_events_->RunLoop(context, writer);
195   }
196 
AddDeviceToResolvingList(::grpc::ServerContext *,const IrkMsg * request,::google::protobuf::Empty *)197   ::grpc::Status AddDeviceToResolvingList(
198       ::grpc::ServerContext* /* context */,
199       const IrkMsg* request,
200       ::google::protobuf::Empty* /* response */) override {
201     log::info("peer={}, type={}", request->peer().address().address(), request->peer().type());
202     Address peer_address;
203     log::assert_that(
204         Address::FromString(request->peer().address().address(), peer_address),
205         "assert failed: Address::FromString(request->peer().address().address(), peer_address)");
206     AddressWithType peer(peer_address, static_cast<AddressType>(request->peer().type()));
207 
208     auto request_peer_irk_length = request->peer_irk().end() - request->peer_irk().begin();
209 
210     if (request_peer_irk_length != kOctet16Length) {
211       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid Peer IRK");
212     }
213 
214     auto request_local_irk_length = request->local_irk().end() - request->local_irk().begin();
215     if (request_local_irk_length != kOctet16Length) {
216       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid Local IRK");
217     }
218 
219     Octet16 peer_irk = {};
220     Octet16 local_irk = {};
221 
222     std::vector<uint8_t> peer_irk_data(request->peer_irk().begin(), request->peer_irk().end());
223     std::copy_n(peer_irk_data.begin(), kOctet16Length, peer_irk.begin());
224 
225     std::vector<uint8_t> local_irk_data(request->local_irk().begin(), request->local_irk().end());
226     std::copy_n(local_irk_data.begin(), kOctet16Length, local_irk.begin());
227 
228     acl_manager_->AddDeviceToResolvingList(peer, peer_irk, local_irk);
229     return ::grpc::Status::OK;
230   }
231 
SendAclData(::grpc::ServerContext *,const LeAclData * request,::google::protobuf::Empty *)232   ::grpc::Status SendAclData(
233       ::grpc::ServerContext* /* context */,
234       const LeAclData* request,
235       ::google::protobuf::Empty* /* response */) override {
236     log::info("handle={}, size={}", request->handle(), request->payload().size());
237     std::promise<void> promise;
238     auto future = promise.get_future();
239     {
240       std::unique_lock<std::mutex> lock(acl_connections_mutex_);
241       auto connection = acl_connections_.find(request->handle());
242       if (connection == acl_connections_.end()) {
243         return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
244       }
245       connection->second.connection_->GetAclQueueEnd()->RegisterEnqueue(
246           facade_handler_,
247           common::Bind(
248               &LeAclManagerFacadeService::enqueue_packet,
249               common::Unretained(this),
250               common::Unretained(request),
251               common::Passed(std::move(promise))));
252       auto status = future.wait_for(std::chrono::milliseconds(1000));
253       if (status != std::future_status::ready) {
254         return ::grpc::Status(::grpc::StatusCode::RESOURCE_EXHAUSTED, "Can't send packet");
255       }
256     }
257     return ::grpc::Status::OK;
258   }
259 
enqueue_packet(const LeAclData * request,std::promise<void> promise)260   std::unique_ptr<BasePacketBuilder> enqueue_packet(const LeAclData* request, std::promise<void> promise) {
261     auto connection = acl_connections_.find(request->handle());
262     log::assert_that(connection != acl_connections_.end(), "handle {}", request->handle());
263     connection->second.connection_->GetAclQueueEnd()->UnregisterEnqueue();
264     std::unique_ptr<RawBuilder> packet =
265         std::make_unique<RawBuilder>(std::vector<uint8_t>(request->payload().begin(), request->payload().end()));
266     promise.set_value();
267     return packet;
268   }
269 
FetchAclData(::grpc::ServerContext * context,const LeHandleMsg * request,::grpc::ServerWriter<LeAclData> * writer)270   ::grpc::Status FetchAclData(
271       ::grpc::ServerContext* context, const LeHandleMsg* request, ::grpc::ServerWriter<LeAclData>* writer) override {
272     log::info("handle={}", request->handle());
273     auto connection = acl_connections_.find(request->handle());
274     if (connection == acl_connections_.end()) {
275       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invalid handle");
276     }
277     return connection->second.pending_acl_data_.RunLoop(context, writer);
278   }
279 
builder_to_string(std::unique_ptr<BasePacketBuilder> builder)280   static inline std::string builder_to_string(std::unique_ptr<BasePacketBuilder> builder) {
281     std::vector<uint8_t> bytes;
282     BitInserter bit_inserter(bytes);
283     builder->Serialize(bit_inserter);
284     return std::string(bytes.begin(), bytes.end());
285   }
286 
on_incoming_acl(std::shared_ptr<LeAclConnection> connection,uint16_t handle)287   void on_incoming_acl(std::shared_ptr<LeAclConnection> connection, uint16_t handle) {
288     log::info("handle={}, addr={}", connection->GetHandle(), connection->GetRemoteAddress());
289     auto packet = connection->GetAclQueueEnd()->TryDequeue();
290     auto connection_tracker = acl_connections_.find(handle);
291     log::assert_that(connection_tracker != acl_connections_.end(), "handle {}", handle);
292     LeAclData acl_data;
293     acl_data.set_handle(handle);
294     acl_data.set_payload(std::string(packet->begin(), packet->end()));
295     connection_tracker->second.pending_acl_data_.OnIncomingEvent(acl_data);
296   }
297 
OnLeConnectSuccess(AddressWithType peer,std::unique_ptr<LeAclConnection> connection)298   void OnLeConnectSuccess(AddressWithType peer, std::unique_ptr<LeAclConnection> connection) override {
299     log::info("handle={}, addr={}", connection->GetHandle(), peer);
300     std::unique_lock<std::mutex> lock(acl_connections_mutex_);
301     std::shared_ptr<LeAclConnection> shared_connection = std::move(connection);
302     uint16_t handle = shared_connection->GetHandle();
303     auto role = shared_connection->GetRole();
304     if (role == Role::PERIPHERAL) {
305       log::assert_that(
306           incoming_connection_events_ != nullptr,
307           "assert failed: incoming_connection_events_ != nullptr");
308       if (per_connection_events_.find(peer) == per_connection_events_.end()) {
309         per_connection_events_.emplace(peer, incoming_connection_events_);
310       } else {
311         per_connection_events_[peer] = incoming_connection_events_;
312       }
313       incoming_connection_events_.reset();
314     } else if (direct_connection_address_ == peer) {
315       direct_connection_address_ = AddressWithType();
316       per_connection_events_.emplace(peer, direct_connection_events_);
317       direct_connection_events_.reset();
318     } else {
319       log::assert_that(
320           per_connection_events_.count(peer) > 0,
321           "No connection request for {}",
322           ADDRESS_TO_LOGGABLE_CSTR(peer));
323     }
324     acl_connections_.erase(handle);
325     acl_connections_.emplace(
326         std::piecewise_construct,
327         std::forward_as_tuple(handle),
328         std::forward_as_tuple(handle, shared_connection, per_connection_events_[peer]));
329     shared_connection->GetAclQueueEnd()->RegisterDequeue(
330         facade_handler_,
331         common::Bind(&LeAclManagerFacadeService::on_incoming_acl, common::Unretained(this), shared_connection, handle));
332     auto callbacks = acl_connections_.find(handle)->second.GetCallbacks();
333     shared_connection->RegisterCallbacks(callbacks, facade_handler_);
334     {
335       std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
336           ErrorCode::SUCCESS, handle, role, peer.GetAddressType(), peer.GetAddress(), 1, 2, 3, ClockAccuracy::PPM_20);
337       LeConnectionEvent success;
338       success.set_payload(builder_to_string(std::move(builder)));
339       per_connection_events_[peer]->OnIncomingEvent(success);
340     }
341   }
342 
OnLeConnectFail(AddressWithType address,ErrorCode reason)343   void OnLeConnectFail(AddressWithType address, ErrorCode reason) override {
344     log::info("addr={}, reason={}", address, ErrorCodeText(reason));
345     std::unique_ptr<BasePacketBuilder> builder = LeConnectionCompleteBuilder::Create(
346         reason, 0, Role::CENTRAL, address.GetAddressType(), address.GetAddress(), 0, 0, 0, ClockAccuracy::PPM_20);
347     LeConnectionEvent fail;
348     fail.set_payload(builder_to_string(std::move(builder)));
349     if (address == direct_connection_address_) {
350       direct_connection_address_ = AddressWithType();
351       direct_connection_events_->OnIncomingEvent(fail);
352     } else {
353       per_connection_events_[address]->OnIncomingEvent(fail);
354     }
355   }
356 
357   class Connection : public LeConnectionManagementCallbacks {
358    public:
Connection(uint16_t handle,std::shared_ptr<LeAclConnection> connection,std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream)359     Connection(
360         uint16_t handle,
361         std::shared_ptr<LeAclConnection> connection,
362         std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream)
363         : handle_(handle), connection_(std::move(connection)), event_stream_(std::move(event_stream)) {}
OnConnectionUpdate(hci::ErrorCode,uint16_t connection_interval,uint16_t connection_latency,uint16_t supervision_timeout)364     void OnConnectionUpdate(
365         hci::ErrorCode /* hci_status */,
366         uint16_t connection_interval,
367         uint16_t connection_latency,
368         uint16_t supervision_timeout) override {
369       log::info(
370           "interval: 0x{:x}, latency: 0x{:x}, timeout 0x{:x}",
371           connection_interval,
372           connection_latency,
373           supervision_timeout);
374     }
375 
OnDataLengthChange(uint16_t tx_octets,uint16_t tx_time,uint16_t rx_octets,uint16_t rx_time)376     void OnDataLengthChange(uint16_t tx_octets, uint16_t tx_time, uint16_t rx_octets, uint16_t rx_time) override {
377       log::info(
378           "tx_octets: 0x{:x}, tx_time: 0x{:x}, rx_octets 0x{:x}, rx_time 0x{:x}",
379           tx_octets,
380           tx_time,
381           rx_octets,
382           rx_time);
383     }
384 
OnPhyUpdate(hci::ErrorCode,uint8_t,uint8_t)385     void OnPhyUpdate(
386         hci::ErrorCode /* hci_status */, uint8_t /* tx_phy */, uint8_t /* rx_phy */) override {}
OnDisconnection(ErrorCode reason)387     void OnDisconnection(ErrorCode reason) override {
388       log::info("reason: {}", ErrorCodeText(reason));
389       std::unique_ptr<BasePacketBuilder> builder =
390           DisconnectionCompleteBuilder::Create(ErrorCode::SUCCESS, handle_, reason);
391       LeConnectionEvent disconnection;
392       disconnection.set_payload(builder_to_string(std::move(builder)));
393       event_stream_->OnIncomingEvent(disconnection);
394     }
395 
OnReadRemoteVersionInformationComplete(hci::ErrorCode,uint8_t,uint16_t,uint16_t)396     void OnReadRemoteVersionInformationComplete(
397         hci::ErrorCode /* hci_status */,
398         uint8_t /* lmp_version */,
399         uint16_t /* manufacturer_name */,
400         uint16_t /* sub_version */) override {}
OnLeReadRemoteFeaturesComplete(hci::ErrorCode,uint64_t)401     void OnLeReadRemoteFeaturesComplete(
402         hci::ErrorCode /* hci_status */, uint64_t /* features */) override {}
403 
GetCallbacks()404     LeConnectionManagementCallbacks* GetCallbacks() {
405       return this;
406     }
OnLeSubrateChange(hci::ErrorCode hci_status,uint16_t subrate_factor,uint16_t peripheral_latency,uint16_t continuation_number,uint16_t supervision_timeout)407     void OnLeSubrateChange(
408         hci::ErrorCode hci_status,
409         uint16_t subrate_factor,
410         uint16_t peripheral_latency,
411         uint16_t continuation_number,
412         uint16_t supervision_timeout) override {
413       log::info(
414           "hci_status: {}, subrate_factor: {:#x}, peripheral_latency: {:#x}, continuation_number: "
415           "{:#x}, supervision_timeout: {:#x}",
416           ErrorCodeText(hci_status),
417           subrate_factor,
418           peripheral_latency,
419           continuation_number,
420           supervision_timeout);
421     }
422 
423     uint16_t handle_;
424     std::shared_ptr<LeAclConnection> connection_;
425     std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> event_stream_;
426     ::bluetooth::grpc::GrpcEventQueue<LeAclData> pending_acl_data_{std::string("PendingAclData") +
427                                                                    std::to_string(handle_)};
428   };
429 
IsOnBackgroundList(::grpc::ServerContext *,const::blueberry::facade::hci::BackgroundRequestMsg * request,::blueberry::facade::hci::BackgroundResultMsg * msg)430   ::grpc::Status IsOnBackgroundList(
431       ::grpc::ServerContext* /* context */,
432       const ::blueberry::facade::hci::BackgroundRequestMsg* request,
433       ::blueberry::facade::hci::BackgroundResultMsg* msg) {
434     Address peer_address;
435     log::assert_that(
436         Address::FromString(request->peer_address().address().address(), peer_address),
437         "assert failed: Address::FromString(request->peer_address().address().address(), "
438         "peer_address)");
439     AddressWithType peer(peer_address, static_cast<AddressType>(request->peer_address().type()));
440     std::promise<bool> promise;
441     auto future = promise.get_future();
442     acl_manager_->IsOnBackgroundList(peer, std::move(promise));
443     msg->set_is_on_background_list(future.get());
444     return ::grpc::Status::OK;
445   }
446 
RemoveFromBackgroundList(::grpc::ServerContext *,const::blueberry::facade::hci::BackgroundRequestMsg * request,::google::protobuf::Empty *)447   ::grpc::Status RemoveFromBackgroundList(
448       ::grpc::ServerContext* /* context */,
449       const ::blueberry::facade::hci::BackgroundRequestMsg* request,
450       ::google::protobuf::Empty* /* response */) {
451     Address peer_address;
452     log::assert_that(
453         Address::FromString(request->peer_address().address().address(), peer_address),
454         "assert failed: Address::FromString(request->peer_address().address().address(), "
455         "peer_address)");
456     AddressWithType peer(peer_address, static_cast<AddressType>(request->peer_address().type()));
457     acl_manager_->RemoveFromBackgroundList(peer);
458     return ::grpc::Status::OK;
459   }
460 
461  private:
462   AclManager* acl_manager_;
463   ::bluetooth::os::Handler* facade_handler_;
464   mutable std::mutex acl_connections_mutex_;
465   std::map<bluetooth::hci::AddressWithType, std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>>>
466       per_connection_events_;
467   std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> direct_connection_events_;
468   bluetooth::hci::AddressWithType direct_connection_address_;
469   std::shared_ptr<::bluetooth::grpc::GrpcEventQueue<LeConnectionEvent>> incoming_connection_events_;
470   std::map<uint16_t, Connection> acl_connections_;
471 };
472 
ListDependencies(ModuleList * list) const473 void LeAclManagerFacadeModule::ListDependencies(ModuleList* list) const {
474   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
475   list->add<AclManager>();
476 }
477 
Start()478 void LeAclManagerFacadeModule::Start() {
479   ::bluetooth::grpc::GrpcFacadeModule::Start();
480   service_ = new LeAclManagerFacadeService(GetDependency<AclManager>(), GetHandler());
481 }
482 
Stop()483 void LeAclManagerFacadeModule::Stop() {
484   delete service_;
485   ::bluetooth::grpc::GrpcFacadeModule::Stop();
486 }
487 
GetService() const488 ::grpc::Service* LeAclManagerFacadeModule::GetService() const {
489   return service_;
490 }
491 
492 const ModuleFactory LeAclManagerFacadeModule::Factory =
__anonf9eedfcf0102() 493     ::bluetooth::ModuleFactory([]() { return new LeAclManagerFacadeModule(); });
494 
495 }  // namespace facade
496 }  // namespace hci
497 }  // namespace bluetooth
498