diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-12 14:27:29 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2020-10-13 09:35:20 +0000 |
commit | c30a6232df03e1efbd9f3b226777b07e087a1122 (patch) | |
tree | e992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/device/bluetooth/bluez | |
parent | 7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff) | |
download | qtwebengine-chromium-85-based.tar.gz |
BASELINE: Update Chromium to 85.0.4183.14085-based
Change-Id: Iaa42f4680837c57725b1344f108c0196741f6057
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/device/bluetooth/bluez')
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, |