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 <cstdint>
18 #include <unordered_map>
19 #include <utility>
20 
21 #include "common/bidi_queue.h"
22 #include "common/bind.h"
23 #include "hci/address.h"
24 #include "hci/address_with_type.h"
25 #include "hci/facade/le_advertising_manager_facade.grpc.pb.h"
26 #include "hci/facade/le_advertising_manager_facade.h"
27 #include "hci/facade/le_advertising_manager_facade.pb.h"
28 #include "hci/le_advertising_manager.h"
29 #include "os/log.h"
30 
31 namespace bluetooth {
32 namespace hci {
33 namespace facade {
34 
35 using ::grpc::ServerAsyncResponseWriter;
36 using ::grpc::ServerAsyncWriter;
37 using ::grpc::ServerContext;
38 using ::grpc::ServerWriter;
39 using ::grpc::Status;
40 
41 using ::bluetooth::facade::BluetoothAddress;
42 using ::bluetooth::facade::BluetoothAddressTypeEnum;
43 
GapDataFromProto(const GapDataMsg & gap_data_proto)44 hci::GapData GapDataFromProto(const GapDataMsg& gap_data_proto) {
45   hci::GapData gap_data;
46   auto data_copy = std::make_shared<std::vector<uint8_t>>(gap_data_proto.data().begin(), gap_data_proto.data().end());
47   packet::PacketView<packet::kLittleEndian> packet(data_copy);
48   auto after = hci::GapData::Parse(&gap_data, packet.begin());
49   ASSERT(after != packet.begin());
50   return gap_data;
51 }
52 
AdvertisingConfigFromProto(const AdvertisingConfig & config_proto,hci::AdvertisingConfig * config)53 bool AdvertisingConfigFromProto(const AdvertisingConfig& config_proto, hci::AdvertisingConfig* config) {
54   for (const auto& elem : config_proto.advertisement()) {
55     config->advertisement.push_back(GapDataFromProto(elem));
56   }
57 
58   for (const auto& elem : config_proto.scan_response()) {
59     config->scan_response.push_back(GapDataFromProto(elem));
60   }
61 
62   if (config_proto.interval_min() > UINT16_MAX || config_proto.interval_min() < 0) {
63     LOG_WARN("Bad interval_min: %d", config_proto.interval_min());
64     return false;
65   }
66   config->interval_min = static_cast<uint16_t>(config_proto.interval_min());
67 
68   if (config_proto.interval_max() > UINT16_MAX || config_proto.interval_max() < 0) {
69     LOG_WARN("Bad interval_max: %d", config_proto.interval_max());
70     return false;
71   }
72   config->interval_max = static_cast<uint16_t>(config_proto.interval_max());
73 
74   config->advertising_type = static_cast<hci::AdvertisingType>(config_proto.advertising_type());
75 
76   config->own_address_type = static_cast<::bluetooth::hci::OwnAddressType>(config_proto.own_address_type());
77 
78   config->peer_address_type = static_cast<::bluetooth::hci::PeerAddressType>(config_proto.peer_address_type());
79 
80   hci::Address::FromString(config_proto.peer_address().address(), config->peer_address);
81 
82   if (config_proto.channel_map() > UINT8_MAX || config_proto.channel_map() < 0) {
83     LOG_WARN("Bad channel_map: %d", config_proto.channel_map());
84     return false;
85   }
86   config->channel_map = static_cast<uint8_t>(config_proto.channel_map());
87 
88   if (config_proto.tx_power() > UINT8_MAX || config_proto.tx_power() < 0) {
89     LOG_WARN("Bad tx_power: %d", config_proto.tx_power());
90     return false;
91   }
92 
93   config->filter_policy = static_cast<hci::AdvertisingFilterPolicy>(config_proto.filter_policy());
94 
95   config->tx_power = static_cast<uint8_t>(config_proto.tx_power());
96 
97   return true;
98 }
99 
ExtendedAdvertisingConfigFromProto(const ExtendedAdvertisingConfig & config_proto,hci::ExtendedAdvertisingConfig * config)100 bool ExtendedAdvertisingConfigFromProto(
101     const ExtendedAdvertisingConfig& config_proto, hci::ExtendedAdvertisingConfig* config) {
102   AdvertisingConfigFromProto(config_proto.advertising_config(), config);
103   config->connectable = config_proto.connectable();
104   config->scannable = config_proto.scannable();
105   config->directed = config_proto.directed();
106   config->high_duty_directed_connectable = config_proto.high_duty_directed_connectable();
107   config->legacy_pdus = config_proto.legacy_pdus();
108   config->anonymous = config_proto.anonymous();
109   config->include_tx_power = config_proto.include_tx_power();
110   config->use_le_coded_phy = config_proto.use_le_coded_phy();
111   if (config_proto.secondary_map_skip() < 0 || config_proto.secondary_map_skip() > 0xFF) {
112     LOG_WARN("Base secondary_map_skip: 0x%x", config_proto.secondary_map_skip());
113     return false;
114   }
115   config->secondary_max_skip = config_proto.secondary_map_skip();
116   if (config_proto.secondary_advertising_phy() <= 0 || config_proto.secondary_advertising_phy() > 3) {
117     LOG_WARN("Base secondary_advertising_phy: 0x%x", config_proto.secondary_advertising_phy());
118     return false;
119   }
120   config->secondary_advertising_phy = static_cast<SecondaryPhyType>(config_proto.secondary_advertising_phy());
121   if (config_proto.sid() < 0 || config_proto.sid() > 0xF) {
122     LOG_WARN("Base sid: 0x%x", config_proto.sid());
123     return false;
124   }
125   config->sid = config_proto.sid();
126   config->enable_scan_request_notifications =
127       config_proto.enable_scan_request_notification() ? Enable::ENABLED : Enable::DISABLED;
128   return true;
129 }
130 
131 class LeAdvertiser {
132  public:
LeAdvertiser(hci::AdvertisingConfig config)133   LeAdvertiser(hci::AdvertisingConfig config) : config_(std::move(config)) {}
134 
ScanCallback(Address address,AddressType address_type)135   void ScanCallback(Address address, AddressType address_type) {}
136 
TerminatedCallback(ErrorCode error_code,uint8_t,uint8_t)137   void TerminatedCallback(ErrorCode error_code, uint8_t, uint8_t) {}
138 
GetAdvertiserId()139   hci::AdvertiserId GetAdvertiserId() {
140     return id_;
141   }
142 
SetAdvertiserId(hci::AdvertiserId id)143   void SetAdvertiserId(hci::AdvertiserId id) {
144     id_ = id;
145   }
146 
147  private:
148   hci::AdvertiserId id_ = LeAdvertisingManager::kInvalidId;
149   hci::AdvertisingConfig config_;
150 };
151 
152 class LeAdvertisingManagerFacadeService : public LeAdvertisingManagerFacade::Service {
153  public:
LeAdvertisingManagerFacadeService(LeAdvertisingManager * le_advertising_manager,os::Handler * facade_handler)154   LeAdvertisingManagerFacadeService(LeAdvertisingManager* le_advertising_manager, os::Handler* facade_handler)
155       : le_advertising_manager_(le_advertising_manager), facade_handler_(facade_handler) {
156     ASSERT(le_advertising_manager_ != nullptr);
157     ASSERT(facade_handler_ != nullptr);
158   }
159 
CreateAdvertiser(::grpc::ServerContext * context,const CreateAdvertiserRequest * request,CreateAdvertiserResponse * response)160   ::grpc::Status CreateAdvertiser(::grpc::ServerContext* context, const CreateAdvertiserRequest* request,
161                                   CreateAdvertiserResponse* response) override {
162     hci::ExtendedAdvertisingConfig config = {};
163     config.legacy_pdus = true;
164     config.secondary_advertising_phy = SecondaryPhyType::LE_1M;
165     if (!AdvertisingConfigFromProto(request->config(), &config)) {
166       LOG_WARN("Error parsing advertising config %s", request->SerializeAsString().c_str());
167       response->set_advertiser_id(LeAdvertisingManager::kInvalidId);
168       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Error while parsing advertising config");
169     }
170     LeAdvertiser le_advertiser(config);
171     auto advertiser_id = le_advertising_manager_->ExtendedCreateAdvertiser(
172         -1,
173         config,
174         common::Bind(&LeAdvertiser::ScanCallback, common::Unretained(&le_advertiser)),
175         common::Bind(&LeAdvertiser::TerminatedCallback, common::Unretained(&le_advertiser)),
176         0,
177         0,
178         facade_handler_);
179     if (advertiser_id != LeAdvertisingManager::kInvalidId) {
180       le_advertiser.SetAdvertiserId(advertiser_id);
181       le_advertisers_.push_back(le_advertiser);
182     } else {
183       LOG_WARN("Failed to create advertiser");
184     }
185     response->set_advertiser_id(advertiser_id);
186     return ::grpc::Status::OK;
187   }
188 
ExtendedCreateAdvertiser(::grpc::ServerContext * context,const ExtendedCreateAdvertiserRequest * request,ExtendedCreateAdvertiserResponse * response)189   ::grpc::Status ExtendedCreateAdvertiser(::grpc::ServerContext* context,
190                                           const ExtendedCreateAdvertiserRequest* request,
191                                           ExtendedCreateAdvertiserResponse* response) override {
192     hci::ExtendedAdvertisingConfig config = {};
193     if (!ExtendedAdvertisingConfigFromProto(request->config(), &config)) {
194       LOG_WARN("Error parsing extended advertising config %s", request->SerializeAsString().c_str());
195       response->set_advertiser_id(LeAdvertisingManager::kInvalidId);
196       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Error while parsing extended advertising config");
197     }
198     LeAdvertiser le_advertiser(config);
199     auto advertiser_id = le_advertising_manager_->ExtendedCreateAdvertiser(
200         -1,
201         config,
202         common::Bind(&LeAdvertiser::ScanCallback, common::Unretained(&le_advertiser)),
203         common::Bind(&LeAdvertiser::TerminatedCallback, common::Unretained(&le_advertiser)),
204         0,
205         0,
206         facade_handler_);
207     if (advertiser_id != LeAdvertisingManager::kInvalidId) {
208       le_advertiser.SetAdvertiserId(advertiser_id);
209       le_advertisers_.push_back(le_advertiser);
210     } else {
211       LOG_WARN("Failed to create advertiser");
212     }
213     response->set_advertiser_id(advertiser_id);
214     return ::grpc::Status::OK;
215   }
216 
GetNumberOfAdvertisingInstances(::grpc::ServerContext * context,const::google::protobuf::Empty * request,GetNumberOfAdvertisingInstancesResponse * response)217   ::grpc::Status GetNumberOfAdvertisingInstances(::grpc::ServerContext* context,
218                                                  const ::google::protobuf::Empty* request,
219                                                  GetNumberOfAdvertisingInstancesResponse* response) override {
220     response->set_num_advertising_instances(le_advertising_manager_->GetNumberOfAdvertisingInstances());
221     return ::grpc::Status::OK;
222   }
223 
RemoveAdvertiser(::grpc::ServerContext * context,const RemoveAdvertiserRequest * request,::google::protobuf::Empty * response)224   ::grpc::Status RemoveAdvertiser(::grpc::ServerContext* context, const RemoveAdvertiserRequest* request,
225                                   ::google::protobuf::Empty* response) override {
226     if (request->advertiser_id() == LeAdvertisingManager::kInvalidId) {
227       LOG_WARN("Invalid advertiser ID %d", request->advertiser_id());
228       return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invlid advertiser ID received");
229     }
230     le_advertising_manager_->RemoveAdvertiser(request->advertiser_id());
231     for (auto iter = le_advertisers_.begin(); iter != le_advertisers_.end();) {
232       if (iter->GetAdvertiserId() == request->advertiser_id()) {
233         iter = le_advertisers_.erase(iter);
234       } else {
235         ++iter;
236       }
237     }
238     return ::grpc::Status::OK;
239   }
240 
241   std::vector<LeAdvertiser> le_advertisers_;
242   LeAdvertisingManager* le_advertising_manager_;
243   os::Handler* facade_handler_;
244 };
245 
ListDependencies(ModuleList * list)246 void LeAdvertisingManagerFacadeModule::ListDependencies(ModuleList* list) {
247   ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
248   list->add<hci::LeAdvertisingManager>();
249 }
250 
Start()251 void LeAdvertisingManagerFacadeModule::Start() {
252   ::bluetooth::grpc::GrpcFacadeModule::Start();
253   service_ = new LeAdvertisingManagerFacadeService(GetDependency<hci::LeAdvertisingManager>(), GetHandler());
254 }
255 
Stop()256 void LeAdvertisingManagerFacadeModule::Stop() {
257   delete service_;
258   ::bluetooth::grpc::GrpcFacadeModule::Stop();
259 }
260 
GetService() const261 ::grpc::Service* LeAdvertisingManagerFacadeModule::GetService() const {
262   return service_;
263 }
264 
265 const ModuleFactory LeAdvertisingManagerFacadeModule::Factory =
__anonbbb588350102() 266     ::bluetooth::ModuleFactory([]() { return new LeAdvertisingManagerFacadeModule(); });
267 
268 }  // namespace facade
269 }  // namespace hci
270 }  // namespace bluetooth
271