Commit a179fd40 authored by Qiyu Hu's avatar Qiyu Hu Committed by Commit Bot

bluetooth: Support reliable write

 - Add ExecuteWrite to device to commit or abort changes
   in different characteristic
 - Add PrepareWriteValue() in remote characteristic API

A relevant patch is crrev.com/c/1065067

BUG=b:78650442
CQ-DEPEND=CL:1079668
TEST=Pass CtsVerifier test for reliable write on client side. Unittest.

Change-Id: Ibd1a68b9a3a1973c5287b46d41ec652f9d9f8352
Reviewed-on: https://chromium-review.googlesource.com/1065080
Commit-Queue: Qiyu Hu <qiyuh@google.com>
Reviewed-by: default avatarGiovanni Ortuño Urquidi <ortuno@chromium.org>
Reviewed-by: default avatarMiao-chen Chou <mcchou@chromium.org>
Cr-Commit-Position: refs/heads/master@{#563140}
parent f06540c5
...@@ -561,6 +561,20 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice { ...@@ -561,6 +561,20 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDevice {
std::vector<BluetoothRemoteGattService*> GetPrimaryServicesByUUID( std::vector<BluetoothRemoteGattService*> GetPrimaryServicesByUUID(
const BluetoothUUID& service_uuid); const BluetoothUUID& service_uuid);
#if defined(OS_CHROMEOS)
typedef base::Callback<void(device::BluetoothGattService::GattErrorCode)>
ExecuteWriteErrorCallback;
typedef base::Callback<void(device::BluetoothGattService::GattErrorCode)>
AbortWriteErrorCallback;
// Executes all the previous prepare writes in a reliable write session.
virtual void ExecuteWrite(
const base::Closure& callback,
const ExecuteWriteErrorCallback& error_callback) = 0;
// Aborts all the previous prepare writes in a reliable write session.
virtual void AbortWrite(const base::Closure& callback,
const AbortWriteErrorCallback& error_callback) = 0;
#endif
protected: protected:
// BluetoothGattConnection is a friend to call Add/RemoveGattConnection. // BluetoothGattConnection is a friend to call Add/RemoveGattConnection.
friend BluetoothGattConnection; friend BluetoothGattConnection;
......
...@@ -133,6 +133,19 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristic ...@@ -133,6 +133,19 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristic
const base::Closure& callback, const base::Closure& callback,
const ErrorCallback& error_callback) = 0; const ErrorCallback& error_callback) = 0;
#if defined(OS_CHROMEOS)
// Sends a prepare write request to a remote characteristic with the value
// |value|. |callback| is called to signal success and |error_callback| for
// failures. This method only applies to remote characteristics and will fail
// for those that are locally hosted.
// Callers should use BluetoothDevice::ExecuteWrite() to commit or
// BluetoothDevice::AbortWrite() to abort the change.
virtual void PrepareWriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
#endif
// Sends a write request to a remote characteristic with the value |value| // Sends a write request to a remote characteristic with the value |value|
// without waiting for a response. This method returns false to signal // without waiting for a response. This method returns false to signal
// failures. When attempting to write the remote characteristic true is // failures. When attempting to write the remote characteristic true is
......
...@@ -666,6 +666,26 @@ void BluetoothDeviceBlueZ::GetServiceRecords( ...@@ -666,6 +666,26 @@ void BluetoothDeviceBlueZ::GetServiceRecords(
weak_ptr_factory_.GetWeakPtr(), error_callback)); weak_ptr_factory_.GetWeakPtr(), error_callback));
} }
#if defined(OS_CHROMEOS)
void BluetoothDeviceBlueZ::ExecuteWrite(
const base::Closure& callback,
const ExecuteWriteErrorCallback& error_callback) {
bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->ExecuteWrite(
object_path_, callback,
base::Bind(&BluetoothDeviceBlueZ::OnExecuteWriteError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
void BluetoothDeviceBlueZ::AbortWrite(
const base::Closure& callback,
const AbortWriteErrorCallback& error_callback) {
bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->AbortWrite(
object_path_, callback,
base::Bind(&BluetoothDeviceBlueZ::OnAbortWriteError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
#endif
void BluetoothDeviceBlueZ::UpdateServiceData() { void BluetoothDeviceBlueZ::UpdateServiceData() {
bluez::BluetoothDeviceClient::Properties* properties = bluez::BluetoothDeviceClient::Properties* properties =
bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties( bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient()->GetProperties(
...@@ -863,6 +883,30 @@ void BluetoothDeviceBlueZ::OnGetServiceRecordsError( ...@@ -863,6 +883,30 @@ void BluetoothDeviceBlueZ::OnGetServiceRecordsError(
error_callback.Run(code); error_callback.Run(code);
} }
#if defined(OS_CHROMEOS)
void BluetoothDeviceBlueZ::OnExecuteWriteError(
const ExecuteWriteErrorCallback& error_callback,
const std::string& error_name,
const std::string& error_message) {
BLUETOOTH_LOG(EVENT) << object_path_.value()
<< ": Failed to execute write: " << error_name << ": "
<< error_message;
error_callback.Run(
BluetoothGattServiceBlueZ::DBusErrorToServiceError(error_name));
}
void BluetoothDeviceBlueZ::OnAbortWriteError(
const AbortWriteErrorCallback& error_callback,
const std::string& error_name,
const std::string& error_message) {
BLUETOOTH_LOG(EVENT) << object_path_.value()
<< ": Failed to abort write: " << error_name << ": "
<< error_message;
error_callback.Run(
BluetoothGattServiceBlueZ::DBusErrorToServiceError(error_name));
}
#endif
void BluetoothDeviceBlueZ::ConnectInternal( void BluetoothDeviceBlueZ::ConnectInternal(
bool after_pairing, bool after_pairing,
const base::Closure& callback, const base::Closure& callback,
......
...@@ -104,6 +104,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ ...@@ -104,6 +104,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ
void Pair(device::BluetoothDevice::PairingDelegate* pairing_delegate, void Pair(device::BluetoothDevice::PairingDelegate* pairing_delegate,
const base::Closure& callback, const base::Closure& callback,
const ConnectErrorCallback& error_callback) override; const ConnectErrorCallback& error_callback) override;
#if defined(OS_CHROMEOS)
void ExecuteWrite(const base::Closure& callback,
const ExecuteWriteErrorCallback& error_callback) override;
void AbortWrite(const base::Closure& callback,
const AbortWriteErrorCallback& error_callback) override;
#endif
// Returns the complete list of service records discovered for on this // Returns the complete list of service records discovered for on this
// device via SDP. If called before discovery is complete, it may return // device via SDP. If called before discovery is complete, it may return
...@@ -203,6 +209,16 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ ...@@ -203,6 +209,16 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceBlueZ
const std::string& error_name, const std::string& error_name,
const std::string& error_message); const std::string& error_message);
#if defined(OS_CHROMEOS)
void OnExecuteWriteError(const ExecuteWriteErrorCallback& error_callback,
const std::string& error_name,
const std::string& error_message);
void OnAbortWriteError(const AbortWriteErrorCallback& error_callback,
const std::string& error_name,
const std::string& error_message);
#endif
// Internal method to initiate a connection to this device, and methods called // Internal method to initiate a connection to this device, and methods called
// by dbus:: on completion of the D-Bus method call. // by dbus:: on completion of the D-Bus method call.
void ConnectInternal(bool after_pairing, void ConnectInternal(bool after_pairing,
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h"
#include "device/bluetooth/bluetooth_remote_gatt_service.h" #include "device/bluetooth/bluetooth_remote_gatt_service.h"
#include "device/bluetooth/bluetooth_uuid.h" #include "device/bluetooth/bluetooth_uuid.h"
#include "device/bluetooth/bluez/bluetooth_device_bluez.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" #include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" #include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
...@@ -1848,4 +1849,98 @@ TEST_F(BluetoothGattBlueZTest, NotifySessionsMadeInactive) { ...@@ -1848,4 +1849,98 @@ TEST_F(BluetoothGattBlueZTest, NotifySessionsMadeInactive) {
EXPECT_TRUE(update_sessions_[0]->IsActive()); EXPECT_TRUE(update_sessions_[0]->IsActive());
} }
#if defined(OS_CHROMEOS)
TEST_F(BluetoothGattBlueZTest, ReliableWrite) {
fake_bluetooth_device_client_->CreateDevice(
dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
BluetoothDeviceBlueZ* device = static_cast<BluetoothDeviceBlueZ*>(
adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress));
ASSERT_TRUE(device);
TestBluetoothAdapterObserver observer(adapter_);
// Expose the fake Heart Rate service. This will asynchronously expose
// characteristics.
fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
ASSERT_EQ(1, observer.gatt_service_added_count());
BluetoothRemoteGattService* service =
device->GetGattService(observer.last_gatt_service_id());
// Run the message loop so that the characteristics appear.
base::RunLoop().Run();
// Request to start notifications.
service
->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
->GetHeartRateMeasurementPath()
.value())
->StartNotifySession(
base::Bind(&BluetoothGattBlueZTest::NotifySessionCallback,
base::Unretained(this)),
base::Bind(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
base::RunLoop().Run();
// Obtain writable Heart Rate Control Point characteristic.
BluetoothRemoteGattCharacteristic* characteristic =
service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
->GetHeartRateControlPointPath()
.value());
std::vector<uint8_t> write_value = {0x01};
// Prepare 1000 writes.
success_callback_count_ = 0;
error_callback_count_ = 0;
observer.Reset();
for (int i = 0; i < 1000; ++i) {
characteristic->PrepareWriteRemoteCharacteristic(
write_value,
base::Bind(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::Bind(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
}
EXPECT_EQ(1000, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
// Abort.
device->AbortWrite(base::Bind(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::Bind(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1001, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
// Prepare another 1000 writes.
success_callback_count_ = 0;
error_callback_count_ = 0;
observer.Reset();
for (int i = 0; i < 1000; ++i) {
characteristic->PrepareWriteRemoteCharacteristic(
write_value,
base::Bind(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::Bind(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
}
EXPECT_EQ(1000, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
// Execute.
device->ExecuteWrite(base::Bind(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::Bind(&BluetoothGattBlueZTest::ServiceErrorCallback,
base::Unretained(this)));
EXPECT_EQ(1001, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(1000, observer.gatt_characteristic_value_changed_count());
}
#endif
} // namespace bluez } // namespace bluez
...@@ -204,6 +204,25 @@ void BluetoothRemoteGattCharacteristicBlueZ::WriteRemoteCharacteristic( ...@@ -204,6 +204,25 @@ void BluetoothRemoteGattCharacteristicBlueZ::WriteRemoteCharacteristic(
weak_ptr_factory_.GetWeakPtr(), error_callback)); weak_ptr_factory_.GetWeakPtr(), error_callback));
} }
#if defined(OS_CHROMEOS)
void BluetoothRemoteGattCharacteristicBlueZ::PrepareWriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) {
VLOG(1) << "Sending GATT characteristic prepare write request to "
<< "characteristic: " << GetIdentifier()
<< ", UUID: " << GetUUID().canonical_value()
<< ", with value: " << value << ".";
bluez::BluezDBusManager::Get()
->GetBluetoothGattCharacteristicClient()
->PrepareWriteValue(
object_path(), value, callback,
base::Bind(&BluetoothRemoteGattCharacteristicBlueZ::OnWriteError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
#endif
void BluetoothRemoteGattCharacteristicBlueZ::SubscribeToNotifications( void BluetoothRemoteGattCharacteristicBlueZ::SubscribeToNotifications(
device::BluetoothRemoteGattDescriptor* ccc_descriptor, device::BluetoothRemoteGattDescriptor* ccc_descriptor,
const base::Closure& callback, const base::Closure& callback,
......
...@@ -64,6 +64,12 @@ class BluetoothRemoteGattCharacteristicBlueZ ...@@ -64,6 +64,12 @@ class BluetoothRemoteGattCharacteristicBlueZ
void WriteRemoteCharacteristic(const std::vector<uint8_t>& value, void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
const base::Closure& callback, const base::Closure& callback,
const ErrorCallback& error_callback) override; const ErrorCallback& error_callback) override;
#if defined(OS_CHROMEOS)
void PrepareWriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
#endif
protected: protected:
void SubscribeToNotifications( void SubscribeToNotifications(
......
...@@ -503,6 +503,52 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient, ...@@ -503,6 +503,52 @@ class BluetoothDeviceClientImpl : public BluetoothDeviceClient,
weak_ptr_factory_.GetWeakPtr(), error_callback)); weak_ptr_factory_.GetWeakPtr(), error_callback));
} }
void ExecuteWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
bluetooth_device::kExecuteWrite);
dbus::ObjectProxy* object_proxy =
object_manager_->GetObjectProxy(object_path);
if (!object_proxy) {
error_callback.Run(kUnknownDeviceError, "");
return;
}
dbus::MessageWriter writer(&method_call);
writer.AppendBool(true);
object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), callback),
base::BindOnce(&BluetoothDeviceClientImpl::OnError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
void AbortWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::MethodCall method_call(bluetooth_device::kBluetoothDeviceInterface,
bluetooth_device::kExecuteWrite);
dbus::ObjectProxy* object_proxy =
object_manager_->GetObjectProxy(object_path);
if (!object_proxy) {
error_callback.Run(kUnknownDeviceError, "");
return;
}
dbus::MessageWriter writer(&method_call);
writer.AppendBool(false);
object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&BluetoothDeviceClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), callback),
base::BindOnce(&BluetoothDeviceClientImpl::OnError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
protected: protected:
void Init(dbus::Bus* bus, void Init(dbus::Bus* bus,
const std::string& bluetooth_service_name) override { const std::string& bluetooth_service_name) override {
......
...@@ -242,6 +242,16 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient { ...@@ -242,6 +242,16 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceClient : public BluezDBusClient {
const ServiceRecordsCallback& callback, const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) = 0; const ErrorCallback& error_callback) = 0;
// Executes all the privous prepare writes in a reliable write session.
virtual void ExecuteWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// Aborts all the privous prepare writes in a reliable write session.
virtual void AbortWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// Creates the instance. // Creates the instance.
static BluetoothDeviceClient* Create(); static BluetoothDeviceClient* Create();
......
...@@ -140,6 +140,34 @@ class BluetoothGattCharacteristicClientImpl ...@@ -140,6 +140,34 @@ class BluetoothGattCharacteristicClientImpl
weak_ptr_factory_.GetWeakPtr(), error_callback)); weak_ptr_factory_.GetWeakPtr(), error_callback));
} }
void PrepareWriteValue(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) override {
dbus::ObjectProxy* object_proxy =
object_manager_->GetObjectProxy(object_path);
if (!object_proxy) {
error_callback.Run(kUnknownCharacteristicError, "");
return;
}
dbus::MethodCall method_call(
bluetooth_gatt_characteristic::kBluetoothGattCharacteristicInterface,
bluetooth_gatt_characteristic::kPrepareWriteValue);
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfBytes(value.data(), value.size());
base::DictionaryValue dict;
dbus::AppendValueData(&writer, dict);
object_proxy->CallMethodWithErrorCallback(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&BluetoothGattCharacteristicClientImpl::OnSuccess,
weak_ptr_factory_.GetWeakPtr(), callback),
base::BindOnce(&BluetoothGattCharacteristicClientImpl::OnError,
weak_ptr_factory_.GetWeakPtr(), error_callback));
}
// BluetoothGattCharacteristicClient override. // BluetoothGattCharacteristicClient override.
void StartNotify(const dbus::ObjectPath& object_path, void StartNotify(const dbus::ObjectPath& object_path,
const base::Closure& callback, const base::Closure& callback,
......
...@@ -109,6 +109,14 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicClient ...@@ -109,6 +109,14 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicClient
const base::Closure& callback, const base::Closure& callback,
const ErrorCallback& error_callback) = 0; const ErrorCallback& error_callback) = 0;
// Issues a request to prepare write the value of GATT characteristic with
// object path |object_path| with value |value|.
// Invokes |callback| on success and |error_callback| on failure.
virtual void PrepareWriteValue(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// Starts a notification session from this characteristic with object path // Starts a notification session from this characteristic with object path
// |object_path| if it supports value notifications or indications. Invokes // |object_path| if it supports value notifications or indications. Invokes
// |callback| on success and |error_callback| on failure. // |callback| on success and |error_callback| on failure.
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h" #include "device/bluetooth/bluez/bluetooth_service_attribute_value_bluez.h"
#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h" #include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h" #include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
...@@ -625,6 +626,28 @@ void FakeBluetoothDeviceClient::GetServiceRecords( ...@@ -625,6 +626,28 @@ void FakeBluetoothDeviceClient::GetServiceRecords(
callback.Run(CreateFakeServiceRecords()); callback.Run(CreateFakeServiceRecords());
} }
void FakeBluetoothDeviceClient::ExecuteWrite(
const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) {
for (const auto& prepare_write_request : prepare_write_requests_) {
bluez::BluezDBusManager::Get()
->GetBluetoothGattCharacteristicClient()
->WriteValue(prepare_write_request.first, prepare_write_request.second,
base::DoNothing(), base::DoNothing());
}
prepare_write_requests_.clear();
callback.Run();
}
void FakeBluetoothDeviceClient::AbortWrite(
const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) {
prepare_write_requests_.clear();
callback.Run();
}
void FakeBluetoothDeviceClient::BeginDiscoverySimulation( void FakeBluetoothDeviceClient::BeginDiscoverySimulation(
const dbus::ObjectPath& adapter_path) { const dbus::ObjectPath& adapter_path) {
VLOG(1) << "starting discovery simulation"; VLOG(1) << "starting discovery simulation";
...@@ -1885,4 +1908,10 @@ void FakeBluetoothDeviceClient::CreateTestDevice( ...@@ -1885,4 +1908,10 @@ void FakeBluetoothDeviceClient::CreateTestDevice(
observer.DeviceAdded(device_path); observer.DeviceAdded(device_path);
} }
void FakeBluetoothDeviceClient::AddPrepareWriteRequest(
const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value) {
prepare_write_requests_.emplace_back(object_path, value);
}
} // namespace bluez } // namespace bluez
...@@ -109,6 +109,12 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient ...@@ -109,6 +109,12 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
void GetServiceRecords(const dbus::ObjectPath& object_path, void GetServiceRecords(const dbus::ObjectPath& object_path,
const ServiceRecordsCallback& callback, const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) override; const ErrorCallback& error_callback) override;
void ExecuteWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void AbortWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void SetSimulationIntervalMs(int interval_ms); void SetSimulationIntervalMs(int interval_ms);
...@@ -186,6 +192,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient ...@@ -186,6 +192,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
const std::map<std::string, std::vector<uint8_t>>& service_data, const std::map<std::string, std::vector<uint8_t>>& service_data,
const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data); const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data);
// Adds a pending prepare write request to |object_path|.
void AddPrepareWriteRequest(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value);
static const char kTestPinCode[]; static const char kTestPinCode[];
static const int kTestPassKey; static const int kTestPassKey;
...@@ -364,6 +374,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient ...@@ -364,6 +374,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
// Controls the fake behavior to allow more extensive UI testing without // Controls the fake behavior to allow more extensive UI testing without
// having to cycle the discovery simulation. // having to cycle the discovery simulation.
bool delay_start_discovery_; bool delay_start_discovery_;
// Pending prepare write requests.
std::vector<std::pair<dbus::ObjectPath, std::vector<uint8_t>>>
prepare_write_requests_;
}; };
} // namespace bluez } // namespace bluez
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h" #include "base/time/time.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h" #include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_device_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h" #include "device/bluetooth/dbus/fake_bluetooth_gatt_descriptor_client.h"
#include "third_party/cros_system_api/dbus/service_constants.h" #include "third_party/cros_system_api/dbus/service_constants.h"
...@@ -257,6 +258,7 @@ void FakeBluetoothGattCharacteristicClient::WriteValue( ...@@ -257,6 +258,7 @@ void FakeBluetoothGattCharacteristicClient::WriteValue(
} else if (value[0] == 1) { } else if (value[0] == 1) {
// TODO(jamuraa): make this happen when the callback happens // TODO(jamuraa): make this happen when the callback happens
calories_burned_ = 0; calories_burned_ = 0;
ScheduleHeartRateMeasurementValueChange();
completed_callback = callback; completed_callback = callback;
} }
...@@ -268,6 +270,46 @@ void FakeBluetoothGattCharacteristicClient::WriteValue( ...@@ -268,6 +270,46 @@ void FakeBluetoothGattCharacteristicClient::WriteValue(
completed_callback.Run(); completed_callback.Run();
} }
void FakeBluetoothGattCharacteristicClient::PrepareWriteValue(
const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) {
if (!authenticated_) {
error_callback.Run(bluetooth_gatt_service::kErrorNotPaired, "Please login");
return;
}
if (!authorized_) {
error_callback.Run(bluetooth_gatt_service::kErrorNotAuthorized,
"Authorize first");
return;
}
if (!IsHeartRateVisible()) {
error_callback.Run(kUnknownCharacteristicError, "");
return;
}
if (object_path.value() == heart_rate_measurement_path_) {
error_callback.Run(bluetooth_gatt_service::kErrorNotSupported,
"Action not supported on this characteristic");
return;
}
if (object_path.value() != heart_rate_control_point_path_) {
error_callback.Run(bluetooth_gatt_service::kErrorNotPermitted,
"Writes of this value are not allowed");
return;
}
DCHECK(heart_rate_control_point_properties_.get());
static_cast<FakeBluetoothDeviceClient*>(
bluez::BluezDBusManager::Get()->GetBluetoothDeviceClient())
->AddPrepareWriteRequest(object_path, value);
callback.Run();
}
void FakeBluetoothGattCharacteristicClient::StartNotify( void FakeBluetoothGattCharacteristicClient::StartNotify(
const dbus::ObjectPath& object_path, const dbus::ObjectPath& object_path,
const base::Closure& callback, const base::Closure& callback,
......
...@@ -58,6 +58,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicClient ...@@ -58,6 +58,10 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicClient
const std::vector<uint8_t>& value, const std::vector<uint8_t>& value,
const base::Closure& callback, const base::Closure& callback,
const ErrorCallback& error_callback) override; const ErrorCallback& error_callback) override;
void PrepareWriteValue(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void StartNotify(const dbus::ObjectPath& object_path, void StartNotify(const dbus::ObjectPath& object_path,
const base::Closure& callback, const base::Closure& callback,
const ErrorCallback& error_callback) override; const ErrorCallback& error_callback) override;
......
...@@ -338,4 +338,17 @@ void FakePeripheral::DispatchDiscoveryResponse() { ...@@ -338,4 +338,17 @@ void FakePeripheral::DispatchDiscoveryResponse() {
void FakePeripheral::DisconnectGatt() { void FakePeripheral::DisconnectGatt() {
} }
#if defined(OS_CHROMEOS)
void FakePeripheral::ExecuteWrite(
const base::Closure& callback,
const ExecuteWriteErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
void FakePeripheral::AbortWrite(const base::Closure& callback,
const AbortWriteErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
#endif
} // namespace bluetooth } // namespace bluetooth
...@@ -113,6 +113,12 @@ class FakePeripheral : public device::BluetoothDevice { ...@@ -113,6 +113,12 @@ class FakePeripheral : public device::BluetoothDevice {
const GattConnectionCallback& callback, const GattConnectionCallback& callback,
const ConnectErrorCallback& error_callback) override; const ConnectErrorCallback& error_callback) override;
bool IsGattServicesDiscoveryComplete() const override; bool IsGattServicesDiscoveryComplete() const override;
#if defined(OS_CHROMEOS)
void ExecuteWrite(const base::Closure& callback,
const ExecuteWriteErrorCallback& error_callback) override;
void AbortWrite(const base::Closure& callback,
const AbortWriteErrorCallback& error_callback) override;
#endif
protected: protected:
void CreateGattConnectionImpl() override; void CreateGattConnectionImpl() override;
......
...@@ -183,6 +183,15 @@ void FakeRemoteGattCharacteristic::WriteRemoteCharacteristic( ...@@ -183,6 +183,15 @@ void FakeRemoteGattCharacteristic::WriteRemoteCharacteristic(
value)); value));
} }
#if defined(OS_CHROMEOS)
void FakeRemoteGattCharacteristic::PrepareWriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) {
NOTIMPLEMENTED();
}
#endif
bool FakeRemoteGattCharacteristic::WriteWithoutResponse( bool FakeRemoteGattCharacteristic::WriteWithoutResponse(
base::span<const uint8_t> value) { base::span<const uint8_t> value) {
if (properties_ & PROPERTY_WRITE_WITHOUT_RESPONSE) { if (properties_ & PROPERTY_WRITE_WITHOUT_RESPONSE) {
......
...@@ -92,6 +92,12 @@ class FakeRemoteGattCharacteristic ...@@ -92,6 +92,12 @@ class FakeRemoteGattCharacteristic
void WriteRemoteCharacteristic(const std::vector<uint8_t>& value, void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
const base::Closure& callback, const base::Closure& callback,
const ErrorCallback& error_callback) override; const ErrorCallback& error_callback) override;
#if defined(OS_CHROMEOS)
void PrepareWriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
#endif
bool WriteWithoutResponse(base::span<const uint8_t> value) override; bool WriteWithoutResponse(base::span<const uint8_t> value) override;
protected: protected:
......
...@@ -105,6 +105,14 @@ class MockBluetoothDevice : public BluetoothDevice { ...@@ -105,6 +105,14 @@ class MockBluetoothDevice : public BluetoothDevice {
BluetoothRemoteGattService*(const std::string&)); BluetoothRemoteGattService*(const std::string&));
MOCK_METHOD0(CreateGattConnectionImpl, void()); MOCK_METHOD0(CreateGattConnectionImpl, void());
MOCK_METHOD0(DisconnectGatt, void()); MOCK_METHOD0(DisconnectGatt, void());
#if defined(OS_CHROMEOS)
MOCK_METHOD2(ExecuteWrite,
void(const base::Closure& callback,
const ExecuteWriteErrorCallback& error_callback));
MOCK_METHOD2(AbortWrite,
void(const base::Closure& callback,
const AbortWriteErrorCallback& error_callback));
#endif
// BluetoothDevice manages the lifetime of its BluetoothGATTServices. // BluetoothDevice manages the lifetime of its BluetoothGATTServices.
// This method takes ownership of the MockBluetoothGATTServices. This is only // This method takes ownership of the MockBluetoothGATTServices. This is only
......
...@@ -59,6 +59,12 @@ class MockBluetoothGattCharacteristic ...@@ -59,6 +59,12 @@ class MockBluetoothGattCharacteristic
void(const std::vector<uint8_t>&, void(const std::vector<uint8_t>&,
const base::Closure&, const base::Closure&,
const ErrorCallback&)); const ErrorCallback&));
#if defined(OS_CHROMEOS)
MOCK_METHOD3(PrepareWriteRemoteCharacteristic,
void(const std::vector<uint8_t>&,
const base::Closure&,
const ErrorCallback&));
#endif
void AddMockDescriptor( void AddMockDescriptor(
std::unique_ptr<MockBluetoothGattDescriptor> mock_descriptor); std::unique_ptr<MockBluetoothGattDescriptor> mock_descriptor);
......
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