1 /*
2  * Copyright 2020 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 "l2cap/le/facade.h"
18 
19 #include <bluetooth/log.h>
20 
21 #include "blueberry/facade/l2cap/le/facade.grpc.pb.h"
22 #include "grpc/grpc_event_queue.h"
23 #include "l2cap/le/dynamic_channel.h"
24 #include "l2cap/le/dynamic_channel_manager.h"
25 #include "l2cap/le/dynamic_channel_service.h"
26 #include "l2cap/le/l2cap_le_module.h"
27 #include "l2cap/le/security_policy.h"
28 #include "l2cap/psm.h"
29 #include "packet/raw_builder.h"
30 
31 namespace bluetooth {
32 namespace l2cap {
33 namespace le {
34 
35 using namespace blueberry::facade::l2cap::le;
36 
SecurityLevelToPolicy(SecurityLevel level)37 SecurityPolicy SecurityLevelToPolicy(SecurityLevel level) {
38   switch (level) {
39     case SecurityLevel::NO_SECURITY:
40       return SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK;
41     case SecurityLevel::UNAUTHENTICATED_PAIRING_WITH_ENCRYPTION:
42       return SecurityPolicy::ENCRYPTED_TRANSPORT;
43     case SecurityLevel::AUTHENTICATED_PAIRING_WITH_ENCRYPTION:
44       return SecurityPolicy::AUTHENTICATED_ENCRYPTED_TRANSPORT;
45     case SecurityLevel::AUTHENTICATED_PAIRING_WITH_128_BIT_KEY:
46       return SecurityPolicy::_NOT_FOR_YOU__AUTHENTICATED_PAIRING_WITH_128_BIT_KEY;
47     case SecurityLevel::AUTHORIZATION:
48       return SecurityPolicy::_NOT_FOR_YOU__AUTHORIZATION;
49     default:
50       return SecurityPolicy::NO_SECURITY_WHATSOEVER_PLAINTEXT_TRANSPORT_OK;
51   }
52 }
53 
54 static constexpr auto kChannelOpenTimeout = std::chrono::seconds(4);
55 
56 class L2capLeModuleFacadeService : public L2capLeModuleFacade::Service {
57  public:
L2capLeModuleFacadeService(L2capLeModule * l2cap_layer,os::Handler * facade_handler)58   L2capLeModuleFacadeService(L2capLeModule* l2cap_layer, os::Handler* facade_handler)
59       : l2cap_layer_(l2cap_layer), facade_handler_(facade_handler) {
60     log::assert_that(l2cap_layer_ != nullptr, "assert failed: l2cap_layer_ != nullptr");
61     log::assert_that(facade_handler_ != nullptr, "assert failed: facade_handler_ != nullptr");
62   }
63 
FetchL2capData(::grpc::ServerContext * context,const::google::protobuf::Empty *,::grpc::ServerWriter<::bluetooth::l2cap::le::L2capPacket> * writer)64   ::grpc::Status FetchL2capData(
65       ::grpc::ServerContext* context,
66       const ::google::protobuf::Empty* /* request */,
67       ::grpc::ServerWriter<::bluetooth::l2cap::le::L2capPacket>* writer) override {
68     return pending_l2cap_data_.RunLoop(context, writer);
69   }
70 
OpenDynamicChannel(::grpc::ServerContext *,const OpenDynamicChannelRequest * request,OpenDynamicChannelResponse * response)71   ::grpc::Status OpenDynamicChannel(
72       ::grpc::ServerContext* /* context */,
73       const OpenDynamicChannelRequest* request,
74       OpenDynamicChannelResponse* response) override {
75     auto service_helper = dynamic_channel_helper_map_.find(request->psm());
76     if (service_helper == dynamic_channel_helper_map_.end()) {
77       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
78     }
79     hci::Address peer_address;
80     log::assert_that(
81         hci::Address::FromString(request->remote().address().address(), peer_address),
82         "assert failed: hci::Address::FromString(request->remote().address().address(), "
83         "peer_address)");
84     // TODO: Support different address type
85     hci::AddressWithType peer(peer_address, hci::AddressType::RANDOM_DEVICE_ADDRESS);
86     service_helper->second->Connect(peer);
87     response->set_status(
88         static_cast<int>(service_helper->second->channel_open_fail_reason_.l2cap_connection_response_result));
89     return ::grpc::Status::OK;
90   }
91 
CloseDynamicChannel(::grpc::ServerContext *,const CloseDynamicChannelRequest * request,::google::protobuf::Empty *)92   ::grpc::Status CloseDynamicChannel(
93       ::grpc::ServerContext* /* context */,
94       const CloseDynamicChannelRequest* request,
95       ::google::protobuf::Empty* /* response */) override {
96     auto service_helper = dynamic_channel_helper_map_.find(request->psm());
97     if (service_helper == dynamic_channel_helper_map_.end()) {
98       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
99     }
100     if (service_helper->second->channel_ == nullptr) {
101       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open");
102     }
103     auto address = service_helper->second->channel_->GetDevice().GetAddress();
104     hci::Address peer_address;
105     log::assert_that(
106         hci::Address::FromString(request->remote().address().address(), peer_address),
107         "assert failed: hci::Address::FromString(request->remote().address().address(), "
108         "peer_address)");
109     if (address != peer_address) {
110       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Remote address doesn't match");
111     }
112     service_helper->second->channel_->Close();
113     return ::grpc::Status::OK;
114   }
115 
SetDynamicChannel(::grpc::ServerContext *,const::bluetooth::l2cap::le::SetEnableDynamicChannelRequest * request,::google::protobuf::Empty *)116   ::grpc::Status SetDynamicChannel(
117       ::grpc::ServerContext* /* context */,
118       const ::bluetooth::l2cap::le::SetEnableDynamicChannelRequest* request,
119       ::google::protobuf::Empty* /* response */) override {
120     if (request->enable()) {
121       dynamic_channel_helper_map_.emplace(request->psm(), std::make_unique<L2capDynamicChannelHelper>(
122                                                               this, l2cap_layer_, facade_handler_, request->psm(),
123                                                               SecurityLevelToPolicy(request->security_level())));
124       return ::grpc::Status::OK;
125     } else {
126       auto service_helper = dynamic_channel_helper_map_.find(request->psm());
127       if (service_helper == dynamic_channel_helper_map_.end()) {
128         return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
129       }
130       service_helper->second->service_->Unregister(common::BindOnce([] {}), facade_handler_);
131       return ::grpc::Status::OK;
132     }
133   }
134 
SendDynamicChannelPacket(::grpc::ServerContext *,const::bluetooth::l2cap::le::DynamicChannelPacket * request,::google::protobuf::Empty *)135   ::grpc::Status SendDynamicChannelPacket(
136       ::grpc::ServerContext* /* context */,
137       const ::bluetooth::l2cap::le::DynamicChannelPacket* request,
138       ::google::protobuf::Empty* /* response */) override {
139     std::unique_lock<std::mutex> lock(channel_map_mutex_);
140     if (dynamic_channel_helper_map_.find(request->psm()) == dynamic_channel_helper_map_.end()) {
141       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Psm not registered");
142     }
143     std::vector<uint8_t> packet(request->payload().begin(), request->payload().end());
144     if (!dynamic_channel_helper_map_[request->psm()]->SendPacket(packet)) {
145       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open");
146     }
147     return ::grpc::Status::OK;
148   }
149 
150   class L2capDynamicChannelHelper {
151    public:
L2capDynamicChannelHelper(L2capLeModuleFacadeService * service,L2capLeModule * l2cap_layer,os::Handler * handler,Psm psm,SecurityPolicy security_policy)152     L2capDynamicChannelHelper(L2capLeModuleFacadeService* service, L2capLeModule* l2cap_layer, os::Handler* handler,
153                               Psm psm, SecurityPolicy security_policy)
154         : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), psm_(psm) {
155       dynamic_channel_manager_ = l2cap_layer_->GetDynamicChannelManager();
156       dynamic_channel_manager_->RegisterService(
157           psm, {}, security_policy,
158           common::BindOnce(&L2capDynamicChannelHelper::on_l2cap_service_registration_complete,
159                            common::Unretained(this)),
160           common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)), handler_);
161     }
162 
~L2capDynamicChannelHelper()163     ~L2capDynamicChannelHelper() {
164       if (channel_ != nullptr) {
165         channel_->GetQueueUpEnd()->UnregisterDequeue();
166         channel_ = nullptr;
167       }
168     }
169 
Connect(hci::AddressWithType address)170     void Connect(hci::AddressWithType address) {
171       dynamic_channel_manager_->ConnectChannel(
172           address, {}, psm_, common::Bind(&L2capDynamicChannelHelper::on_connection_open, common::Unretained(this)),
173           common::Bind(&L2capDynamicChannelHelper::on_connect_fail, common::Unretained(this)), handler_);
174       std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
175       if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, [this] { return channel_ != nullptr; })) {
176         log::warn("Channel is not open for psm {}", psm_);
177       }
178     }
179 
on_l2cap_service_registration_complete(DynamicChannelManager::RegistrationResult registration_result,std::unique_ptr<DynamicChannelService> service)180     void on_l2cap_service_registration_complete(DynamicChannelManager::RegistrationResult registration_result,
181                                                 std::unique_ptr<DynamicChannelService> service) {
182       if (registration_result != DynamicChannelManager::RegistrationResult::SUCCESS) {
183         log::error("Service registration failed");
184       } else {
185         service_ = std::move(service);
186       }
187     }
188 
189     // invoked from Facade Handler
on_connection_open(std::unique_ptr<DynamicChannel> channel)190     void on_connection_open(std::unique_ptr<DynamicChannel> channel) {
191       {
192         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
193         channel_ = std::move(channel);
194       }
195       channel_open_cv_.notify_all();
196       channel_->RegisterOnCloseCallback(
197           facade_service_->facade_handler_->BindOnceOn(this, &L2capDynamicChannelHelper::on_close_callback));
198       channel_->GetQueueUpEnd()->RegisterDequeue(
199           facade_service_->facade_handler_,
200           common::Bind(&L2capDynamicChannelHelper::on_incoming_packet, common::Unretained(this)));
201     }
202 
on_close_callback(hci::ErrorCode)203     void on_close_callback(hci::ErrorCode /* error_code */) {
204       {
205         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
206         channel_->GetQueueUpEnd()->UnregisterDequeue();
207       }
208       channel_ = nullptr;
209     }
210 
on_connect_fail(DynamicChannelManager::ConnectionResult result)211     void on_connect_fail(DynamicChannelManager::ConnectionResult result) {
212       {
213         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
214         channel_ = nullptr;
215         channel_open_fail_reason_ = result;
216       }
217       channel_open_cv_.notify_all();
218     }
219 
on_incoming_packet()220     void on_incoming_packet() {
221       auto packet = channel_->GetQueueUpEnd()->TryDequeue();
222       std::string data = std::string(packet->begin(), packet->end());
223       L2capPacket l2cap_data;
224       l2cap_data.set_psm(psm_);
225       l2cap_data.set_payload(data);
226       facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data);
227     }
228 
SendPacket(std::vector<uint8_t> packet)229     bool SendPacket(std::vector<uint8_t> packet) {
230       if (channel_ == nullptr) {
231         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
232         if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, [this] { return channel_ != nullptr; })) {
233           log::warn("Channel is not open for psm {}", psm_);
234           return false;
235         }
236       }
237       std::promise<void> promise;
238       auto future = promise.get_future();
239       channel_->GetQueueUpEnd()->RegisterEnqueue(
240           handler_, common::Bind(&L2capDynamicChannelHelper::enqueue_callback, common::Unretained(this), packet,
241                                  common::Passed(std::move(promise))));
242       auto status = future.wait_for(std::chrono::milliseconds(500));
243       if (status != std::future_status::ready) {
244         log::error("Can't send packet because the previous packet wasn't sent yet");
245         return false;
246       }
247       return true;
248     }
249 
enqueue_callback(std::vector<uint8_t> packet,std::promise<void> promise)250     std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet,
251                                                                 std::promise<void> promise) {
252       auto packet_one = std::make_unique<packet::RawBuilder>(2000);
253       packet_one->AddOctets(packet);
254       channel_->GetQueueUpEnd()->UnregisterEnqueue();
255       promise.set_value();
256       return packet_one;
257     }
258 
259     L2capLeModuleFacadeService* facade_service_;
260     L2capLeModule* l2cap_layer_;
261     os::Handler* handler_;
262     std::unique_ptr<DynamicChannelManager> dynamic_channel_manager_;
263     std::unique_ptr<DynamicChannelService> service_;
264     std::unique_ptr<DynamicChannel> channel_ = nullptr;
265     Psm psm_;
266     DynamicChannelManager::ConnectionResult channel_open_fail_reason_;
267     std::condition_variable channel_open_cv_;
268     std::mutex channel_open_cv_mutex_;
269   };
270 
SetFixedChannel(::grpc::ServerContext *,const SetEnableFixedChannelRequest * request,::google::protobuf::Empty *)271   ::grpc::Status SetFixedChannel(
272       ::grpc::ServerContext* /* context */,
273       const SetEnableFixedChannelRequest* request,
274       ::google::protobuf::Empty* /* response */) override {
275     if (request->enable()) {
276       fixed_channel_helper_map_.emplace(request->cid(), std::make_unique<L2capFixedChannelHelper>(
277                                                             this, l2cap_layer_, facade_handler_, request->cid()));
278       return ::grpc::Status::OK;
279     } else {
280       auto service_helper = fixed_channel_helper_map_.find(request->cid());
281       if (service_helper == fixed_channel_helper_map_.end()) {
282         return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Cid not registered");
283       }
284       service_helper->second->channel_->Release();
285       service_helper->second->service_->Unregister(common::BindOnce([] {}), facade_handler_);
286       return ::grpc::Status::OK;
287     }
288   }
289 
SendFixedChannelPacket(::grpc::ServerContext *,const FixedChannelPacket * request,::google::protobuf::Empty *)290   ::grpc::Status SendFixedChannelPacket(
291       ::grpc::ServerContext* /* context */,
292       const FixedChannelPacket* request,
293       ::google::protobuf::Empty* /* response */) override {
294     std::unique_lock<std::mutex> lock(channel_map_mutex_);
295     if (fixed_channel_helper_map_.find(request->cid()) == fixed_channel_helper_map_.end()) {
296       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Cid not registered");
297     }
298     std::vector<uint8_t> packet(request->payload().begin(), request->payload().end());
299     if (!fixed_channel_helper_map_[request->cid()]->SendPacket(packet)) {
300       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Channel not open");
301     }
302     return ::grpc::Status::OK;
303   }
304 
305   class L2capFixedChannelHelper {
306    public:
L2capFixedChannelHelper(L2capLeModuleFacadeService * service,L2capLeModule * l2cap_layer,os::Handler * handler,Cid cid)307     L2capFixedChannelHelper(L2capLeModuleFacadeService* service, L2capLeModule* l2cap_layer, os::Handler* handler,
308                             Cid cid)
309         : facade_service_(service), l2cap_layer_(l2cap_layer), handler_(handler), cid_(cid) {
310       fixed_channel_manager_ = l2cap_layer_->GetFixedChannelManager();
311       fixed_channel_manager_->RegisterService(
312           cid_,
313           common::BindOnce(&L2capFixedChannelHelper::on_l2cap_service_registration_complete, common::Unretained(this)),
314           common::Bind(&L2capFixedChannelHelper::on_connection_open, common::Unretained(this)), handler_);
315     }
316 
~L2capFixedChannelHelper()317     ~L2capFixedChannelHelper() {
318       if (channel_ != nullptr) {
319         channel_->GetQueueUpEnd()->UnregisterDequeue();
320         channel_->Release();
321         channel_ = nullptr;
322       }
323     }
324 
Connect(hci::AddressWithType address)325     void Connect(hci::AddressWithType address) {
326       fixed_channel_manager_->ConnectServices(
327           address, common::BindOnce(&L2capFixedChannelHelper::on_connect_fail, common::Unretained(this)), handler_);
328       std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
329       if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, [this] { return channel_ != nullptr; })) {
330         log::warn("Channel is not open for cid {}", cid_);
331       }
332     }
333 
on_l2cap_service_registration_complete(FixedChannelManager::RegistrationResult registration_result,std::unique_ptr<FixedChannelService> service)334     void on_l2cap_service_registration_complete(FixedChannelManager::RegistrationResult registration_result,
335                                                 std::unique_ptr<FixedChannelService> service) {
336       if (registration_result != FixedChannelManager::RegistrationResult::SUCCESS) {
337         log::error("Service registration failed");
338       } else {
339         service_ = std::move(service);
340       }
341     }
342 
343     // invoked from Facade Handler
on_connection_open(std::unique_ptr<FixedChannel> channel)344     void on_connection_open(std::unique_ptr<FixedChannel> channel) {
345       {
346         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
347         channel_ = std::move(channel);
348         channel_->RegisterOnCloseCallback(
349             handler_, common::BindOnce(&L2capFixedChannelHelper::on_close_callback, common::Unretained(this)));
350         channel_->Acquire();
351       }
352       channel_open_cv_.notify_all();
353       channel_->GetQueueUpEnd()->RegisterDequeue(
354           facade_service_->facade_handler_,
355           common::Bind(&L2capFixedChannelHelper::on_incoming_packet, common::Unretained(this)));
356     }
357 
on_close_callback(hci::ErrorCode)358     void on_close_callback(hci::ErrorCode /* error_code */) {
359       {
360         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
361         channel_->GetQueueUpEnd()->UnregisterDequeue();
362       }
363       channel_ = nullptr;
364     }
365 
on_connect_fail(FixedChannelManager::ConnectionResult)366     void on_connect_fail(FixedChannelManager::ConnectionResult /* result */) {
367       {
368         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
369         channel_ = nullptr;
370       }
371       channel_open_cv_.notify_all();
372     }
373 
on_incoming_packet()374     void on_incoming_packet() {
375       auto packet = channel_->GetQueueUpEnd()->TryDequeue();
376       std::string data = std::string(packet->begin(), packet->end());
377       L2capPacket l2cap_data;
378       l2cap_data.set_fixed_cid(cid_);
379       l2cap_data.set_payload(data);
380       facade_service_->pending_l2cap_data_.OnIncomingEvent(l2cap_data);
381     }
382 
SendPacket(std::vector<uint8_t> packet)383     bool SendPacket(std::vector<uint8_t> packet) {
384       if (channel_ == nullptr) {
385         std::unique_lock<std::mutex> lock(channel_open_cv_mutex_);
386         if (!channel_open_cv_.wait_for(lock, kChannelOpenTimeout, [this] { return channel_ != nullptr; })) {
387           log::warn("Channel is not open for cid {}", cid_);
388           return false;
389         }
390       }
391       std::promise<void> promise;
392       auto future = promise.get_future();
393       channel_->GetQueueUpEnd()->RegisterEnqueue(
394           handler_, common::Bind(&L2capFixedChannelHelper::enqueue_callback, common::Unretained(this), packet,
395                                  common::Passed(std::move(promise))));
396       auto status = future.wait_for(std::chrono::milliseconds(500));
397       if (status != std::future_status::ready) {
398         log::error("Can't send packet because the previous packet wasn't sent yet");
399         return false;
400       }
401       return true;
402     }
403 
enqueue_callback(std::vector<uint8_t> packet,std::promise<void> promise)404     std::unique_ptr<packet::BasePacketBuilder> enqueue_callback(std::vector<uint8_t> packet,
405                                                                 std::promise<void> promise) {
406       auto packet_one = std::make_unique<packet::RawBuilder>(2000);
407       packet_one->AddOctets(packet);
408       channel_->GetQueueUpEnd()->UnregisterEnqueue();
409       promise.set_value();
410       return packet_one;
411     }
412 
413     L2capLeModuleFacadeService* facade_service_;
414     L2capLeModule* l2cap_layer_;
415     os::Handler* handler_;
416     std::unique_ptr<FixedChannelManager> fixed_channel_manager_;
417     std::unique_ptr<FixedChannelService> service_;
418     std::unique_ptr<FixedChannel> channel_ = nullptr;
419     Cid cid_;
420     std::condition_variable channel_open_cv_;
421     std::mutex channel_open_cv_mutex_;
422   };
423 
SendConnectionParameterUpdate(::grpc::ServerContext *,const ConnectionParameter * request,::google::protobuf::Empty *)424   ::grpc::Status SendConnectionParameterUpdate(
425       ::grpc::ServerContext* /* context */,
426       const ConnectionParameter* request,
427       ::google::protobuf::Empty* /* response */) override {
428     if (dynamic_channel_helper_map_.empty()) {
429       return ::grpc::Status(::grpc::StatusCode::FAILED_PRECONDITION, "Need to open at least one dynamic channel first");
430     }
431     auto& dynamic_channel_helper = dynamic_channel_helper_map_.begin()->second;
432     dynamic_channel_helper->channel_->GetLinkOptions()->UpdateConnectionParameter(
433         request->conn_interval_min(), request->conn_interval_max(), request->conn_latency(),
434         request->supervision_timeout(), request->min_ce_length(), request->max_ce_length());
435 
436     return ::grpc::Status::OK;
437   }
438 
439   L2capLeModule* l2cap_layer_;
440   os::Handler* facade_handler_;
441   std::mutex channel_map_mutex_;
442   std::map<Psm, std::unique_ptr<L2capDynamicChannelHelper>> dynamic_channel_helper_map_;
443   std::map<Cid, std::unique_ptr<L2capFixedChannelHelper>> fixed_channel_helper_map_;
444   ::bluetooth::grpc::GrpcEventQueue<L2capPacket> pending_l2cap_data_{"FetchL2capData"};
445 };
446 
ListDependencies(ModuleList * list) const447 void L2capLeModuleFacadeModule::ListDependencies(ModuleList* list) const {
448   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
449   list->add<l2cap::le::L2capLeModule>();
450 }
451 
Start()452 void L2capLeModuleFacadeModule::Start() {
453   ::bluetooth::grpc::GrpcFacadeModule::Start();
454   service_ = new L2capLeModuleFacadeService(GetDependency<l2cap::le::L2capLeModule>(), GetHandler());
455 }
456 
Stop()457 void L2capLeModuleFacadeModule::Stop() {
458   delete service_;
459   ::bluetooth::grpc::GrpcFacadeModule::Stop();
460 }
461 
GetService() const462 ::grpc::Service* L2capLeModuleFacadeModule::GetService() const {
463   return service_;
464 }
465 
466 const ModuleFactory L2capLeModuleFacadeModule::Factory =
__anonbd0aa1f10702() 467     ::bluetooth::ModuleFactory([]() { return new L2capLeModuleFacadeModule(); });
468 
469 }  // namespace le
470 }  // namespace l2cap
471 }  // namespace bluetooth
472