Commit 004c0486 authored by rkc's avatar rkc Committed by Commit bot

Implement BluetoothDeviceBlueZ::GetServiceRecords.

This CL adds the implementation and tests for GetServiceRecords.
The DBus API used here is out for review at,
https://chromium-review.googlesource.com/#/c/354473/

R=mcchou@chromium.org, xiyuan@chromium.org
BUG=619699

Review-Url: https://codereview.chromium.org/2102093003
Cr-Commit-Position: refs/heads/master@{#403324}
parent 02970ff8
......@@ -554,10 +554,13 @@ void BluetoothDeviceBlueZ::CreateGattConnection(
error_callback);
}
std::vector<BluetoothServiceRecordBlueZ*>
BluetoothDeviceBlueZ::GetServiceRecords() {
// TODO(rkc): Implement this.
return std::vector<BluetoothServiceRecordBlueZ*>();
void BluetoothDeviceBlueZ::GetServiceRecords(
const GetServiceRecordsCallback& callback,
const GetServiceRecordsErrorCallback& error_callback) {
bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetServiceRecords(
object_path_, callback,
base::Bind(&BluetoothDeviceBlueZ::OnGetServiceRecordsError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
BluetoothPairingBlueZ* BluetoothDeviceBlueZ::BeginPairing(
......@@ -704,6 +707,21 @@ void BluetoothDeviceBlueZ::OnGetConnInfoError(
callback.Run(ConnectionInfo());
}
void BluetoothDeviceBlueZ::OnGetServiceRecordsError(
const GetServiceRecordsErrorCallback& error_callback,
const std::string& error_name,
const std::string& error_message) {
VLOG(1) << object_path_.value()
<< ": Failed to get service records: " << error_name << ": "
<< error_message;
BluetoothServiceRecordBlueZ::ErrorCode code =
BluetoothServiceRecordBlueZ::ErrorCode::UNKNOWN;
if (error_name == bluetooth_device::kErrorNotConnected) {
code = BluetoothServiceRecordBlueZ::ErrorCode::ERROR_DEVICE_DISCONNECTED;
}
error_callback.Run(code);
}
void BluetoothDeviceBlueZ::ConnectInternal(
bool after_pairing,
const base::Closure& callback,
......
......@@ -18,6 +18,7 @@
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/bluez/bluetooth_service_record_bluez.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
......@@ -29,7 +30,6 @@ namespace bluez {
class BluetoothAdapterBlueZ;
class BluetoothPairingBlueZ;
class BluetoothServiceRecordBlueZ;
// The BluetoothDeviceBlueZ class implements BluetoothDevice for platforms using
// BlueZ.
......@@ -43,6 +43,11 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ
public bluez::BluetoothDeviceClient::Observer,
public bluez::BluetoothGattServiceClient::Observer {
public:
using GetServiceRecordsCallback =
base::Callback<void(const std::vector<BluetoothServiceRecordBlueZ>&)>;
using GetServiceRecordsErrorCallback =
base::Callback<void(BluetoothServiceRecordBlueZ::ErrorCode)>;
// BluetoothDevice override
uint32_t GetBluetoothClass() const override;
device::BluetoothTransport GetType() const override;
......@@ -96,7 +101,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ
// Returns the complete list of service records discovered for on this
// device via SDP. If called before discovery is complete, it may return
// an incomplete list and/or stale cached records.
std::vector<BluetoothServiceRecordBlueZ*> GetServiceRecords();
void GetServiceRecords(const GetServiceRecordsCallback& callback,
const GetServiceRecordsErrorCallback& error_callback);
// Creates a pairing object with the given delegate |pairing_delegate| and
// establishes it as the pairing context for this device. All pairing-related
......@@ -156,6 +162,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ
const std::string& error_name,
const std::string& error_message);
// Called by dbus:: in case of an error during the GetServiceRecords API call.
void OnGetServiceRecordsError(
const GetServiceRecordsErrorCallback& error_callback,
const std::string& error_name,
const std::string& error_message);
// Internal method to initiate a connection to this device, and methods called
// by dbus:: on completion of the D-Bus method call.
void ConnectInternal(bool after_pairing,
......
......@@ -26,7 +26,7 @@ namespace bluez {
// will be an array of other attributes.
class DEVICE_BLUETOOTH_EXPORT BluetoothServiceAttributeValueBlueZ {
public:
enum Type { NULLTYPE, UINT, INT, UUID, STRING, BOOL, SEQUENCE, URL };
enum Type { NULLTYPE = 0, UINT, INT, UUID, STRING, BOOL, SEQUENCE, URL };
using Sequence = std::vector<BluetoothServiceAttributeValueBlueZ>;
......
......@@ -4,13 +4,13 @@
#include "device/bluetooth/bluez/bluetooth_service_record_bluez.h"
#include <utility>
#include "base/values.h"
namespace bluez {
BluetoothServiceRecordBlueZ::BluetoothServiceRecordBlueZ(
const std::map<uint16_t, BluetoothServiceAttributeValueBlueZ>& attributes)
: attributes_(attributes) {}
BluetoothServiceRecordBlueZ::BluetoothServiceRecordBlueZ() {}
BluetoothServiceRecordBlueZ::BluetoothServiceRecordBlueZ(
const BluetoothServiceRecordBlueZ& record) {
......@@ -35,4 +35,14 @@ BluetoothServiceRecordBlueZ::GetAttributeValue(uint16_t attribute_id) const {
return it->second;
}
void BluetoothServiceRecordBlueZ::AddRecordEntry(
uint16_t id,
const BluetoothServiceAttributeValueBlueZ& value) {
auto it = attributes_.find(id);
if (it != attributes_.end())
attributes_.erase(it);
attributes_.insert(
std::pair<uint16_t, BluetoothServiceAttributeValueBlueZ>(id, value));
}
} // namespace bluez
......@@ -32,9 +32,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothServiceRecordBlueZ {
UNKNOWN
};
explicit BluetoothServiceRecordBlueZ(
const std::map<uint16_t, BluetoothServiceAttributeValueBlueZ>&
attributes);
BluetoothServiceRecordBlueZ();
BluetoothServiceRecordBlueZ(const BluetoothServiceRecordBlueZ& record);
~BluetoothServiceRecordBlueZ();
......@@ -44,6 +42,11 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothServiceRecordBlueZ {
const BluetoothServiceAttributeValueBlueZ& GetAttributeValue(
uint16_t attribute_id) const;
// Add an an entry to this service record. If a record with the given ID
// already exists, it is replaced.
void AddRecordEntry(uint16_t id,
const BluetoothServiceAttributeValueBlueZ& value);
private:
std::map<uint16_t, BluetoothServiceAttributeValueBlueZ> attributes_;
};
......
......@@ -14,7 +14,10 @@
#include "base/run_loop.h"
#include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluez/bluetooth_adapter_bluez.h"
#include "device/bluetooth/bluez/bluetooth_device_bluez.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
#include "device/bluetooth/test/bluetooth_test_bluez.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace bluez {
......@@ -29,28 +32,18 @@ constexpr char kServiceUuid3[] = "00001801-0000-1000-3000-00805f9b34fb";
} // namespace
class BluetoothServiceRecordBlueZTest : public testing::Test {
class BluetoothServiceRecordBlueZTest : public device::BluetoothTestBlueZ {
public:
BluetoothServiceRecordBlueZTest()
: adapter_bluez_(nullptr),
success_callbacks_(0),
error_callbacks_(0),
run_loop_(nullptr),
last_seen_handle_(0) {}
void SetUp() override {
std::unique_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
bluez::BluezDBusManager::GetSetterForTesting();
device::BluetoothAdapterFactory::GetAdapter(
base::Bind(&BluetoothServiceRecordBlueZTest::AdapterCallback,
base::Unretained(this)));
RunRunLoop();
}
void TearDown() override {
device::BluetoothAdapterFactory::Shutdown();
bluez::BluezDBusManager::Shutdown();
BluetoothTestBlueZ::SetUp();
InitWithFakeAdapter();
adapter_bluez_ = static_cast<bluez::BluetoothAdapterBlueZ*>(adapter_.get());
}
uint32_t CreateServiceRecordWithCallbacks(
......@@ -89,39 +82,63 @@ class BluetoothServiceRecordBlueZTest : public testing::Test {
EXPECT_EQ(old_error_callbacks + 1 - success, error_callbacks_);
}
void GetServiceRecords(BluetoothDeviceBlueZ* device, bool expect_success) {
const size_t old_success_callbacks = success_callbacks_;
const size_t old_error_callbacks = error_callbacks_;
records_.clear();
device->GetServiceRecords(
base::Bind(&BluetoothServiceRecordBlueZTest::GetServiceRecordsCallback,
base::Unretained(this)),
base::Bind(&BluetoothServiceRecordBlueZTest::ErrorCallback,
base::Unretained(this)));
size_t success = expect_success ? 1 : 0;
EXPECT_EQ(old_success_callbacks + success, success_callbacks_);
EXPECT_EQ(old_error_callbacks + 1 - success, error_callbacks_);
}
void VerifyRecords() {
EXPECT_EQ(2u, records_.size());
std::vector<uint16_t> ids0 = records_[0].GetAttributeIds();
EXPECT_EQ(2u, ids0.size());
BluetoothServiceAttributeValueBlueZ service_handle0 =
records_[0].GetAttributeValue(ids0[0]);
int32_t int_value;
EXPECT_TRUE(service_handle0.value().GetAsInteger(&int_value));
EXPECT_EQ(0x1337, int_value);
BluetoothServiceAttributeValueBlueZ service_class_list =
records_[0].GetAttributeValue(ids0[1]);
std::string str_value;
EXPECT_TRUE(
service_class_list.sequence()[0].value().GetAsString(&str_value));
EXPECT_EQ("1802", str_value);
std::vector<uint16_t> ids1 = records_[1].GetAttributeIds();
EXPECT_EQ(1u, ids1.size());
BluetoothServiceAttributeValueBlueZ service_handle1 =
records_[1].GetAttributeValue(ids1[0]);
EXPECT_TRUE(service_handle1.value().GetAsInteger(&int_value));
EXPECT_EQ(0xffffffff, static_cast<uint32_t>(int_value));
}
protected:
BluetoothServiceRecordBlueZ CreateaServiceRecord(const std::string uuid) {
std::map<uint16_t, BluetoothServiceAttributeValueBlueZ> attributes;
attributes.insert(std::pair<uint16_t, BluetoothServiceAttributeValueBlueZ>(
kServiceUuidAttributeId,
BluetoothServiceAttributeValueBlueZ(
BluetoothServiceAttributeValueBlueZ::UUID, 16,
base::MakeUnique<base::StringValue>(uuid))));
return BluetoothServiceRecordBlueZ(attributes);
BluetoothServiceRecordBlueZ record;
record.AddRecordEntry(kServiceUuidAttributeId,
BluetoothServiceAttributeValueBlueZ(
BluetoothServiceAttributeValueBlueZ::UUID, 16,
base::MakeUnique<base::StringValue>(uuid)));
return record;
}
scoped_refptr<device::BluetoothAdapter> adapter_;
BluetoothAdapterBlueZ* adapter_bluez_;
size_t success_callbacks_;
size_t error_callbacks_;
private:
void RunRunLoop() {
run_loop_ = base::MakeUnique<base::RunLoop>();
run_loop_->Run();
}
void QuitRunLoop() {
if (run_loop_)
run_loop_->Quit();
}
void AdapterCallback(scoped_refptr<device::BluetoothAdapter> adapter) {
adapter_ = adapter;
adapter_bluez_ = static_cast<BluetoothAdapterBlueZ*>(adapter_.get());
QuitRunLoop();
}
void CreateServiceSuccessCallback(uint32_t handle) {
last_seen_handle_ = handle;
++success_callbacks_;
......@@ -133,9 +150,14 @@ class BluetoothServiceRecordBlueZTest : public testing::Test {
++error_callbacks_;
}
base::MessageLoop message_loop_;
std::unique_ptr<base::RunLoop> run_loop_;
void GetServiceRecordsCallback(
const std::vector<BluetoothServiceRecordBlueZ>& records) {
records_ = records;
++success_callbacks_;
}
uint32_t last_seen_handle_;
std::vector<BluetoothServiceRecordBlueZ> records_;
DISALLOW_COPY_AND_ASSIGN(BluetoothServiceRecordBlueZTest);
};
......@@ -157,4 +179,15 @@ TEST_F(BluetoothServiceRecordBlueZTest, CreateAndRemove) {
RemoveServiceRecordWithCallbacks(handle2, true);
}
TEST_F(BluetoothServiceRecordBlueZTest, GetServiceRecords) {
BluetoothDeviceBlueZ* device =
static_cast<BluetoothDeviceBlueZ*>(adapter_->GetDevice(
bluez::FakeBluetoothDeviceClient::kPairedDeviceAddress));
GetServiceRecords(device, false);
device->Connect(nullptr, GetCallback(Call::EXPECTED),
GetConnectErrorCallback(Call::NOT_EXPECTED));
GetServiceRecords(device, true);
VerifyRecords();
}
} // namespace bluez
......@@ -7,11 +7,13 @@
#include "base/bind.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "dbus/bus.h"
#include "dbus/message.h"
#include "dbus/object_manager.h"
#include "dbus/object_proxy.h"
#include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace bluez {
......@@ -21,6 +23,149 @@ namespace {
// Value returned for the the RSSI or TX power if it cannot be read.
const int kUnknownPower = 127;
std::unique_ptr<BluetoothServiceAttributeValueBlueZ> ReadAttributeValue(
dbus::MessageReader* struct_reader) {
uint8_t type_val;
if (!struct_reader->PopByte(&type_val))
return nullptr;
BluetoothServiceAttributeValueBlueZ::Type type =
static_cast<BluetoothServiceAttributeValueBlueZ::Type>(type_val);
uint32_t size;
if (!struct_reader->PopUint32(&size))
return nullptr;
std::unique_ptr<base::Value> value = nullptr;
switch (type) {
case bluez::BluetoothServiceAttributeValueBlueZ::NULLTYPE: {
break;
}
case bluez::BluetoothServiceAttributeValueBlueZ::UINT:
// Fall through.
case bluez::BluetoothServiceAttributeValueBlueZ::INT: {
switch (size) {
// It doesn't matter what 'sign' the number is, only size.
// Whenever we unpack this value, we will take the raw bits and
// cast it back to the correct sign anyway.
case 1:
uint8_t byte;
if (!struct_reader->PopVariantOfByte(&byte))
return nullptr;
value = base::MakeUnique<base::FundamentalValue>(byte);
break;
case 2:
uint16_t short_val;
if (!struct_reader->PopVariantOfUint16(&short_val))
return nullptr;
value = base::MakeUnique<base::FundamentalValue>(short_val);
break;
case 4:
uint32_t val;
if (!struct_reader->PopVariantOfUint32(&val))
return nullptr;
value = base::MakeUnique<base::FundamentalValue>(
static_cast<int32_t>(val));
break;
case 8:
// Fall through.
// BlueZ should never be sending us this size at the moment since
// the Android SDP records we will create from these raw records
// don't have any fields which use this size. If we ever decide to
// change this, this needs to get fixed.
default:
NOTREACHED();
}
break;
}
case bluez::BluetoothServiceAttributeValueBlueZ::UUID:
// Fall through.
case bluez::BluetoothServiceAttributeValueBlueZ::STRING:
// Fall through.
case bluez::BluetoothServiceAttributeValueBlueZ::URL: {
std::string str;
if (!struct_reader->PopVariantOfString(&str))
return nullptr;
value = base::MakeUnique<base::StringValue>(str);
break;
}
case bluez::BluetoothServiceAttributeValueBlueZ::BOOL: {
bool b;
if (!struct_reader->PopVariantOfBool(&b))
return nullptr;
value = base::MakeUnique<base::FundamentalValue>(b);
break;
}
case bluez::BluetoothServiceAttributeValueBlueZ::SEQUENCE: {
dbus::MessageReader variant_reader(nullptr);
if (!struct_reader->PopVariant(&variant_reader))
return nullptr;
dbus::MessageReader array_reader(nullptr);
if (!variant_reader.PopArray(&array_reader))
return nullptr;
std::unique_ptr<BluetoothServiceAttributeValueBlueZ::Sequence> sequence =
base::MakeUnique<BluetoothServiceAttributeValueBlueZ::Sequence>();
while (array_reader.HasMoreData()) {
dbus::MessageReader sequence_element_struct_reader(nullptr);
if (!array_reader.PopStruct(&sequence_element_struct_reader))
return nullptr;
std::unique_ptr<BluetoothServiceAttributeValueBlueZ> attribute_value =
ReadAttributeValue(&sequence_element_struct_reader);
if (!attribute_value)
return nullptr;
sequence->emplace_back(*attribute_value);
}
return base::MakeUnique<BluetoothServiceAttributeValueBlueZ>(
std::move(sequence));
}
}
return base::MakeUnique<BluetoothServiceAttributeValueBlueZ>(
type, size, std::move(value));
}
std::unique_ptr<BluetoothServiceRecordBlueZ> ReadRecord(
dbus::MessageReader* array_reader) {
std::unique_ptr<BluetoothServiceRecordBlueZ> record =
base::MakeUnique<BluetoothServiceRecordBlueZ>();
while (array_reader->HasMoreData()) {
dbus::MessageReader dict_entry_reader(nullptr);
if (!array_reader->PopDictEntry(&dict_entry_reader))
return nullptr;
uint16_t id;
if (!dict_entry_reader.PopUint16(&id))
return nullptr;
dbus::MessageReader struct_reader(nullptr);
if (!dict_entry_reader.PopStruct(&struct_reader))
return nullptr;
std::unique_ptr<BluetoothServiceAttributeValueBlueZ> attribute_value =
ReadAttributeValue(&struct_reader);
if (!attribute_value)
return nullptr;
record->AddRecordEntry(id, *attribute_value);
}
// return std::move(record);
return record;
}
bool ReadRecordsFromMessage(dbus::MessageReader* reader,
BluetoothDeviceClient::ServiceRecordList* records) {
dbus::MessageReader array_reader(nullptr);
if (!reader->PopArray(&array_reader)) {
return false;
LOG(ERROR) << "Arguments for GetConnInfo invalid.";
}
while (array_reader.HasMoreData()) {
dbus::MessageReader nested_array_reader(nullptr);
if (!array_reader.PopArray(&nested_array_reader))
return false;
std::unique_ptr<BluetoothServiceRecordBlueZ> record =
ReadRecord(&nested_array_reader);
if (!record)
return false;
records->emplace_back(*record);
}
return true;
}
} // namespace
const char BluetoothDeviceClient::kNoResponseError[] =
......@@ -281,6 +426,26 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
void GetServiceRecords(const dbus::ObjectPath& object_path,
const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
bluetooth_device::kGetServiceRecords);
dbus::ObjectProxy* object_proxy =
object_manager_->GetObjectProxy(object_path);
if (!object_proxy) {
error_callback.Run(kUnknownDeviceError, "");
return;
}
object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::Bind(&BluetoothDeviceClientImpl::OnGetServiceRecordsSuccess,
weak_ptr_factory_.GetWeakPtr(), callback),
base::Bind(&BluetoothDeviceClientImpl::OnError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
protected:
void Init(dbus::Bus* bus) override {
object_manager_ = bus->GetObjectManager(
......@@ -344,6 +509,23 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
callback.Run(rssi, transmit_power, max_transmit_power);
}
void OnGetServiceRecordsSuccess(const ServiceRecordsCallback& callback,
dbus::Response* response) {
ServiceRecordList records;
if (!response) {
LOG(ERROR) << "GetServiceRecords succeeded, but no response received.";
callback.Run(records);
return;
}
dbus::MessageReader reader(response);
if (!ReadRecordsFromMessage(&reader, &records)) {
callback.Run(ServiceRecordList());
}
callback.Run(records);
}
// Called when a response for a failed method call is received.
void OnError(const ErrorCallback& error_callback,
dbus::ErrorResponse* response) {
......
......@@ -17,6 +17,7 @@
#include "dbus/object_path.h"
#include "dbus/property.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/bluez/bluetooth_service_record_bluez.h"
#include "device/bluetooth/dbus/bluez_dbus_client.h"
namespace bluez {
......@@ -25,6 +26,23 @@ namespace bluez {
// remote Bluetooth Devices.
class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient {
public:
using ServiceRecordList = std::vector<BluetoothServiceRecordBlueZ>;
// This callback invoked for a successful GetConnInfo API call with the
// RSSI, TX power, and maximum TX power of the current connection.
using ConnInfoCallback = base::Callback<
void(int16_t rssi, int16_t transmit_power, int16_t max_transmit_power)>;
// This callback invoked for a successful GetServiceRecords API call with the
// currently discovered service records.
using ServiceRecordsCallback = base::Callback<void(const ServiceRecordList&)>;
// The ErrorCallback is used by device 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)>;
// Structure of properties associated with bluetooth devices.
struct Properties : public dbus::PropertySet {
// The Bluetooth device address of the device. Read-only.
......@@ -135,12 +153,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient {
// any values should be copied if needed.
virtual Properties* GetProperties(const dbus::ObjectPath& object_path) = 0;
// The ErrorCallback is used by device methods to indicate failure.
// It receives two arguments: the name of the error in |error_name| and
// an optional message in |error_message|.
typedef base::Callback<void(const std::string& error_name,
const std::string& error_message)> ErrorCallback;
// Connects to the device with object path |object_path|, connecting any
// profiles that can be connected to and have been flagged as auto-connected;
// may be used to connect additional profiles for an already connected device,
......@@ -183,12 +195,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient {
const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// The callback invoked for a successful GetConnInfo API call with the
// RSSI, TX power, and maximum TX power of the current connection.
typedef base::Callback<void(int16_t rssi,
int16_t transmit_power,
int16_t max_transmit_power)> ConnInfoCallback;
// Returns the RSSI, TX power, and maximum TX power of a connection to the
// device with object path |object_path|. If the device is not connected, then
// an error will be returned.
......@@ -196,6 +202,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient {
const ConnInfoCallback& callback,
const ErrorCallback& error_callback) = 0;
// Returns the currently discovered service records for the device with
// object path |object_path|. If the device is not connected, then an error
// will be returned.
virtual void GetServiceRecords(const dbus::ObjectPath& object_path,
const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) = 0;
// Creates the instance.
static BluetoothDeviceClient* Create();
......
......@@ -15,8 +15,11 @@
#include <string>
#include <utility>
#include "base/bind_helpers.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
......@@ -24,6 +27,7 @@
#include "base/threading/worker_pool.h"
#include "base/time/time.h"
#include "dbus/file_descriptor.h"
#include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
......@@ -34,6 +38,8 @@
#include "device/bluetooth/dbus/fake_bluetooth_profile_service_provider.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace bluez {
namespace {
// Default interval between simulated events.
......@@ -93,9 +99,38 @@ void SimpleErrorCallback(const std::string& error_name,
VLOG(1) << "Bluetooth Error: " << error_name << ": " << error_message;
}
} // namespace
BluetoothDeviceClient::ServiceRecordList CreateFakeServiceRecords() {
BluetoothDeviceClient::ServiceRecordList records;
std::unique_ptr<BluetoothServiceRecordBlueZ> record1 =
base::MakeUnique<BluetoothServiceRecordBlueZ>();
// ID 0 = handle.
record1->AddRecordEntry(0x0, BluetoothServiceAttributeValueBlueZ(
BluetoothServiceAttributeValueBlueZ::UINT, 4,
base::MakeUnique<base::FundamentalValue>(
static_cast<int32_t>(0x1337))));
// ID 1 = service class id list.
std::unique_ptr<BluetoothServiceAttributeValueBlueZ::Sequence> class_id_list =
base::MakeUnique<BluetoothServiceAttributeValueBlueZ::Sequence>();
class_id_list->emplace_back(BluetoothServiceAttributeValueBlueZ::UUID, 4,
base::MakeUnique<base::StringValue>("1802"));
record1->AddRecordEntry(
0x1, BluetoothServiceAttributeValueBlueZ(std::move(class_id_list)));
records.emplace_back(*record1);
std::unique_ptr<BluetoothServiceRecordBlueZ> record2 =
base::MakeUnique<BluetoothServiceRecordBlueZ>();
// ID 0 = handle.
record2->AddRecordEntry(0x0, BluetoothServiceAttributeValueBlueZ(
BluetoothServiceAttributeValueBlueZ::UINT, 4,
base::MakeUnique<base::FundamentalValue>(
static_cast<int32_t>(0xffffffff))));
records.emplace_back(*record2);
return records;
}
namespace bluez {
} // namespace
const char FakeBluetoothDeviceClient::kTestPinCode[] = "123456";
const int FakeBluetoothDeviceClient::kTestPassKey = 123456;
......@@ -413,7 +448,7 @@ void FakeBluetoothDeviceClient::Disconnect(
Properties* properties = GetProperties(object_path);
if (!properties->connected.value()) {
error_callback.Run("org.bluez.Error.NotConnected", "Not Connected");
error_callback.Run(bluetooth_device::kErrorNotConnected, "Not Connected");
return;
}
......@@ -545,13 +580,25 @@ void FakeBluetoothDeviceClient::GetConnInfo(
const ErrorCallback& error_callback) {
Properties* properties = GetProperties(object_path);
if (!properties->connected.value()) {
error_callback.Run("org.bluez.Error.NotConnected", "Not Connected");
error_callback.Run(bluetooth_device::kErrorNotConnected, "Not Connected");
return;
}
callback.Run(connection_rssi_, transmit_power_, max_transmit_power_);
}
void FakeBluetoothDeviceClient::GetServiceRecords(
const dbus::ObjectPath& object_path,
const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) {
Properties* properties = GetProperties(object_path);
if (!properties->connected.value()) {
error_callback.Run(bluetooth_device::kErrorNotConnected, "Not Connected");
return;
}
callback.Run(CreateFakeServiceRecords());
}
void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
const dbus::ObjectPath& adapter_path) {
VLOG(1) << "starting discovery simulation";
......
......@@ -5,8 +5,7 @@
#ifndef DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
#include <stdint.h>
#include <cstdint>
#include <map>
#include <memory>
#include <vector>
......@@ -102,6 +101,9 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
void GetConnInfo(const dbus::ObjectPath& object_path,
const ConnInfoCallback& callback,
const ErrorCallback& error_callback) override;
void GetServiceRecords(const dbus::ObjectPath& object_path,
const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) override;
void SetSimulationIntervalMs(int interval_ms);
......
......@@ -67,11 +67,6 @@ void BluetoothTestBlueZ::SetUp() {
std::unique_ptr<bluez::BluezDBusManagerSetter> dbus_setter =
bluez::BluezDBusManager::GetSetterForTesting();
fake_bluetooth_device_client_ = new bluez::FakeBluetoothDeviceClient;
// TODO(rkc): This is a big hacky. Creating a device client creates three
// devices by default. For now, the easiest path is to just clear them, but
// a better way will be to only create them as needed. This will require
// looking at a lot of tests but should be done eventually.
fake_bluetooth_device_client_->RemoveAllDevices();
dbus_setter->SetBluetoothDeviceClient(
std::unique_ptr<bluez::BluetoothDeviceClient>(
fake_bluetooth_device_client_));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment