summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrkc <rkc@chromium.org>2015-04-16 12:27:24 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-16 19:27:47 +0000
commit3c011dd0a4d682397b7a1f3c9b786db68d7e967b (patch)
treef161667621239b426e3212fd07177a0e05e46010
parent04ab34e0e1833a71258962285ab1649eae951e0c (diff)
downloadchromium_src-3c011dd0a4d682397b7a1f3c9b786db68d7e967b.zip
chromium_src-3c011dd0a4d682397b7a1f3c9b786db68d7e967b.tar.gz
chromium_src-3c011dd0a4d682397b7a1f3c9b786db68d7e967b.tar.bz2
Add DBus bindings for BLE Advertisement.
This CL adds the DBus bindings needed to be able to host BLE advertisment objects and register those advertisements with BlueZ. R=armansito@chromium.org, jamuraa@chromium.org BUG=466375 Review URL: https://codereview.chromium.org/1052363005 Cr-Commit-Position: refs/heads/master@{#325497}
-rw-r--r--chromeos/chromeos.gyp8
-rw-r--r--chromeos/dbus/bluetooth_le_advertisement_service_provider.cc414
-rw-r--r--chromeos/dbus/bluetooth_le_advertisement_service_provider.h76
-rw-r--r--chromeos/dbus/bluetooth_le_advertising_manager_client.cc187
-rw-r--r--chromeos/dbus/bluetooth_le_advertising_manager_client.h83
-rw-r--r--chromeos/dbus/dbus_client_bundle.cc6
-rw-r--r--chromeos/dbus/dbus_client_bundle.h8
-rw-r--r--chromeos/dbus/dbus_thread_manager.cc12
-rw-r--r--chromeos/dbus/dbus_thread_manager.h4
-rw-r--r--chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc45
-rw-r--r--chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h52
-rw-r--r--chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc107
-rw-r--r--chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h79
13 files changed, 1081 insertions, 0 deletions
diff --git a/chromeos/chromeos.gyp b/chromeos/chromeos.gyp
index 41a30f8..a5df534 100644
--- a/chromeos/chromeos.gyp
+++ b/chromeos/chromeos.gyp
@@ -61,6 +61,10 @@
'dbus/blocking_method_caller.h',
'dbus/bluetooth_adapter_client.cc',
'dbus/bluetooth_adapter_client.h',
+ 'dbus/bluetooth_le_advertising_manager_client.cc',
+ 'dbus/bluetooth_le_advertising_manager_client.h',
+ 'dbus/bluetooth_le_advertisement_service_provider.cc',
+ 'dbus/bluetooth_le_advertisement_service_provider.h',
'dbus/bluetooth_agent_manager_client.cc',
'dbus/bluetooth_agent_manager_client.h',
'dbus/bluetooth_agent_service_provider.cc',
@@ -118,6 +122,10 @@
'dbus/fake_audio_dsp_client.h',
'dbus/fake_bluetooth_adapter_client.cc',
'dbus/fake_bluetooth_adapter_client.h',
+ 'dbus/fake_bluetooth_le_advertising_manager_client.cc',
+ 'dbus/fake_bluetooth_le_advertising_manager_client.h',
+ 'dbus/fake_bluetooth_le_advertisement_service_provider.cc',
+ 'dbus/fake_bluetooth_le_advertisement_service_provider.h',
'dbus/fake_bluetooth_agent_manager_client.cc',
'dbus/fake_bluetooth_agent_manager_client.h',
'dbus/fake_bluetooth_agent_service_provider.cc',
diff --git a/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc b/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc
new file mode 100644
index 0000000..aa3f234
--- /dev/null
+++ b/chromeos/dbus/bluetooth_le_advertisement_service_provider.cc
@@ -0,0 +1,414 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/stl_util.h"
+#include "base/threading/platform_thread.h"
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h"
+#include "dbus/exported_object.h"
+#include "dbus/message.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+namespace {
+const char kErrorInvalidArgs[] = "org.freedesktop.DBus.Error.InvalidArgs";
+} // namespace
+
+// The BluetoothAdvertisementServiceProvider implementation used in production.
+class BluetoothAdvertisementServiceProviderImpl
+ : public BluetoothLEAdvertisementServiceProvider {
+ public:
+ BluetoothAdvertisementServiceProviderImpl(
+ dbus::Bus* bus,
+ const dbus::ObjectPath& object_path,
+ Delegate* delegate,
+ AdvertisementType type,
+ scoped_ptr<UUIDList> service_uuids,
+ scoped_ptr<ManufacturerData> manufacturer_data,
+ scoped_ptr<UUIDList> solicit_uuids,
+ scoped_ptr<ServiceData> service_data)
+ : origin_thread_id_(base::PlatformThread::CurrentId()),
+ bus_(bus),
+ delegate_(delegate),
+ object_path_(object_path),
+ type_(type),
+ service_uuids_(service_uuids.Pass()),
+ manufacturer_data_(manufacturer_data.Pass()),
+ solicit_uuids_(solicit_uuids.Pass()),
+ service_data_(service_data.Pass()),
+ weak_ptr_factory_(this) {
+ DCHECK(bus);
+ DCHECK(delegate);
+
+ VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value();
+
+ exported_object_ = bus_->GetExportedObject(object_path_);
+
+ // Export Bluetooth Advertisement interface methods.
+ exported_object_->ExportMethod(
+ bluetooth_advertisement::kBluetoothAdvertisementIntervace,
+ bluetooth_advertisement::kRelease,
+ base::Bind(&BluetoothAdvertisementServiceProviderImpl::Release,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ // Export dbus property methods.
+ exported_object_->ExportMethod(
+ dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGet,
+ base::Bind(&BluetoothAdvertisementServiceProviderImpl::Get,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ exported_object_->ExportMethod(
+ dbus::kDBusPropertiesInterface, dbus::kDBusPropertiesGetAll,
+ base::Bind(&BluetoothAdvertisementServiceProviderImpl::GetAll,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&BluetoothAdvertisementServiceProviderImpl::OnExported,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ ~BluetoothAdvertisementServiceProviderImpl() override {
+ VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value();
+
+ // Unregister the object path so we can reuse with a new agent.
+ bus_->UnregisterExportedObject(object_path_);
+ }
+
+ private:
+ // Returns true if the current thread is on the origin thread.
+ bool OnOriginThread() {
+ return base::PlatformThread::CurrentId() == origin_thread_id_;
+ }
+
+ // Called by dbus:: when this advertisement is unregistered from the Bluetooth
+ // daemon, generally by our request.
+ void Release(dbus::MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender) {
+ DCHECK(OnOriginThread());
+ DCHECK(delegate_);
+
+ delegate_->Released();
+ }
+
+ // Called by dbus:: when the Bluetooth daemon fetches a single property of
+ // the descriptor.
+ void Get(dbus::MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender) {
+ VLOG(2) << "BluetoothAdvertisementServiceProvider::Get: "
+ << object_path_.value();
+ DCHECK(OnOriginThread());
+
+ dbus::MessageReader reader(method_call);
+
+ std::string interface_name;
+ std::string property_name;
+ if (!reader.PopString(&interface_name) ||
+ !reader.PopString(&property_name) || reader.HasMoreData()) {
+ scoped_ptr<dbus::ErrorResponse> error_response =
+ dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+ "Expected 'ss'.");
+ response_sender.Run(error_response.Pass());
+ return;
+ }
+
+ // Only the advertisement interface is supported.
+ if (interface_name !=
+ bluetooth_advertisement::kBluetoothAdvertisementIntervace) {
+ scoped_ptr<dbus::ErrorResponse> error_response =
+ dbus::ErrorResponse::FromMethodCall(
+ method_call, kErrorInvalidArgs,
+ "No such interface: '" + interface_name + "'.");
+ response_sender.Run(error_response.Pass());
+ return;
+ }
+
+ scoped_ptr<dbus::Response> response =
+ dbus::Response::FromMethodCall(method_call);
+ dbus::MessageWriter writer(response.get());
+ dbus::MessageWriter variant_writer(NULL);
+
+ if (property_name == bluetooth_advertisement::kTypeProperty) {
+ writer.OpenVariant("s", &variant_writer);
+ if (type_ == ADVERTISEMENT_TYPE_BROADCAST) {
+ variant_writer.AppendString("broadcast");
+ } else {
+ variant_writer.AppendString("peripheral");
+ }
+ } else if ((property_name ==
+ bluetooth_advertisement::kServiceUUIDsProperty) &&
+ service_uuids_) {
+ writer.OpenVariant("as", &variant_writer);
+ variant_writer.AppendArrayOfStrings(*service_uuids_);
+ } else if ((property_name ==
+ bluetooth_advertisement::kSolicitUUIDsProperty) &&
+ solicit_uuids_) {
+ writer.OpenVariant("as", &variant_writer);
+ variant_writer.AppendArrayOfStrings(*solicit_uuids_);
+ } else if ((property_name ==
+ bluetooth_advertisement::kManufacturerDataProperty) &&
+ manufacturer_data_) {
+ writer.OpenVariant("o", &variant_writer);
+ AppendManufacturerDataVariant(&variant_writer);
+ } else if ((property_name ==
+ bluetooth_advertisement::kServiceDataProperty) &&
+ service_data_) {
+ writer.OpenVariant("o", &variant_writer);
+ AppendServiceDataVariant(&variant_writer);
+ } else {
+ scoped_ptr<dbus::ErrorResponse> error_response =
+ dbus::ErrorResponse::FromMethodCall(
+ method_call, kErrorInvalidArgs,
+ "No such property: '" + property_name + "'.");
+ response_sender.Run(error_response.Pass());
+ }
+
+ writer.CloseContainer(&variant_writer);
+ response_sender.Run(response.Pass());
+ }
+
+ // Called by dbus:: when the Bluetooth daemon fetches all properties of the
+ // descriptor.
+ void GetAll(dbus::MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender) {
+ VLOG(2) << "BluetoothAdvertisementServiceProvider::GetAll: "
+ << object_path_.value();
+ DCHECK(OnOriginThread());
+
+ dbus::MessageReader reader(method_call);
+
+ std::string interface_name;
+ if (!reader.PopString(&interface_name) || reader.HasMoreData()) {
+ scoped_ptr<dbus::ErrorResponse> error_response =
+ dbus::ErrorResponse::FromMethodCall(method_call, kErrorInvalidArgs,
+ "Expected 's'.");
+ response_sender.Run(error_response.Pass());
+ return;
+ }
+
+ // Only the advertisement interface is supported.
+ if (interface_name !=
+ bluetooth_advertisement::kBluetoothAdvertisementIntervace) {
+ scoped_ptr<dbus::ErrorResponse> error_response =
+ dbus::ErrorResponse::FromMethodCall(
+ method_call, kErrorInvalidArgs,
+ "No such interface: '" + interface_name + "'.");
+ response_sender.Run(error_response.Pass());
+ return;
+ }
+
+ response_sender.Run(CreateGetAllResponse(method_call).Pass());
+ }
+
+ // Called by dbus:: when a method is exported.
+ void OnExported(const std::string& interface_name,
+ const std::string& method_name,
+ bool success) {
+ LOG_IF(WARNING, !success) << "Failed to export " << interface_name << "."
+ << method_name;
+ }
+
+ // Helper for populating the DBus response with the advertisement data.
+ scoped_ptr<dbus::Response> CreateGetAllResponse(
+ dbus::MethodCall* method_call) {
+ VLOG(2) << "Descriptor value obtained from delegate. Responding to "
+ << "GetAll.";
+
+ scoped_ptr<dbus::Response> response =
+ dbus::Response::FromMethodCall(method_call);
+
+ dbus::MessageWriter writer(response.get());
+ dbus::MessageWriter array_writer(NULL);
+
+ writer.OpenArray("{sv}", &array_writer);
+
+ AppendType(&array_writer);
+ AppendServiceUUIDs(&array_writer);
+ AppendManufacturerData(&array_writer);
+ AppendSolicitUUIDs(&array_writer);
+ AppendServiceData(&array_writer);
+
+ writer.CloseContainer(&array_writer);
+ return response;
+ }
+
+ // Called by the Delegate in response to a successful method call to get the
+ // descriptor value.
+ void OnGet(dbus::MethodCall* method_call,
+ dbus::ExportedObject::ResponseSender response_sender,
+ const std::vector<uint8>& value) {
+ VLOG(2) << "Returning descriptor value obtained from delegate.";
+ scoped_ptr<dbus::Response> response =
+ dbus::Response::FromMethodCall(method_call);
+ dbus::MessageWriter writer(response.get());
+ dbus::MessageWriter variant_writer(NULL);
+
+ writer.OpenVariant("ay", &variant_writer);
+ variant_writer.AppendArrayOfBytes(value.data(), value.size());
+ writer.CloseContainer(&variant_writer);
+
+ response_sender.Run(response.Pass());
+ }
+
+ void AppendType(dbus::MessageWriter* array_writer) {
+ dbus::MessageWriter dict_entry_writer(NULL);
+ array_writer->OpenDictEntry(&dict_entry_writer);
+ dict_entry_writer.AppendString(bluetooth_advertisement::kTypeProperty);
+ if (type_ == ADVERTISEMENT_TYPE_BROADCAST) {
+ dict_entry_writer.AppendString("broadcast");
+ } else {
+ dict_entry_writer.AppendString("peripheral");
+ }
+ array_writer->CloseContainer(&dict_entry_writer);
+ }
+
+ void AppendServiceUUIDs(dbus::MessageWriter* array_writer) {
+ dbus::MessageWriter dict_entry_writer(NULL);
+ array_writer->OpenDictEntry(&dict_entry_writer);
+ dict_entry_writer.AppendString(
+ bluetooth_advertisement::kServiceUUIDsProperty);
+ dict_entry_writer.AppendArrayOfStrings(*service_uuids_);
+ array_writer->CloseContainer(&dict_entry_writer);
+ }
+
+ void AppendManufacturerData(dbus::MessageWriter* array_writer) {
+ dbus::MessageWriter dict_entry_writer(NULL);
+ array_writer->OpenDictEntry(&dict_entry_writer);
+ dict_entry_writer.AppendString(
+ bluetooth_advertisement::kManufacturerDataProperty);
+ dbus::MessageWriter variant_writer(NULL);
+ dict_entry_writer.OpenVariant("a{qay}", &variant_writer);
+ AppendManufacturerDataVariant(&variant_writer);
+ dict_entry_writer.CloseContainer(&variant_writer);
+ array_writer->CloseContainer(&dict_entry_writer);
+ }
+
+ void AppendSolicitUUIDs(dbus::MessageWriter* array_writer) {
+ dbus::MessageWriter dict_entry_writer(NULL);
+ array_writer->OpenDictEntry(&dict_entry_writer);
+ dict_entry_writer.AppendString(
+ bluetooth_advertisement::kSolicitUUIDsProperty);
+ dict_entry_writer.AppendArrayOfStrings(*solicit_uuids_);
+ array_writer->CloseContainer(&dict_entry_writer);
+ }
+
+ void AppendServiceData(dbus::MessageWriter* array_writer) {
+ dbus::MessageWriter dict_entry_writer(NULL);
+ array_writer->OpenDictEntry(&dict_entry_writer);
+ dict_entry_writer.AppendString(
+ bluetooth_advertisement::kServiceDataProperty);
+ dbus::MessageWriter variant_writer(NULL);
+ dict_entry_writer.OpenVariant("a{say}", &variant_writer);
+ AppendServiceDataVariant(&variant_writer);
+ dict_entry_writer.CloseContainer(&variant_writer);
+ array_writer->CloseContainer(&dict_entry_writer);
+ }
+
+ void AppendManufacturerDataVariant(dbus::MessageWriter* writer) {
+ dbus::MessageWriter array_writer(NULL);
+ writer->OpenArray("{qay}", &array_writer);
+ for (const auto& m : *manufacturer_data_) {
+ dbus::MessageWriter entry_writer(NULL);
+
+ array_writer.OpenDictEntry(&entry_writer);
+
+ entry_writer.AppendUint32(m.first);
+ entry_writer.AppendArrayOfBytes(vector_as_array(&m.second),
+ m.second.size());
+
+ array_writer.CloseContainer(&entry_writer);
+ }
+ writer->CloseContainer(&array_writer);
+ }
+
+ void AppendServiceDataVariant(dbus::MessageWriter* writer) {
+ dbus::MessageWriter array_writer(NULL);
+ writer->OpenArray("{say}", &array_writer);
+ for (const auto& m : *service_data_) {
+ dbus::MessageWriter entry_writer(NULL);
+
+ array_writer.OpenDictEntry(&entry_writer);
+
+ entry_writer.AppendString(m.first);
+ entry_writer.AppendArrayOfBytes(vector_as_array(&m.second),
+ m.second.size());
+
+ array_writer.CloseContainer(&entry_writer);
+ }
+ writer->CloseContainer(&array_writer);
+ }
+
+ // Origin thread (i.e. the UI thread in production).
+ base::PlatformThreadId origin_thread_id_;
+
+ // D-Bus bus object is exported on, not owned by this object and must
+ // outlive it.
+ dbus::Bus* bus_;
+
+ // All incoming method calls are passed on to the Delegate and a callback
+ // passed to generate the reply. |delegate_| is generally the object that
+ // owns this one, and must outlive it.
+ Delegate* delegate_;
+
+ // D-Bus object path of object we are exporting, kept so we can unregister
+ // again in our destructor.
+ dbus::ObjectPath object_path_;
+
+ // Advertisement data that needs to be provided to BlueZ when requested.
+ AdvertisementType type_;
+ scoped_ptr<UUIDList> service_uuids_;
+ scoped_ptr<ManufacturerData> manufacturer_data_;
+ scoped_ptr<UUIDList> solicit_uuids_;
+ scoped_ptr<ServiceData> service_data_;
+
+ // D-Bus object we are exporting, owned by this object.
+ scoped_refptr<dbus::ExportedObject> exported_object_;
+
+ // Weak pointer factory for generating 'this' pointers that might live longer
+ // than we do.
+ // Note: This should remain the last member so it'll be destroyed and
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<BluetoothAdvertisementServiceProviderImpl>
+ weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementServiceProviderImpl);
+};
+
+BluetoothLEAdvertisementServiceProvider::
+ BluetoothLEAdvertisementServiceProvider() {
+}
+
+BluetoothLEAdvertisementServiceProvider::
+ ~BluetoothLEAdvertisementServiceProvider() {
+}
+
+// static
+BluetoothLEAdvertisementServiceProvider*
+BluetoothLEAdvertisementServiceProvider::Create(
+ dbus::Bus* bus,
+ const dbus::ObjectPath& object_path,
+ Delegate* delegate,
+ AdvertisementType type,
+ scoped_ptr<UUIDList> service_uuids,
+ scoped_ptr<ManufacturerData> manufacturer_data,
+ scoped_ptr<UUIDList> solicit_uuids,
+ scoped_ptr<ServiceData> service_data) {
+ if (!DBusThreadManager::Get()->IsUsingStub(DBusClientBundle::BLUETOOTH)) {
+ return new BluetoothAdvertisementServiceProviderImpl(
+ bus, object_path, delegate, type, service_uuids.Pass(),
+ manufacturer_data.Pass(), solicit_uuids.Pass(), service_data.Pass());
+ } else {
+ return new FakeBluetoothLEAdvertisementServiceProvider(object_path,
+ delegate);
+ }
+}
+
+} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_le_advertisement_service_provider.h b/chromeos/dbus/bluetooth_le_advertisement_service_provider.h
new file mode 100644
index 0000000..4cea5d8
--- /dev/null
+++ b/chromeos/dbus/bluetooth_le_advertisement_service_provider.h
@@ -0,0 +1,76 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+#define CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+
+#include <stdint.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "dbus/bus.h"
+#include "dbus/file_descriptor.h"
+#include "dbus/object_path.h"
+
+namespace chromeos {
+
+// BluetoothAdvertisementServiceProvider is used to provide a D-Bus object that
+// the Bluetooth daemon can communicate with to advertise data.
+class CHROMEOS_EXPORT BluetoothLEAdvertisementServiceProvider {
+ public:
+ using UUIDList = std::vector<std::string>;
+ using ManufacturerData = std::map<uint16_t, std::vector<uint8_t>>;
+ using ServiceData = std::map<std::string, std::vector<uint8_t>>;
+
+ // Type of advertisement.
+ enum AdvertisementType {
+ ADVERTISEMENT_TYPE_BROADCAST,
+ ADVERTISEMENT_TYPE_PERIPHERAL
+ };
+
+ // Interface for reacting to advertisement changes.
+ class Delegate {
+ public:
+ virtual ~Delegate() {}
+
+ // This method will be called when the advertisement is unregistered from
+ // the Bluetooth daemon, generally at shutdown or if the adapter goes away.
+ // It may be used to perform cleanup tasks. This corresponds to the
+ // org.bluez.LEAdvertisement1.Release method and is renamed to avoid a
+ // conflict with base::Refcounted<T>.
+ virtual void Released() = 0;
+ };
+
+ virtual ~BluetoothLEAdvertisementServiceProvider();
+
+ // Creates the instance where |bus| is the D-Bus bus connection to export
+ // the object onto, |object_path| is the object path that it should have
+ // and |delegate| is the object to which all method calls will be passed
+ // and responses generated from.
+ static BluetoothLEAdvertisementServiceProvider* Create(
+ dbus::Bus* bus,
+ const dbus::ObjectPath& object_path,
+ Delegate* delegate,
+ AdvertisementType type,
+ scoped_ptr<UUIDList> service_uuids,
+ scoped_ptr<ManufacturerData> manufacturer_data,
+ scoped_ptr<UUIDList> solicit_uuids,
+ scoped_ptr<ServiceData> service_data);
+
+ protected:
+ BluetoothLEAdvertisementServiceProvider();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisementServiceProvider);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/bluetooth_le_advertising_manager_client.cc b/chromeos/dbus/bluetooth_le_advertising_manager_client.cc
new file mode 100644
index 0000000..00f4f67
--- /dev/null
+++ b/chromeos/dbus/bluetooth_le_advertising_manager_client.cc
@@ -0,0 +1,187 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/observer_list.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_manager.h"
+#include "dbus/object_proxy.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+const char BluetoothLEAdvertisingManagerClient::kNoResponseError[] =
+ "org.chromium.Error.NoResponse";
+
+// The BluetoothAdvertisementManagerClient implementation used in production.
+class BluetoothAdvertisementManagerClientImpl
+ : public BluetoothLEAdvertisingManagerClient,
+ public dbus::ObjectManager::Interface {
+ public:
+ BluetoothAdvertisementManagerClientImpl()
+ : object_manager_(NULL), weak_ptr_factory_(this) {}
+
+ ~BluetoothAdvertisementManagerClientImpl() override {
+ object_manager_->UnregisterInterface(
+ bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface);
+ }
+
+ // BluetoothAdapterClient override.
+ void AddObserver(
+ BluetoothLEAdvertisingManagerClient::Observer* observer) override {
+ DCHECK(observer);
+ observers_.AddObserver(observer);
+ }
+
+ // BluetoothAdapterClient override.
+ void RemoveObserver(
+ BluetoothLEAdvertisingManagerClient::Observer* observer) override {
+ DCHECK(observer);
+ observers_.RemoveObserver(observer);
+ }
+
+ // dbus::ObjectManager::Interface override.
+ dbus::PropertySet* CreateProperties(
+ dbus::ObjectProxy* object_proxy,
+ const dbus::ObjectPath& object_path,
+ const std::string& interface_name) override {
+ return new dbus::PropertySet(object_proxy, interface_name,
+ dbus::PropertySet::PropertyChangedCallback());
+ }
+
+ // BluetoothAdvertisementManagerClient override.
+ void RegisterAdvertisement(const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) override {
+ dbus::MethodCall method_call(
+ bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface,
+ bluetooth_advertising_manager::kRegisterAdvertisement);
+
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendObjectPath(advertisement_object_path);
+
+ // Empty dictionary for options.
+ dbus::MessageWriter dict_entry_writer(NULL);
+ writer.OpenDictEntry(&dict_entry_writer);
+ writer.CloseContainer(&dict_entry_writer);
+
+ writer.AppendObjectPath(advertisement_object_path);
+
+ dbus::ObjectProxy* object_proxy =
+ object_manager_->GetObjectProxy(manager_object_path);
+ object_proxy->CallMethodWithErrorCallback(
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&BluetoothAdvertisementManagerClientImpl::OnSuccess,
+ weak_ptr_factory_.GetWeakPtr(), callback),
+ base::Bind(&BluetoothAdvertisementManagerClientImpl::OnError,
+ weak_ptr_factory_.GetWeakPtr(), error_callback));
+ }
+
+ // BluetoothAdvertisementManagerClient override.
+ void UnregisterAdvertisement(
+ const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) override {
+ dbus::MethodCall method_call(
+ bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface,
+ bluetooth_advertising_manager::kUnregisterAdvertisement);
+
+ dbus::MessageWriter writer(&method_call);
+ writer.AppendObjectPath(advertisement_object_path);
+
+ dbus::ObjectProxy* object_proxy =
+ object_manager_->GetObjectProxy(manager_object_path);
+ object_proxy->CallMethodWithErrorCallback(
+ &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
+ base::Bind(&BluetoothAdvertisementManagerClientImpl::OnSuccess,
+ weak_ptr_factory_.GetWeakPtr(), callback),
+ base::Bind(&BluetoothAdvertisementManagerClientImpl::OnError,
+ weak_ptr_factory_.GetWeakPtr(), error_callback));
+ }
+
+ protected:
+ void Init(dbus::Bus* bus) override {
+ DCHECK(bus);
+ object_manager_ = bus->GetObjectManager(
+ bluetooth_object_manager::kBluetoothObjectManagerServiceName,
+ dbus::ObjectPath(
+ bluetooth_object_manager::kBluetoothObjectManagerServicePath));
+ object_manager_->RegisterInterface(
+ bluetooth_advertising_manager::kBluetoothAdvertisingManagerInterface,
+ this);
+ }
+
+ private:
+ // Called by dbus::ObjectManager when an object with the advertising manager
+ // interface is created. Informs observers.
+ void ObjectAdded(const dbus::ObjectPath& object_path,
+ const std::string& interface_name) override {
+ FOR_EACH_OBSERVER(BluetoothLEAdvertisingManagerClient::Observer, observers_,
+ AdvertisingManagerAdded(object_path));
+ }
+
+ // Called by dbus::ObjectManager when an object with the advertising manager
+ // interface is removed. Informs observers.
+ void ObjectRemoved(const dbus::ObjectPath& object_path,
+ const std::string& interface_name) override {
+ FOR_EACH_OBSERVER(BluetoothLEAdvertisingManagerClient::Observer, observers_,
+ AdvertisingManagerRemoved(object_path));
+ }
+
+ // Called when a response for successful method call is received.
+ void OnSuccess(const base::Closure& callback, dbus::Response* response) {
+ DCHECK(response);
+ callback.Run();
+ }
+
+ // Called when a response for a failed method call is received.
+ void OnError(const ErrorCallback& error_callback,
+ dbus::ErrorResponse* response) {
+ // Error response has optional error message argument.
+ std::string error_name;
+ std::string error_message;
+ if (response) {
+ dbus::MessageReader reader(response);
+ error_name = response->GetErrorName();
+ reader.PopString(&error_message);
+ } else {
+ error_name = kNoResponseError;
+ error_message = "";
+ }
+ error_callback.Run(error_name, error_message);
+ }
+
+ dbus::ObjectManager* object_manager_;
+
+ // List of observers interested in event notifications from us.
+ ObserverList<BluetoothLEAdvertisingManagerClient::Observer> observers_;
+
+ // Weak pointer factory for generating 'this' pointers that might live longer
+ // than we do.
+ // Note: This should remain the last member so it'll be destroyed and
+ // invalidate its weak pointers before any other members are destroyed.
+ base::WeakPtrFactory<BluetoothAdvertisementManagerClientImpl>
+ weak_ptr_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(BluetoothAdvertisementManagerClientImpl);
+};
+
+BluetoothLEAdvertisingManagerClient::BluetoothLEAdvertisingManagerClient() {
+}
+
+BluetoothLEAdvertisingManagerClient::~BluetoothLEAdvertisingManagerClient() {
+}
+
+BluetoothLEAdvertisingManagerClient*
+BluetoothLEAdvertisingManagerClient::Create() {
+ return new BluetoothAdvertisementManagerClientImpl();
+}
+
+} // namespace chromeos
diff --git a/chromeos/dbus/bluetooth_le_advertising_manager_client.h b/chromeos/dbus/bluetooth_le_advertising_manager_client.h
new file mode 100644
index 0000000..5160a9f
--- /dev/null
+++ b/chromeos/dbus/bluetooth_le_advertising_manager_client.h
@@ -0,0 +1,83 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+#define CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+
+#include <string>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/values.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/dbus_client.h"
+#include "dbus/object_path.h"
+
+namespace chromeos {
+
+// BluetoothAdvertisingManagerClient is used to communicate with the advertising
+// manager object of the BlueZ daemon.
+class CHROMEOS_EXPORT BluetoothLEAdvertisingManagerClient : public DBusClient {
+ public:
+ // Interface for observing changes to advertising managers.
+ class Observer {
+ public:
+ virtual ~Observer() {}
+
+ // Called when an advertising manager with object path |object_path| is
+ // added to the system.
+ virtual void AdvertisingManagerAdded(const dbus::ObjectPath& object_path) {}
+
+ // Called when an advertising manager with object path |object_path| is
+ // removed from the system.
+ virtual void AdvertisingManagerRemoved(
+ const dbus::ObjectPath& object_path) {}
+ };
+
+ ~BluetoothLEAdvertisingManagerClient() override;
+
+ // Adds and removes observers for events which change the advertising
+ // managers on the system.
+ virtual void AddObserver(Observer* observer) = 0;
+ virtual void RemoveObserver(Observer* observer) = 0;
+
+ // The ErrorCallback is used by advertising manager methods to indicate
+ // failure. It receives two arguments: the name of the error in |error_name|
+ // and an optional message in |error_message|.
+ using ErrorCallback = base::Callback<void(const std::string& error_name,
+ const std::string& error_message)>;
+
+ // Registers an advertisement with the DBus object path
+ // |advertisement_object_path| with BlueZ's advertising manager.
+ virtual void RegisterAdvertisement(
+ const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) = 0;
+
+ // Unregisters an advertisement with the DBus object path
+ // |advertisement_object_path| with BlueZ's advertising manager.
+ virtual void UnregisterAdvertisement(
+ const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) = 0;
+
+ // Creates the instance.
+ static BluetoothLEAdvertisingManagerClient* Create();
+
+ // Constants used to indicate exceptional error conditions.
+ static const char kNoResponseError[];
+
+ protected:
+ BluetoothLEAdvertisingManagerClient();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(BluetoothLEAdvertisingManagerClient);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_DBUS_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
diff --git a/chromeos/dbus/dbus_client_bundle.cc b/chromeos/dbus/dbus_client_bundle.cc
index 608f2e3..3296736 100644
--- a/chromeos/dbus/dbus_client_bundle.cc
+++ b/chromeos/dbus/dbus_client_bundle.cc
@@ -21,6 +21,7 @@
#include "chromeos/dbus/bluetooth_gatt_manager_client.h"
#include "chromeos/dbus/bluetooth_gatt_service_client.h"
#include "chromeos/dbus/bluetooth_input_client.h"
+#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
#include "chromeos/dbus/bluetooth_media_client.h"
#include "chromeos/dbus/bluetooth_media_transport_client.h"
#include "chromeos/dbus/bluetooth_profile_manager_client.h"
@@ -40,6 +41,7 @@
#include "chromeos/dbus/fake_bluetooth_gatt_manager_client.h"
#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h"
#include "chromeos/dbus/fake_bluetooth_input_client.h"
+#include "chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h"
#include "chromeos/dbus/fake_bluetooth_media_client.h"
#include "chromeos/dbus/fake_bluetooth_media_transport_client.h"
#include "chromeos/dbus/fake_bluetooth_profile_manager_client.h"
@@ -161,6 +163,8 @@ DBusClientBundle::DBusClientBundle(DBusClientTypeMask unstub_client_mask)
if (!IsUsingStub(BLUETOOTH)) {
bluetooth_adapter_client_.reset(BluetoothAdapterClient::Create());
+ bluetooth_le_advertising_manager_client_.reset(
+ BluetoothLEAdvertisingManagerClient::Create());
bluetooth_agent_manager_client_.reset(
BluetoothAgentManagerClient::Create());
bluetooth_device_client_.reset(BluetoothDeviceClient::Create());
@@ -180,6 +184,8 @@ DBusClientBundle::DBusClientBundle(DBusClientTypeMask unstub_client_mask)
BluetoothGattServiceClient::Create());
} else {
bluetooth_adapter_client_.reset(new FakeBluetoothAdapterClient);
+ bluetooth_le_advertising_manager_client_.reset(
+ new FakeBluetoothLEAdvertisingManagerClient);
bluetooth_agent_manager_client_.reset(new FakeBluetoothAgentManagerClient);
bluetooth_device_client_.reset(new FakeBluetoothDeviceClient);
bluetooth_input_client_.reset(new FakeBluetoothInputClient);
diff --git a/chromeos/dbus/dbus_client_bundle.h b/chromeos/dbus/dbus_client_bundle.h
index 2801b4f..6db1953 100644
--- a/chromeos/dbus/dbus_client_bundle.h
+++ b/chromeos/dbus/dbus_client_bundle.h
@@ -23,6 +23,7 @@ class BluetoothGattDescriptorClient;
class BluetoothGattManagerClient;
class BluetoothGattServiceClient;
class BluetoothInputClient;
+class BluetoothLEAdvertisingManagerClient;
class BluetoothMediaClient;
class BluetoothMediaTransportClient;
class BluetoothProfileManagerClient;
@@ -123,6 +124,11 @@ class CHROMEOS_EXPORT DBusClientBundle {
return bluetooth_adapter_client_.get();
}
+ BluetoothLEAdvertisingManagerClient*
+ bluetooth_le_advertising_manager_client() {
+ return bluetooth_le_advertising_manager_client_.get();
+ }
+
BluetoothAgentManagerClient* bluetooth_agent_manager_client() {
return bluetooth_agent_manager_client_.get();
}
@@ -296,6 +302,8 @@ class CHROMEOS_EXPORT DBusClientBundle {
scoped_ptr<ApManagerClient> ap_manager_client_;
scoped_ptr<AudioDspClient> audio_dsp_client_;
scoped_ptr<BluetoothAdapterClient> bluetooth_adapter_client_;
+ scoped_ptr<BluetoothLEAdvertisingManagerClient>
+ bluetooth_le_advertising_manager_client_;
scoped_ptr<BluetoothAgentManagerClient> bluetooth_agent_manager_client_;
scoped_ptr<BluetoothDeviceClient> bluetooth_device_client_;
scoped_ptr<BluetoothGattCharacteristicClient>
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc
index 6db36c2..3f55270 100644
--- a/chromeos/dbus/dbus_thread_manager.cc
+++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -19,6 +19,7 @@
#include "chromeos/dbus/bluetooth_gatt_manager_client.h"
#include "chromeos/dbus/bluetooth_gatt_service_client.h"
#include "chromeos/dbus/bluetooth_input_client.h"
+#include "chromeos/dbus/bluetooth_le_advertising_manager_client.h"
#include "chromeos/dbus/bluetooth_media_client.h"
#include "chromeos/dbus/bluetooth_media_transport_client.h"
#include "chromeos/dbus/bluetooth_profile_manager_client.h"
@@ -132,6 +133,11 @@ BluetoothAdapterClient* DBusThreadManager::GetBluetoothAdapterClient() {
return client_bundle_->bluetooth_adapter_client();
}
+BluetoothLEAdvertisingManagerClient*
+DBusThreadManager::GetBluetoothLEAdvertisingManagerClient() {
+ return client_bundle_->bluetooth_le_advertising_manager_client();
+}
+
BluetoothAgentManagerClient*
DBusThreadManager::GetBluetoothAgentManagerClient() {
return client_bundle_->bluetooth_agent_manager_client();
@@ -488,6 +494,12 @@ void DBusThreadManagerSetter::SetBluetoothAdapterClient(
client.Pass();
}
+void DBusThreadManagerSetter::SetBluetoothLEAdvertisingManagerClient(
+ scoped_ptr<BluetoothLEAdvertisingManagerClient> client) {
+ DBusThreadManager::Get()->client_bundle_->
+ bluetooth_le_advertising_manager_client_ = client.Pass();
+}
+
void DBusThreadManagerSetter::SetBluetoothAgentManagerClient(
scoped_ptr<BluetoothAgentManagerClient> client) {
DBusThreadManager::Get()->client_bundle_->bluetooth_agent_manager_client_ =
diff --git a/chromeos/dbus/dbus_thread_manager.h b/chromeos/dbus/dbus_thread_manager.h
index 26d5f86..408d846 100644
--- a/chromeos/dbus/dbus_thread_manager.h
+++ b/chromeos/dbus/dbus_thread_manager.h
@@ -29,6 +29,7 @@ class AmplifierClient;
class ApManagerClient;
class AudioDspClient;
class BluetoothAdapterClient;
+class BluetoothLEAdvertisingManagerClient;
class BluetoothAgentManagerClient;
class BluetoothDeviceClient;
class BluetoothGattCharacteristicClient;
@@ -126,6 +127,7 @@ class CHROMEOS_EXPORT DBusThreadManager {
ApManagerClient* GetApManagerClient();
AudioDspClient* GetAudioDspClient();
BluetoothAdapterClient* GetBluetoothAdapterClient();
+ BluetoothLEAdvertisingManagerClient* GetBluetoothLEAdvertisingManagerClient();
BluetoothAgentManagerClient* GetBluetoothAgentManagerClient();
BluetoothDeviceClient* GetBluetoothDeviceClient();
BluetoothGattCharacteristicClient* GetBluetoothGattCharacteristicClient();
@@ -213,6 +215,8 @@ class CHROMEOS_EXPORT DBusThreadManagerSetter {
void SetAmplifierClient(scoped_ptr<AmplifierClient> client);
void SetAudioDspClient(scoped_ptr<AudioDspClient> client);
void SetBluetoothAdapterClient(scoped_ptr<BluetoothAdapterClient> client);
+ void SetBluetoothLEAdvertisingManagerClient(
+ scoped_ptr<BluetoothLEAdvertisingManagerClient> client);
void SetBluetoothAgentManagerClient(
scoped_ptr<BluetoothAgentManagerClient> client);
void SetBluetoothDeviceClient(scoped_ptr<BluetoothDeviceClient> client);
diff --git a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc b/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc
new file mode 100644
index 0000000..24bfb4f
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.cc
@@ -0,0 +1,45 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chromeos/dbus/dbus_thread_manager.h"
+#include "fake_bluetooth_le_advertisement_service_provider.h"
+#include "fake_bluetooth_le_advertising_manager_client.h"
+
+namespace chromeos {
+
+FakeBluetoothLEAdvertisementServiceProvider::
+ FakeBluetoothLEAdvertisementServiceProvider(
+ const dbus::ObjectPath& object_path,
+ Delegate* delegate)
+ : object_path_(object_path), delegate_(delegate) {
+ VLOG(1) << "Creating Bluetooth Advertisement: " << object_path_.value();
+
+ FakeBluetoothLEAdvertisingManagerClient*
+ fake_bluetooth_profile_manager_client =
+ static_cast<FakeBluetoothLEAdvertisingManagerClient*>(
+ DBusThreadManager::Get()
+ ->GetBluetoothLEAdvertisingManagerClient());
+ fake_bluetooth_profile_manager_client->RegisterAdvertisementServiceProvider(
+ this);
+}
+
+FakeBluetoothLEAdvertisementServiceProvider::
+ ~FakeBluetoothLEAdvertisementServiceProvider() {
+ VLOG(1) << "Cleaning up Bluetooth Advertisement: " << object_path_.value();
+
+ FakeBluetoothLEAdvertisingManagerClient*
+ fake_bluetooth_profile_manager_client =
+ static_cast<FakeBluetoothLEAdvertisingManagerClient*>(
+ DBusThreadManager::Get()
+ ->GetBluetoothLEAdvertisingManagerClient());
+ fake_bluetooth_profile_manager_client->UnregisterAdvertisementServiceProvider(
+ this);
+}
+
+void FakeBluetoothLEAdvertisementServiceProvider::Release() {
+ VLOG(1) << object_path_.value() << ": Release";
+ delegate_->Released();
+}
+
+} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h b/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h
new file mode 100644
index 0000000..c56abb4
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_le_advertisement_service_provider.h
@@ -0,0 +1,52 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+#define CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/memory/scoped_ptr.h"
+#include "chromeos/chromeos_export.h"
+#include "chromeos/dbus/bluetooth_le_advertisement_service_provider.h"
+#include "dbus/file_descriptor.h"
+#include "dbus/object_path.h"
+
+namespace chromeos {
+
+// FakeBluetoothAdvertisementServiceProvider simulates the behavior of a local
+// Bluetooth agent object and is used both in test cases in place of a
+// mock and on the Linux desktop.
+class CHROMEOS_EXPORT FakeBluetoothLEAdvertisementServiceProvider
+ : public BluetoothLEAdvertisementServiceProvider {
+ public:
+ FakeBluetoothLEAdvertisementServiceProvider(
+ const dbus::ObjectPath& object_path,
+ Delegate* delegate);
+ ~FakeBluetoothLEAdvertisementServiceProvider() override;
+
+ // Each of these calls the equivalent
+ // BluetoothAdvertisementServiceProvider::Delegate method on the object passed
+ // on construction.
+ void Release();
+
+ const dbus::ObjectPath& object_path() { return object_path_; }
+
+ private:
+ friend class FakeBluetoothLEAdvertisingManagerClient;
+
+ // D-Bus object path we are faking.
+ dbus::ObjectPath object_path_;
+
+ // All incoming method calls are passed on to the Delegate and a callback
+ // passed to generate the reply. |delegate_| is generally the object that
+ // owns this one, and must outlive it.
+ Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisementServiceProvider);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISEMENT_SERVICE_PROVIDER_H_
diff --git a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc b/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc
new file mode 100644
index 0000000..8145d1c
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.cc
@@ -0,0 +1,107 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "base/message_loop/message_loop.h"
+#include "dbus/bus.h"
+#include "dbus/message.h"
+#include "dbus/object_proxy.h"
+#include "fake_bluetooth_le_advertisement_service_provider.h"
+#include "fake_bluetooth_le_advertising_manager_client.h"
+#include "third_party/cros_system_api/dbus/service_constants.h"
+
+namespace chromeos {
+
+const char FakeBluetoothLEAdvertisingManagerClient::kAdvertisingManagerPath[] =
+ "/fake/hci0";
+
+FakeBluetoothLEAdvertisingManagerClient::
+ FakeBluetoothLEAdvertisingManagerClient() {
+}
+
+FakeBluetoothLEAdvertisingManagerClient::
+ ~FakeBluetoothLEAdvertisingManagerClient() {
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::Init(dbus::Bus* bus) {
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::AddObserver(Observer* observer) {
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::RemoveObserver(
+ Observer* observer) {
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::RegisterAdvertisement(
+ const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) {
+ VLOG(1) << "RegisterAdvertisment: " << advertisement_object_path.value();
+
+ if (manager_object_path != dbus::ObjectPath(kAdvertisingManagerPath)) {
+ error_callback.Run(kNoResponseError, "Invalid Advertising Manager path.");
+ return;
+ }
+
+ ServiceProviderMap::iterator iter =
+ service_provider_map_.find(advertisement_object_path);
+ if (iter == service_provider_map_.end()) {
+ error_callback.Run(bluetooth_advertising_manager::kErrorInvalidArguments,
+ "Advertisement object not registered");
+ } else if (!currently_registered_.value().empty()) {
+ error_callback.Run(bluetooth_advertising_manager::kErrorFailed,
+ "Maximum advertisements reached");
+ } else if (advertisement_object_path != currently_registered_) {
+ error_callback.Run(bluetooth_advertising_manager::kErrorAlreadyExists,
+ "Already advertising.");
+ } else {
+ currently_registered_ = advertisement_object_path;
+ base::MessageLoop::current()->PostTask(FROM_HERE, callback);
+ }
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::UnregisterAdvertisement(
+ const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) {
+ VLOG(1) << "UnregisterAdvertisment: " << advertisement_object_path.value();
+
+ if (manager_object_path != dbus::ObjectPath(kAdvertisingManagerPath)) {
+ error_callback.Run(kNoResponseError, "Invalid Advertising Manager path.");
+ return;
+ }
+
+ ServiceProviderMap::iterator iter =
+ service_provider_map_.find(advertisement_object_path);
+ if (iter == service_provider_map_.end()) {
+ error_callback.Run(bluetooth_advertising_manager::kErrorDoesNotExist,
+ "Advertisement not registered");
+ } else if (advertisement_object_path != currently_registered_) {
+ error_callback.Run(bluetooth_advertising_manager::kErrorDoesNotExist,
+ "Does not exist");
+ } else {
+ currently_registered_ = dbus::ObjectPath("");
+ base::MessageLoop::current()->PostTask(FROM_HERE, callback);
+ }
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::
+ RegisterAdvertisementServiceProvider(
+ FakeBluetoothLEAdvertisementServiceProvider* service_provider) {
+ service_provider_map_[service_provider->object_path_] = service_provider;
+}
+
+void FakeBluetoothLEAdvertisingManagerClient::
+ UnregisterAdvertisementServiceProvider(
+ FakeBluetoothLEAdvertisementServiceProvider* service_provider) {
+ ServiceProviderMap::iterator iter =
+ service_provider_map_.find(service_provider->object_path_);
+ if (iter != service_provider_map_.end() && iter->second == service_provider)
+ service_provider_map_.erase(iter);
+}
+
+} // namespace chromeos
diff --git a/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h b/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h
new file mode 100644
index 0000000..ff340e8
--- /dev/null
+++ b/chromeos/dbus/fake_bluetooth_le_advertising_manager_client.h
@@ -0,0 +1,79 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+#define CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_
+
+#include <map>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/observer_list.h"
+#include "bluetooth_le_advertising_manager_client.h"
+#include "chromeos/chromeos_export.h"
+#include "dbus/object_path.h"
+#include "dbus/property.h"
+
+namespace chromeos {
+
+class FakeBluetoothLEAdvertisementServiceProvider;
+
+// FakeBluetoothAdvertisementManagerClient simulates the behavior of the
+// Bluetooth
+// Daemon's profile manager object and is used both in test cases in place of a
+// mock and on the Linux desktop.
+class CHROMEOS_EXPORT FakeBluetoothLEAdvertisingManagerClient
+ : public BluetoothLEAdvertisingManagerClient {
+ public:
+ FakeBluetoothLEAdvertisingManagerClient();
+ ~FakeBluetoothLEAdvertisingManagerClient() override;
+
+ // DBusClient overrides:
+ void Init(dbus::Bus* bus) override;
+
+ // BluetoothAdvertisingManagerClient overrides:
+ void AddObserver(Observer* observer) override;
+ void RemoveObserver(Observer* observer) override;
+ void RegisterAdvertisement(const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) override;
+ void UnregisterAdvertisement(
+ const dbus::ObjectPath& manager_object_path,
+ const dbus::ObjectPath& advertisement_object_path,
+ const base::Closure& callback,
+ const ErrorCallback& error_callback) override;
+
+ // Register, unregister and retrieve pointers to profile server providers.
+ void RegisterAdvertisementServiceProvider(
+ FakeBluetoothLEAdvertisementServiceProvider* service_provider);
+ void UnregisterAdvertisementServiceProvider(
+ FakeBluetoothLEAdvertisementServiceProvider* service_provider);
+ FakeBluetoothLEAdvertisementServiceProvider* GetAdvertisementServiceProvider(
+ const std::string& uuid);
+
+ // Advertising manager path that we simulate.
+ static const char kAdvertisingManagerPath[];
+
+ private:
+ // Map of a D-Bus object path to the FakeBluetoothAdvertisementServiceProvider
+ // registered for it; maintained by RegisterAdvertisementServiceProvider() and
+ // UnregisterProfileServiceProvicer() called by the constructor and
+ // destructor of FakeBluetoothAdvertisementServiceProvider.
+ typedef std::map<dbus::ObjectPath,
+ FakeBluetoothLEAdvertisementServiceProvider*>
+ ServiceProviderMap;
+ ServiceProviderMap service_provider_map_;
+
+ // Holds the currently registered advertisement. If there is no advertisement
+ // registered, this path is empty.
+ dbus::ObjectPath currently_registered_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeBluetoothLEAdvertisingManagerClient);
+};
+
+} // namespace chromeos
+
+#endif // CHROMEOS_DBUS_FAKE_BLUETOOTH_LE_ADVERTISING_MANAGER_CLIENT_H_