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";
 }