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 return true;
97 }
98
99 class LeAdvertiser {
100 public:
LeAdvertiser(hci::AdvertisingConfig config)101 LeAdvertiser(hci::AdvertisingConfig config) : config_(std::move(config)) {}
102
ScanCallback(Address address,AddressType address_type)103 void ScanCallback(Address address, AddressType address_type) {}
104
TerminatedCallback(ErrorCode error_code,uint8_t,uint8_t)105 void TerminatedCallback(ErrorCode error_code, uint8_t, uint8_t) {}
106
GetAdvertiserId()107 hci::AdvertiserId GetAdvertiserId() {
108 return id_;
109 }
110
SetAdvertiserId(hci::AdvertiserId id)111 void SetAdvertiserId(hci::AdvertiserId id) {
112 id_ = id;
113 }
114
115 private:
116 hci::AdvertiserId id_ = LeAdvertisingManager::kInvalidId;
117 hci::AdvertisingConfig config_;
118 };
119
120 class LeAdvertisingManagerFacadeService : public LeAdvertisingManagerFacade::Service {
121 public:
LeAdvertisingManagerFacadeService(LeAdvertisingManager * le_advertising_manager,os::Handler * facade_handler)122 LeAdvertisingManagerFacadeService(LeAdvertisingManager* le_advertising_manager, os::Handler* facade_handler)
123 : le_advertising_manager_(le_advertising_manager), facade_handler_(facade_handler) {
124 ASSERT(le_advertising_manager_ != nullptr);
125 ASSERT(facade_handler_ != nullptr);
126 }
127
CreateAdvertiser(::grpc::ServerContext * context,const CreateAdvertiserRequest * request,CreateAdvertiserResponse * response)128 ::grpc::Status CreateAdvertiser(::grpc::ServerContext* context, const CreateAdvertiserRequest* request,
129 CreateAdvertiserResponse* response) override {
130 hci::ExtendedAdvertisingConfig config = {};
131 if (!AdvertisingConfigFromProto(request->config(), &config)) {
132 LOG_WARN("Error parsing advertising config %s", request->SerializeAsString().c_str());
133 response->set_advertiser_id(LeAdvertisingManager::kInvalidId);
134 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Error while parsing advertising config");
135 }
136 LeAdvertiser le_advertiser(config);
137 auto advertiser_id = le_advertising_manager_->ExtendedCreateAdvertiser(
138 -1,
139 config,
140 common::Bind(&LeAdvertiser::ScanCallback, common::Unretained(&le_advertiser)),
141 common::Bind(&LeAdvertiser::TerminatedCallback, common::Unretained(&le_advertiser)),
142 0,
143 0,
144 facade_handler_);
145 if (advertiser_id != LeAdvertisingManager::kInvalidId) {
146 le_advertiser.SetAdvertiserId(advertiser_id);
147 le_advertisers_.push_back(le_advertiser);
148 } else {
149 LOG_WARN("Failed to create advertiser");
150 }
151 response->set_advertiser_id(advertiser_id);
152 return ::grpc::Status::OK;
153 }
154
ExtendedCreateAdvertiser(::grpc::ServerContext * context,const ExtendedCreateAdvertiserRequest * request,ExtendedCreateAdvertiserResponse * response)155 ::grpc::Status ExtendedCreateAdvertiser(::grpc::ServerContext* context,
156 const ExtendedCreateAdvertiserRequest* request,
157 ExtendedCreateAdvertiserResponse* response) override {
158 LOG_WARN("ExtendedCreateAdvertiser is not implemented");
159 response->set_advertiser_id(LeAdvertisingManager::kInvalidId);
160 return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "ExtendedCreateAdvertiser is not implemented");
161 }
162
GetNumberOfAdvertisingInstances(::grpc::ServerContext * context,const::google::protobuf::Empty * request,GetNumberOfAdvertisingInstancesResponse * response)163 ::grpc::Status GetNumberOfAdvertisingInstances(::grpc::ServerContext* context,
164 const ::google::protobuf::Empty* request,
165 GetNumberOfAdvertisingInstancesResponse* response) override {
166 response->set_num_advertising_instances(le_advertising_manager_->GetNumberOfAdvertisingInstances());
167 return ::grpc::Status::OK;
168 }
169
RemoveAdvertiser(::grpc::ServerContext * context,const RemoveAdvertiserRequest * request,::google::protobuf::Empty * response)170 ::grpc::Status RemoveAdvertiser(::grpc::ServerContext* context, const RemoveAdvertiserRequest* request,
171 ::google::protobuf::Empty* response) override {
172 if (request->advertiser_id() == LeAdvertisingManager::kInvalidId) {
173 LOG_WARN("Invalid advertiser ID %d", request->advertiser_id());
174 return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invlid advertiser ID received");
175 }
176 le_advertising_manager_->RemoveAdvertiser(request->advertiser_id());
177 for (auto iter = le_advertisers_.begin(); iter != le_advertisers_.end();) {
178 if (iter->GetAdvertiserId() == request->advertiser_id()) {
179 iter = le_advertisers_.erase(iter);
180 } else {
181 ++iter;
182 }
183 }
184 return ::grpc::Status::OK;
185 }
186
187 std::vector<LeAdvertiser> le_advertisers_;
188 LeAdvertisingManager* le_advertising_manager_;
189 os::Handler* facade_handler_;
190 };
191
ListDependencies(ModuleList * list)192 void LeAdvertisingManagerFacadeModule::ListDependencies(ModuleList* list) {
193 ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
194 list->add<hci::LeAdvertisingManager>();
195 }
196
Start()197 void LeAdvertisingManagerFacadeModule::Start() {
198 ::bluetooth::grpc::GrpcFacadeModule::Start();
199 service_ = new LeAdvertisingManagerFacadeService(GetDependency<hci::LeAdvertisingManager>(), GetHandler());
200 }
201
Stop()202 void LeAdvertisingManagerFacadeModule::Stop() {
203 delete service_;
204 ::bluetooth::grpc::GrpcFacadeModule::Stop();
205 }
206
GetService() const207 ::grpc::Service* LeAdvertisingManagerFacadeModule::GetService() const {
208 return service_;
209 }
210
211 const ModuleFactory LeAdvertisingManagerFacadeModule::Factory =
__anon092ea8300102() 212 ::bluetooth::ModuleFactory([]() { return new LeAdvertisingManagerFacadeModule(); });
213
214 } // namespace facade
215 } // namespace hci
216 } // namespace bluetooth
217