summaryrefslogtreecommitdiff
path: root/chromium/device/bluetooth/bluez
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/device/bluetooth/bluez')
-rw-r--r--chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc89
-rw-r--r--chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc8
-rw-r--r--chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc443
-rw-r--r--chromium/device/bluetooth/bluez/bluetooth_pairing_bluez.cc2
-rw-r--r--chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc33
-rw-r--r--chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h5
6 files changed, 513 insertions, 67 deletions
diff --git a/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
index 6e6928e0ca2..bbea7dffa02 100644
--- a/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
+++ b/chromium/device/bluetooth/bluez/bluetooth_adapter_bluez.cc
@@ -1523,6 +1523,8 @@ void BluetoothAdapterBlueZ::UpdateFilter(
void BluetoothAdapterBlueZ::StartScanWithFilter(
std::unique_ptr<device::BluetoothDiscoveryFilter> discovery_filter,
DiscoverySessionResultCallback callback) {
+ DCHECK(discovery_filter.get());
+
if (!IsPresent()) {
std::move(callback).Run(
true, UMABluetoothDiscoverySessionOutcome::ADAPTER_NOT_PRESENT);
@@ -1532,39 +1534,16 @@ void BluetoothAdapterBlueZ::StartScanWithFilter(
BLUETOOTH_LOG(EVENT) << __func__;
auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
-
- if (discovery_filter && !discovery_filter->IsDefault()) {
- std::unique_ptr<BluetoothDiscoveryFilter> df(
- new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_DUAL));
- df->CopyFrom(*discovery_filter);
- SetDiscoveryFilter(
- std::move(df),
- base::BindRepeating(
- &BluetoothAdapterBlueZ::OnPreSetDiscoveryFilter,
- weak_ptr_factory_.GetWeakPtr(),
- base::BindRepeating(copyable_callback, /*is_error=*/false,
- UMABluetoothDiscoverySessionOutcome::SUCCESS),
- base::BindRepeating(copyable_callback, true)),
- base::BindOnce(
- &BluetoothAdapterBlueZ::OnPreSetDiscoveryFilterError,
- weak_ptr_factory_.GetWeakPtr(),
- base::BindRepeating(copyable_callback, /*is_error=*/false,
- UMABluetoothDiscoverySessionOutcome::SUCCESS),
- base::BindOnce(copyable_callback, true)));
- return;
- }
-
- // This is the first request to start device discovery.
- bluez::BluezDBusManager::Get()->GetBluetoothAdapterClient()->StartDiscovery(
- object_path_,
- base::BindOnce(
- &BluetoothAdapterBlueZ::OnStartDiscovery,
+ SetDiscoveryFilter(
+ std::move(discovery_filter),
+ base::BindRepeating(
+ &BluetoothAdapterBlueZ::OnPreSetDiscoveryFilter,
weak_ptr_factory_.GetWeakPtr(),
base::BindRepeating(copyable_callback, /*is_error=*/false,
UMABluetoothDiscoverySessionOutcome::SUCCESS),
base::BindRepeating(copyable_callback, true)),
base::BindOnce(
- &BluetoothAdapterBlueZ::OnStartDiscoveryError,
+ &BluetoothAdapterBlueZ::OnPreSetDiscoveryFilterError,
weak_ptr_factory_.GetWeakPtr(),
base::BindRepeating(copyable_callback, /*is_error=*/false,
UMABluetoothDiscoverySessionOutcome::SUCCESS),
@@ -1607,6 +1586,8 @@ void BluetoothAdapterBlueZ::SetDiscoveryFilter(
std::unique_ptr<BluetoothDiscoveryFilter> discovery_filter,
const base::Closure& callback,
DiscoverySessionErrorCallback error_callback) {
+ DCHECK(discovery_filter.get());
+
if (!IsPresent()) {
std::move(error_callback)
.Run(UMABluetoothDiscoverySessionOutcome::ADAPTER_REMOVED);
@@ -1614,36 +1595,32 @@ void BluetoothAdapterBlueZ::SetDiscoveryFilter(
}
bluez::BluetoothAdapterClient::DiscoveryFilter dbus_discovery_filter;
+ uint16_t pathloss;
+ int16_t rssi;
+ uint8_t transport;
+ std::set<device::BluetoothUUID> uuids;
+
+ if (discovery_filter->GetPathloss(&pathloss))
+ dbus_discovery_filter.pathloss = std::make_unique<uint16_t>(pathloss);
+
+ if (discovery_filter->GetRSSI(&rssi))
+ dbus_discovery_filter.rssi = std::make_unique<int16_t>(rssi);
+
+ transport = discovery_filter->GetTransport();
+ if (transport == device::BLUETOOTH_TRANSPORT_LE) {
+ dbus_discovery_filter.transport = std::make_unique<std::string>("le");
+ } else if (transport == device::BLUETOOTH_TRANSPORT_CLASSIC) {
+ dbus_discovery_filter.transport = std::make_unique<std::string>("bredr");
+ } else if (transport == device::BLUETOOTH_TRANSPORT_DUAL) {
+ dbus_discovery_filter.transport = std::make_unique<std::string>("auto");
+ }
- if (discovery_filter.get() && !discovery_filter->IsDefault()) {
- uint16_t pathloss;
- int16_t rssi;
- uint8_t transport;
- std::set<device::BluetoothUUID> uuids;
-
- if (discovery_filter->GetPathloss(&pathloss))
- dbus_discovery_filter.pathloss.reset(new uint16_t(pathloss));
-
- if (discovery_filter->GetRSSI(&rssi))
- dbus_discovery_filter.rssi.reset(new int16_t(rssi));
-
- transport = discovery_filter->GetTransport();
- if (transport == device::BLUETOOTH_TRANSPORT_LE) {
- dbus_discovery_filter.transport.reset(new std::string("le"));
- } else if (transport == device::BLUETOOTH_TRANSPORT_CLASSIC) {
- dbus_discovery_filter.transport.reset(new std::string("bredr"));
- } else if (transport == device::BLUETOOTH_TRANSPORT_DUAL) {
- dbus_discovery_filter.transport.reset(new std::string("auto"));
- }
-
- discovery_filter->GetUUIDs(uuids);
- if (uuids.size()) {
- dbus_discovery_filter.uuids = std::unique_ptr<std::vector<std::string>>(
- new std::vector<std::string>);
+ discovery_filter->GetUUIDs(uuids);
+ if (uuids.size()) {
+ dbus_discovery_filter.uuids = std::make_unique<std::vector<std::string>>();
- for (const auto& it : uuids)
- dbus_discovery_filter.uuids.get()->push_back(it.value());
- }
+ for (const auto& it : uuids)
+ dbus_discovery_filter.uuids.get()->push_back(it.value());
}
auto copyable_error_callback =
diff --git a/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc
index fadcb54401f..2d060a3424d 100644
--- a/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc
+++ b/chromium/device/bluetooth/bluez/bluetooth_device_bluez.cc
@@ -853,11 +853,13 @@ void BluetoothDeviceBlueZ::UpdateGattServices(
// Add all previously unknown GATT services associated with the device.
GattServiceAdded(service_path);
- // If the service does not belong in this device, there is nothing left to
- // do.
+ // |service_paths| includes all services for all devices, not just this
+ // device. GetGattService() will return nullptr for services belonging
+ // to other devices, so we skip those and keep looking for services that
+ // belong to this device.
BluetoothRemoteGattService* service = GetGattService(service_path.value());
if (service == nullptr) {
- return;
+ continue;
}
// Notify of GATT discovery complete if we haven't before.
diff --git a/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc b/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
index 1f81414ef63..b59f4ace1d4 100644
--- a/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
+++ b/chromium/device/bluetooth/bluez/bluetooth_gatt_bluez_unittest.cc
@@ -50,6 +50,7 @@ using device::BluetoothUUID;
using device::TestBluetoothAdapterObserver;
using UUIDSet = device::BluetoothDevice::UUIDSet;
+using WriteType = device::BluetoothRemoteGattCharacteristic::WriteType;
typedef std::unordered_map<device::BluetoothDevice*,
device::BluetoothDevice::UUIDSet>
@@ -96,7 +97,7 @@ void AddDeviceFilterWithUUID(BluetoothDiscoveryFilter* filter,
class BluetoothGattBlueZTest : public testing::Test {
public:
BluetoothGattBlueZTest()
- : fake_bluetooth_gatt_service_client_(NULL),
+ : fake_bluetooth_gatt_service_client_(nullptr),
success_callback_count_(0),
error_callback_count_(0) {}
@@ -1027,7 +1028,7 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue) {
characteristic->GetIdentifier());
EXPECT_EQ(kHeartRateMeasurementUUID, characteristic->GetUUID());
characteristic->WriteRemoteCharacteristic(
- write_value,
+ write_value, WriteType::kWithResponse,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
@@ -1050,7 +1051,7 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue) {
characteristic->GetIdentifier());
EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
characteristic->WriteRemoteCharacteristic(
- write_value,
+ write_value, WriteType::kWithResponse,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
@@ -1077,7 +1078,7 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue) {
characteristic->GetIdentifier());
EXPECT_EQ(kHeartRateControlPointUUID, characteristic->GetUUID());
characteristic->WriteRemoteCharacteristic(
- write_value,
+ write_value, WriteType::kWithResponse,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
@@ -1095,7 +1096,7 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue) {
invalid_write_length.push_back(0x01);
invalid_write_length.push_back(0x00);
characteristic->WriteRemoteCharacteristic(
- invalid_write_length,
+ invalid_write_length, WriteType::kWithResponse,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
@@ -1109,6 +1110,227 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue) {
std::vector<uint8_t> invalid_write_value;
invalid_write_value.push_back(0x02);
characteristic->WriteRemoteCharacteristic(
+ invalid_write_value, WriteType::kWithResponse,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(1, success_callback_count_);
+ EXPECT_EQ(4, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED, last_service_error_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ // Issue a read request.
+ characteristic = service->GetCharacteristic(
+ fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
+ .value());
+ ASSERT_TRUE(characteristic);
+ EXPECT_EQ(
+ fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
+ .value(),
+ characteristic->GetIdentifier());
+ EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
+ characteristic->ReadRemoteCharacteristic(
+ base::BindOnce(&BluetoothGattBlueZTest::ValueCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(2, success_callback_count_);
+ EXPECT_EQ(4, error_callback_count_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+ EXPECT_TRUE(ValuesEqual(characteristic->GetValue(), last_read_value_));
+
+ // Test long-running actions.
+ fake_bluetooth_gatt_characteristic_client_->SetExtraProcessing(1);
+ characteristic = service->GetCharacteristic(
+ fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
+ .value());
+ ASSERT_TRUE(characteristic);
+ EXPECT_EQ(
+ fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
+ .value(),
+ characteristic->GetIdentifier());
+ EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
+ characteristic->ReadRemoteCharacteristic(
+ base::BindOnce(&BluetoothGattBlueZTest::ValueCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+
+ // Callback counts shouldn't change, this one will be delayed until after
+ // tne next one.
+ EXPECT_EQ(2, success_callback_count_);
+ EXPECT_EQ(4, error_callback_count_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ // Next read should error because IN_PROGRESS
+ characteristic->ReadRemoteCharacteristic(
+ base::BindOnce(&BluetoothGattBlueZTest::ValueCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(5, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS,
+ last_service_error_);
+
+ // But previous call finished.
+ EXPECT_EQ(3, success_callback_count_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+ EXPECT_TRUE(ValuesEqual(characteristic->GetValue(), last_read_value_));
+ fake_bluetooth_gatt_characteristic_client_->SetExtraProcessing(0);
+
+ // Test unauthorized actions.
+ fake_bluetooth_gatt_characteristic_client_->SetAuthorized(false);
+ characteristic->ReadRemoteCharacteristic(
+ base::BindOnce(&BluetoothGattBlueZTest::ValueCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(3, success_callback_count_);
+ EXPECT_EQ(6, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_NOT_AUTHORIZED,
+ last_service_error_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+ fake_bluetooth_gatt_characteristic_client_->SetAuthorized(true);
+
+ // Test unauthenticated / needs login.
+ fake_bluetooth_gatt_characteristic_client_->SetAuthenticated(false);
+ characteristic->ReadRemoteCharacteristic(
+ base::BindOnce(&BluetoothGattBlueZTest::ValueCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(3, success_callback_count_);
+ EXPECT_EQ(7, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_NOT_PAIRED,
+ last_service_error_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+ fake_bluetooth_gatt_characteristic_client_->SetAuthenticated(true);
+}
+
+TEST_F(BluetoothGattBlueZTest, DeprecatedGattCharacteristicValue) {
+ fake_bluetooth_device_client_->CreateDevice(
+ dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ BluetoothDevice* device =
+ 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());
+
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ // Run the message loop so that the characteristics appear.
+ base::RunLoop().Run();
+
+ // Issue write request to non-writable characteristics.
+ observer.Reset();
+
+ std::vector<uint8_t> write_value;
+ write_value.push_back(0x01);
+ BluetoothRemoteGattCharacteristic* characteristic =
+ service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
+ ->GetHeartRateMeasurementPath()
+ .value());
+ ASSERT_TRUE(characteristic);
+ EXPECT_FALSE(characteristic->IsNotifying());
+ EXPECT_EQ(
+ fake_bluetooth_gatt_characteristic_client_->GetHeartRateMeasurementPath()
+ .value(),
+ characteristic->GetIdentifier());
+ EXPECT_EQ(kHeartRateMeasurementUUID, characteristic->GetUUID());
+ characteristic->DeprecatedWriteRemoteCharacteristic(
+ write_value,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_TRUE(observer.last_gatt_characteristic_id().empty());
+ EXPECT_FALSE(observer.last_gatt_characteristic_uuid().IsValid());
+ EXPECT_EQ(0, success_callback_count_);
+ EXPECT_EQ(1, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_NOT_SUPPORTED,
+ last_service_error_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ characteristic = service->GetCharacteristic(
+ fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
+ .value());
+ ASSERT_TRUE(characteristic);
+ EXPECT_EQ(
+ fake_bluetooth_gatt_characteristic_client_->GetBodySensorLocationPath()
+ .value(),
+ characteristic->GetIdentifier());
+ EXPECT_EQ(kBodySensorLocationUUID, characteristic->GetUUID());
+ characteristic->DeprecatedWriteRemoteCharacteristic(
+ write_value,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_TRUE(observer.last_gatt_characteristic_id().empty());
+ EXPECT_FALSE(observer.last_gatt_characteristic_uuid().IsValid());
+ EXPECT_EQ(0, success_callback_count_);
+ EXPECT_EQ(2, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED,
+ last_service_error_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ // Issue write request to writable characteristic. The "Body Sensor Location"
+ // characteristic does not send notifications and WriteValue does not result
+ // in a CharacteristicValueChanged event, thus no such event should be
+ // received.
+ characteristic = service->GetCharacteristic(
+ fake_bluetooth_gatt_characteristic_client_->GetHeartRateControlPointPath()
+ .value());
+ ASSERT_TRUE(characteristic);
+ EXPECT_EQ(
+ fake_bluetooth_gatt_characteristic_client_->GetHeartRateControlPointPath()
+ .value(),
+ characteristic->GetIdentifier());
+ EXPECT_EQ(kHeartRateControlPointUUID, characteristic->GetUUID());
+ characteristic->DeprecatedWriteRemoteCharacteristic(
+ write_value,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_TRUE(observer.last_gatt_characteristic_id().empty());
+ EXPECT_FALSE(observer.last_gatt_characteristic_uuid().IsValid());
+ EXPECT_EQ(1, success_callback_count_);
+ EXPECT_EQ(2, error_callback_count_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ // Issue some invalid write requests to the characteristic.
+ // The value should still not change.
+
+ std::vector<uint8_t> invalid_write_length;
+ invalid_write_length.push_back(0x01);
+ invalid_write_length.push_back(0x00);
+ characteristic->DeprecatedWriteRemoteCharacteristic(
+ invalid_write_length,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(1, success_callback_count_);
+ EXPECT_EQ(3, error_callback_count_);
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH,
+ last_service_error_);
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+
+ std::vector<uint8_t> invalid_write_value;
+ invalid_write_value.push_back(0x02);
+ characteristic->DeprecatedWriteRemoteCharacteristic(
invalid_write_value,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
@@ -1288,12 +1510,63 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Write_Write) {
std::vector<uint8_t> write_value = {0x01};
characteristic->WriteRemoteCharacteristic(
- write_value, base::BindLambdaForTesting([&] {
+ write_value, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
SuccessCallback();
EXPECT_EQ(1, success_callback_count_);
EXPECT_EQ(0, error_callback_count_);
characteristic->WriteRemoteCharacteristic(
+ write_value, WriteType::kWithResponse,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ }),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(2, success_callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+}
+
+// Test a write request issued from the success callback of another write
+// request.
+TEST_F(BluetoothGattBlueZTest,
+ GattCharacteristicValue_Nested_DeprecatedWrite_DeprecatedWrite) {
+ fake_bluetooth_device_client_->CreateDevice(
+ dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ BluetoothDevice* device =
+ 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();
+
+ // 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};
+ characteristic->DeprecatedWriteRemoteCharacteristic(
+ write_value, base::BindLambdaForTesting([&] {
+ SuccessCallback();
+ EXPECT_EQ(1, success_callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+
+ characteristic->DeprecatedWriteRemoteCharacteristic(
write_value,
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
@@ -1349,6 +1622,62 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Read_Write) {
.value());
characteristic->WriteRemoteCharacteristic(
+ std::vector<uint8_t>({0x01}), WriteType::kWithResponse,
+ base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ }),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(2, success_callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+}
+
+// Test a write request issued from the success callback of a read request.
+TEST_F(BluetoothGattBlueZTest,
+ GattCharacteristicValue_Nested_Read_DeprecatedWrite) {
+ fake_bluetooth_device_client_->CreateDevice(
+ dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ BluetoothDevice* device =
+ 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();
+
+ // Obtain readable Body Sensor Location characteristic.
+ BluetoothRemoteGattCharacteristic* characteristic =
+ service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
+ ->GetBodySensorLocationPath()
+ .value());
+
+ characteristic->ReadRemoteCharacteristic(
+ base::BindLambdaForTesting([&](const std::vector<uint8_t>& data) {
+ ValueCallback(data);
+ EXPECT_EQ(1, success_callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+ EXPECT_EQ(characteristic->GetValue(), last_read_value_);
+
+ // Obtain writable Heart Rate Control Point characteristic.
+ characteristic = service->GetCharacteristic(
+ fake_bluetooth_gatt_characteristic_client_
+ ->GetHeartRateControlPointPath()
+ .value());
+
+ characteristic->DeprecatedWriteRemoteCharacteristic(
std::vector<uint8_t>({0x01}),
base::BindOnce(&BluetoothGattBlueZTest::SuccessCallback,
base::Unretained(this)),
@@ -1391,6 +1720,62 @@ TEST_F(BluetoothGattBlueZTest, GattCharacteristicValue_Nested_Write_Read) {
.value());
characteristic->WriteRemoteCharacteristic(
+ std::vector<uint8_t>({0x01}), WriteType::kWithResponse,
+ base::BindLambdaForTesting([&] {
+ SuccessCallback();
+ EXPECT_EQ(1, success_callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+
+ // Obtain readable Body Sensor Location characteristic.
+ characteristic = service->GetCharacteristic(
+ fake_bluetooth_gatt_characteristic_client_
+ ->GetBodySensorLocationPath()
+ .value());
+
+ characteristic->ReadRemoteCharacteristic(
+ base::BindOnce(&BluetoothGattBlueZTest::ValueCallback,
+ base::Unretained(this)),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ }),
+ base::BindOnce(&BluetoothGattBlueZTest::ServiceErrorCallback,
+ base::Unretained(this)));
+ EXPECT_EQ(2, success_callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+ EXPECT_EQ(characteristic->GetValue(), last_read_value_);
+}
+
+// Test a read request issued from the success callback of a write request.
+TEST_F(BluetoothGattBlueZTest,
+ GattCharacteristicValue_Nested_DeprecatedWrite_Read) {
+ fake_bluetooth_device_client_->CreateDevice(
+ dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ BluetoothDevice* device =
+ 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();
+
+ // Obtain writable Heart Rate Control Point characteristic.
+ BluetoothRemoteGattCharacteristic* characteristic =
+ service->GetCharacteristic(fake_bluetooth_gatt_characteristic_client_
+ ->GetHeartRateControlPointPath()
+ .value());
+
+ characteristic->DeprecatedWriteRemoteCharacteristic(
std::vector<uint8_t>({0x01}), base::BindLambdaForTesting([&] {
SuccessCallback();
EXPECT_EQ(1, success_callback_count_);
@@ -2018,4 +2403,50 @@ TEST_F(BluetoothGattBlueZTest, NotificationType) {
}
#endif
+TEST_F(BluetoothGattBlueZTest, MultipleDevices) {
+ fake_bluetooth_device_client_->CreateDevice(
+ dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ bluez::FakeBluetoothDeviceClient::Properties* properties1 =
+ fake_bluetooth_device_client_->GetProperties(
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ properties1->services_resolved.ReplaceValue(false);
+
+ fake_bluetooth_gatt_service_client_->ExposeHeartRateService(
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
+ while (!fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible())
+ base::RunLoop().RunUntilIdle();
+ ASSERT_TRUE(fake_bluetooth_gatt_service_client_->IsHeartRateVisible());
+ ASSERT_TRUE(fake_bluetooth_gatt_characteristic_client_->IsHeartRateVisible());
+
+ fake_bluetooth_device_client_->CreateDevice(
+ dbus::ObjectPath(bluez::FakeBluetoothAdapterClient::kAdapterPath),
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kDualPath));
+ bluez::FakeBluetoothDeviceClient::Properties* properties2 =
+ fake_bluetooth_device_client_->GetProperties(
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kDualPath));
+ properties2->services_resolved.ReplaceValue(false);
+
+ fake_bluetooth_gatt_service_client_->ExposeBatteryService(
+ dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kDualPath));
+ ASSERT_TRUE(fake_bluetooth_gatt_service_client_->IsBatteryServiceVisible());
+
+ BluetoothDeviceBlueZ* device1 = static_cast<BluetoothDeviceBlueZ*>(
+ adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kLowEnergyAddress));
+ ASSERT_TRUE(device1);
+ BluetoothDeviceBlueZ* device2 = static_cast<BluetoothDeviceBlueZ*>(
+ adapter_->GetDevice(bluez::FakeBluetoothDeviceClient::kDualAddress));
+ ASSERT_TRUE(device2);
+
+ TestBluetoothAdapterObserver observer(adapter_);
+
+ EXPECT_EQ(0, observer.gatt_discovery_complete_count());
+
+ properties1->services_resolved.ReplaceValue(true);
+ properties2->services_resolved.ReplaceValue(true);
+
+ // Since BlueZ iterates all services for all devices for each device, this
+ // can catch errors like https://crbug.com/1087648
+ EXPECT_EQ(2, observer.gatt_discovery_complete_count());
+}
} // namespace bluez
diff --git a/chromium/device/bluetooth/bluez/bluetooth_pairing_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_pairing_bluez.cc
index b6e96297052..e0bb2b6ae37 100644
--- a/chromium/device/bluetooth/bluez/bluetooth_pairing_bluez.cc
+++ b/chromium/device/bluetooth/bluez/bluetooth_pairing_bluez.cc
@@ -67,7 +67,7 @@ BluetoothPairingBlueZ::~BluetoothPairingBlueZ() {
.Run(bluez::BluetoothAgentServiceProvider::Delegate::CANCELLED);
}
- pairing_delegate_ = NULL;
+ pairing_delegate_ = nullptr;
}
void BluetoothPairingBlueZ::RequestPinCode(
diff --git a/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc b/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
index 18f508f36fb..d68db58794f 100644
--- a/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
+++ b/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.cc
@@ -24,6 +24,7 @@
#include "device/bluetooth/bluez/bluetooth_remote_gatt_service_bluez.h"
#include "device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "third_party/cros_system_api/dbus/bluetooth/dbus-constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace bluez {
@@ -173,16 +174,46 @@ void BluetoothRemoteGattCharacteristicBlueZ::ReadRemoteCharacteristic(
void BluetoothRemoteGattCharacteristicBlueZ::WriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
+ WriteType write_type,
base::OnceClosure callback,
ErrorCallback error_callback) {
DVLOG(1) << "Sending GATT characteristic write request to characteristic: "
<< GetIdentifier() << ", UUID: " << GetUUID().canonical_value()
+ << ", with value: " << value << ", with response: "
+ << ((write_type == WriteType::kWithoutResponse) ? "no" : "yes")
+ << ".";
+
+ const char* type_option;
+ switch (write_type) {
+ case WriteType::kWithResponse:
+ type_option = bluetooth_gatt_characteristic::kTypeRequest;
+ break;
+ case WriteType::kWithoutResponse:
+ type_option = bluetooth_gatt_characteristic::kTypeCommand;
+ break;
+ }
+
+ bluez::BluezDBusManager::Get()
+ ->GetBluetoothGattCharacteristicClient()
+ ->WriteValue(
+ object_path(), value, type_option, std::move(callback),
+ base::BindOnce(&BluetoothRemoteGattCharacteristicBlueZ::OnWriteError,
+ weak_ptr_factory_.GetWeakPtr(),
+ std::move(error_callback)));
+}
+
+void BluetoothRemoteGattCharacteristicBlueZ::
+ DeprecatedWriteRemoteCharacteristic(const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) {
+ DVLOG(1) << "Sending GATT characteristic write request to characteristic: "
+ << GetIdentifier() << ", UUID: " << GetUUID().canonical_value()
<< ", with value: " << value << ".";
bluez::BluezDBusManager::Get()
->GetBluetoothGattCharacteristicClient()
->WriteValue(
- object_path(), value, std::move(callback),
+ object_path(), value, "", std::move(callback),
base::BindOnce(&BluetoothRemoteGattCharacteristicBlueZ::OnWriteError,
weak_ptr_factory_.GetWeakPtr(),
std::move(error_callback)));
diff --git a/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h b/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
index f435e4ddbd4..164aa707956 100644
--- a/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
+++ b/chromium/device/bluetooth/bluez/bluetooth_remote_gatt_characteristic_bluez.h
@@ -57,8 +57,13 @@ class BluetoothRemoteGattCharacteristicBlueZ
void ReadRemoteCharacteristic(ValueCallback callback,
ErrorCallback error_callback) override;
void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
+ WriteType write_type,
base::OnceClosure callback,
ErrorCallback error_callback) override;
+ void DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) override;
#if defined(OS_CHROMEOS)
void PrepareWriteRemoteCharacteristic(const std::vector<uint8_t>& value,
base::OnceClosure callback,