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