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 "neighbor/facade/facade.h"
18 
19 #include <memory>
20 
21 #include "common/bind.h"
22 #include "grpc/grpc_event_queue.h"
23 #include "hci/hci_packets.h"
24 #include "neighbor/facade/facade.grpc.pb.h"
25 
26 using ::grpc::ServerAsyncResponseWriter;
27 using ::grpc::ServerAsyncWriter;
28 using ::grpc::ServerContext;
29 
30 namespace bluetooth {
31 namespace neighbor {
32 namespace facade {
33 
34 class NeighborFacadeService : public NeighborFacade::Service {
35  public:
NeighborFacadeService(ConnectabilityModule * connectability_module,DiscoverabilityModule * discoverability_module,InquiryModule * inquiry_module,NameModule * name_module,PageModule *,ScanModule * scan_module,::bluetooth::os::Handler * facade_handler)36   NeighborFacadeService(
37       ConnectabilityModule* connectability_module,
38       DiscoverabilityModule* discoverability_module,
39       InquiryModule* inquiry_module,
40       NameModule* name_module,
41       PageModule*,
42       ScanModule* scan_module,
43       ::bluetooth::os::Handler* facade_handler)
44       : connectability_module_(connectability_module),
45         discoverability_module_(discoverability_module),
46         inquiry_module_(inquiry_module),
47         name_module_(name_module),
48         scan_module_(scan_module),
49         facade_handler_(facade_handler) {}
50 
SetConnectability(::grpc::ServerContext * context,const::bluetooth::neighbor::EnableMsg * request,::google::protobuf::Empty * response)51   ::grpc::Status SetConnectability(
52       ::grpc::ServerContext* context,
53       const ::bluetooth::neighbor::EnableMsg* request,
54       ::google::protobuf::Empty* response) override {
55     if (request->enabled()) {
56       connectability_module_->StartConnectability();
57     } else {
58       connectability_module_->StopConnectability();
59     }
60     return ::grpc::Status::OK;
61   }
62 
SetDiscoverability(::grpc::ServerContext * context,const::bluetooth::neighbor::DiscoverabilitiyMsg * request,::google::protobuf::Empty * response)63   ::grpc::Status SetDiscoverability(
64       ::grpc::ServerContext* context,
65       const ::bluetooth::neighbor::DiscoverabilitiyMsg* request,
66       ::google::protobuf::Empty* response) override {
67     switch (request->mode()) {
68       case DiscoverabilityMode::OFF:
69         discoverability_module_->StopDiscoverability();
70         break;
71       case DiscoverabilityMode::LIMITED:
72         discoverability_module_->StartLimitedDiscoverability();
73         break;
74       case DiscoverabilityMode::GENERAL:
75         discoverability_module_->StartGeneralDiscoverability();
76         break;
77       default:
78         LOG_ALWAYS_FATAL("Unknown discoverability mode %d", static_cast<int>(request->mode()));
79     }
80     return ::grpc::Status::OK;
81   }
82 
SetInquiryMode(::grpc::ServerContext * context,const::bluetooth::neighbor::InquiryMsg * request,::grpc::ServerWriter<InquiryResultMsg> * writer)83   ::grpc::Status SetInquiryMode(
84       ::grpc::ServerContext* context,
85       const ::bluetooth::neighbor::InquiryMsg* request,
86       ::grpc::ServerWriter<InquiryResultMsg>* writer) override {
87     inquiry_module_->RegisterCallbacks(inquiry_callbacks_);
88     switch (request->result_mode()) {
89       case ResultMode::STANDARD:
90         inquiry_module_->SetStandardInquiryResultMode();
91         break;
92       case ResultMode::RSSI:
93         inquiry_module_->SetInquiryWithRssiResultMode();
94         break;
95       case ResultMode::EXTENDED:
96         inquiry_module_->SetExtendedInquiryResultMode();
97         break;
98       default:
99         LOG_ALWAYS_FATAL("Unknown result mode %d", static_cast<int>(request->result_mode()));
100     }
101     switch (request->inquiry_mode()) {
102       case DiscoverabilityMode::OFF:
103         inquiry_module_->StopInquiry();
104         break;
105       case DiscoverabilityMode::LIMITED:
106         inquiry_module_->StartLimitedInquiry(request->length_1_28s(), request->max_results());
107         break;
108       case DiscoverabilityMode::GENERAL:
109         inquiry_module_->StartGeneralInquiry(request->length_1_28s(), request->max_results());
110         break;
111       default:
112         LOG_ALWAYS_FATAL("Unknown discoverability mode %d", static_cast<int>(request->inquiry_mode()));
113     }
114     return pending_events_.RunLoop(context, writer);
115   }
116 
ReadRemoteName(::grpc::ServerContext * context,const::bluetooth::neighbor::RemoteNameRequestMsg * request,::google::protobuf::Empty * response)117   ::grpc::Status ReadRemoteName(
118       ::grpc::ServerContext* context,
119       const ::bluetooth::neighbor::RemoteNameRequestMsg* request,
120       ::google::protobuf::Empty* response) override {
121     hci::Address remote;
122     ASSERT(hci::Address::FromString(request->address(), remote));
123     hci::PageScanRepetitionMode mode;
124     switch (request->page_scan_repetition_mode()) {
125       case 0:
126         mode = hci::PageScanRepetitionMode::R0;
127         break;
128       case 1:
129         mode = hci::PageScanRepetitionMode::R1;
130         break;
131       case 2:
132         mode = hci::PageScanRepetitionMode::R2;
133         break;
134       default:
135         LOG_ALWAYS_FATAL("Unknown PageScanRepetition mode %d", static_cast<int>(request->page_scan_repetition_mode()));
136     }
137     name_module_->ReadRemoteNameRequest(
138         remote,
139         mode,
140         request->clock_offset(),
141         (request->clock_offset() != 0 ? hci::ClockOffsetValid::VALID : hci::ClockOffsetValid::INVALID),
142         common::Bind(&NeighborFacadeService::on_remote_name, common::Unretained(this)),
143         facade_handler_);
144     return ::grpc::Status::OK;
145   }
146 
GetRemoteNameEvents(::grpc::ServerContext * context,const::google::protobuf::Empty * request,::grpc::ServerWriter<RemoteNameResponseMsg> * writer)147   ::grpc::Status GetRemoteNameEvents(
148       ::grpc::ServerContext* context,
149       const ::google::protobuf::Empty* request,
150       ::grpc::ServerWriter<RemoteNameResponseMsg>* writer) override {
151     return pending_remote_names_.RunLoop(context, writer);
152   }
153 
EnableInquiryScan(::grpc::ServerContext * context,const::bluetooth::neighbor::EnableMsg * request,::google::protobuf::Empty * response)154   ::grpc::Status EnableInquiryScan(
155       ::grpc::ServerContext* context,
156       const ::bluetooth::neighbor::EnableMsg* request,
157       ::google::protobuf::Empty* response) override {
158     if (request->enabled()) {
159       scan_module_->SetInquiryScan();
160     } else {
161       scan_module_->ClearInquiryScan();
162     }
163     return ::grpc::Status::OK;
164   }
165 
EnablePageScan(::grpc::ServerContext * context,const::bluetooth::neighbor::EnableMsg * request,::google::protobuf::Empty * response)166   ::grpc::Status EnablePageScan(
167       ::grpc::ServerContext* context,
168       const ::bluetooth::neighbor::EnableMsg* request,
169       ::google::protobuf::Empty* response) override {
170     if (request->enabled()) {
171       scan_module_->SetPageScan();
172     } else {
173       scan_module_->ClearPageScan();
174     }
175     return ::grpc::Status::OK;
176   }
177 
178  private:
on_incoming_inquiry_result(hci::EventPacketView view)179   void on_incoming_inquiry_result(hci::EventPacketView view) {
180     InquiryResultMsg inquiry_result_msg;
181     inquiry_result_msg.set_packet(std::string(view.begin(), view.end()));
182     pending_events_.OnIncomingEvent(std::move(inquiry_result_msg));
183   }
184 
on_incoming_inquiry_complete(hci::ErrorCode status)185   void on_incoming_inquiry_complete(hci::ErrorCode status) {
186     InquiryResultMsg inquiry_result_msg;
187     inquiry_result_msg.set_packet(hci::ErrorCodeText(status));
188     pending_events_.OnIncomingEvent(std::move(inquiry_result_msg));
189   }
190 
191   InquiryCallbacks inquiry_callbacks_{
__anon26ee629a0102() 192       .result = [this](hci::InquiryResultView view) { on_incoming_inquiry_result(view); },
__anon26ee629a0202() 193       .result_with_rssi = [this](hci::InquiryResultWithRssiView view) { on_incoming_inquiry_result(view); },
__anon26ee629a0302() 194       .extended_result = [this](hci::ExtendedInquiryResultView view) { on_incoming_inquiry_result(view); },
__anon26ee629a0402() 195       .complete = [this](hci::ErrorCode status) { on_incoming_inquiry_complete(status); }};
196 
on_remote_name(hci::ErrorCode status,hci::Address address,std::array<uint8_t,248> name)197   void on_remote_name(hci::ErrorCode status, hci::Address address, std::array<uint8_t, 248> name) {
198     RemoteNameResponseMsg response;
199     response.set_status(static_cast<int>(status));
200     response.set_address(address.ToString());
201     response.set_name(name.begin(), name.size());
202     pending_remote_names_.OnIncomingEvent(response);
203   }
204 
205   ConnectabilityModule* connectability_module_;
206   DiscoverabilityModule* discoverability_module_;
207   InquiryModule* inquiry_module_;
208   NameModule* name_module_;
209   ScanModule* scan_module_;
210   ::bluetooth::os::Handler* facade_handler_;
211   ::bluetooth::grpc::GrpcEventQueue<InquiryResultMsg> pending_events_{"InquiryResponses"};
212   ::bluetooth::grpc::GrpcEventQueue<RemoteNameResponseMsg> pending_remote_names_{"RemoteNameResponses"};
213 };
214 
ListDependencies(ModuleList * list)215 void NeighborFacadeModule::ListDependencies(ModuleList* list) {
216   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
217   list->add<ConnectabilityModule>();
218   list->add<DiscoverabilityModule>();
219   list->add<InquiryModule>();
220   list->add<NameModule>();
221   list->add<PageModule>();
222   list->add<ScanModule>();
223 }
224 
Start()225 void NeighborFacadeModule::Start() {
226   ::bluetooth::grpc::GrpcFacadeModule::Start();
227   service_ = new NeighborFacadeService(
228       GetDependency<ConnectabilityModule>(),
229       GetDependency<DiscoverabilityModule>(),
230       GetDependency<InquiryModule>(),
231       GetDependency<NameModule>(),
232       GetDependency<PageModule>(),
233       GetDependency<ScanModule>(),
234       GetHandler());
235 }
236 
Stop()237 void NeighborFacadeModule::Stop() {
238   delete service_;
239   ::bluetooth::grpc::GrpcFacadeModule::Stop();
240 }
241 
GetService() const242 ::grpc::Service* NeighborFacadeModule::GetService() const {
243   return service_;
244 }
245 
246 const ModuleFactory NeighborFacadeModule::Factory =
__anon26ee629a0502() 247     ::bluetooth::ModuleFactory([]() { return new NeighborFacadeModule(); });
248 
249 }  // namespace facade
250 }  // namespace neighbor
251 }  // namespace bluetooth
252