Merge changes Id8582211,I6cd71506 am: 717ad0f8a6
am: 64453a3048
Change-Id: I830a2e788f4277771dd8e870d51effd1358d0eeb
diff --git a/gd/Android.bp b/gd/Android.bp
index 9145772..037c517 100644
--- a/gd/Android.bp
+++ b/gd/Android.bp
@@ -398,6 +398,7 @@
"facade/rootservice.proto",
"hal/facade.proto",
"hci/facade.proto",
+ "hci/facade/le_advertising_manager_facade.proto",
"l2cap/classic/facade.proto",
],
}
@@ -421,6 +422,8 @@
"hal/facade.pb.h",
"hci/facade.grpc.pb.h",
"hci/facade.pb.h",
+ "hci/facade/le_advertising_manager_facade.grpc.pb.h",
+ "hci/facade/le_advertising_manager_facade.pb.h",
"l2cap/classic/facade.grpc.pb.h",
"l2cap/classic/facade.pb.h",
],
@@ -445,6 +448,8 @@
"hal/facade.pb.cc",
"hci/facade.grpc.pb.cc",
"hci/facade.pb.cc",
+ "hci/facade/le_advertising_manager_facade.grpc.pb.cc",
+ "hci/facade/le_advertising_manager_facade.pb.cc",
"l2cap/classic/facade.grpc.pb.cc",
"l2cap/classic/facade.pb.cc",
],
@@ -461,6 +466,7 @@
"touch $(genDir)/hal/__init__.py; " +
"touch $(genDir)/hal/cert/__init__.py; " +
"touch $(genDir)/hci/__init__.py; " +
+ "touch $(genDir)/hci/facade/__init__.py; " +
"touch $(genDir)/hci/cert/__init__.py; " +
"touch $(genDir)/l2cap/classic/__init__.py; " +
"touch $(genDir)/l2cap/classic/cert/__init__.py; ",
@@ -482,6 +488,9 @@
"hci/__init__.py",
"hci/facade_pb2_grpc.py",
"hci/facade_pb2.py",
+ "hci/facade/__init__.py",
+ "hci/facade/le_advertising_manager_facade_pb2_grpc.py",
+ "hci/facade/le_advertising_manager_facade_pb2.py",
"l2cap/classic/__init__.py",
"l2cap/classic/facade_pb2_grpc.py",
"l2cap/classic/facade_pb2.py",
diff --git a/gd/cert/gd_device.py b/gd/cert/gd_device.py
index 17454f3..8f84dbc 100644
--- a/gd/cert/gd_device.py
+++ b/gd/cert/gd_device.py
@@ -21,6 +21,7 @@
from facade import rootservice_pb2_grpc as facade_rootservice_pb2_grpc
from hal import facade_pb2_grpc as hal_facade_pb2_grpc
from hci import facade_pb2_grpc as hci_facade_pb2_grpc
+from hci.facade import le_advertising_manager_facade_pb2_grpc
from l2cap.classic import facade_pb2_grpc as l2cap_facade_pb2_grpc
ACTS_CONTROLLER_CONFIG_NAME = "GdDevice"
@@ -71,6 +72,7 @@
self.hci = hci_facade_pb2_grpc.AclManagerFacadeStub(self.grpc_channel)
self.hci_classic_security = hci_facade_pb2_grpc.ClassicSecurityManagerFacadeStub(self.grpc_channel)
self.l2cap = l2cap_facade_pb2_grpc.L2capClassicModuleFacadeStub(self.grpc_channel)
+ self.hci_le_advertising_manager = le_advertising_manager_facade_pb2_grpc.LeAdvertisingManagerFacadeStub(self.grpc_channel)
# Event streams
self.hal.hci_event_stream = EventStream(self.hal.FetchHciEvent)
diff --git a/gd/facade/common.proto b/gd/facade/common.proto
index bf35409..358db04 100644
--- a/gd/facade/common.proto
+++ b/gd/facade/common.proto
@@ -23,3 +23,15 @@
message BluetoothAddress {
bytes address = 1;
}
+
+enum BluetoothAddressTypeEnum {
+ PUBLIC_DEVICE_ADDRESS = 0x0;
+ RANDOM_DEVICE_ADDRESS = 0x1;
+ PUBLIC_IDENTITY_ADDRESS = 0x2;
+ RANDOM_IDENTITY_ADDRESS = 0x3;
+}
+
+enum BluetoothPeerAddressTypeEnum {
+ PUBLIC_DEVICE_OR_IDENTITY_ADDRESS = 0x0;
+ RANDOM_DEVICE_OR_IDENTITY_ADDRESS = 0x1;
+}
diff --git a/gd/hci/Android.bp b/gd/hci/Android.bp
index 8784a49..c656b56 100644
--- a/gd/hci/Android.bp
+++ b/gd/hci/Android.bp
@@ -39,6 +39,7 @@
name: "BluetoothFacade_hci_layer",
srcs: [
"facade.cc",
+ "facade/le_advertising_manager_facade.cc"
],
}
diff --git a/gd/hci/facade/le_advertising_manager_facade.cc b/gd/hci/facade/le_advertising_manager_facade.cc
new file mode 100644
index 0000000..4478229
--- /dev/null
+++ b/gd/hci/facade/le_advertising_manager_facade.cc
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdint>
+#include <unordered_map>
+#include <utility>
+
+#include "common/bidi_queue.h"
+#include "common/bind.h"
+#include "grpc/grpc_event_stream.h"
+#include "hci/address.h"
+#include "hci/address_with_type.h"
+#include "hci/facade/le_advertising_manager_facade.grpc.pb.h"
+#include "hci/facade/le_advertising_manager_facade.h"
+#include "hci/facade/le_advertising_manager_facade.pb.h"
+#include "hci/le_advertising_manager.h"
+#include "os/log.h"
+#include "packet/raw_builder.h"
+
+namespace bluetooth {
+namespace hci {
+namespace facade {
+
+using ::grpc::ServerAsyncResponseWriter;
+using ::grpc::ServerAsyncWriter;
+using ::grpc::ServerContext;
+using ::grpc::ServerWriter;
+using ::grpc::Status;
+
+using ::bluetooth::facade::BluetoothAddress;
+using ::bluetooth::facade::BluetoothAddressTypeEnum;
+using ::bluetooth::facade::EventStreamRequest;
+using ::bluetooth::grpc::GrpcEventStream;
+using ::bluetooth::grpc::GrpcEventStreamCallback;
+
+hci::GapData GapDataFromProto(const GapData& gap_data_proto) {
+ hci::GapData gap_data;
+ auto data_copy = std::make_shared<std::vector<uint8_t>>(gap_data_proto.data().begin(), gap_data_proto.data().end());
+ packet::PacketView<packet::kLittleEndian> packet(data_copy);
+ auto after = hci::GapData::Parse(&gap_data, packet.begin());
+ ASSERT(after != packet.begin());
+ return gap_data;
+}
+
+bool AdvertisingConfigFromProto(const AdvertisingConfig& config_proto, hci::AdvertisingConfig* config) {
+ for (const auto& elem : config_proto.advertisement()) {
+ config->advertisement.push_back(GapDataFromProto(elem));
+ }
+
+ for (const auto& elem : config_proto.scan_response()) {
+ config->scan_response.push_back(GapDataFromProto(elem));
+ }
+
+ hci::Address::FromString(config_proto.random_address().address(), config->random_address);
+
+ if (config_proto.interval_min() > UINT16_MAX || config_proto.interval_min() < 0) {
+ LOG_WARN("Bad interval_min: %d", config_proto.interval_min());
+ return false;
+ }
+ config->interval_min = static_cast<uint16_t>(config_proto.interval_min());
+
+ if (config_proto.interval_max() > UINT16_MAX || config_proto.interval_max() < 0) {
+ LOG_WARN("Bad interval_max: %d", config_proto.interval_max());
+ return false;
+ }
+ config->interval_max = static_cast<uint16_t>(config_proto.interval_max());
+
+ config->event_type = static_cast<hci::AdvertisingEventType>(config_proto.event_type());
+
+ config->address_type = static_cast<::bluetooth::hci::AddressType>(config_proto.address_type());
+
+ config->peer_address_type = static_cast<::bluetooth::hci::PeerAddressType>(config_proto.peer_address_type());
+
+ hci::Address::FromString(config_proto.peer_address().address(), config->peer_address);
+
+ if (config_proto.channel_map() > UINT8_MAX || config_proto.channel_map() < 0) {
+ LOG_WARN("Bad channel_map: %d", config_proto.channel_map());
+ return false;
+ }
+ config->channel_map = static_cast<uint8_t>(config_proto.channel_map());
+
+ if (config_proto.tx_power() > UINT8_MAX || config_proto.tx_power() < 0) {
+ LOG_WARN("Bad tx_power: %d", config_proto.tx_power());
+ return false;
+ }
+
+ config->filter_policy = static_cast<hci::AdvertisingFilterPolicy>(config_proto.filter_policy());
+
+ config->tx_power = static_cast<uint8_t>(config_proto.tx_power());
+ return true;
+}
+
+class LeAdvertiser {
+ public:
+ LeAdvertiser(hci::AdvertisingConfig config) : config_(std::move(config)) {}
+
+ void ScanCallback(Address address, AddressType address_type) {}
+
+ void TerminatedCallback(ErrorCode error_code, uint8_t, uint8_t) {}
+
+ hci::AdvertiserId GetAdvertiserId() {
+ return id_;
+ }
+
+ void SetAdvertiserId(hci::AdvertiserId id) {
+ id_ = id;
+ }
+
+ private:
+ hci::AdvertiserId id_ = LeAdvertisingManager::kInvalidId;
+ hci::AdvertisingConfig config_;
+};
+
+class LeAdvertisingManagerFacadeService : public LeAdvertisingManagerFacade::Service {
+ public:
+ LeAdvertisingManagerFacadeService(LeAdvertisingManager* le_advertising_manager, os::Handler* facade_handler)
+ : le_advertising_manager_(le_advertising_manager), facade_handler_(facade_handler) {
+ ASSERT(le_advertising_manager_ != nullptr);
+ ASSERT(facade_handler_ != nullptr);
+ }
+
+ ::grpc::Status CreateAdvertiser(::grpc::ServerContext* context,
+ const ::bluetooth::hci::facade::CreateAdvertiserRequest* request,
+ ::bluetooth::hci::facade::CreateAdvertiserResponse* response) override {
+ hci::AdvertisingConfig config = {};
+ if (!AdvertisingConfigFromProto(request->config(), &config)) {
+ LOG_WARN("Error parsing advertising config %s", request->SerializeAsString().c_str());
+ response->set_advertiser_id(LeAdvertisingManager::kInvalidId);
+ return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Error while parsing advertising config");
+ }
+ LeAdvertiser le_advertiser(config);
+ auto advertiser_id = le_advertising_manager_->CreateAdvertiser(
+ config, common::Bind(&LeAdvertiser::ScanCallback, common::Unretained(&le_advertiser)),
+ common::Bind(&LeAdvertiser::TerminatedCallback, common::Unretained(&le_advertiser)), facade_handler_);
+ if (advertiser_id != LeAdvertisingManager::kInvalidId) {
+ le_advertiser.SetAdvertiserId(advertiser_id);
+ le_advertisers_.push_back(le_advertiser);
+ } else {
+ LOG_WARN("Failed to create advertiser");
+ }
+ response->set_advertiser_id(advertiser_id);
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status ExtendedCreateAdvertiser(
+ ::grpc::ServerContext* context, const ::bluetooth::hci::facade::ExtendedCreateAdvertiserRequest* request,
+ ::bluetooth::hci::facade::ExtendedCreateAdvertiserResponse* response) override {
+ LOG_WARN("ExtendedCreateAdvertiser is not implemented");
+ response->set_advertiser_id(LeAdvertisingManager::kInvalidId);
+ return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, "ExtendedCreateAdvertiser is not implemented");
+ }
+
+ ::grpc::Status GetNumberOfAdvertisingInstances(
+ ::grpc::ServerContext* context, const ::google::protobuf::Empty* request,
+ ::bluetooth::hci::facade::GetNumberOfAdvertisingInstancesResponse* response) override {
+ response->set_num_advertising_instances(le_advertising_manager_->GetNumberOfAdvertisingInstances());
+ return ::grpc::Status::OK;
+ }
+
+ ::grpc::Status RemoveAdvertiser(::grpc::ServerContext* context,
+ const ::bluetooth::hci::facade::RemoveAdvertiserRequest* request,
+ ::google::protobuf::Empty* response) override {
+ if (request->advertiser_id() == LeAdvertisingManager::kInvalidId) {
+ LOG_WARN("Invalid advertiser ID %d", request->advertiser_id());
+ return ::grpc::Status(::grpc::StatusCode::INVALID_ARGUMENT, "Invlid advertiser ID received");
+ }
+ le_advertising_manager_->RemoveAdvertiser(request->advertiser_id());
+ for (auto iter = le_advertisers_.begin(); iter != le_advertisers_.end();) {
+ if (iter->GetAdvertiserId() == request->advertiser_id()) {
+ iter = le_advertisers_.erase(iter);
+ } else {
+ ++iter;
+ }
+ }
+ return ::grpc::Status::OK;
+ }
+
+ std::vector<LeAdvertiser> le_advertisers_;
+ LeAdvertisingManager* le_advertising_manager_;
+ os::Handler* facade_handler_;
+};
+
+void LeAdvertisingManagerFacadeModule::ListDependencies(ModuleList* list) {
+ ::bluetooth::grpc::GrpcFacadeModule::ListDependencies(list);
+ list->add<hci::LeAdvertisingManager>();
+}
+
+void LeAdvertisingManagerFacadeModule::Start() {
+ ::bluetooth::grpc::GrpcFacadeModule::Start();
+ service_ = new LeAdvertisingManagerFacadeService(GetDependency<hci::LeAdvertisingManager>(), GetHandler());
+}
+
+void LeAdvertisingManagerFacadeModule::Stop() {
+ delete service_;
+ ::bluetooth::grpc::GrpcFacadeModule::Stop();
+}
+
+::grpc::Service* LeAdvertisingManagerFacadeModule::GetService() const {
+ return service_;
+}
+
+const ModuleFactory LeAdvertisingManagerFacadeModule::Factory =
+ ::bluetooth::ModuleFactory([]() { return new LeAdvertisingManagerFacadeModule(); });
+
+} // namespace facade
+} // namespace hci
+} // namespace bluetooth
diff --git a/gd/hci/facade/le_advertising_manager_facade.h b/gd/hci/facade/le_advertising_manager_facade.h
new file mode 100644
index 0000000..721132e
--- /dev/null
+++ b/gd/hci/facade/le_advertising_manager_facade.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <grpc++/grpc++.h>
+
+#include "grpc/grpc_module.h"
+
+namespace bluetooth {
+namespace hci {
+namespace facade {
+
+class LeAdvertisingManagerFacadeService;
+
+class LeAdvertisingManagerFacadeModule : public ::bluetooth::grpc::GrpcFacadeModule {
+ public:
+ static const ModuleFactory Factory;
+
+ void ListDependencies(ModuleList* list) override;
+ void Start() override;
+ void Stop() override;
+
+ ::grpc::Service* GetService() const override;
+
+ private:
+ LeAdvertisingManagerFacadeService* service_;
+};
+
+} // namespace facade
+} // namespace hci
+} // namespace bluetooth
\ No newline at end of file
diff --git a/gd/hci/facade/le_advertising_manager_facade.proto b/gd/hci/facade/le_advertising_manager_facade.proto
new file mode 100644
index 0000000..f3fdca5
--- /dev/null
+++ b/gd/hci/facade/le_advertising_manager_facade.proto
@@ -0,0 +1,90 @@
+syntax = "proto3";
+
+package bluetooth.hci.facade;
+
+import "google/protobuf/empty.proto";
+import "facade/common.proto";
+
+service LeAdvertisingManagerFacade {
+ rpc CreateAdvertiser(CreateAdvertiserRequest) returns (CreateAdvertiserResponse) {}
+ rpc ExtendedCreateAdvertiser(ExtendedCreateAdvertiserRequest) returns (ExtendedCreateAdvertiserResponse) {}
+ rpc GetNumberOfAdvertisingInstances(google.protobuf.Empty) returns (GetNumberOfAdvertisingInstancesResponse) {}
+ rpc RemoveAdvertiser(RemoveAdvertiserRequest) returns (google.protobuf.Empty) {}
+}
+
+message GapData {
+ bytes data = 1;
+}
+
+enum AdvertisingEventType {
+ ADV_IND = 0x0;
+ ADV_DIRECT_IND = 0x1;
+ ADV_SCAN_IND = 0x2;
+ ADV_NONCONN_IND = 0x3;
+ ADV_DIRECT_IND_LOW = 0x4;
+}
+
+enum AdvertisingFilterPolicy {
+ ALL_DEVICES = 0x0;
+ WHITELISTED_SCAN = 0x1;
+ WHITELISTED_CONNECT = 0x2;
+ WHITELISTED_SCAN_AND_CONNECT = 0x3;
+};
+
+message AdvertisingConfig {
+ repeated GapData advertisement = 1;
+ repeated GapData scan_response = 2;
+ bluetooth.facade.BluetoothAddress random_address = 3;
+ // Unit: number of Bluetooth slots in 0.125 ms increment
+ int32 interval_min = 4;
+ // Unit: number of Bluetooth slots in 0.125 ms increment
+ int32 interval_max = 5;
+ AdvertisingEventType event_type = 6;
+ bluetooth.facade.BluetoothAddressTypeEnum address_type = 7;
+ bluetooth.facade.BluetoothPeerAddressTypeEnum peer_address_type = 8;
+ bluetooth.facade.BluetoothAddress peer_address = 9;
+ int32 channel_map = 10;
+ AdvertisingFilterPolicy filter_policy = 11;
+ int32 tx_power = 12;
+}
+
+message ExtendedAdvertisingConfig {
+ AdvertisingConfig advertising_config = 1;
+ bool connectable = 2;
+ bool scannable = 3;
+ bool directed = 4;
+ bool high_duty_directed_connectable = 5;
+ bool legacy_pdus = 6;
+ bool anonymous = 7;
+ bool include_tx_power = 8;
+ bool use_le_coded_phy = 9;
+ int32 secondary_map_skip = 10;
+ int32 secondary_advertising_phy = 11;
+ int32 sid = 12;
+ bool enable_scan_request_notification = 13;
+}
+
+message CreateAdvertiserRequest {
+ AdvertisingConfig config = 1;
+}
+
+message CreateAdvertiserResponse {
+ // -1 on error
+ int32 advertiser_id = 1;
+}
+
+message ExtendedCreateAdvertiserRequest {
+ ExtendedAdvertisingConfig config = 1;
+}
+
+message ExtendedCreateAdvertiserResponse {
+ int32 advertiser_id = 1;
+}
+
+message GetNumberOfAdvertisingInstancesResponse {
+ int32 num_advertising_instances = 1;
+}
+
+message RemoveAdvertiserRequest {
+ int32 advertiser_id = 1;
+}
\ No newline at end of file
diff --git a/gd/packet/parser/fields/fixed_field.cc b/gd/packet/parser/fields/fixed_field.cc
index c728797..a307653 100644
--- a/gd/packet/parser/fields/fixed_field.cc
+++ b/gd/packet/parser/fields/fixed_field.cc
@@ -28,6 +28,10 @@
s << "public:\n";
}
+std::string FixedField::GetBuilderParameterType() const {
+ return "";
+}
+
bool FixedField::GenBuilderParameter(std::ostream&) const {
// No parameter needed for a fixed field.
return false;
diff --git a/gd/packet/parser/fields/fixed_field.h b/gd/packet/parser/fields/fixed_field.h
index 41ffa0f..c2b2b7b 100644
--- a/gd/packet/parser/fields/fixed_field.h
+++ b/gd/packet/parser/fields/fixed_field.h
@@ -33,6 +33,8 @@
virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ virtual std::string GetBuilderParameterType() const override;
+
virtual bool GenBuilderParameter(std::ostream&) const override;
virtual bool HasParameterValidator() const override;
diff --git a/gd/packet/parser/fields/size_field.cc b/gd/packet/parser/fields/size_field.cc
index eafb139..0a1b80b 100644
--- a/gd/packet/parser/fields/size_field.cc
+++ b/gd/packet/parser/fields/size_field.cc
@@ -32,6 +32,10 @@
s << "public:\n";
}
+std::string SizeField::GetBuilderParameterType() const {
+ return "";
+}
+
bool SizeField::GenBuilderParameter(std::ostream&) const {
// There is no builder parameter for a size field
return false;
diff --git a/gd/packet/parser/fields/size_field.h b/gd/packet/parser/fields/size_field.h
index 859be5a..b6e8639 100644
--- a/gd/packet/parser/fields/size_field.h
+++ b/gd/packet/parser/fields/size_field.h
@@ -32,6 +32,8 @@
virtual void GenGetter(std::ostream& s, Size start_offset, Size end_offset) const override;
+ virtual std::string GetBuilderParameterType() const override;
+
virtual bool GenBuilderParameter(std::ostream&) const override;
virtual bool HasParameterValidator() const override;
diff --git a/gd/packet/parser/struct_def.cc b/gd/packet/parser/struct_def.cc
index bdeb780..16ef742 100644
--- a/gd/packet/parser/struct_def.cc
+++ b/gd/packet/parser/struct_def.cc
@@ -193,8 +193,19 @@
}
s << ">(m, \"" << name_ << "\")";
s << ".def(py::init<>())";
- s << ".def(\"Serialize\", &" << GetTypeName() << "::Serialize)";
+ s << ".def(\"Serialize\", [](" << GetTypeName() << "& obj){";
+ s << "std::vector<uint8_t> bytes;";
+ s << "BitInserter bi(bytes);";
+ s << "obj.Serialize(bi);";
+ s << "return bytes;})";
s << ".def(\"Parse\", &" << name_ << "::Parse)";
+ s << ".def(\"size\", &" << name_ << "::size)";
+ for (const auto& field : fields_) {
+ if (field->GetBuilderParameterType().empty()) {
+ continue;
+ }
+ s << ".def_readwrite(\"" << field->GetName() << "\", &" << name_ << "::" << field->GetName() << "_)";
+ }
s << ";\n";
}