summaryrefslogtreecommitdiff
path: root/chromium/device/bluetooth
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-12 14:27:29 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-13 09:35:20 +0000
commitc30a6232df03e1efbd9f3b226777b07e087a1122 (patch)
treee992f45784689f373bcc38d1b79a239ebe17ee23 /chromium/device/bluetooth
parent7b5b123ac58f58ffde0f4f6e488bcd09aa4decd3 (diff)
downloadqtwebengine-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')
-rw-r--r--chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java5
-rw-r--r--chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java4
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter.cc1
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter_mac.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter_mac_metrics.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter_mac_metrics_unittest.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter_unittest.cc47
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter_winrt.cc128
-rw-r--r--chromium/device/bluetooth/bluetooth_adapter_winrt.h13
-rw-r--r--chromium/device/bluetooth/bluetooth_device.cc1
-rw-r--r--chromium/device/bluetooth/bluetooth_device_unittest.cc47
-rw-r--r--chromium/device/bluetooth/bluetooth_device_winrt.cc330
-rw-r--r--chromium/device/bluetooth/bluetooth_device_winrt.h48
-rw-r--r--chromium/device/bluetooth/bluetooth_discovery_manager_mac.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_discovery_session.cc1
-rw-r--r--chromium/device/bluetooth/bluetooth_discovery_session.h23
-rw-r--r--chromium/device/bluetooth/bluetooth_init_win.cc8
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_advertisement_manager_mac.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_device_watcher_mac.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm1
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_win.cc11
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_win.h3
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_win_fake.cc10
-rw-r--r--chromium/device/bluetooth/bluetooth_low_energy_win_fake.h3
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.cc6
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.h33
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc42
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h14
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h8
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm65
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc1220
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc40
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h5
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc99
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h6
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc3
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc10
-rw-r--r--chromium/device/bluetooth/bluetooth_remote_gatt_service_winrt.h1
-rw-r--r--chromium/device/bluetooth/bluetooth_task_manager_win.cc13
-rw-r--r--chromium/device/bluetooth/bluetooth_task_manager_win.h2
-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
-rw-r--r--chromium/device/bluetooth/cast/bluetooth_adapter_cast.cc1
-rw-r--r--chromium/device/bluetooth/cast/bluetooth_device_cast.cc1
-rw-r--r--chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc28
-rw-r--r--chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h5
-rw-r--r--chromium/device/bluetooth/dbus/bluetooth_gatt_application_service_provider.cc1
-rw-r--r--chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc11
-rw-r--r--chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h6
-rw-r--r--chromium/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc1
-rw-r--r--chromium/device/bluetooth/dbus/bluetooth_gatt_service_client.cc1
-rw-r--r--chromium/device/bluetooth/dbus/bluez_dbus_manager.cc1
-rw-r--r--chromium/device/bluetooth/dbus/bluez_dbus_thread_manager.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc4
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc477
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h2
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc2
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_media_client.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc1
-rw-r--r--chromium/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc1
-rw-r--r--chromium/device/bluetooth/device.cc2
-rw-r--r--chromium/device/bluetooth/public/mojom/BUILD.gn5
-rw-r--r--chromium/device/bluetooth/public/mojom/test/fake_bluetooth.mojom11
74 files changed, 2660 insertions, 747 deletions
diff --git a/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java b/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java
index 41344a1b708..39156474261 100644
--- a/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java
+++ b/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/ChromeBluetoothRemoteGattCharacteristic.java
@@ -130,11 +130,14 @@ final class ChromeBluetoothRemoteGattCharacteristic {
// Implements BluetoothRemoteGattCharacteristicAndroid::WriteRemoteCharacteristic.
@CalledByNative
- private boolean writeRemoteCharacteristic(byte[] value) {
+ private boolean writeRemoteCharacteristic(byte[] value, int writeType) {
if (!mCharacteristic.setValue(value)) {
Log.i(TAG, "writeRemoteCharacteristic setValue failed.");
return false;
}
+ if (writeType != 0) {
+ mCharacteristic.setWriteType(writeType);
+ }
if (!mChromeDevice.mBluetoothGatt.writeCharacteristic(mCharacteristic)) {
Log.i(TAG, "writeRemoteCharacteristic writeCharacteristic failed.");
return false;
diff --git a/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java b/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java
index 14984469ca1..3829a8ff345 100644
--- a/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java
+++ b/chromium/device/bluetooth/android/java/src/org/chromium/device/bluetooth/Wrappers.java
@@ -605,6 +605,10 @@ class Wrappers {
public boolean setValue(byte[] value) {
return mCharacteristic.setValue(value);
}
+
+ public void setWriteType(int writeType) {
+ mCharacteristic.setWriteType(writeType);
+ }
}
/**
diff --git a/chromium/device/bluetooth/bluetooth_adapter.cc b/chromium/device/bluetooth/bluetooth_adapter.cc
index 02207f53fc7..34d5ac03ac5 100644
--- a/chromium/device/bluetooth/bluetooth_adapter.cc
+++ b/chromium/device/bluetooth/bluetooth_adapter.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
diff --git a/chromium/device/bluetooth/bluetooth_adapter_mac.mm b/chromium/device/bluetooth/bluetooth_adapter_mac.mm
index 0b2c4e6d169..b29b68be6fa 100644
--- a/chromium/device/bluetooth/bluetooth_adapter_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_adapter_mac.mm
@@ -15,6 +15,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/memory/ptr_util.h"
#include "base/numerics/safe_conversions.h"
diff --git a/chromium/device/bluetooth/bluetooth_adapter_mac_metrics.mm b/chromium/device/bluetooth/bluetooth_adapter_mac_metrics.mm
index a9cd7606177..36eb4a0c23e 100644
--- a/chromium/device/bluetooth/bluetooth_adapter_mac_metrics.mm
+++ b/chromium/device/bluetooth/bluetooth_adapter_mac_metrics.mm
@@ -9,6 +9,7 @@
#include "base/mac/mac_util.h"
#include "base/metrics/histogram_functions.h"
+#include "base/notreached.h"
namespace {
diff --git a/chromium/device/bluetooth/bluetooth_adapter_mac_metrics_unittest.mm b/chromium/device/bluetooth/bluetooth_adapter_mac_metrics_unittest.mm
index 00d17c175be..974e3128fd0 100644
--- a/chromium/device/bluetooth/bluetooth_adapter_mac_metrics_unittest.mm
+++ b/chromium/device/bluetooth/bluetooth_adapter_mac_metrics_unittest.mm
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/logging.h"
#include "base/test/metrics/histogram_tester.h"
#include "device/bluetooth/test/bluetooth_test_mac.h"
diff --git a/chromium/device/bluetooth/bluetooth_adapter_unittest.cc b/chromium/device/bluetooth/bluetooth_adapter_unittest.cc
index 55f6b2d8333..593c5782a30 100644
--- a/chromium/device/bluetooth/bluetooth_adapter_unittest.cc
+++ b/chromium/device/bluetooth/bluetooth_adapter_unittest.cc
@@ -14,6 +14,7 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
@@ -131,12 +132,6 @@ class TestBluetoothAdapter final : public BluetoothAdapter {
void TestErrorCallback() {}
- void TestOnStartDiscoverySession(
- std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
- ++callback_count_;
- discovery_sessions_holder_.push(std::move(discovery_session));
- }
-
void OnStartDiscoverySessionQuitLoop(
base::Closure run_loop_quit,
std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
@@ -723,7 +718,7 @@ TEST_F(BluetoothTest, MAYBE_ConstructDefaultAdapter) {
EXPECT_EQ(adapter_->IsPowered(), adapter_->IsPowered());
EXPECT_FALSE(adapter_->IsDiscoverable());
EXPECT_FALSE(adapter_->IsDiscovering());
-}
+} // namespace device
// TODO(scheib): Enable BluetoothTest fixture tests on all platforms.
#if defined(OS_ANDROID) || defined(OS_MACOSX)
@@ -1420,6 +1415,34 @@ TEST_F(BluetoothTest, MAYBE_TogglePowerBeforeScan) {
EXPECT_TRUE(discovery_sessions_[0]->IsActive());
}
+#if defined(OS_WIN)
+TEST_P(BluetoothTestWinrtOnly, DiscoverySessionFailure) {
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+
+ InitWithFakeAdapter();
+ TestBluetoothAdapterObserver observer(adapter_);
+ EXPECT_FALSE(adapter_->IsDiscovering());
+
+ StartLowEnergyDiscoverySession();
+ EXPECT_EQ(1, callback_count_);
+ EXPECT_EQ(0, error_callback_count_);
+ EXPECT_TRUE(adapter_->IsDiscovering());
+ EXPECT_EQ(1, observer.discovering_changed_count());
+ EXPECT_TRUE(observer.last_discovering());
+ ASSERT_EQ((size_t)1, discovery_sessions_.size());
+ EXPECT_TRUE(discovery_sessions_[0]->IsActive());
+
+ SimulateLowEnergyDiscoveryFailure();
+ EXPECT_FALSE(adapter_->IsDiscovering());
+ EXPECT_FALSE(discovery_sessions_[0]->IsActive());
+ EXPECT_EQ(2, observer.discovering_changed_count());
+ EXPECT_FALSE(observer.last_discovering());
+}
+#endif // defined(OS_WIN)
+
#if defined(OS_MACOSX)
#define MAYBE_TurnOffAdapterWithConnectedDevice \
TurnOffAdapterWithConnectedDevice
@@ -2093,9 +2116,15 @@ TEST_F(BluetoothTest, DiscoverConnectedLowEnergyDeviceTwice) {
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
-INSTANTIATE_TEST_SUITE_P(All, BluetoothTestWinrt, ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(All,
+ BluetoothTestWinrt,
+ ::testing::ValuesIn(kBluetoothTestWinrtParamAll));
+
+INSTANTIATE_TEST_SUITE_P(
+ All,
+ BluetoothTestWinrtOnly,
+ ::testing::ValuesIn(kBluetoothTestWinrtParamWinrtOnly));
-INSTANTIATE_TEST_SUITE_P(All, BluetoothTestWinrtOnly, ::testing::Values(true));
#endif // defined(OS_WIN)
} // namespace device
diff --git a/chromium/device/bluetooth/bluetooth_adapter_winrt.cc b/chromium/device/bluetooth/bluetooth_adapter_winrt.cc
index 0fd2637cd33..1b380be9c80 100644
--- a/chromium/device/bluetooth/bluetooth_adapter_winrt.cc
+++ b/chromium/device/bluetooth/bluetooth_adapter_winrt.cc
@@ -51,6 +51,7 @@ namespace {
namespace uwp {
using ABI::Windows::Devices::Bluetooth::BluetoothAdapter;
} // namespace uwp
+using ABI::Windows::Devices::Bluetooth::BluetoothError;
using ABI::Windows::Devices::Bluetooth::IBluetoothAdapter;
using ABI::Windows::Devices::Bluetooth::IBluetoothAdapterStatics;
using ABI::Windows::Devices::Bluetooth::IID_IBluetoothAdapterStatics;
@@ -64,7 +65,6 @@ using ABI::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEAdvertisementWatcherStatus_Aborted;
using ABI::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEManufacturerData;
-using ABI::Windows::Devices::Bluetooth::Advertisement::BluetoothLEScanningMode;
using ABI::Windows::Devices::Bluetooth::Advertisement::
BluetoothLEScanningMode_Active;
using ABI::Windows::Devices::Bluetooth::Advertisement::
@@ -72,8 +72,6 @@ using ABI::Windows::Devices::Bluetooth::Advertisement::
using ABI::Windows::Devices::Bluetooth::Advertisement::
IBluetoothLEAdvertisementDataSection;
using ABI::Windows::Devices::Bluetooth::Advertisement::
- IBluetoothLEAdvertisementPublisherFactory;
-using ABI::Windows::Devices::Bluetooth::Advertisement::
IBluetoothLEAdvertisementReceivedEventArgs;
using ABI::Windows::Devices::Bluetooth::Advertisement::
IBluetoothLEAdvertisementWatcher;
@@ -463,26 +461,6 @@ base::Optional<std::string> ExtractDeviceName(
return base::win::ScopedHString(local_name).GetAsUTF8();
}
-void ExtractAndUpdateAdvertisementData(
- IBluetoothLEAdvertisementReceivedEventArgs* received,
- BluetoothDevice* device) {
- int16_t rssi = 0;
- HRESULT hr = received->get_RawSignalStrengthInDBm(&rssi);
- if (FAILED(hr)) {
- BLUETOOTH_LOG(ERROR) << "get_RawSignalStrengthInDBm() failed: "
- << logging::SystemErrorCodeToString(hr);
- }
-
- ComPtr<IBluetoothLEAdvertisement> advertisement = GetAdvertisement(received);
- static_cast<BluetoothDeviceWinrt*>(device)->UpdateLocalName(
- ExtractDeviceName(advertisement.Get()));
- device->UpdateAdvertisementData(rssi, ExtractFlags(advertisement.Get()),
- ExtractAdvertisedUUIDs(advertisement.Get()),
- ExtractTxPower(advertisement.Get()),
- ExtractServiceData(advertisement.Get()),
- ExtractManufacturerData(advertisement.Get()));
-}
-
RadioState GetState(IRadio* radio) {
RadioState state;
HRESULT hr = radio->get_State(&state);
@@ -951,12 +929,12 @@ void BluetoothAdapterWinrt::StartScanWithFilter(
return;
}
- auto advertisement_received_token = AddTypedEventHandler(
+ advertisement_received_token_ = AddTypedEventHandler(
ble_advertisement_watcher_.Get(),
&IBluetoothLEAdvertisementWatcher::add_Received,
base::BindRepeating(&BluetoothAdapterWinrt::OnAdvertisementReceived,
weak_ptr_factory_.GetWeakPtr()));
- if (!advertisement_received_token) {
+ if (!advertisement_received_token_) {
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), /*is_error=*/true,
@@ -964,13 +942,25 @@ void BluetoothAdapterWinrt::StartScanWithFilter(
return;
}
- advertisement_received_token_ = *advertisement_received_token;
+ advertisement_watcher_stopped_token_ = AddTypedEventHandler(
+ ble_advertisement_watcher_.Get(),
+ &IBluetoothLEAdvertisementWatcher::add_Stopped,
+ base::BindRepeating(&BluetoothAdapterWinrt::OnAdvertisementWatcherStopped,
+ weak_ptr_factory_.GetWeakPtr()));
+ if (!advertisement_watcher_stopped_token_) {
+ RemoveAdvertisementWatcherEventHandlers();
+ ui_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(callback), /*is_error=*/true,
+ UMABluetoothDiscoverySessionOutcome::UNKNOWN));
+ return;
+ }
hr = ble_advertisement_watcher_->Start();
if (FAILED(hr)) {
BLUETOOTH_LOG(ERROR) << "Starting the Advertisement Watcher failed: "
<< logging::SystemErrorCodeToString(hr);
- RemoveAdvertisementReceivedHandler();
+ RemoveAdvertisementWatcherEventHandlers();
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), /*is_error=*/true,
@@ -987,7 +977,7 @@ void BluetoothAdapterWinrt::StartScanWithFilter(
BLUETOOTH_LOG(ERROR)
<< "Starting Advertisement Watcher failed, it is in the Aborted "
"state.";
- RemoveAdvertisementReceivedHandler();
+ RemoveAdvertisementWatcherEventHandlers();
ui_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(std::move(callback), /*is_error=*/true,
@@ -995,6 +985,10 @@ void BluetoothAdapterWinrt::StartScanWithFilter(
return;
}
+ for (auto& observer : observers_) {
+ observer.AdapterDiscoveringChanged(this, /*discovering=*/true);
+ }
+
ui_task_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false,
UMABluetoothDiscoverySessionOutcome::SUCCESS));
@@ -1003,7 +997,7 @@ void BluetoothAdapterWinrt::StartScanWithFilter(
void BluetoothAdapterWinrt::StopScan(DiscoverySessionResultCallback callback) {
DCHECK_EQ(NumDiscoverySessions(), 0);
- RemoveAdvertisementReceivedHandler();
+ RemoveAdvertisementWatcherEventHandlers();
HRESULT hr = ble_advertisement_watcher_->Stop();
if (FAILED(hr)) {
BLUETOOTH_LOG(ERROR) << "Stopped the Advertisement Watcher failed: "
@@ -1015,8 +1009,14 @@ void BluetoothAdapterWinrt::StopScan(DiscoverySessionResultCallback callback) {
return;
}
- for (auto& device : devices_)
+ for (auto& device : devices_) {
device.second->ClearAdvertisementData();
+ }
+
+ for (auto& observer : observers_) {
+ observer.AdapterDiscoveringChanged(this, /*discovering=*/false);
+ }
+
ble_advertisement_watcher_.Reset();
ui_task_runner_->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), /*is_error=*/false,
@@ -1329,14 +1329,58 @@ void BluetoothAdapterWinrt::OnAdvertisementReceived(
}
BluetoothDevice* const device = it->second.get();
- ExtractAndUpdateAdvertisementData(received, device);
+
+ int16_t rssi = 0;
+ hr = received->get_RawSignalStrengthInDBm(&rssi);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(ERROR) << "get_RawSignalStrengthInDBm() failed: "
+ << logging::SystemErrorCodeToString(hr);
+ }
+
+ // Extract the remaining advertisement data.
+ ComPtr<IBluetoothLEAdvertisement> advertisement = GetAdvertisement(received);
+ base::Optional<std::string> device_name =
+ ExtractDeviceName(advertisement.Get());
+ base::Optional<int8_t> tx_power = ExtractTxPower(advertisement.Get());
+ BluetoothDevice::UUIDList advertised_uuids =
+ ExtractAdvertisedUUIDs(advertisement.Get());
+ BluetoothDevice::ServiceDataMap service_data_map =
+ ExtractServiceData(advertisement.Get());
+ BluetoothDevice::ManufacturerDataMap manufacturer_data_map =
+ ExtractManufacturerData(advertisement.Get());
+
+ static_cast<BluetoothDeviceWinrt*>(device)->UpdateLocalName(device_name);
+ device->UpdateAdvertisementData(rssi, ExtractFlags(advertisement.Get()),
+ advertised_uuids, tx_power, service_data_map,
+ manufacturer_data_map);
for (auto& observer : observers_) {
+ observer.DeviceAdvertisementReceived(
+ bluetooth_address, device->GetName(),
+ /*advertisement_name=*/device_name, rssi, tx_power,
+ device->GetAppearance(), advertised_uuids, service_data_map,
+ manufacturer_data_map);
is_new_device ? observer.DeviceAdded(this, device)
: observer.DeviceChanged(this, device);
}
}
+void BluetoothAdapterWinrt::OnAdvertisementWatcherStopped(
+ ABI::Windows::Devices::Bluetooth::Advertisement::
+ IBluetoothLEAdvertisementWatcher* watcher,
+ ABI::Windows::Devices::Bluetooth::Advertisement::
+ IBluetoothLEAdvertisementWatcherStoppedEventArgs* args) {
+ BluetoothError error;
+ HRESULT hr = args->get_Error(&error);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(ERROR) << "get_Error() failed: " << hr;
+ return;
+ }
+ BLUETOOTH_LOG(DEBUG) << "OnAdvertisementWatcherStopped() error=" << error;
+
+ MarkDiscoverySessionsAsInactive();
+}
+
void BluetoothAdapterWinrt::OnRegisterAdvertisement(
BluetoothAdvertisement* advertisement,
const CreateAdvertisementCallback& callback) {
@@ -1409,13 +1453,23 @@ void BluetoothAdapterWinrt::TryRemovePoweredRadioEventHandlers() {
}
}
-void BluetoothAdapterWinrt::RemoveAdvertisementReceivedHandler() {
+void BluetoothAdapterWinrt::RemoveAdvertisementWatcherEventHandlers() {
DCHECK(ble_advertisement_watcher_);
- HRESULT hr = ble_advertisement_watcher_->remove_Received(
- advertisement_received_token_);
- if (FAILED(hr)) {
- BLUETOOTH_LOG(ERROR) << "Removing the Received Handler failed: "
- << logging::SystemErrorCodeToString(hr);
+ if (advertisement_received_token_) {
+ HRESULT hr = ble_advertisement_watcher_->remove_Received(
+ *advertisement_received_token_);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(ERROR) << "Removing the Received Handler failed: "
+ << logging::SystemErrorCodeToString(hr);
+ }
+ }
+ if (advertisement_watcher_stopped_token_) {
+ HRESULT hr = ble_advertisement_watcher_->remove_Stopped(
+ *advertisement_watcher_stopped_token_);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(ERROR) << "Removing the Stopped Handler failed: "
+ << logging::SystemErrorCodeToString(hr);
+ }
}
}
diff --git a/chromium/device/bluetooth/bluetooth_adapter_winrt.h b/chromium/device/bluetooth/bluetooth_adapter_winrt.h
index 9bb463abbf9..fbb47308d9d 100644
--- a/chromium/device/bluetooth/bluetooth_adapter_winrt.h
+++ b/chromium/device/bluetooth/bluetooth_adapter_winrt.h
@@ -198,7 +198,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterWinrt : public BluetoothAdapter {
ABI::Windows::Devices::Bluetooth::Advertisement::
IBluetoothLEAdvertisementWatcher* watcher,
ABI::Windows::Devices::Bluetooth::Advertisement::
- IBluetoothLEAdvertisementReceivedEventArgs* received);
+ IBluetoothLEAdvertisementReceivedEventArgs* args);
+
+ void OnAdvertisementWatcherStopped(
+ ABI::Windows::Devices::Bluetooth::Advertisement::
+ IBluetoothLEAdvertisementWatcher* watcher,
+ ABI::Windows::Devices::Bluetooth::Advertisement::
+ IBluetoothLEAdvertisementWatcherStoppedEventArgs* args);
void OnRegisterAdvertisement(BluetoothAdvertisement* advertisement,
const CreateAdvertisementCallback& callback);
@@ -212,7 +218,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterWinrt : public BluetoothAdapter {
void TryRemovePoweredRadioEventHandlers();
- void RemoveAdvertisementReceivedHandler();
+ void RemoveAdvertisementWatcherEventHandlers();
bool is_initialized_ = false;
bool radio_access_allowed_ = false;
@@ -237,7 +243,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterWinrt : public BluetoothAdapter {
std::vector<scoped_refptr<BluetoothAdvertisement>> pending_advertisements_;
- EventRegistrationToken advertisement_received_token_;
+ base::Optional<EventRegistrationToken> advertisement_received_token_;
+ base::Optional<EventRegistrationToken> advertisement_watcher_stopped_token_;
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::Advertisement::
IBluetoothLEAdvertisementWatcher>
ble_advertisement_watcher_;
diff --git a/chromium/device/bluetooth/bluetooth_device.cc b/chromium/device/bluetooth/bluetooth_device.cc
index a567ff6d9db..c5cbedcc978 100644
--- a/chromium/device/bluetooth/bluetooth_device.cc
+++ b/chromium/device/bluetooth/bluetooth_device.cc
@@ -10,6 +10,7 @@
#include <string>
#include <utility>
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
diff --git a/chromium/device/bluetooth/bluetooth_device_unittest.cc b/chromium/device/bluetooth/bluetooth_device_unittest.cc
index e2f11788406..d46bfd80480 100644
--- a/chromium/device/bluetooth/bluetooth_device_unittest.cc
+++ b/chromium/device/bluetooth/bluetooth_device_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -584,10 +585,20 @@ TEST_F(BluetoothTest, MAYBE_AdvertisementData_Discovery) {
EXPECT_EQ(ToInt8(TestTxPower::LOWEST), device->GetInquiryTxPower().value());
}
-#if defined(OS_ANDROID) || defined(OS_MACOSX)
// TODO(dougt) As I turn on new platforms for WebBluetooth Scanning,
// I will relax this #ifdef
-TEST_F(BluetoothTest, DeviceAdvertisementReceived) {
+#if defined(OS_ANDROID) || defined(OS_MACOSX) || defined(OS_WIN)
+#define MAYBE_DeviceAdvertisementReceived DeviceAdvertisementReceived
+#else
+#define MAYBE_DeviceAdvertisementReceived DISABLED_DeviceAdvertisementReceived
+#endif
+// Tests that the Bluetooth adapter observer is notified when a device
+// advertisement is received.
+#if defined(OS_WIN)
+TEST_P(BluetoothTestWinrtOnly, DeviceAdvertisementReceived) {
+#else
+TEST_F(BluetoothTest, MAYBE_DeviceAdvertisementReceived) {
+#endif
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
@@ -599,28 +610,34 @@ TEST_F(BluetoothTest, DeviceAdvertisementReceived) {
StartLowEnergyDiscoverySession();
SimulateLowEnergyDevice(1);
- EXPECT_EQ(1, observer.device_advertisement_raw_received_count());
- EXPECT_EQ(kTestDeviceAddress1,
- observer.device_last_device_name().value_or(""));
- EXPECT_EQ(kTestDeviceName,
- observer.device_last_advertisement_name().value_or(""));
+ ASSERT_EQ(1, observer.device_advertisement_raw_received_count());
+ EXPECT_EQ(kTestDeviceName, observer.last_device_name().value_or(""));
+ EXPECT_EQ(kTestDeviceName, observer.last_advertisement_name().value_or(""));
+ EXPECT_EQ(static_cast<int>(TestRSSI::LOWEST),
+ observer.last_rssi().value_or(-1));
+ EXPECT_EQ(static_cast<int>(TestTxPower::LOWEST),
+ observer.last_tx_power().value_or(-1));
- // TestRSSI::LOWEST
- EXPECT_EQ(-81, observer.device_last_rssi().value_or(-1));
+ // BluetoothDevice::GetAppearance() is not implemented on all platforms.
+ // TODO(crbug.com/588083): Check this property when it is implemented.
- // TestTxPower::LOWEST
- EXPECT_EQ(-40, observer.device_last_tx_power().value_or(-1));
+ const device::BluetoothDevice::UUIDList kTestAdvertisedUUIDs = {
+ BluetoothUUID(kTestUUIDGenericAccess),
+ BluetoothUUID(kTestUUIDGenericAttribute)};
+ EXPECT_EQ(kTestAdvertisedUUIDs, observer.last_advertised_uuids());
- // TODO(crbug.com/588083)
- // EXPECT_EQ(0x04, observer.device_last_appearance());
+ const device::BluetoothDevice::ServiceDataMap kTestServiceDataMap = {
+ {BluetoothUUID(kTestUUIDHeartRate), {1}}};
+ EXPECT_EQ(kTestServiceDataMap, observer.last_service_data_map());
- // TODO(dougt): Service Data, ManufacturerData, Advertised UUID
+ const device::BluetoothDevice::ManufacturerDataMap kTestManufacturerDataMap =
+ {{kTestManufacturerId, {1, 2, 3, 4}}};
+ EXPECT_EQ(kTestManufacturerDataMap, observer.last_manufacturer_data_map());
// Double check that we can receive another advertisement.
SimulateLowEnergyDevice(2);
EXPECT_EQ(2, observer.device_advertisement_raw_received_count());
}
-#endif
#if defined(OS_ANDROID) || defined(OS_MACOSX)
#define MAYBE_GetUUIDs_Connection GetUUIDs_Connection
diff --git a/chromium/device/bluetooth/bluetooth_device_winrt.cc b/chromium/device/bluetooth/bluetooth_device_winrt.cc
index b1785fa92e6..bdb2afdc94c 100644
--- a/chromium/device/bluetooth/bluetooth_device_winrt.cc
+++ b/chromium/device/bluetooth/bluetooth_device_winrt.cc
@@ -32,26 +32,30 @@ namespace {
using ABI::Windows::Devices::Bluetooth::BluetoothConnectionStatus;
using ABI::Windows::Devices::Bluetooth::BluetoothConnectionStatus_Connected;
+using ABI::Windows::Devices::Bluetooth::BluetoothError;
+using ABI::Windows::Devices::Bluetooth::BluetoothError_Success;
using ABI::Windows::Devices::Bluetooth::BluetoothLEDevice;
+using ABI::Windows::Devices::Bluetooth::IBluetoothDeviceId;
+using ABI::Windows::Devices::Bluetooth::IBluetoothDeviceIdStatics;
+using ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice;
+using ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice2;
+using ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice4;
+using ABI::Windows::Devices::Bluetooth::IBluetoothLEDeviceStatics;
+using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattSession;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
- GattCommunicationStatus;
+ GattSessionStatus;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
- GattCommunicationStatus_Success;
+ GattSessionStatus_Active;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
- GattDeviceServicesResult;
+ GattSessionStatus_Closed;
+using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
- IGattDeviceServicesResult;
-using ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice2;
-using ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice3;
-using ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice;
-using ABI::Windows::Devices::Bluetooth::IBluetoothLEDeviceStatics;
-using ABI::Windows::Devices::Enumeration::DevicePairingResultStatus;
-using ABI::Windows::Devices::Enumeration::IDeviceInformation2;
+ IGattSessionStatics;
using ABI::Windows::Devices::Enumeration::IDeviceInformation;
+using ABI::Windows::Devices::Enumeration::IDeviceInformation2;
using ABI::Windows::Devices::Enumeration::IDeviceInformationCustomPairing;
-using ABI::Windows::Devices::Enumeration::IDeviceInformationPairing2;
using ABI::Windows::Devices::Enumeration::IDeviceInformationPairing;
-using ABI::Windows::Devices::Enumeration::IDevicePairingRequestedEventArgs;
+using ABI::Windows::Devices::Enumeration::IDeviceInformationPairing2;
using ABI::Windows::Foundation::IAsyncOperation;
using ABI::Windows::Foundation::IClosable;
using Microsoft::WRL::ComPtr;
@@ -118,7 +122,26 @@ void CloseDevice(ComPtr<IBluetoothLEDevice> ble_device) {
hr = closable->Close();
if (FAILED(hr)) {
- BLUETOOTH_LOG(DEBUG) << "IClosable::close() failed: "
+ BLUETOOTH_LOG(DEBUG) << "IClosable::Close() failed: "
+ << logging::SystemErrorCodeToString(hr);
+ }
+}
+
+void CloseGattSession(ComPtr<IGattSession> gatt_session) {
+ if (!gatt_session)
+ return;
+
+ ComPtr<IClosable> closable;
+ HRESULT hr = gatt_session.As(&closable);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "As IClosable failed: "
+ << logging::SystemErrorCodeToString(hr);
+ return;
+ }
+
+ hr = closable->Close();
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "IClosable::Close() failed: "
<< logging::SystemErrorCodeToString(hr);
}
}
@@ -132,6 +155,15 @@ void RemoveConnectionStatusHandler(IBluetoothLEDevice* ble_device,
}
}
+void RemoveGattSessionStatusHandler(IGattSession* gatt_session,
+ EventRegistrationToken token) {
+ HRESULT hr = gatt_session->remove_SessionStatusChanged(token);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "Removing ConnectionStatus Handler failed: "
+ << logging::SystemErrorCodeToString(hr);
+ }
+}
+
void RemoveGattServicesChangedHandler(IBluetoothLEDevice* ble_device,
EventRegistrationToken token) {
HRESULT hr = ble_device->remove_GattServicesChanged(token);
@@ -161,6 +193,7 @@ BluetoothDeviceWinrt::BluetoothDeviceWinrt(BluetoothAdapterWinrt* adapter,
}
BluetoothDeviceWinrt::~BluetoothDeviceWinrt() {
+ CloseGattSession(gatt_session_);
CloseDevice(ble_device_);
ClearEventRegistrations();
}
@@ -241,14 +274,15 @@ bool BluetoothDeviceWinrt::IsPaired() const {
}
bool BluetoothDeviceWinrt::IsConnected() const {
- return IsGattConnected();
+ return ble_device_ &&
+ connection_status_ == BluetoothConnectionStatus_Connected;
}
bool BluetoothDeviceWinrt::IsGattConnected() const {
- if (!ble_device_)
- return false;
+ if (!observe_gatt_session_status_change_events_)
+ return IsConnected();
- return connection_status_;
+ return gatt_session_ && gatt_session_status_ == GattSessionStatus_Active;
}
bool BluetoothDeviceWinrt::IsConnectable() const {
@@ -426,10 +460,7 @@ void BluetoothDeviceWinrt::CreateGattConnectionImpl(
BLUETOOTH_LOG(DEBUG)
<< "GetBluetoothLEDeviceStaticsActivationFactory failed: "
<< logging::SystemErrorCodeToString(hr);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BluetoothDeviceWinrt::DidFailToConnectGatt,
- weak_ptr_factory_.GetWeakPtr(),
- ConnectErrorCode::ERROR_FAILED));
+ NotifyGattConnectFailure();
return;
}
@@ -444,45 +475,53 @@ void BluetoothDeviceWinrt::CreateGattConnectionImpl(
BLUETOOTH_LOG(DEBUG)
<< "BluetoothLEDevice::FromBluetoothAddressAsync failed: "
<< logging::SystemErrorCodeToString(hr);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BluetoothDeviceWinrt::DidFailToConnectGatt,
- weak_ptr_factory_.GetWeakPtr(),
- ConnectErrorCode::ERROR_FAILED));
+ NotifyGattConnectFailure();
return;
}
- target_uuid_ = std::move(service_uuid);
hr = base::win::PostAsyncResults(
std::move(from_bluetooth_address_op),
- base::BindOnce(&BluetoothDeviceWinrt::OnFromBluetoothAddress,
- weak_ptr_factory_.GetWeakPtr()));
+ base::BindOnce(
+ &BluetoothDeviceWinrt::OnBluetoothLEDeviceFromBluetoothAddress,
+ weak_ptr_factory_.GetWeakPtr()));
if (FAILED(hr)) {
BLUETOOTH_LOG(DEBUG) << "PostAsyncResults failed: "
<< logging::SystemErrorCodeToString(hr);
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&BluetoothDeviceWinrt::DidFailToConnectGatt,
- weak_ptr_factory_.GetWeakPtr(),
- ConnectErrorCode::ERROR_FAILED));
+ NotifyGattConnectFailure();
return;
}
- pending_on_from_bluetooth_address_ = true;
+ target_uuid_ = std::move(service_uuid);
+ pending_gatt_service_discovery_start_ = true;
+}
+
+void BluetoothDeviceWinrt::NotifyGattConnectFailure() {
+ // Reset |pending_gatt_service_discovery_start_| so that
+ // UpgradeToFullDiscovery() doesn't mistakenly believe GATT discovery is
+ // imminent and therefore avoids starting one itself.
+ pending_gatt_service_discovery_start_ = false;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&BluetoothDeviceWinrt::DidFailToConnectGatt,
+ weak_ptr_factory_.GetWeakPtr(),
+ ConnectErrorCode::ERROR_FAILED));
}
void BluetoothDeviceWinrt::UpgradeToFullDiscovery() {
// |CreateGattConnectionImpl| has been called previously but having a specific
// |target_uuid_| was too optimistic and now a complete enumeration of
// services is needed.
- DCHECK(pending_on_from_bluetooth_address_ || connection_status_);
target_uuid_.reset();
- if (pending_on_from_bluetooth_address_) {
- // |OnFromBluetoothAddress| hasn't been called yet. Updating |target_uuid_|
- // will be sufficient to change the discovery that will be started.
+ if (pending_gatt_service_discovery_start_) {
+ // There is an imminent call to StartDiscovery(). Resetting |target_uuid_|
+ // now will be sufficient to change the discovery that will be started.
return;
}
+ DCHECK(ble_device_);
+ DCHECK(!observe_gatt_session_status_change_events_ || IsGattConnected());
+
// Restart discovery.
StartGattDiscovery();
}
@@ -494,6 +533,7 @@ void BluetoothDeviceWinrt::DisconnectGatt() {
// remaining references, so that the OS disconnects.
// Reference:
// - https://docs.microsoft.com/en-us/windows/uwp/devices-sensors/gatt-client
+ CloseGattSession(gatt_session_);
CloseDevice(ble_device_);
ClearGattServices();
@@ -511,13 +551,20 @@ HRESULT BluetoothDeviceWinrt::GetBluetoothLEDeviceStaticsActivationFactory(
RuntimeClass_Windows_Devices_Bluetooth_BluetoothLEDevice>(statics);
}
-void BluetoothDeviceWinrt::OnFromBluetoothAddress(
+HRESULT BluetoothDeviceWinrt::GetGattSessionStaticsActivationFactory(
+ IGattSessionStatics** statics) const {
+ return base::win::GetActivationFactory<
+ IGattSessionStatics,
+ RuntimeClass_Windows_Devices_Bluetooth_GenericAttributeProfile_GattSession>(
+ statics);
+}
+
+void BluetoothDeviceWinrt::OnBluetoothLEDeviceFromBluetoothAddress(
ComPtr<IBluetoothLEDevice> ble_device) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- pending_on_from_bluetooth_address_ = false;
if (!ble_device) {
BLUETOOTH_LOG(DEBUG) << "Getting Device From Bluetooth Address failed.";
- DidFailToConnectGatt(ConnectErrorCode::ERROR_FAILED);
+ NotifyGattConnectFailure();
return;
}
@@ -532,40 +579,168 @@ void BluetoothDeviceWinrt::OnFromBluetoothAddress(
base::BindRepeating(&BluetoothDeviceWinrt::OnConnectionStatusChanged,
weak_ptr_factory_.GetWeakPtr()));
- // For paired devices the OS immediately establishes a GATT connection after
- // the first advertisement. In this case our handler is registered too late to
- // catch the initial connection changed event, and we need to perform an
- // explicit check ourselves.
- if (IsGattConnected())
- DidConnectGatt();
-
- gatt_services_changed_token_ = AddTypedEventHandler(
- ble_device_.Get(), &IBluetoothLEDevice::add_GattServicesChanged,
- base::BindRepeating(&BluetoothDeviceWinrt::OnGattServicesChanged,
- weak_ptr_factory_.GetWeakPtr()));
-
- // Initiating the GATT discovery will result in a GATT connection attempt as
- // well and triggers OnConnectionStatusChanged on success.
- StartGattDiscovery();
-
name_changed_token_ = AddTypedEventHandler(
ble_device_.Get(), &IBluetoothLEDevice::add_NameChanged,
base::BindRepeating(&BluetoothDeviceWinrt::OnNameChanged,
weak_ptr_factory_.GetWeakPtr()));
+
+ if (!observe_gatt_session_status_change_events_) {
+ // GattSession SessionStatusChanged events can not be observed on
+ // 1703 (RS2) because BluetoothLEDevice::GetDeviceId() is not
+ // available. Instead, initiate GATT discovery which should result
+ // in a GATT connection attempt as well and trigger
+ // OnConnectionStatusChanged on success.
+ if (IsGattConnected()) {
+ DidConnectGatt();
+ }
+ StartGattDiscovery();
+ return;
+ }
+
+ // Next, obtain a GattSession so we can tell the OS to maintain a GATT
+ // connection with |ble_device_|.
+
+ // BluetoothLEDevice::GetDeviceId()
+ ComPtr<IBluetoothLEDevice4> ble_device_4;
+ HRESULT hr = ble_device_.As(&ble_device_4);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "Obtaining IBluetoothLEDevice4 failed: "
+ << logging::SystemErrorCodeToString(hr);
+ NotifyGattConnectFailure();
+ return;
+ }
+ ComPtr<IBluetoothDeviceId> bluetooth_device_id;
+ hr = ble_device_4->get_BluetoothDeviceId(&bluetooth_device_id);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "BluetoothDeviceId::FromId failed: "
+ << logging::SystemErrorCodeToString(hr);
+ NotifyGattConnectFailure();
+ return;
+ }
+
+ // GattSession::FromDeviceIdAsync()
+ IGattSessionStatics* gatt_session_statics = nullptr;
+ hr = GetGattSessionStaticsActivationFactory(&gatt_session_statics);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "GetGattSessionStaticsActivationFactory() failed: "
+ << logging::SystemErrorCodeToString(hr);
+ NotifyGattConnectFailure();
+ return;
+ }
+ ComPtr<IAsyncOperation<GattSession*>> gatt_session_from_device_id_async_op;
+ hr = gatt_session_statics->FromDeviceIdAsync(
+ bluetooth_device_id.Get(), &gatt_session_from_device_id_async_op);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "GattSession::FromDeviceId failed: "
+ << logging::SystemErrorCodeToString(hr);
+ NotifyGattConnectFailure();
+ return;
+ }
+ hr = base::win::PostAsyncResults(
+ std::move(gatt_session_from_device_id_async_op),
+ base::BindOnce(&BluetoothDeviceWinrt::OnGattSessionFromDeviceId,
+ weak_ptr_factory_.GetWeakPtr()));
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "PostAsyncResults failed: "
+ << logging::SystemErrorCodeToString(hr);
+ NotifyGattConnectFailure();
+ return;
+ }
+}
+
+void BluetoothDeviceWinrt::OnGattSessionFromDeviceId(
+ ComPtr<IGattSession> gatt_session) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(observe_gatt_session_status_change_events_);
+
+ if (!gatt_session) {
+ BLUETOOTH_LOG(DEBUG) << "Getting GattSession failed";
+ NotifyGattConnectFailure();
+ return;
+ }
+
+ gatt_session_ = std::move(gatt_session);
+
+ // Tell the OS to automatically establish and maintain a GATT connection.
+ HRESULT hr = gatt_session_->put_MaintainConnection(true);
+ if (FAILED(hr)) {
+ BLUETOOTH_LOG(DEBUG) << "Setting GattSession.MaintainConnection failed: "
+ << logging::SystemErrorCodeToString(hr);
+ NotifyGattConnectFailure();
+ return;
+ }
+
+ // Observe GattSessionStatus changes.
+ gatt_session_->get_SessionStatus(&gatt_session_status_);
+ gatt_session_status_changed_token_ = AddTypedEventHandler(
+ gatt_session_.Get(), &IGattSession::add_SessionStatusChanged,
+ base::BindRepeating(&BluetoothDeviceWinrt::OnGattSessionStatusChanged,
+ weak_ptr_factory_.GetWeakPtr()));
+
+ // Check whether we missed the initial GattSessionStatus change notification
+ // because the OS had already established a connection.
+ if (IsGattConnected()) {
+ DidConnectGatt();
+ StartGattDiscovery();
+ }
+}
+
+void BluetoothDeviceWinrt::OnGattSessionStatusChanged(
+ IGattSession* gatt_session,
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+ IGattSessionStatusChangedEventArgs* event_args) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ DCHECK(observe_gatt_session_status_change_events_);
+ DCHECK_EQ(gatt_session_.Get(), gatt_session);
+
+ GattSessionStatus old_status = gatt_session_status_;
+ event_args->get_Status(&gatt_session_status_);
+
+ BluetoothError error;
+ event_args->get_Error(&error);
+ BLUETOOTH_LOG(DEBUG) << "OnGattSessionStatusChanged() status="
+ << gatt_session_status_ << ", error=" << error;
+
+ if (pending_gatt_service_discovery_start_ &&
+ error != BluetoothError_Success) {
+ NotifyGattConnectFailure();
+ return;
+ }
+
+ // Spurious status change notifications may occur.
+ if (old_status == gatt_session_status_) {
+ return;
+ }
+
+ if (IsGattConnected()) {
+ DidConnectGatt();
+ StartGattDiscovery();
+ } else {
+ gatt_discoverer_.reset();
+ ClearGattServices();
+ DidDisconnectGatt();
+ }
}
void BluetoothDeviceWinrt::OnConnectionStatusChanged(
IBluetoothLEDevice* ble_device,
IInspectable* object) {
- BluetoothConnectionStatus new_status;
- ble_device->get_ConnectionStatus(&new_status);
- // Windows sometimes returns a status changed event with a status that has
- // not changed.
- if (new_status == connection_status_)
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ BluetoothConnectionStatus old_status = connection_status_;
+ ble_device->get_ConnectionStatus(&connection_status_);
+ BLUETOOTH_LOG(DEBUG) << "OnConnectionStatusChanged() status="
+ << connection_status_;
+
+ // Spurious status change notifications may occur.
+ if (old_status == connection_status_) {
return;
+ }
+
+ if (observe_gatt_session_status_change_events_) {
+ return;
+ }
- connection_status_ = new_status;
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
if (IsGattConnected()) {
DidConnectGatt();
} else {
@@ -577,15 +752,23 @@ void BluetoothDeviceWinrt::OnConnectionStatusChanged(
void BluetoothDeviceWinrt::OnGattServicesChanged(IBluetoothLEDevice* ble_device,
IInspectable* object) {
+ BLUETOOTH_LOG(DEBUG) << "OnGattServicesChanged()";
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // Note: We don't clear out |gatt_services_| here, as we don't want to break
+ // TODO(crbug/1085596): This event fires once for every newly discovered GATT
+ // service. Hence, the initial GATT service discovery aborts and restarts
+ // itself here once for every service discovered, which is unnecessary and
+ // slow.
+
+ // We don't clear out |gatt_services_| here, as we don't want to break
// existing references to Gatt Services that did not change.
device_uuids_.ClearServiceUUIDs();
+
SetGattServicesDiscoveryComplete(false);
adapter_->NotifyDeviceChanged(this);
if (IsGattConnected()) {
// In order to stop a potential ongoing GATT discovery, the GattDiscoverer
// is reset and a new discovery is initiated.
+ BLUETOOTH_LOG(DEBUG) << "Discovering GATT services anew";
StartGattDiscovery();
}
}
@@ -597,6 +780,14 @@ void BluetoothDeviceWinrt::OnNameChanged(IBluetoothLEDevice* ble_device,
}
void BluetoothDeviceWinrt::StartGattDiscovery() {
+ BLUETOOTH_LOG(DEBUG) << "StartGattDiscovery()";
+ pending_gatt_service_discovery_start_ = false;
+ if (!gatt_services_changed_token_) {
+ gatt_services_changed_token_ = AddTypedEventHandler(
+ ble_device_.Get(), &IBluetoothLEDevice::add_GattServicesChanged,
+ base::BindRepeating(&BluetoothDeviceWinrt::OnGattServicesChanged,
+ weak_ptr_factory_.GetWeakPtr()));
+ }
gatt_discoverer_ =
std::make_unique<BluetoothGattDiscovererWinrt>(ble_device_, target_uuid_);
gatt_discoverer_->StartGattDiscovery(
@@ -605,9 +796,11 @@ void BluetoothDeviceWinrt::StartGattDiscovery() {
}
void BluetoothDeviceWinrt::OnGattDiscoveryComplete(bool success) {
+ BLUETOOTH_LOG(DEBUG) << "OnGattDiscoveryComplete() success=" << success;
if (!success) {
- if (!IsGattConnected())
- DidFailToConnectGatt(ConnectErrorCode::ERROR_FAILED);
+ if (!IsGattConnected()) {
+ NotifyGattConnectFailure();
+ }
gatt_discoverer_.reset();
return;
}
@@ -661,6 +854,11 @@ void BluetoothDeviceWinrt::ClearEventRegistrations() {
*connection_changed_token_);
}
+ if (gatt_session_status_changed_token_) {
+ RemoveGattSessionStatusHandler(gatt_session_.Get(),
+ *gatt_session_status_changed_token_);
+ }
+
if (gatt_services_changed_token_) {
RemoveGattServicesChangedHandler(ble_device_.Get(),
*gatt_services_changed_token_);
diff --git a/chromium/device/bluetooth/bluetooth_device_winrt.h b/chromium/device/bluetooth/bluetooth_device_winrt.h
index 94b4b7140fb..d29c2890028 100644
--- a/chromium/device/bluetooth/bluetooth_device_winrt.h
+++ b/chromium/device/bluetooth/bluetooth_device_winrt.h
@@ -5,6 +5,7 @@
#ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_WINRT_H_
#define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_WINRT_H_
+#include <windows.devices.bluetooth.genericattributeprofile.h>
#include <windows.devices.bluetooth.h>
#include <wrl/client.h>
@@ -14,10 +15,13 @@
#include <string>
#include "base/callback_forward.h"
+#include "base/feature_list.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/threading/thread_checker.h"
+#include "base/win/windows_version.h"
+#include "device/base/features.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_export.h"
@@ -100,19 +104,38 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWinrt : public BluetoothDevice {
void UpgradeToFullDiscovery() override;
void DisconnectGatt() override;
- // This is declared virtual so that they can be overridden by tests.
+ // Declared virtual so that it can be overridden by tests.
virtual HRESULT GetBluetoothLEDeviceStaticsActivationFactory(
ABI::Windows::Devices::Bluetooth::IBluetoothLEDeviceStatics** statics)
const;
+ // Declared virtual so that it can be overridden by tests.
+ virtual HRESULT GetGattSessionStaticsActivationFactory(
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+ IGattSessionStatics** statics) const;
+
Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice>
ble_device_;
+ Microsoft::WRL::ComPtr<
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession>
+ gatt_session_;
private:
- void OnFromBluetoothAddress(
+ void OnBluetoothLEDeviceFromBluetoothAddress(
Microsoft::WRL::ComPtr<
ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice> ble_device);
+ void OnGattSessionFromDeviceId(
+ Microsoft::WRL::ComPtr<ABI::Windows::Devices::Bluetooth::
+ GenericAttributeProfile::IGattSession>
+ gatt_session);
+
+ void OnGattSessionStatusChanged(
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::IGattSession*
+ gatt_session,
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+ IGattSessionStatusChangedEventArgs* event_args);
+
void OnConnectionStatusChanged(
ABI::Windows::Devices::Bluetooth::IBluetoothLEDevice* ble_device,
IInspectable* object);
@@ -127,23 +150,42 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceWinrt : public BluetoothDevice {
void StartGattDiscovery();
void OnGattDiscoveryComplete(bool success);
+ void NotifyGattConnectFailure();
void ClearGattServices();
void ClearEventRegistrations();
ABI::Windows::Devices::Bluetooth::BluetoothConnectionStatus
connection_status_;
+ ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattSessionStatus
+ gatt_session_status_;
uint64_t raw_address_;
std::string address_;
base::Optional<std::string> local_name_;
std::unique_ptr<BluetoothPairingWinrt> pairing_;
- bool pending_on_from_bluetooth_address_ = false;
+ // Indicates whether the device should subscribe to GattSession
+ // SessionStatusChanged events. Doing so requires calling
+ // BluetoothLEDevice::GetDeviceId() which is only available on 1709
+ // (RS3) or newer. If false, GATT connection reliability may be
+ // degraded.
+ bool observe_gatt_session_status_change_events_ =
+ base::FeatureList::IsEnabled(kNewBLEGattSessionHandling) &&
+ base::win::GetVersion() >= base::win::Version::WIN10_RS3;
+
+ // Indicates whether a GATT service discovery is imminent. Discovery
+ // begins once GattSessionStatus for the device changes to |Active|
+ // if |observe_gatt_session_status_change_events_| is true, or once
+ // the BluetoothLEDevice has been obtained from
+ // FromBluetoothAddressAsync() otherwise.
+ bool pending_gatt_service_discovery_start_ = false;
+
base::Optional<BluetoothUUID> target_uuid_;
std::unique_ptr<BluetoothGattDiscovererWinrt> gatt_discoverer_;
base::Optional<EventRegistrationToken> connection_changed_token_;
+ base::Optional<EventRegistrationToken> gatt_session_status_changed_token_;
base::Optional<EventRegistrationToken> gatt_services_changed_token_;
base::Optional<EventRegistrationToken> name_changed_token_;
diff --git a/chromium/device/bluetooth/bluetooth_discovery_manager_mac.mm b/chromium/device/bluetooth/bluetooth_discovery_manager_mac.mm
index caa09ebd376..3331f05ba8e 100644
--- a/chromium/device/bluetooth/bluetooth_discovery_manager_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_discovery_manager_mac.mm
@@ -7,6 +7,7 @@
#import <IOBluetooth/objc/IOBluetoothDevice.h>
#import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h>
+#include "base/check_op.h"
#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
diff --git a/chromium/device/bluetooth/bluetooth_discovery_session.cc b/chromium/device/bluetooth/bluetooth_discovery_session.cc
index 9830d6c33a5..7f09a1eee21 100644
--- a/chromium/device/bluetooth/bluetooth_discovery_session.cc
+++ b/chromium/device/bluetooth/bluetooth_discovery_session.cc
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/logging.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_discovery_filter.h"
diff --git a/chromium/device/bluetooth/bluetooth_discovery_session.h b/chromium/device/bluetooth/bluetooth_discovery_session.h
index 2f94f3324b4..1d1ac97efbc 100644
--- a/chromium/device/bluetooth/bluetooth_discovery_session.h
+++ b/chromium/device/bluetooth/bluetooth_discovery_session.h
@@ -47,12 +47,10 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDiscoverySession {
INACTIVE
};
- // Destructor automatically terminates the discovery session. If this
- // results in a call to the underlying system to stop device discovery
- // (i.e. this instance represents the last active discovery session),
- // the call may not always succeed. To be notified of such failures,
- // users are highly encouraged to call BluetoothDiscoverySession::Stop,
- // instead of relying on the destructor.
+ // Terminates the discovery session. If this is the last active discovery
+ // session, a call to the underlying system to stop device discovery is made.
+ // Users may call BluetoothDiscoverySession::Stop() if they need to observe
+ // the result of that operation, but this is usually unnecessary.
virtual ~BluetoothDiscoverySession();
// Returns true if the session is active, false otherwise. If false, the
@@ -63,14 +61,11 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDiscoverySession {
// discovery continues.
virtual bool IsActive() const;
- // Requests this discovery session instance to stop. If this instance is
- // active, the session will stop. On success, |callback| is called and
- // on error |error_callback| is called. After a successful invocation, the
- // adapter may or may not stop device discovery, depending on whether or not
- // other active discovery sessions are present. Users are highly encouraged
- // to call this method to end a discovery session, instead of relying on the
- // destructor, so that they can be notified of the result via the callback
- // arguments.
+ // Requests this discovery session instance to stop. If this is the last
+ // active discovery session, a call to the underlying system to stop device
+ // discovery is made, and |error_callback| will be invoked if such a call
+ // fails. Typically, users can ignore this and simply destroy the instance
+ // instead of calling Stop().
virtual void Stop(base::Closure callback = base::DoNothing(),
ErrorCallback error_callback = base::DoNothing());
diff --git a/chromium/device/bluetooth/bluetooth_init_win.cc b/chromium/device/bluetooth/bluetooth_init_win.cc
index ab41d47174b..c623f10e6c1 100644
--- a/chromium/device/bluetooth/bluetooth_init_win.cc
+++ b/chromium/device/bluetooth/bluetooth_init_win.cc
@@ -4,7 +4,7 @@
#include "device/bluetooth/bluetooth_init_win.h"
-#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/scoped_thread_priority.h"
namespace {
@@ -28,8 +28,10 @@ bool HasBluetoothStack() {
} has_bluetooth_stack = HBS_UNKNOWN;
if (has_bluetooth_stack == HBS_UNKNOWN) {
- base::ScopedBlockingCall scoped_blocking_call(
- FROM_HERE, base::BlockingType::MAY_BLOCK);
+ // Mitigate the issues caused by loading DLLs on a background thread
+ // (http://crbug/973868).
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY_REPEATEDLY();
+
HRESULT hr = E_FAIL;
__try {
hr = __HrLoadAllImportsForDll("bthprops.cpl");
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_advertisement_manager_mac.mm b/chromium/device/bluetooth/bluetooth_low_energy_advertisement_manager_mac.mm
index a7b03c84975..e78ca6b190f 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_advertisement_manager_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_low_energy_advertisement_manager_mac.mm
@@ -5,6 +5,7 @@
#include "device/bluetooth/bluetooth_low_energy_advertisement_manager_mac.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
#include "base/optional.h"
#include "base/strings/sys_string_conversions.h"
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm b/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm
index 6f343a774b2..93a4ba716f2 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_low_energy_device_mac.mm
@@ -7,6 +7,7 @@
#import <CoreFoundation/CoreFoundation.h>
#include <stddef.h>
+#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/memory/ptr_util.h"
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_device_watcher_mac.mm b/chromium/device/bluetooth/bluetooth_low_energy_device_watcher_mac.mm
index 955d36777f8..ad46a81a983 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_device_watcher_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_low_energy_device_watcher_mac.mm
@@ -8,6 +8,7 @@
#include "base/bind.h"
#include "base/files/file_util.h"
+#include "base/logging.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/task_traits.h"
#include "device/bluetooth/bluetooth_adapter_mac.h"
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm b/chromium/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
index a128699d9ae..e9ca28150ff 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_low_energy_discovery_manager_mac.mm
@@ -6,6 +6,7 @@
#include <memory>
+#include "base/logging.h"
#include "base/mac/mac_util.h"
#include "base/strings/sys_string_conversions.h"
#include "device/bluetooth/bluetooth_adapter_mac.h"
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_win.cc b/chromium/device/bluetooth/bluetooth_low_energy_win.cc
index c2a4ae29246..013e0574972 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_win.cc
+++ b/chromium/device/bluetooth/bluetooth_low_energy_win.cc
@@ -801,20 +801,15 @@ HRESULT BluetoothLowEnergyWrapper::ReadCharacteristicValue(
HRESULT BluetoothLowEnergyWrapper::WriteCharacteristicValue(
base::FilePath& service_path,
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
- PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) {
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value,
+ ULONG flags) {
base::File file(service_path, base::File::FLAG_OPEN | base::File::FLAG_READ |
base::File::FLAG_WRITE);
if (!file.IsValid())
return HRESULT_FROM_WIN32(ERROR_OPEN_FAILED);
- ULONG flag = BLUETOOTH_GATT_FLAG_NONE;
- if (!characteristic->IsWritable) {
- DCHECK(characteristic->IsWritableWithoutResponse);
- flag |= BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
- }
-
return BluetoothGATTSetCharacteristicValue(
- file.GetPlatformFile(), characteristic, new_value, NULL, flag);
+ file.GetPlatformFile(), characteristic, new_value, {}, flags);
}
HRESULT BluetoothLowEnergyWrapper::RegisterGattEvents(
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_win.h b/chromium/device/bluetooth/bluetooth_low_energy_win.h
index e582d4cbaa8..e248c97c8b8 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_win.h
+++ b/chromium/device/bluetooth/bluetooth_low_energy_win.h
@@ -188,7 +188,8 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyWrapper {
virtual HRESULT WriteCharacteristicValue(
base::FilePath& service_path,
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
- PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value);
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value,
+ ULONG flags);
// Register GATT events of |event_type| in the service with service device
// path |service_path|. |event_parameter| is the event's parameter. |callback|
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_win_fake.cc b/chromium/device/bluetooth/bluetooth_low_energy_win_fake.cc
index dcf4db10232..b25021dd531 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_win_fake.cc
+++ b/chromium/device/bluetooth/bluetooth_low_energy_win_fake.cc
@@ -216,7 +216,15 @@ HRESULT BluetoothLowEnergyWrapperFake::ReadCharacteristicValue(
HRESULT BluetoothLowEnergyWrapperFake::WriteCharacteristicValue(
base::FilePath& service_path,
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
- PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) {
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value,
+ ULONG flags) {
+ // Web Bluetooth implementation currently only supports no flags or write
+ // without response flag even if Windows supports other flags
+ if (flags != BLUETOOTH_GATT_FLAG_NONE &&
+ flags != BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE) {
+ return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
+ }
+
GattCharacteristic* target_characteristic =
GetSimulatedGattCharacteristic(service_path, characteristic);
if (target_characteristic == nullptr)
diff --git a/chromium/device/bluetooth/bluetooth_low_energy_win_fake.h b/chromium/device/bluetooth/bluetooth_low_energy_win_fake.h
index 9f0e2c0e0c6..01c482dd35d 100644
--- a/chromium/device/bluetooth/bluetooth_low_energy_win_fake.h
+++ b/chromium/device/bluetooth/bluetooth_low_energy_win_fake.h
@@ -130,7 +130,8 @@ class BluetoothLowEnergyWrapperFake : public BluetoothLowEnergyWrapper {
HRESULT WriteCharacteristicValue(
base::FilePath& service_path,
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
- PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value) override;
+ PBTH_LE_GATT_CHARACTERISTIC_VALUE new_value,
+ ULONG flags) override;
HRESULT RegisterGattEvents(
base::FilePath& service_path,
BTH_LE_GATT_EVENT_TYPE type,
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
index 3d1252dc2d6..9cc33c1135c 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.cc
@@ -107,12 +107,6 @@ void BluetoothRemoteGattCharacteristic::StartNotifySession(
}
#endif
-bool BluetoothRemoteGattCharacteristic::WriteWithoutResponse(
- base::span<const uint8_t> value) {
- NOTIMPLEMENTED();
- return false;
-}
-
bool BluetoothRemoteGattCharacteristic::AddDescriptor(
std::unique_ptr<BluetoothRemoteGattDescriptor> descriptor) {
if (!descriptor)
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.h b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.h
index 64b0875ded6..75996110686 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.h
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic.h
@@ -42,6 +42,12 @@ class BluetoothRemoteGattDescriptor;
class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristic
: public virtual BluetoothGattCharacteristic {
public:
+ // Parameter for WriteRemoteCharacteristic
+ enum class WriteType {
+ kWithResponse,
+ kWithoutResponse,
+ };
+
// The ValueCallback is used to return the value of a remote characteristic
// upon a read request.
using ValueCallback = base::OnceCallback<void(const std::vector<uint8_t>&)>;
@@ -136,13 +142,25 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristic
virtual void ReadRemoteCharacteristic(ValueCallback callback,
ErrorCallback error_callback) = 0;
+ // Sends a write request to a remote characteristic with the value |value|
+ // using the specified |write_type|. |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.
+ virtual void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
+ WriteType write_type,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) = 0;
+
+ // DEPRECATED: Use WriteRemoteCharacteristic instead. This method remains
+ // for backward compatibility.
// Sends a 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.
- virtual void WriteRemoteCharacteristic(const std::vector<uint8_t>& value,
- base::OnceClosure callback,
- ErrorCallback error_callback) = 0;
+ virtual void DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) = 0;
#if defined(OS_CHROMEOS)
// Sends a prepare write request to a remote characteristic with the value
@@ -157,15 +175,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristic
ErrorCallback error_callback) = 0;
#endif
- // Sends a write request to a remote characteristic with the value |value|
- // without waiting for a response. This method returns false to signal
- // failures. When attempting to write the remote characteristic true is
- // returned without a guarantee of success. This method only applies to remote
- // characteristics and will fail for those that are locally hosted.
- // This method is currently implemented only on macOS.
- // TODO(https://crbug.com/831524): Implement it on other platforms as well.
- virtual bool WriteWithoutResponse(base::span<const uint8_t> value);
-
protected:
using DescriptorMap =
base::flat_map<std::string,
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
index 395d1dbe209..fe92a2b85c8 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.cc
@@ -152,6 +152,7 @@ void BluetoothRemoteGattCharacteristicAndroid::ReadRemoteCharacteristic(
void BluetoothRemoteGattCharacteristicAndroid::WriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
+ WriteType write_type,
base::OnceClosure callback,
ErrorCallback error_callback) {
if (read_pending_ || write_pending_) {
@@ -162,9 +163,48 @@ void BluetoothRemoteGattCharacteristicAndroid::WriteRemoteCharacteristic(
return;
}
+ AndroidWriteType android_write_type;
+ switch (write_type) {
+ case WriteType::kWithResponse:
+ android_write_type = AndroidWriteType::kDefault;
+ break;
+ case WriteType::kWithoutResponse:
+ android_write_type = AndroidWriteType::kNoResponse;
+ break;
+ }
+
+ JNIEnv* env = AttachCurrentThread();
+ if (!Java_ChromeBluetoothRemoteGattCharacteristic_writeRemoteCharacteristic(
+ env, j_characteristic_, base::android::ToJavaByteArray(env, value),
+ static_cast<int>(android_write_type))) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(error_callback),
+ BluetoothRemoteGattService::GATT_ERROR_FAILED));
+ return;
+ }
+
+ write_pending_ = true;
+ write_callback_ = std::move(callback);
+ write_error_callback_ = std::move(error_callback);
+}
+
+void BluetoothRemoteGattCharacteristicAndroid::
+ DeprecatedWriteRemoteCharacteristic(const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) {
+ if (read_pending_ || write_pending_) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(error_callback),
+ BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
+ return;
+ }
+
JNIEnv* env = AttachCurrentThread();
if (!Java_ChromeBluetoothRemoteGattCharacteristic_writeRemoteCharacteristic(
- env, j_characteristic_, base::android::ToJavaByteArray(env, value))) {
+ env, j_characteristic_, base::android::ToJavaByteArray(env, value),
+ static_cast<int>(AndroidWriteType::kNone))) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
base::BindOnce(std::move(error_callback),
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
index 63811345a6e..7710e77ce2a 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_android.h
@@ -66,8 +66,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicAndroid
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;
// Called when value changed event occurs.
void OnChanged(JNIEnv* env,
@@ -108,6 +113,15 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicAndroid
ErrorCallback error_callback) override;
private:
+ // Android API characteristic write type flags.
+ // https://developer.android.com/reference/android/bluetooth/BluetoothGattCharacteristic.html
+ enum class AndroidWriteType {
+ kNone = 0,
+ kNoResponse = 1 << 0,
+ kDefault = 1 << 1,
+ kSigned = 1 << 2,
+ };
+
BluetoothRemoteGattCharacteristicAndroid(
BluetoothAdapterAndroid* adapter,
BluetoothRemoteGattServiceAndroid* service,
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
index 34e4a46769b..71510e2bddc 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h
@@ -44,9 +44,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicMac
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;
- bool WriteWithoutResponse(base::span<const uint8_t> value) override;
+ void DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) override;
protected:
void SubscribeToNotifications(BluetoothRemoteGattDescriptor* ccc_descriptor,
@@ -82,8 +86,6 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicMac
bool IsReadable() const;
// Returns true if the characteristic is writable.
bool IsWritable() const;
- // Returns true if the characteristic is writable without response.
- bool IsWritableWithoutResponse() const;
// Returns true if the characteristic supports notifications or indications.
bool SupportsNotificationsOrIndications() const;
// Returns the write type (with or without responses).
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
index 65020670281..ec869f70c2f 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_mac.mm
@@ -5,6 +5,7 @@
#include "device/bluetooth/bluetooth_remote_gatt_characteristic_mac.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -154,6 +155,46 @@ void BluetoothRemoteGattCharacteristicMac::ReadRemoteCharacteristic(
void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
+ WriteType write_type,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) {
+ if (HasPendingRead() || HasPendingWrite()) {
+ DVLOG(1) << *this << ": Characteristic write already in progress.";
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(error_callback),
+ BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS));
+ return;
+ }
+ DVLOG(1) << *this << ": Write characteristic.";
+ write_characteristic_value_callbacks_ =
+ std::make_pair(std::move(callback), std::move(error_callback));
+ base::scoped_nsobject<NSData> nsdata_value(
+ [[NSData alloc] initWithBytes:value.data() length:value.size()]);
+
+ CBCharacteristicWriteType cb_write_type;
+ switch (write_type) {
+ case WriteType::kWithResponse:
+ cb_write_type = CBCharacteristicWriteWithResponse;
+ break;
+ case WriteType::kWithoutResponse:
+ cb_write_type = CBCharacteristicWriteWithoutResponse;
+ break;
+ }
+
+ [GetCBPeripheral() writeValue:nsdata_value
+ forCharacteristic:cb_characteristic_
+ type:cb_write_type];
+ if (cb_write_type == CBCharacteristicWriteWithoutResponse) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&BluetoothRemoteGattCharacteristicMac::DidWriteValue,
+ weak_ptr_factory_.GetWeakPtr(), nil));
+ }
+}
+
+void BluetoothRemoteGattCharacteristicMac::DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
base::OnceClosure callback,
ErrorCallback error_callback) {
if (!IsWritable()) {
@@ -189,26 +230,6 @@ void BluetoothRemoteGattCharacteristicMac::WriteRemoteCharacteristic(
}
}
-bool BluetoothRemoteGattCharacteristicMac::WriteWithoutResponse(
- base::span<const uint8_t> value) {
- if (!IsWritableWithoutResponse()) {
- DVLOG(1) << *this << ": Characteristic not writable without response.";
- return false;
- }
- if (HasPendingRead() || HasPendingWrite()) {
- DVLOG(1) << *this << ": Characteristic write already in progress.";
- return false;
- }
-
- DVLOG(1) << *this << ": Write characteristic without response.";
- base::scoped_nsobject<NSData> nsdata_value(
- [[NSData alloc] initWithBytes:value.data() length:value.size()]);
- [GetCBPeripheral() writeValue:nsdata_value
- forCharacteristic:cb_characteristic_
- type:CBCharacteristicWriteWithoutResponse];
- return true;
-}
-
void BluetoothRemoteGattCharacteristicMac::SubscribeToNotifications(
BluetoothRemoteGattDescriptor* ccc_descriptor,
base::OnceClosure callback,
@@ -407,10 +428,6 @@ bool BluetoothRemoteGattCharacteristicMac::IsWritable() const {
(properties & PROPERTY_WRITE_WITHOUT_RESPONSE);
}
-bool BluetoothRemoteGattCharacteristicMac::IsWritableWithoutResponse() const {
- return (GetProperties() & PROPERTY_WRITE_WITHOUT_RESPONSE);
-}
-
bool BluetoothRemoteGattCharacteristicMac::SupportsNotificationsOrIndications()
const {
BluetoothGattCharacteristic::Properties properties = GetProperties();
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
index 3834b62cdd4..4581effa62f 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/test/bind_test_util.h"
@@ -34,6 +35,7 @@
using testing::_;
using testing::Invoke;
+using WriteType = device::BluetoothRemoteGattCharacteristic::WriteType;
namespace device {
@@ -151,7 +153,7 @@ class BluetoothRemoteGattCharacteristicTest :
// these two cases, this small utility function is added.
bool IsClassicWin() {
#if defined(OS_WIN)
- return !GetParam();
+ return !UsesNewBleImplementation();
#else
return false;
#endif
@@ -419,7 +421,50 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
+ base::RunLoop loop;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(empty_vector, last_write_value_);
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothRemoteGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop.Run();
+
+ // Duplicate write reported from OS shouldn't cause a problem:
+ SimulateGattCharacteristicWrite(characteristic1_);
+ base::RunLoop().RunUntilIdle();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_Empty \
+ DeprecatedWriteRemoteCharacteristic_Empty
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_Empty \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_Empty
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic with empty value buffer.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ DeprecatedWriteRemoteCharacteristic_Empty) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_Empty) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
SimulateGattCharacteristicWrite(characteristic1_);
@@ -496,8 +541,60 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
- bool write_error_callback_called = false;
+ base::RunLoop loop;
characteristic1_->WriteRemoteCharacteristic(
+ {} /* value */, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothRemoteGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ // Retrying Write should fail:
+ characteristic1_->WriteRemoteCharacteristic(
+ {} /* value */, WriteType::kWithResponse,
+ base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothRemoteGattService::GattErrorCode error_code) {
+ EXPECT_EQ(
+ BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS,
+ error_code);
+ loop.Quit();
+ }));
+ }));
+
+ DeleteDevice(device_); // TODO(576906) delete only the characteristic.
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_Retry_DeprecatedWriteRemoteCharacteristic_DuringDestruction_Fails \
+ Retry_DeprecatedWriteRemoteCharacteristic_DuringDestruction_Fails
+#else
+#define MAYBE_Retry_DeprecatedWriteRemoteCharacteristic_DuringDestruction_Fails \
+ DISABLED_Retry_DeprecatedWriteRemoteCharacteristic_DuringDestruction_Fails
+#endif
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ Retry_DeprecatedWriteRemoteCharacteristic_DuringDestruction_Fails) {
+#else
+TEST_F(
+ BluetoothRemoteGattCharacteristicTest,
+ MAYBE_Retry_DeprecatedWriteRemoteCharacteristic_DuringDestruction_Fails) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ bool write_error_callback_called = false;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
{} /* value */, GetCallback(Call::NOT_EXPECTED),
base::BindLambdaForTesting(
[&](BluetoothRemoteGattService::GattErrorCode error_code) {
@@ -505,7 +602,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
error_code);
write_error_callback_called = true;
// Retrying Write should fail:
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
{} /* value */, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
}));
@@ -617,8 +714,8 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
DISABLED_WriteRemoteCharacteristic_AfterDeleted
#endif
// Tests WriteRemoteCharacteristic completing after Chrome objects are deleted.
-// macOS: Not applicable: This can never happen if CBPeripheral delegate is set
-// to nil.
+// macOS: Not applicable: This can never happen if CBPeripheral
+// delegate is set to nil.
// WinRT: Not applicable: Pending callbacks won't fire once the underlying
// object is destroyed.
#if defined(OS_WIN)
@@ -636,7 +733,54 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
std::vector<uint8_t> empty_vector;
+ base::RunLoop loop;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothGattService::GATT_ERROR_FAILED, error_code);
+ loop.Quit();
+ }));
+
+ RememberCharacteristicForSubsequentAction(characteristic1_);
+ DeleteDevice(device_); // TODO(576906) delete only the characteristic.
+
+ SimulateGattCharacteristicWrite(/* use remembered characteristic */ nullptr);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_AfterDeleted \
+ DeprecatedWriteRemoteCharacteristic_AfterDeleted
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_AfterDeleted \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_AfterDeleted
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic completing after Chrome objects are
+// deleted.
+// macOS: Not applicable: This can never happen if CBPeripheral
+// delegate is set to nil.
+// WinRT: Not applicable: Pending callbacks won't fire once the underlying
+// object is destroyed.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWin32Only,
+ DeprecatedWriteRemoteCharacteristic_AfterDeleted) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_AfterDeleted) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
@@ -671,8 +815,65 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop;
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothRemoteGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ loop.Quit();
+ }));
+
+// Set up for receiving a write response after disconnection.
+// On macOS and WinRT no events arrive after disconnection so there is no point
+// in building the infrastructure to test this behavior. FYI
+// the code CHECKs that responses arrive only when the device is connected.
+#if defined(OS_ANDROID)
+ RememberCharacteristicForSubsequentAction(characteristic1_);
+#endif // defined(OS_ANDROID)
+
+ ASSERT_EQ(1u, adapter_->GetDevices().size());
+ SimulateDeviceBreaksConnection(adapter_->GetDevices()[0]);
+ loop.Run();
+
+// Dispatch write response after disconnection. See above explanation for why
+// we don't do this in macOS and WinRT.
+#if defined(OS_ANDROID)
+ SimulateGattCharacteristicWrite(/* use remembered characteristic */ nullptr);
+ base::RunLoop().RunUntilIdle();
+#endif // defined(OS_ANDROID)
+}
+
+// TODO(crbug.com/663131): Enable test on windows when disconnection is
+// implemented.
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_Disconnected \
+ DeprecatedWriteRemoteCharacteristic_Disconnected
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_Disconnected \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_Disconnected
+#endif
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrtOnly,
+ DeprecatedWriteRemoteCharacteristic_Disconnected) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_Disconnected) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
@@ -780,8 +981,8 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
base::RunLoop().RunUntilIdle();
EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
-// TODO(https://crbug.com/699694): Remove this #if once the bug on Windows is
-// fixed.
+ // TODO(https://crbug.com/699694): Remove this #if once the bug on Windows is
+ // fixed.
if (IsClassicWin()) {
EXPECT_FALSE(observer.last_gatt_characteristic_id().empty());
EXPECT_TRUE(observer.last_gatt_characteristic_uuid().IsValid());
@@ -812,9 +1013,57 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, MAYBE_WriteRemoteCharacteristic) {
TestBluetoothAdapterObserver observer(adapter_);
+ base::RunLoop loop;
uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
std::vector<uint8_t> test_vector(values, values + base::size(values));
characteristic1_->WriteRemoteCharacteristic(
+ test_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+
+ // TODO(crbug.com/653291): remove this if once the bug on windows is
+ // fixed.
+ if (!IsClassicWin())
+ EXPECT_EQ(0, observer.gatt_characteristic_value_changed_count());
+ EXPECT_EQ(test_vector, last_write_value_);
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic \
+ DeprecatedWriteRemoteCharacteristic
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic \
+ DISABLED_DeprecatedWriteRemoteCharacteristic
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic with non-empty value buffer.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ DeprecatedWriteRemoteCharacteristic) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ TestBluetoothAdapterObserver observer(adapter_);
+
+ uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
+ std::vector<uint8_t> test_vector(values, values + base::size(values));
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
@@ -899,9 +1148,69 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop1;
uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
std::vector<uint8_t> test_vector(values, values + base::size(values));
characteristic1_->WriteRemoteCharacteristic(
+ test_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector, last_write_value_);
+ loop1.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error" << error_code;
+ loop1.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop1.Run();
+
+ // Write again, with different value:
+ ResetEventCounts();
+ base::RunLoop loop2;
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(empty_vector, last_write_value_);
+ loop2.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error" << error_code;
+ loop2.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop2.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_Twice \
+ DeprecatedWriteRemoteCharacteristic_Twice
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_Twice \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_Twice
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic multiple times.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ DeprecatedWriteRemoteCharacteristic_Twice) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_Twice) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ uint8_t values[] = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
+ std::vector<uint8_t> test_vector(values, values + base::size(values));
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
@@ -915,7 +1224,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
// Write again, with different value:
ResetEventCounts();
std::vector<uint8_t> empty_vector;
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
@@ -999,9 +1308,76 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop1;
std::vector<uint8_t> test_vector1;
test_vector1.push_back(111);
characteristic1_->WriteRemoteCharacteristic(
+ test_vector1, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ if (IsClassicWin()) {
+ EXPECT_EQ(test_vector1, last_write_value_);
+ }
+ loop1.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error" << error_code;
+ loop1.Quit();
+ }));
+ if (!IsClassicWin()) {
+ EXPECT_EQ(test_vector1, last_write_value_);
+ }
+
+ base::RunLoop loop2;
+ std::vector<uint8_t> test_vector2;
+ test_vector2.push_back(222);
+ characteristic2_->WriteRemoteCharacteristic(
+ test_vector2, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ if (IsClassicWin()) {
+ EXPECT_EQ(test_vector2, last_write_value_);
+ }
+ loop2.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error" << error_code;
+ loop2.Quit();
+ }));
+ if (!IsClassicWin()) {
+ EXPECT_EQ(test_vector2, last_write_value_);
+ }
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop1.Run();
+
+ SimulateGattCharacteristicWrite(characteristic2_);
+ loop2.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_MultipleCharacteristics \
+ DeprecatedWriteRemoteCharacteristic_MultipleCharacteristics
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_MultipleCharacteristics \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_MultipleCharacteristics
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic on two characteristics.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ DeprecatedWriteRemoteCharacteristic_MultipleCharacteristics) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_MultipleCharacteristics) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> test_vector1;
+ test_vector1.push_back(111);
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector1, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
if (!IsClassicWin())
@@ -1009,7 +1385,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
std::vector<uint8_t> test_vector2;
test_vector2.push_back(222);
- characteristic2_->WriteRemoteCharacteristic(
+ characteristic2_->DeprecatedWriteRemoteCharacteristic(
test_vector2, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
if (!IsClassicWin())
@@ -1110,10 +1486,67 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop;
std::vector<uint8_t> test_vector_1 = {0, 1, 2, 3, 4};
std::vector<uint8_t> test_vector_2 = {0xf, 0xf0, 0xff};
characteristic1_->WriteRemoteCharacteristic(
+ test_vector_1, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector_1, last_write_value_);
+
+ characteristic1_->WriteRemoteCharacteristic(
+ test_vector_2, WriteType::kWithResponse,
+ base::BindLambdaForTesting([&] {
+ EXPECT_EQ(2, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector_2, last_write_value_);
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_RemoteCharacteristic_Nested_DeprecatedWrite_DeprecatedWrite \
+ RemoteCharacteristic_Nested_DeprecatedWrite_DeprecatedWrite
+#else
+#define MAYBE_RemoteCharacteristic_Nested_DeprecatedWrite_DeprecatedWrite \
+ DISABLED_RemoteCharacteristic_Nested_DeprecatedWrite_DeprecatedWrite
+#endif
+// Tests a nested DeprecatedWriteRemoteCharacteristic from within another
+// DeprecatedWriteRemoteCharacteristic.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ RemoteCharacteristic_Nested_DeprecatedWrite_DeprecatedWrite) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_RemoteCharacteristic_Nested_DeprecatedWrite_DeprecatedWrite) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> test_vector_1 = {0, 1, 2, 3, 4};
+ std::vector<uint8_t> test_vector_2 = {0xf, 0xf0, 0xff};
+
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector_1, base::BindLambdaForTesting([&] {
GetCallback(Call::EXPECTED).Run();
@@ -1122,7 +1555,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
EXPECT_EQ(0, error_callback_count_);
EXPECT_EQ(test_vector_1, last_write_value_);
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector_2, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
SimulateGattCharacteristicWrite(characteristic1_);
@@ -1162,6 +1595,67 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop;
+ std::vector<uint8_t> test_vector_1 = {0, 1, 2, 3, 4};
+ std::vector<uint8_t> test_vector_2 = {0xf, 0xf0, 0xff};
+
+ characteristic1_->ReadRemoteCharacteristic(
+ base::BindLambdaForTesting([&](const std::vector<uint8_t>& data) {
+ EXPECT_EQ(1, gatt_read_characteristic_attempts_);
+ EXPECT_EQ(0, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector_1, data);
+ EXPECT_EQ(test_vector_1, characteristic1_->GetValue());
+
+ characteristic1_->WriteRemoteCharacteristic(
+ test_vector_2, WriteType::kWithResponse,
+ base::BindLambdaForTesting([&] {
+ EXPECT_EQ(1, gatt_read_characteristic_attempts_);
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector_2, last_write_value_);
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ SimulateGattCharacteristicRead(characteristic1_, test_vector_1);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_RemoteCharacteristic_Nested_Read_DeprecatedWrite \
+ RemoteCharacteristic_Nested_Read_DeprecatedWrite
+#else
+#define MAYBE_RemoteCharacteristic_Nested_Read_DeprecatedWrite \
+ DISABLED_RemoteCharacteristic_Nested_Read_DeprecatedWrite
+#endif
+// Tests a nested DeprecatedWriteRemoteCharacteristic from within a
+// ReadRemoteCharacteristic.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ RemoteCharacteristic_Nested_Read_DeprecatedWrite) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_RemoteCharacteristic_Nested_Read_DeprecatedWrite) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_READ |
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
std::vector<uint8_t> test_vector_1 = {0, 1, 2, 3, 4};
std::vector<uint8_t> test_vector_2 = {0xf, 0xf0, 0xff};
@@ -1176,7 +1670,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
EXPECT_EQ(test_vector_1, last_read_value_);
EXPECT_EQ(test_vector_1, characteristic1_->GetValue());
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector_2, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
SimulateGattCharacteristicWrite(characteristic1_);
@@ -1216,10 +1710,69 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop;
std::vector<uint8_t> test_vector_1 = {0, 1, 2, 3, 4};
std::vector<uint8_t> test_vector_2 = {0xf, 0xf0, 0xff};
characteristic1_->WriteRemoteCharacteristic(
+ test_vector_1, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(0, gatt_read_characteristic_attempts_);
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector_1, last_write_value_);
+
+ characteristic1_->ReadRemoteCharacteristic(
+ base::BindLambdaForTesting([&](const std::vector<uint8_t>& data) {
+ EXPECT_EQ(1, gatt_read_characteristic_attempts_);
+ EXPECT_EQ(1, gatt_write_characteristic_attempts_);
+ EXPECT_EQ(test_vector_2, data);
+ EXPECT_EQ(test_vector_2, characteristic1_->GetValue());
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+ SimulateGattCharacteristicRead(characteristic1_, test_vector_2);
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_RemoteCharacteristic_Nested_DeprecatedWrite_Read \
+ RemoteCharacteristic_Nested_DeprecatedWrite_Read
+#else
+#define MAYBE_RemoteCharacteristic_Nested_DeprecatedWrite_Read \
+ DISABLED_RemoteCharacteristic_Nested_DeprecatedWrite_Read
+#endif
+// Tests a nested ReadRemoteCharacteristic from within a
+// DeprecatedWriteRemoteCharacteristic.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ RemoteCharacteristic_Nested_DeprecatedWrite_Read) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_RemoteCharacteristic_Nested_DeprecatedWrite_Read) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_READ |
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> test_vector_1 = {0, 1, 2, 3, 4};
+ std::vector<uint8_t> test_vector_2 = {0xf, 0xf0, 0xff};
+
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
test_vector_1, base::BindLambdaForTesting([&] {
GetCallback(Call::EXPECTED).Run();
@@ -1297,8 +1850,47 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, MAYBE_WriteError) {
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop;
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH,
+ error_code);
+ loop.Quit();
+ }));
+ SimulateGattCharacteristicWriteError(
+ characteristic1_, BluetoothRemoteGattService::GATT_ERROR_INVALID_LENGTH);
+ // Only the error above should be reported to the caller.
+ SimulateGattCharacteristicWriteError(
+ characteristic1_, BluetoothRemoteGattService::GATT_ERROR_FAILED);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteError DeprecatedWriteError
+#else
+#define MAYBE_DeprecatedWriteError DISABLED_DeprecatedWriteError
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic asynchronous error.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt, DeprecatedWriteError) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest, MAYBE_DeprecatedWriteError) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
SimulateGattCharacteristicWriteError(
@@ -1358,8 +1950,54 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, MAYBE_WriteSynchronousError) {
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
SimulateGattCharacteristicWriteWillFailSynchronouslyOnce(characteristic1_);
+ base::RunLoop loop1;
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop1.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ loop1.Quit();
+ }));
+ loop1.Run();
+
+ // After failing once, can succeed:
+ ResetEventCounts();
+ base::RunLoop loop2;
+ characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ SUCCEED();
+ loop2.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop2.Quit();
+ }));
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop2.Run();
+}
+
+#if defined(OS_ANDROID)
+#define MAYBE_DeprecatedWriteSynchronousError DeprecatedWriteSynchronousError
+#else
+#define MAYBE_DeprecatedWriteSynchronousError \
+ DISABLED_DeprecatedWriteSynchronousError
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic synchronous error.
+// This test doesn't apply to macOS and WinRT since a synchronous API does not
+// exist.
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteSynchronousError) {
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate());
+
+ SimulateGattCharacteristicWriteWillFailSynchronouslyOnce(characteristic1_);
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
EXPECT_EQ(0, gatt_write_characteristic_attempts_);
@@ -1371,7 +2009,7 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, MAYBE_WriteSynchronousError) {
// After failing once, can succeed:
ResetEventCounts();
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
EXPECT_EQ(1, gatt_write_characteristic_attempts_);
@@ -1433,7 +2071,8 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
#define MAYBE_WriteRemoteCharacteristic_WritePending \
DISABLED_WriteRemoteCharacteristic_WritePending
#endif
-// Tests WriteRemoteCharacteristic error with a pending write operation.
+// Tests WriteRemoteCharacteristic error with a pending write
+// operation.
#if defined(OS_WIN)
TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
WriteRemoteCharacteristic_WritePending) {
@@ -1448,11 +2087,67 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop1;
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ SUCCEED();
+ loop1.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop1.Quit();
+ }));
+ base::RunLoop loop2;
+ characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop2.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS,
+ error_code);
+ loop2.Quit();
+ }));
+
+ loop2.Run();
+
+ // Initial write should still succeed:
+ ResetEventCounts();
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop1.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_WritePending \
+ DeprecatedWriteRemoteCharacteristic_WritePending
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_WritePending \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_WritePending
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic error with a pending write
+// operation.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ DeprecatedWriteRemoteCharacteristic_WritePending) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_WritePending) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
@@ -1494,8 +2189,64 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop1;
+ base::RunLoop loop2;
std::vector<uint8_t> empty_vector;
characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ SUCCEED();
+ loop1.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop1.Quit();
+ }));
+ characteristic1_->ReadRemoteCharacteristic(
+ base::BindLambdaForTesting([&](const std::vector<uint8_t>& data) {
+ ADD_FAILURE() << "unexpected success";
+ loop2.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS,
+ error_code);
+ loop2.Quit();
+ }));
+
+ loop2.Run();
+
+ // Initial write should still succeed:
+ ResetEventCounts();
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop1.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_ReadRemoteCharacteristic_DeprecatedWritePending \
+ ReadRemoteCharacteristic_DeprecatedWritePending
+#else
+#define MAYBE_ReadRemoteCharacteristic_DeprecatedWritePending \
+ DISABLED_ReadRemoteCharacteristic_DeprecatedWritePending
+#endif
+// Tests ReadRemoteCharacteristic error with a pending write operation.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ ReadRemoteCharacteristic_DeprecatedWritePending) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_ReadRemoteCharacteristic_DeprecatedWritePending) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_READ |
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
characteristic1_->ReadRemoteCharacteristic(
@@ -1540,11 +2291,67 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop1;
+ base::RunLoop loop2;
+ std::vector<uint8_t> empty_vector;
+ characteristic1_->ReadRemoteCharacteristic(
+ base::BindLambdaForTesting([&](const std::vector<uint8_t>& data) {
+ SUCCEED();
+ loop1.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop1.Quit();
+ }));
+ characteristic1_->WriteRemoteCharacteristic(
+ empty_vector, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop2.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS,
+ error_code);
+ loop2.Quit();
+ }));
+ loop2.Run();
+
+ // Initial read should still succeed:
+ ResetEventCounts();
+ SimulateGattCharacteristicRead(characteristic1_, empty_vector);
+ loop1.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_ReadPending \
+ DeprecatedWriteRemoteCharacteristic_ReadPending
+#else
+#define MAYBE_DeprecatedWriteRemoteCharacteristic_ReadPending \
+ DISABLED_DeprecatedWriteRemoteCharacteristic_ReadPending
+#endif
+// Tests DeprecatedWriteRemoteCharacteristic error with a pending Read
+// operation.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ DeprecatedWriteRemoteCharacteristic_ReadPending) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteRemoteCharacteristic_ReadPending) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_READ |
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
std::vector<uint8_t> empty_vector;
characteristic1_->ReadRemoteCharacteristic(
GetReadValueCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
empty_vector, GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
base::RunLoop().RunUntilIdle();
@@ -1656,8 +2463,60 @@ TEST_F(BluetoothRemoteGattCharacteristicTest,
TestBluetoothAdapterObserver observer(adapter_);
+ base::RunLoop loop;
std::vector<uint8_t> write_value = {111};
characteristic1_->WriteRemoteCharacteristic(
+ write_value, WriteType::kWithResponse, base::BindLambdaForTesting([&] {
+ EXPECT_EQ(write_value, last_write_value_);
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ ADD_FAILURE() << "unexpected error: " << error_code;
+ loop.Quit();
+ }));
+
+ std::vector<uint8_t> notification_value = {222};
+ SimulateGattCharacteristicChanged(characteristic1_, notification_value);
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_EQ(notification_value, characteristic1_->GetValue());
+ EXPECT_EQ(1, observer.gatt_characteristic_value_changed_count());
+
+ observer.Reset();
+ SimulateGattCharacteristicWrite(characteristic1_);
+ loop.Run();
+}
+
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_Notification_During_DeprecatedWriteRemoteCharacteristic \
+ Notification_During_DeprecatedWriteRemoteCharacteristic
+#else
+#define MAYBE_Notification_During_DeprecatedWriteRemoteCharacteristic \
+ DISABLED_Notification_During_DeprecatedWriteRemoteCharacteristic
+#endif
+// Tests that a notification arriving during a pending write doesn't
+// cause a crash.
+#if defined(OS_WIN)
+TEST_P(BluetoothRemoteGattCharacteristicTestWinrt,
+ Notification_During_DeprecatedWriteRemoteCharacteristic) {
+#else
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_Notification_During_DeprecatedWriteRemoteCharacteristic) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(StartNotifyBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_NOTIFY |
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE,
+ NotifyValueState::NOTIFY));
+
+ TestBluetoothAdapterObserver observer(adapter_);
+
+ std::vector<uint8_t> write_value = {111};
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
write_value, GetCallback(Call::EXPECTED),
GetGattErrorCallback(Call::NOT_EXPECTED));
@@ -3344,9 +4203,47 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, MAYBE_WriteDuringDisconnect) {
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+ base::RunLoop loop;
SimulateGattDisconnection(device_);
- // Do not yet call RunUntilIdle() to process the disconnect task.
+ // Do not yet call loop.Run() to process the disconnect task.
characteristic1_->WriteRemoteCharacteristic(
+ std::vector<uint8_t>(), WriteType::kWithResponse,
+ base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ loop.Quit();
+ }));
+
+ loop.Run();
+}
+
+#if defined(OS_ANDROID)
+#define MAYBE_DeprecatedWriteDuringDisconnect DeprecatedWriteDuringDisconnect
+#else
+#define MAYBE_DeprecatedWriteDuringDisconnect \
+ DISABLED_DeprecatedWriteDuringDisconnect
+#endif
+// Tests that write requests after a device disconnects but before the
+// disconnect task runs result in an error.
+// macOS: Does not apply. All events arrive on the UI Thread.
+// TODO(crbug.com/694102): Enable this test on Windows.
+TEST_F(BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteDuringDisconnect) {
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
+
+ SimulateGattDisconnection(device_);
+ // Do not yet call RunUntilIdle() to process the disconnect task.
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
@@ -3382,7 +4279,52 @@ TEST_F(
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
+ base::RunLoop loop;
characteristic1_->WriteRemoteCharacteristic(
+ std::vector<uint8_t>(), WriteType::kWithoutResponse,
+ base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ loop.Quit();
+ }));
+ SimulateDeviceBreaksConnection(adapter_->GetDevices()[0]);
+
+ loop.Run();
+}
+
+#if defined(OS_MACOSX)
+#define MAYBE_WriteWithoutResponseOnlyCharacteristic_DeprecatedWriteRemoteCharacteristicDuringDisconnect \
+ WriteWithoutResponseOnlyCharacteristic_DeprecatedWriteRemoteCharacteristicDuringDisconnect
+#else
+#define MAYBE_WriteWithoutResponseOnlyCharacteristic_DeprecatedWriteRemoteCharacteristicDuringDisconnect \
+ DISABLED_WriteWithoutResponseOnlyCharacteristic_DeprecatedWriteRemoteCharacteristicDuringDisconnect
+#endif
+// Tests that writing without response during a disconnect results in an error.
+// Only applies to macOS and WinRT whose events arrive all on the UI thread. See
+// other *DuringDisconnect tests for Android and Windows whose events arrive on
+// a different thread.
+#if defined(OS_WIN)
+TEST_P(
+ BluetoothRemoteGattCharacteristicTestWinrtOnly,
+ WriteWithoutResponseOnlyCharacteristic_DeprecatedWriteRemoteCharacteristicDuringDisconnect) {
+#else
+TEST_F(
+ BluetoothRemoteGattCharacteristicTest,
+ MAYBE_WriteWithoutResponseOnlyCharacteristic_DeprecatedWriteRemoteCharacteristicDuringDisconnect) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
+
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
SimulateDeviceBreaksConnection(adapter_->GetDevices()[0]);
@@ -3418,6 +4360,49 @@ TEST_F(
base::RunLoop loop;
characteristic1_->WriteRemoteCharacteristic(
+ std::vector<uint8_t>(), WriteType::kWithoutResponse,
+ base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ gatt_connections_[0]->Disconnect();
+ loop.Quit();
+ }));
+ SimulateDeviceBreaksConnection(adapter_->GetDevices()[0]);
+ loop.Run();
+}
+
+// Tests that closing the GATT connection when a characteristic value write
+// fails due to a disconnect is safe.
+#if defined(OS_ANDROID) || defined(OS_MACOSX)
+#define MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_CloseConnectionDuringDisconnect \
+ DeprecatedWriteWithoutResponseOnlyCharacteristic_CloseConnectionDuringDisconnect
+#else
+#define MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_CloseConnectionDuringDisconnect \
+ DISABLED_DeprecatedWriteWithoutResponseOnlyCharacteristic_CloseConnectionDuringDisconnect
+#endif
+#if defined(OS_WIN)
+TEST_P(
+ BluetoothRemoteGattCharacteristicTestWinrtOnly,
+ DeprecatedWriteWithoutResponseOnlyCharacteristic_CloseConnectionDuringDisconnect) {
+#else
+TEST_F(
+ BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_CloseConnectionDuringDisconnect) {
+#endif
+ if (!PlatformSupportsLowEnergy()) {
+ LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
+ return;
+ }
+ ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
+ BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
+
+ base::RunLoop loop;
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED),
base::BindLambdaForTesting(
[&](BluetoothGattService::GattErrorCode error_code) {
@@ -3451,33 +4436,40 @@ TEST_F(
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
+ base::RunLoop loop;
characteristic1_->WriteRemoteCharacteristic(
- std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED),
- GetGattErrorCallback(Call::EXPECTED));
+ std::vector<uint8_t>(), WriteType::kWithoutResponse,
+ base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ loop.Quit();
+ }));
gatt_connections_[0]->Disconnect();
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
- last_gatt_error_code_);
+ loop.Run();
SimulateGattDisconnection(device_);
base::RunLoop().RunUntilIdle();
}
#if defined(OS_MACOSX)
-#define MAYBE_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic \
- WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic
+#define MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledDuringWriteRemoteCharacteristic \
+ DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledDuringWriteRemoteCharacteristic
#else
-#define MAYBE_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic \
- DISABLED_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic
+#define MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledDuringWriteRemoteCharacteristic \
+ DISABLED_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledDuringWriteRemoteCharacteristic
#endif
-// Tests that disconnecting right before a write without response results in an
+// Tests that disconnecting right after a write without response results in an
// error.
// TODO(crbug.com/726534): Enable on other platforms depending on the resolution
// of crbug.com/726534.
TEST_F(
BluetoothRemoteGattCharacteristicTest,
- MAYBE_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic) {
+ MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledDuringWriteRemoteCharacteristic) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
@@ -3485,10 +4477,10 @@ TEST_F(
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
- gatt_connections_[0]->Disconnect();
- characteristic1_->WriteRemoteCharacteristic(
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED),
GetGattErrorCallback(Call::EXPECTED));
+ gatt_connections_[0]->Disconnect();
base::RunLoop().RunUntilIdle();
EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
@@ -3499,145 +4491,78 @@ TEST_F(
}
#if defined(OS_MACOSX)
-#define MAYBE_WriteWithoutResponse_PropertyNotPresent \
- WriteWithoutResponse_PropertyNotPresent
-#else
-#define MAYBE_WriteWithoutResponse_PropertyNotPresent \
- DISABLED_WriteWithoutResponse_PropertyNotPresent
-#endif
-// Tests that WriteWithoutResponse fails when a characteristic does not have the
-// required property.
-// TODO(https://crbug.com/831524): Enable for other platforms once supported.
-#if defined(OS_WIN)
-TEST_P(BluetoothRemoteGattCharacteristicTestWinrtOnly,
- WriteWithoutResponse_PropertyNotPresent) {
-#else
-TEST_F(BluetoothRemoteGattCharacteristicTest,
- MAYBE_WriteWithoutResponse_PropertyNotPresent) {
-#endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
- BluetoothRemoteGattCharacteristic::PROPERTY_WRITE));
-
- std::vector<uint8_t> test_vector = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
- EXPECT_FALSE(characteristic1_->WriteWithoutResponse(test_vector));
-}
-
-#if defined(OS_MACOSX)
-#define MAYBE_WriteWithoutResponse_PendingWrite \
- WriteWithoutResponse_PendingWrite
-#else
-#define MAYBE_WriteWithoutResponse_PendingWrite \
- DISABLED_WriteWithoutResponse_PendingWrite
-#endif
-// Tests that WriteWithoutResponse fails when a characteristic already has a
-// pending write.
-// TODO(https://crbug.com/831524): Enable for other platforms once supported.
-#if defined(OS_WIN)
-TEST_P(BluetoothRemoteGattCharacteristicTestWinrtOnly,
- WriteWithoutResponse_PendingWrite) {
+#define MAYBE_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic \
+ WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic
#else
-TEST_F(BluetoothRemoteGattCharacteristicTest,
- MAYBE_WriteWithoutResponse_PendingWrite) {
+#define MAYBE_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic \
+ DISABLED_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic
#endif
+// Tests that disconnecting right before a write without response results in an
+// error.
+// TODO(crbug.com/726534): Enable on other platforms depending on the resolution
+// of crbug.com/726534.
+TEST_F(
+ BluetoothRemoteGattCharacteristicTest,
+ MAYBE_WriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
- BluetoothRemoteGattCharacteristic::PROPERTY_WRITE |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
- std::vector<uint8_t> test_vector = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
+ base::RunLoop loop;
+ gatt_connections_[0]->Disconnect();
characteristic1_->WriteRemoteCharacteristic(
- test_vector, GetCallback(Call::EXPECTED),
- GetGattErrorCallback(Call::NOT_EXPECTED));
-
- // Explicitly make sure that the callback has not been invoked yet. Since
- // WriteRemoteCharacteristic is still pending, this results in an error for
- // WriteWithoutResponse.
- EXPECT_EQ(0, callback_count_);
- EXPECT_FALSE(characteristic1_->WriteWithoutResponse(test_vector));
+ std::vector<uint8_t>(), WriteType::kWithoutResponse,
+ base::BindLambdaForTesting([&] {
+ ADD_FAILURE() << "unexpected success";
+ loop.Quit();
+ }),
+ base::BindLambdaForTesting(
+ [&](BluetoothGattService::GattErrorCode error_code) {
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ error_code);
+ loop.Quit();
+ }));
+ loop.Run();
- // Test that the failed WriteWithoutReponse request does not interfere with
- // the pending WriteRemoteCharacteristic request.
- SimulateGattCharacteristicWrite(characteristic1_);
+ SimulateGattDisconnection(device_);
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, callback_count_);
- EXPECT_EQ(test_vector, last_write_value_);
}
#if defined(OS_MACOSX)
-#define MAYBE_WriteWithoutResponse_PendingRead WriteWithoutResponse_PendingRead
+#define MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic \
+ DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic
#else
-#define MAYBE_WriteWithoutResponse_PendingRead \
- DISABLED_WriteWithoutResponse_PendingRead
-#endif
-// Tests that WriteWithoutResponse fails when a characteristic already has a
-// pending read.
-// TODO(https://crbug.com/831524): Enable for other platforms once supported.
-#if defined(OS_WIN)
-TEST_P(BluetoothRemoteGattCharacteristicTestWinrtOnly,
- WriteWithoutResponse_PendingRead) {
-#else
-TEST_F(BluetoothRemoteGattCharacteristicTest,
- MAYBE_WriteWithoutResponse_PendingRead) {
+#define MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic \
+ DISABLED_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic
#endif
+// Tests that disconnecting right before a write without response results in an
+// error.
+// TODO(crbug.com/726534): Enable on other platforms depending on the resolution
+// of crbug.com/726534.
+TEST_F(
+ BluetoothRemoteGattCharacteristicTest,
+ MAYBE_DeprecatedWriteWithoutResponseOnlyCharacteristic_DisconnectCalledBeforeWriteRemoteCharacteristic) {
if (!PlatformSupportsLowEnergy()) {
LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
return;
}
ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
- BluetoothRemoteGattCharacteristic::PROPERTY_READ |
BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
- characteristic1_->ReadRemoteCharacteristic(
- GetReadValueCallback(Call::EXPECTED),
- GetGattErrorCallback(Call::NOT_EXPECTED));
-
- // Explicitly make sure that the callback has not been invoked yet. Since
- // ReadRemoteCharacteristic is still pending, this results in an error for
- // WriteWithoutResponse.
- EXPECT_EQ(0, callback_count_);
- std::vector<uint8_t> test_vector = {0, 1, 2, 3, 4, 0xf, 0xf0, 0xff};
- EXPECT_FALSE(characteristic1_->WriteWithoutResponse(test_vector));
-
- // Test that the failed WriteWithoutReponse request does not interfere with
- // the pending ReadRemoteCharacteristic request.
- SimulateGattCharacteristicRead(characteristic1_, test_vector);
+ gatt_connections_[0]->Disconnect();
+ characteristic1_->DeprecatedWriteRemoteCharacteristic(
+ std::vector<uint8_t>(), GetCallback(Call::NOT_EXPECTED),
+ GetGattErrorCallback(Call::EXPECTED));
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(1, callback_count_);
- EXPECT_EQ(test_vector, last_read_value_);
-}
-#if defined(OS_MACOSX)
-#define MAYBE_WriteWithoutResponse_Success WriteWithoutResponse_Success
-#else
-#define MAYBE_WriteWithoutResponse_Success DISABLED_WriteWithoutResponse_Success
-#endif
-// Tests that WriteWithoutResponse indicates success if the proper conditions
-// are met.
-// TODO(https://crbug.com/831524): Enable for other platforms once supported.
-#if defined(OS_WIN)
-TEST_P(BluetoothRemoteGattCharacteristicTestWinrtOnly,
- WriteWithoutResponse_Success) {
-#else
-TEST_F(BluetoothRemoteGattCharacteristicTest,
- MAYBE_WriteWithoutResponse_Success) {
-#endif
- if (!PlatformSupportsLowEnergy()) {
- LOG(WARNING) << "Low Energy Bluetooth unavailable, skipping unit test.";
- return;
- }
- ASSERT_NO_FATAL_FAILURE(FakeCharacteristicBoilerplate(
- BluetoothRemoteGattCharacteristic::PROPERTY_WRITE_WITHOUT_RESPONSE));
+ EXPECT_EQ(BluetoothRemoteGattService::GATT_ERROR_FAILED,
+ last_gatt_error_code_);
- std::vector<uint8_t> test_vector = {1, 2, 3, 4};
- EXPECT_TRUE(characteristic1_->WriteWithoutResponse(test_vector));
- EXPECT_EQ(test_vector, last_write_value_);
+ SimulateGattDisconnection(device_);
+ base::RunLoop().RunUntilIdle();
}
#if defined(OS_ANDROID)
@@ -3843,20 +4768,19 @@ TEST_F(BluetoothRemoteGattCharacteristicTest, ExtraDidDiscoverDescriptorsCall) {
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
-INSTANTIATE_TEST_SUITE_P(
- All,
- BluetoothRemoteGattCharacteristicTestWinrt,
- ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(All,
+ BluetoothRemoteGattCharacteristicTestWinrt,
+ ::testing::ValuesIn(kBluetoothTestWinrtParamAll));
INSTANTIATE_TEST_SUITE_P(
All,
BluetoothRemoteGattCharacteristicTestWin32Only,
- ::testing::Values(false));
+ ::testing::ValuesIn(kBluetoothTestWinrtParamWin32Only));
INSTANTIATE_TEST_SUITE_P(
All,
BluetoothRemoteGattCharacteristicTestWinrtOnly,
- ::testing::Values(true));
+ ::testing::ValuesIn(kBluetoothTestWinrtParamWinrtOnly));
#endif // defined(OS_WIN)
} // namespace device
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
index dfe278ab735..54d4effdcdd 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.cc
@@ -159,6 +159,40 @@ void BluetoothRemoteGattCharacteristicWin::ReadRemoteCharacteristic(
void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
+ WriteType write_type,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) {
+ DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
+
+ if (characteristic_value_read_or_write_in_progress_) {
+ std::move(error_callback)
+ .Run(BluetoothRemoteGattService::GATT_ERROR_IN_PROGRESS);
+ return;
+ }
+
+ ULONG flags;
+ switch (write_type) {
+ case WriteType::kWithResponse:
+ flags = BLUETOOTH_GATT_FLAG_NONE;
+ break;
+ case WriteType::kWithoutResponse:
+ flags = BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
+ break;
+ }
+
+ characteristic_value_read_or_write_in_progress_ = true;
+ write_characteristic_value_callbacks_ =
+ std::make_pair(std::move(callback), std::move(error_callback));
+ task_manager_->PostWriteGattCharacteristicValue(
+ parent_service_->GetServicePath(), characteristic_info_.get(), value,
+ flags,
+ base::Bind(&BluetoothRemoteGattCharacteristicWin::
+ OnWriteRemoteCharacteristicValueCallback,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothRemoteGattCharacteristicWin::DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
base::OnceClosure callback,
ErrorCallback error_callback) {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
@@ -176,11 +210,17 @@ void BluetoothRemoteGattCharacteristicWin::WriteRemoteCharacteristic(
return;
}
+ ULONG flags = BLUETOOTH_GATT_FLAG_NONE;
+ if (!characteristic_info_->IsWritable) {
+ flags |= BLUETOOTH_GATT_FLAG_WRITE_WITHOUT_RESPONSE;
+ }
+
characteristic_value_read_or_write_in_progress_ = true;
write_characteristic_value_callbacks_ =
std::make_pair(std::move(callback), std::move(error_callback));
task_manager_->PostWriteGattCharacteristicValue(
parent_service_->GetServicePath(), characteristic_info_.get(), value,
+ flags,
base::Bind(&BluetoothRemoteGattCharacteristicWin::
OnWriteRemoteCharacteristicValueCallback,
weak_ptr_factory_.GetWeakPtr()));
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
index 56a3212b8b0..50fcaac8f3d 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_win.h
@@ -45,8 +45,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicWin
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;
// Update included descriptors.
void Update();
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
index 8e340c5dbad..2e5a0a979e4 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.cc
@@ -46,6 +46,8 @@ using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
GattCommunicationStatus_Success;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::GattReadResult;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
+ GattWriteOption;
+using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
GattWriteOption_WriteWithoutResponse;
using ABI::Windows::Devices::Bluetooth::GenericAttributeProfile::
GattWriteOption_WriteWithResponse;
@@ -203,17 +205,9 @@ void BluetoothRemoteGattCharacteristicWinrt::ReadRemoteCharacteristic(
void BluetoothRemoteGattCharacteristicWinrt::WriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
+ WriteType write_type,
base::OnceClosure callback,
ErrorCallback error_callback) {
- if (!(GetProperties() & PROPERTY_WRITE) &&
- !(GetProperties() & PROPERTY_WRITE_WITHOUT_RESPONSE)) {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(std::move(error_callback),
- BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED));
- return;
- }
-
if (pending_read_callbacks_ || pending_write_callbacks_) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE,
@@ -246,13 +240,19 @@ void BluetoothRemoteGattCharacteristicWinrt::WriteRemoteCharacteristic(
return;
}
+ GattWriteOption write_option;
+ switch (write_type) {
+ case WriteType::kWithResponse:
+ write_option = GattWriteOption_WriteWithResponse;
+ break;
+ case WriteType::kWithoutResponse:
+ write_option = GattWriteOption_WriteWithoutResponse;
+ break;
+ }
+
ComPtr<IAsyncOperation<GattWriteResult*>> write_value_op;
hr = characteristic_3->WriteValueWithResultAndOptionAsync(
- buffer.Get(),
- (GetProperties() & PROPERTY_WRITE) ? GattWriteOption_WriteWithResponse
- : GattWriteOption_WriteWithoutResponse,
-
- &write_value_op);
+ buffer.Get(), write_option, &write_value_op);
if (FAILED(hr)) {
BLUETOOTH_LOG(DEBUG)
<< "GattCharacteristic::WriteValueWithResultAndOptionAsync failed: "
@@ -284,6 +284,27 @@ void BluetoothRemoteGattCharacteristicWinrt::WriteRemoteCharacteristic(
std::move(callback), std::move(error_callback));
}
+void BluetoothRemoteGattCharacteristicWinrt::
+ DeprecatedWriteRemoteCharacteristic(const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) {
+ if (!(GetProperties() & PROPERTY_WRITE) &&
+ !(GetProperties() & PROPERTY_WRITE_WITHOUT_RESPONSE)) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(error_callback),
+ BluetoothRemoteGattService::GATT_ERROR_NOT_PERMITTED));
+ return;
+ }
+
+ WriteType write_type = (GetProperties() & PROPERTY_WRITE)
+ ? WriteType::kWithResponse
+ : WriteType::kWithoutResponse;
+
+ WriteRemoteCharacteristic(value, write_type, std::move(callback),
+ std::move(error_callback));
+}
+
void BluetoothRemoteGattCharacteristicWinrt::UpdateDescriptors(
BluetoothGattDiscovererWinrt* gatt_discoverer) {
const auto* gatt_descriptors =
@@ -311,56 +332,6 @@ void BluetoothRemoteGattCharacteristicWinrt::UpdateDescriptors(
std::swap(descriptors, descriptors_);
}
-bool BluetoothRemoteGattCharacteristicWinrt::WriteWithoutResponse(
- base::span<const uint8_t> value) {
- if (!(GetProperties() & PROPERTY_WRITE_WITHOUT_RESPONSE))
- return false;
-
- if (pending_read_callbacks_ || pending_write_callbacks_)
- return false;
-
- ComPtr<IGattCharacteristic3> characteristic_3;
- HRESULT hr = characteristic_.As(&characteristic_3);
- if (FAILED(hr)) {
- BLUETOOTH_LOG(DEBUG) << "As IGattCharacteristic3 failed: "
- << logging::SystemErrorCodeToString(hr);
- return false;
- }
-
- ComPtr<IBuffer> buffer;
- hr = base::win::CreateIBufferFromData(value.data(), value.size(), &buffer);
- if (FAILED(hr)) {
- BLUETOOTH_LOG(DEBUG) << "base::win::CreateIBufferFromData failed: "
- << logging::SystemErrorCodeToString(hr);
- return false;
- }
-
- ComPtr<IAsyncOperation<GattWriteResult*>> write_value_op;
- // Note: As we are ignoring the result WriteValueWithOptionAsync() would work
- // as well, but re-using WriteValueWithResultAndOptionAsync() does simplify
- // the testing code and there is no difference in production.
- hr = characteristic_3->WriteValueWithResultAndOptionAsync(
- buffer.Get(), GattWriteOption_WriteWithoutResponse, &write_value_op);
- if (FAILED(hr)) {
- BLUETOOTH_LOG(DEBUG)
- << "GattCharacteristic::WriteValueWithResultAndOptionAsync failed: "
- << logging::SystemErrorCodeToString(hr);
- return false;
- }
-
- // While we are ignoring the response, we still post the async_op in order to
- // extend its lifetime until the operation has completed.
- hr =
- base::win::PostAsyncResults(std::move(write_value_op), base::DoNothing());
- if (FAILED(hr)) {
- BLUETOOTH_LOG(DEBUG) << "PostAsyncResults failed: "
- << logging::SystemErrorCodeToString(hr);
- return false;
- }
-
- return true;
-}
-
IGattCharacteristic*
BluetoothRemoteGattCharacteristicWinrt::GetCharacteristicForTesting() {
return characteristic_.Get();
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h
index c1d7df05a32..1402fa2354c 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h
@@ -48,9 +48,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothRemoteGattCharacteristicWinrt
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;
- bool WriteWithoutResponse(base::span<const uint8_t> value) override;
+ void DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) override;
void UpdateDescriptors(BluetoothGattDiscovererWinrt* gatt_discoverer);
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc
index b0d14a15cd3..1a410cbc377 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_descriptor_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/logging.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "build/build_config.h"
@@ -999,7 +1000,7 @@ TEST_F(BluetoothRemoteGattDescriptorTest, ReadRemoteDescriptor_NSNumber) {
INSTANTIATE_TEST_SUITE_P(
All,
BluetoothRemoteGattDescriptorTestWinrtOnly,
- ::testing::Values(true));
+ ::testing::ValuesIn(kBluetoothTestWinrtParamWinrtOnly));
#endif // defined(OS_WIN)
} // namespace device
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc b/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc
index 70221d3bc1e..5ba4392be5e 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_unittest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/logging.h"
#include "base/run_loop.h"
#include "build/build_config.h"
#include "device/bluetooth/bluetooth_gatt_service.h"
@@ -415,7 +416,7 @@ TEST_F(BluetoothRemoteGattServiceTest, MAYBE_SimulateGattServiceRemove) {
SimulateGattServiceRemoved(device->GetGattService(removed_service));
base::RunLoop().RunUntilIdle();
#if defined(OS_WIN)
- if (!GetParam()) {
+ if (!UsesNewBleImplementation()) {
// The GattServicesRemoved event is not implemented for WinRT.
EXPECT_EQ(1, observer.gatt_service_removed_count());
}
@@ -597,10 +598,9 @@ TEST_F(BluetoothRemoteGattServiceTest, ExtraDidDiscoverCharacteristicsCall) {
#endif // defined(OS_MACOSX)
#if defined(OS_WIN)
-INSTANTIATE_TEST_SUITE_P(
- All,
- BluetoothRemoteGattServiceTestWinrt,
- ::testing::Bool());
+INSTANTIATE_TEST_SUITE_P(All,
+ BluetoothRemoteGattServiceTestWinrt,
+ ::testing::ValuesIn(kBluetoothTestWinrtParamAll));
#endif // defined(OS_WIN)
} // namespace device
diff --git a/chromium/device/bluetooth/bluetooth_remote_gatt_service_winrt.h b/chromium/device/bluetooth/bluetooth_remote_gatt_service_winrt.h
index e8c990dc7c2..75852935344 100644
--- a/chromium/device/bluetooth/bluetooth_remote_gatt_service_winrt.h
+++ b/chromium/device/bluetooth/bluetooth_remote_gatt_service_winrt.h
@@ -14,6 +14,7 @@
#include <string>
#include <vector>
+#include "base/logging.h"
#include "base/macros.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/bluetooth_remote_gatt_characteristic_winrt.h"
diff --git a/chromium/device/bluetooth/bluetooth_task_manager_win.cc b/chromium/device/bluetooth/bluetooth_task_manager_win.cc
index 4f1883f4edc..55a425be257 100644
--- a/chromium/device/bluetooth/bluetooth_task_manager_win.cc
+++ b/chromium/device/bluetooth/bluetooth_task_manager_win.cc
@@ -12,6 +12,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
#include "base/no_destructor.h"
@@ -20,6 +21,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
+#include "base/threading/scoped_thread_priority.h"
#include "device/bluetooth/bluetooth_classic_win.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_init_win.h"
@@ -644,6 +646,10 @@ int BluetoothTaskManagerWin::DiscoverClassicDeviceServicesWorker(
const GUID& protocol_uuid,
bool search_cached_services_only,
std::vector<std::unique_ptr<ServiceRecordState>>* service_record_states) {
+ // Mitigate the issues caused by loading DLLs on a background thread
+ // (http://crbug/973868).
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
// Bluetooth and WSAQUERYSET for Service Inquiry. See http://goo.gl/2v9pyt.
WSAQUERYSET sdp_query;
ZeroMemory(&sdp_query, sizeof(sdp_query));
@@ -869,6 +875,7 @@ void BluetoothTaskManagerWin::WriteGattCharacteristicValue(
base::FilePath service_path,
BTH_LE_GATT_CHARACTERISTIC characteristic,
std::vector<uint8_t> new_value,
+ ULONG flags,
const HResultCallback& callback) {
ULONG length = (ULONG)(sizeof(ULONG) + new_value.size());
std::vector<UCHAR> data(length);
@@ -880,7 +887,7 @@ void BluetoothTaskManagerWin::WriteGattCharacteristicValue(
HRESULT hr = le_wrapper_->WriteCharacteristicValue(
service_path, (PBTH_LE_GATT_CHARACTERISTIC)(&characteristic),
- win_new_value);
+ win_new_value, flags);
ui_task_runner_->PostTask(FROM_HERE, base::BindOnce(callback, hr));
}
@@ -987,12 +994,14 @@ void BluetoothTaskManagerWin::PostWriteGattCharacteristicValue(
const base::FilePath& service_path,
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
const std::vector<uint8_t>& new_value,
+ ULONG flags,
const HResultCallback& callback) {
DCHECK(ui_task_runner_->RunsTasksInCurrentSequence());
bluetooth_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&BluetoothTaskManagerWin::WriteGattCharacteristicValue,
- this, service_path, *characteristic, new_value, callback));
+ this, service_path, *characteristic, new_value, flags,
+ callback));
}
void BluetoothTaskManagerWin::PostRegisterGattCharacteristicValueChangedEvent(
diff --git a/chromium/device/bluetooth/bluetooth_task_manager_win.h b/chromium/device/bluetooth/bluetooth_task_manager_win.h
index de693e2ede5..bd7181e7977 100644
--- a/chromium/device/bluetooth/bluetooth_task_manager_win.h
+++ b/chromium/device/bluetooth/bluetooth_task_manager_win.h
@@ -186,6 +186,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
const base::FilePath& service_path,
const PBTH_LE_GATT_CHARACTERISTIC characteristic,
const std::vector<uint8_t>& new_value,
+ ULONG flags,
const HResultCallback& callback);
// Post a task to register to receive value changed notifications from
@@ -319,6 +320,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothTaskManagerWin
void WriteGattCharacteristicValue(base::FilePath service_path,
BTH_LE_GATT_CHARACTERISTIC characteristic,
std::vector<uint8_t> new_value,
+ ULONG flags,
const HResultCallback& callback);
void RegisterGattCharacteristicValueChangedEvent(
base::FilePath service_path,
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,
diff --git a/chromium/device/bluetooth/cast/bluetooth_adapter_cast.cc b/chromium/device/bluetooth/cast/bluetooth_adapter_cast.cc
index 1eee419655c..5113465e533 100644
--- a/chromium/device/bluetooth/cast/bluetooth_adapter_cast.cc
+++ b/chromium/device/bluetooth/cast/bluetooth_adapter_cast.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/no_destructor.h"
#include "base/task/post_task.h"
#include "base/threading/sequenced_task_runner_handle.h"
diff --git a/chromium/device/bluetooth/cast/bluetooth_device_cast.cc b/chromium/device/bluetooth/cast/bluetooth_device_cast.cc
index 4ec0b249e26..17da5222f60 100644
--- a/chromium/device/bluetooth/cast/bluetooth_device_cast.cc
+++ b/chromium/device/bluetooth/cast/bluetooth_device_cast.cc
@@ -10,6 +10,7 @@
#include <utility>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "chromecast/device/bluetooth/bluetooth_util.h"
#include "chromecast/device/bluetooth/le/remote_characteristic.h"
diff --git a/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc b/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc
index 83cdc280981..e52f00359e6 100644
--- a/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc
+++ b/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.cc
@@ -10,10 +10,12 @@
#include "base/callback.h"
#include "base/callback_forward.h"
#include "base/containers/queue.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "chromecast/device/bluetooth/le/remote_characteristic.h"
#include "chromecast/device/bluetooth/le/remote_descriptor.h"
+#include "chromecast/public/bluetooth/gatt.h"
#include "device/bluetooth/cast/bluetooth_remote_gatt_descriptor_cast.h"
#include "device/bluetooth/cast/bluetooth_remote_gatt_service_cast.h"
#include "device/bluetooth/cast/bluetooth_utils.h"
@@ -143,6 +145,32 @@ void BluetoothRemoteGattCharacteristicCast::ReadRemoteCharacteristic(
void BluetoothRemoteGattCharacteristicCast::WriteRemoteCharacteristic(
const std::vector<uint8_t>& value,
+ WriteType write_type,
+ base::OnceClosure callback,
+ ErrorCallback error_callback) {
+ using ChromecastWriteType = chromecast::bluetooth_v2_shlib::Gatt::WriteType;
+
+ ChromecastWriteType chromecast_write_type;
+ switch (write_type) {
+ case WriteType::kWithResponse:
+ chromecast_write_type = ChromecastWriteType::WRITE_TYPE_DEFAULT;
+ break;
+ case WriteType::kWithoutResponse:
+ chromecast_write_type = ChromecastWriteType::WRITE_TYPE_NO_RESPONSE;
+ break;
+ }
+
+ remote_characteristic_->WriteAuth(
+ chromecast::bluetooth_v2_shlib::Gatt::Client::AUTH_REQ_NONE,
+ chromecast_write_type, value,
+ base::BindOnce(
+ &BluetoothRemoteGattCharacteristicCast::OnWriteRemoteCharacteristic,
+ weak_factory_.GetWeakPtr(), value, std::move(callback),
+ std::move(error_callback)));
+}
+
+void BluetoothRemoteGattCharacteristicCast::DeprecatedWriteRemoteCharacteristic(
+ const std::vector<uint8_t>& value,
base::OnceClosure callback,
ErrorCallback error_callback) {
remote_characteristic_->Write(
diff --git a/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h b/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h
index f42c545fece..af4dd712c5f 100644
--- a/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h
+++ b/chromium/device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h
@@ -48,8 +48,13 @@ class BluetoothRemoteGattCharacteristicCast
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;
// Called by BluetoothAdapterCast to set the value when a new notification
// comes in.
diff --git a/chromium/device/bluetooth/dbus/bluetooth_gatt_application_service_provider.cc b/chromium/device/bluetooth/dbus/bluetooth_gatt_application_service_provider.cc
index 6ccfcc27914..611e810ffb6 100644
--- a/chromium/device/bluetooth/dbus/bluetooth_gatt_application_service_provider.cc
+++ b/chromium/device/bluetooth/dbus/bluetooth_gatt_application_service_provider.cc
@@ -7,6 +7,7 @@
#include <string>
#include <utility>
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "device/bluetooth/bluetooth_gatt_characteristic.h"
#include "device/bluetooth/bluez/bluetooth_gatt_service_bluez.h"
diff --git a/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc b/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
index ec4a928cdb2..4ae1703db72 100644
--- a/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
+++ b/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
@@ -14,6 +15,7 @@
#include "dbus/bus.h"
#include "dbus/object_manager.h"
#include "dbus/values_util.h"
+#include "third_party/cros_system_api/dbus/bluetooth/dbus-constants.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
namespace bluez {
@@ -113,6 +115,7 @@ class BluetoothGattCharacteristicClientImpl
// BluetoothGattCharacteristicClient override.
void WriteValue(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
+ base::StringPiece type_option,
base::OnceClosure callback,
ErrorCallback error_callback) override {
dbus::ObjectProxy* object_proxy =
@@ -128,8 +131,14 @@ class BluetoothGattCharacteristicClientImpl
dbus::MessageWriter writer(&method_call);
writer.AppendArrayOfBytes(value.data(), value.size());
- // Append empty option dict
+ // Append option dict
base::DictionaryValue dict;
+ if (!type_option.empty()) {
+ // NB: the "type" option was added in BlueZ 5.51. Older versions of BlueZ
+ // will ignore this option.
+ dict.SetStringKey(bluetooth_gatt_characteristic::kOptionType,
+ type_option);
+ }
dbus::AppendValueData(&writer, dict);
object_proxy->CallMethodWithErrorCallback(
diff --git a/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h b/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
index b76a8317d39..93b4cc76c15 100644
--- a/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
+++ b/chromium/device/bluetooth/dbus/bluetooth_gatt_characteristic_client.h
@@ -105,10 +105,12 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothGattCharacteristicClient
ErrorCallback error_callback) = 0;
// Issues a request to write the value of GATT characteristic with object path
- // |object_path| with value |value|. Invokes |callback| on success and
- // |error_callback| on failure.
+ // |object_path| with value |value| and |type_option|. |type_option| is
+ // bluetooth_gatt_characteristic::kTypeRequest or kTypeCommand, or "" to omit
+ // the option. Invokes |callback| on success and |error_callback| on failure.
virtual void WriteValue(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
+ base::StringPiece type_option,
base::OnceClosure callback,
ErrorCallback error_callback) = 0;
diff --git a/chromium/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc b/chromium/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
index ff3f0d53765..c2fbd87c6fd 100644
--- a/chromium/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
+++ b/chromium/device/bluetooth/dbus/bluetooth_gatt_descriptor_client.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
diff --git a/chromium/device/bluetooth/dbus/bluetooth_gatt_service_client.cc b/chromium/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
index 014f26f6ceb..2ea601b5c78 100644
--- a/chromium/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
+++ b/chromium/device/bluetooth/dbus/bluetooth_gatt_service_client.cc
@@ -5,6 +5,7 @@
#include "device/bluetooth/dbus/bluetooth_gatt_service_client.h"
#include "base/bind.h"
+#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
diff --git a/chromium/device/bluetooth/dbus/bluez_dbus_manager.cc b/chromium/device/bluetooth/dbus/bluez_dbus_manager.cc
index 9edc0a39a1a..bd1df9bfe7b 100644
--- a/chromium/device/bluetooth/dbus/bluez_dbus_manager.cc
+++ b/chromium/device/bluetooth/dbus/bluez_dbus_manager.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/system/sys_info.h"
#include "base/threading/thread.h"
diff --git a/chromium/device/bluetooth/dbus/bluez_dbus_thread_manager.cc b/chromium/device/bluetooth/dbus/bluez_dbus_thread_manager.cc
index 31793710e2b..8b606656703 100644
--- a/chromium/device/bluetooth/dbus/bluez_dbus_thread_manager.cc
+++ b/chromium/device/bluetooth/dbus/bluez_dbus_thread_manager.cc
@@ -4,6 +4,7 @@
#include "device/bluetooth/dbus/bluez_dbus_thread_manager.h"
+#include "base/logging.h"
#include "base/message_loop/message_pump_type.h"
#include "base/threading/thread.h"
#include "dbus/bus.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
index 4885352ee59..48107e1091d 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_agent_manager_client.cc
@@ -11,7 +11,7 @@
namespace bluez {
FakeBluetoothAgentManagerClient::FakeBluetoothAgentManagerClient()
- : service_provider_(NULL) {}
+ : service_provider_(nullptr) {}
FakeBluetoothAgentManagerClient::~FakeBluetoothAgentManagerClient() = default;
@@ -81,7 +81,7 @@ void FakeBluetoothAgentManagerClient::RegisterAgentServiceProvider(
void FakeBluetoothAgentManagerClient::UnregisterAgentServiceProvider(
FakeBluetoothAgentServiceProvider* service_provider) {
if (service_provider_ == service_provider)
- service_provider_ = NULL;
+ service_provider_ = nullptr;
}
FakeBluetoothAgentServiceProvider*
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
index 2266c059d4f..edfe29d3b31 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_agent_service_provider.cc
@@ -4,6 +4,7 @@
#include "device/bluetooth/dbus/fake_bluetooth_agent_service_provider.h"
+#include "base/logging.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_agent_manager_client.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc
index 3f137c01978..23c5fe33b0b 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.cc
@@ -650,6 +650,7 @@ void FakeBluetoothDeviceClient::ExecuteWrite(
bluez::BluezDBusManager::Get()
->GetBluetoothGattCharacteristicClient()
->WriteValue(prepare_write_request.first, prepare_write_request.second,
+ bluetooth_gatt_characteristic::kTypeRequest,
base::DoNothing(), base::DoNothing());
}
prepare_write_requests_.clear();
@@ -882,248 +883,242 @@ void FakeBluetoothDeviceClient::CreateDeviceWithProperties(
observer.DeviceAdded(device_path);
}
-std::unique_ptr<base::ListValue>
-FakeBluetoothDeviceClient::GetBluetoothDevicesAsDictionaries() const {
- std::unique_ptr<base::ListValue> predefined_devices(new base::ListValue);
- std::unique_ptr<base::DictionaryValue> pairedDevice(
- new base::DictionaryValue);
- pairedDevice->SetString("path", kPairedDevicePath);
- pairedDevice->SetString("address", kPairedDeviceAddress);
- pairedDevice->SetString("name", kPairedDeviceName);
- pairedDevice->SetString("alias", kPairedDeviceName);
- pairedDevice->SetString("pairingMethod", "");
- pairedDevice->SetString("pairingAuthToken", "");
- pairedDevice->SetString("pairingAction", "");
- pairedDevice->SetInteger("classValue", kPairedDeviceClass);
- pairedDevice->SetBoolean("discoverable", true);
- pairedDevice->SetBoolean("isTrusted", true);
- pairedDevice->SetBoolean("paired", true);
- pairedDevice->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(pairedDevice));
-
- std::unique_ptr<base::DictionaryValue> legacyDevice(
- new base::DictionaryValue);
- legacyDevice->SetString("path", kLegacyAutopairPath);
- legacyDevice->SetString("address", kLegacyAutopairAddress);
- legacyDevice->SetString("name", kLegacyAutopairName);
- legacyDevice->SetString("alias", kLegacyAutopairName);
- legacyDevice->SetString("pairingMethod", "");
- legacyDevice->SetString("pairingAuthToken", "");
- legacyDevice->SetString("pairingAction", "");
- legacyDevice->SetInteger("classValue", kLegacyAutopairClass);
- legacyDevice->SetBoolean("isTrusted", true);
- legacyDevice->SetBoolean("discoverable", false);
- legacyDevice->SetBoolean("paired", false);
- legacyDevice->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(legacyDevice));
-
- std::unique_ptr<base::DictionaryValue> pin(new base::DictionaryValue);
- pin->SetString("path", kDisplayPinCodePath);
- pin->SetString("address", kDisplayPinCodeAddress);
- pin->SetString("name", kDisplayPinCodeName);
- pin->SetString("alias", kDisplayPinCodeName);
- pin->SetString("pairingMethod", kPairingMethodPinCode);
- pin->SetString("pairingAuthToken", kTestPinCode);
- pin->SetString("pairingAction", kPairingActionDisplay);
- pin->SetInteger("classValue", kDisplayPinCodeClass);
- pin->SetBoolean("isTrusted", false);
- pin->SetBoolean("discoverable", false);
- pin->SetBoolean("paired", false);
- pin->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(pin));
-
- std::unique_ptr<base::DictionaryValue> vanishing(new base::DictionaryValue);
- vanishing->SetString("path", kVanishingDevicePath);
- vanishing->SetString("address", kVanishingDeviceAddress);
- vanishing->SetString("name", kVanishingDeviceName);
- vanishing->SetString("alias", kVanishingDeviceName);
- vanishing->SetString("pairingMethod", "");
- vanishing->SetString("pairingAuthToken", "");
- vanishing->SetString("pairingAction", "");
- vanishing->SetInteger("classValue", kVanishingDeviceClass);
- vanishing->SetBoolean("isTrusted", false);
- vanishing->SetBoolean("discoverable", false);
- vanishing->SetBoolean("paired", false);
- vanishing->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(vanishing));
-
- std::unique_ptr<base::DictionaryValue> connect_unpairable(
- new base::DictionaryValue);
- connect_unpairable->SetString("path", kConnectUnpairablePath);
- connect_unpairable->SetString("address", kConnectUnpairableAddress);
- connect_unpairable->SetString("name", kConnectUnpairableName);
- connect_unpairable->SetString("pairingMethod", "");
- connect_unpairable->SetString("pairingAuthToken", "");
- connect_unpairable->SetString("pairingAction", "");
- connect_unpairable->SetString("alias", kConnectUnpairableName);
- connect_unpairable->SetInteger("classValue", kConnectUnpairableClass);
- connect_unpairable->SetBoolean("isTrusted", false);
- connect_unpairable->SetBoolean("discoverable", false);
- connect_unpairable->SetBoolean("paired", false);
- connect_unpairable->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(connect_unpairable));
-
- std::unique_ptr<base::DictionaryValue> passkey(new base::DictionaryValue);
- passkey->SetString("path", kDisplayPasskeyPath);
- passkey->SetString("address", kDisplayPasskeyAddress);
- passkey->SetString("name", kDisplayPasskeyName);
- passkey->SetString("alias", kDisplayPasskeyName);
- passkey->SetString("pairingMethod", kPairingMethodPassKey);
- passkey->SetInteger("pairingAuthToken", kTestPassKey);
- passkey->SetString("pairingAction", kPairingActionDisplay);
- passkey->SetInteger("classValue", kDisplayPasskeyClass);
- passkey->SetBoolean("isTrusted", false);
- passkey->SetBoolean("discoverable", false);
- passkey->SetBoolean("paired", false);
- passkey->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(passkey));
-
- std::unique_ptr<base::DictionaryValue> request_pin(new base::DictionaryValue);
- request_pin->SetString("path", kRequestPinCodePath);
- request_pin->SetString("address", kRequestPinCodeAddress);
- request_pin->SetString("name", kRequestPinCodeName);
- request_pin->SetString("alias", kRequestPinCodeName);
- request_pin->SetString("pairingMethod", "");
- request_pin->SetString("pairingAuthToken", "");
- request_pin->SetString("pairingAction", kPairingActionRequest);
- request_pin->SetInteger("classValue", kRequestPinCodeClass);
- request_pin->SetBoolean("isTrusted", false);
- request_pin->SetBoolean("discoverable", false);
- request_pin->SetBoolean("paired", false);
- request_pin->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(request_pin));
-
- std::unique_ptr<base::DictionaryValue> confirm(new base::DictionaryValue);
- confirm->SetString("path", kConfirmPasskeyPath);
- confirm->SetString("address", kConfirmPasskeyAddress);
- confirm->SetString("name", kConfirmPasskeyName);
- confirm->SetString("alias", kConfirmPasskeyName);
- confirm->SetString("pairingMethod", "");
- confirm->SetInteger("pairingAuthToken", kTestPassKey);
- confirm->SetString("pairingAction", kPairingActionConfirmation);
- confirm->SetInteger("classValue", kConfirmPasskeyClass);
- confirm->SetBoolean("isTrusted", false);
- confirm->SetBoolean("discoverable", false);
- confirm->SetBoolean("paired", false);
- confirm->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(confirm));
-
- std::unique_ptr<base::DictionaryValue> request_passkey(
- new base::DictionaryValue);
- request_passkey->SetString("path", kRequestPasskeyPath);
- request_passkey->SetString("address", kRequestPasskeyAddress);
- request_passkey->SetString("name", kRequestPasskeyName);
- request_passkey->SetString("alias", kRequestPasskeyName);
- request_passkey->SetString("pairingMethod", kPairingMethodPassKey);
- request_passkey->SetString("pairingAction", kPairingActionRequest);
- request_passkey->SetInteger("pairingAuthToken", kTestPassKey);
- request_passkey->SetInteger("classValue", kRequestPasskeyClass);
- request_passkey->SetBoolean("isTrusted", false);
- request_passkey->SetBoolean("discoverable", false);
- request_passkey->SetBoolean("paired", false);
- request_passkey->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(request_passkey));
-
- std::unique_ptr<base::DictionaryValue> unconnectable(
- new base::DictionaryValue);
- unconnectable->SetString("path", kUnconnectableDevicePath);
- unconnectable->SetString("address", kUnconnectableDeviceAddress);
- unconnectable->SetString("name", kUnconnectableDeviceName);
- unconnectable->SetString("alias", kUnconnectableDeviceName);
- unconnectable->SetString("pairingMethod", "");
- unconnectable->SetString("pairingAuthToken", "");
- unconnectable->SetString("pairingAction", "");
- unconnectable->SetInteger("classValue", kUnconnectableDeviceClass);
- unconnectable->SetBoolean("isTrusted", true);
- unconnectable->SetBoolean("discoverable", false);
- unconnectable->SetBoolean("paired", false);
- unconnectable->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(unconnectable));
-
- std::unique_ptr<base::DictionaryValue> unpairable(new base::DictionaryValue);
- unpairable->SetString("path", kUnpairableDevicePath);
- unpairable->SetString("address", kUnpairableDeviceAddress);
- unpairable->SetString("name", kUnpairableDeviceName);
- unpairable->SetString("alias", kUnpairableDeviceName);
- unpairable->SetString("pairingMethod", "");
- unpairable->SetString("pairingAuthToken", "");
- unpairable->SetString("pairingAction", kPairingActionFail);
- unpairable->SetInteger("classValue", kUnpairableDeviceClass);
- unpairable->SetBoolean("isTrusted", false);
- unpairable->SetBoolean("discoverable", false);
- unpairable->SetBoolean("paired", false);
- unpairable->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(unpairable));
-
- std::unique_ptr<base::DictionaryValue> just_works(new base::DictionaryValue);
- just_works->SetString("path", kJustWorksPath);
- just_works->SetString("address", kJustWorksAddress);
- just_works->SetString("name", kJustWorksName);
- just_works->SetString("alias", kJustWorksName);
- just_works->SetString("pairingMethod", "");
- just_works->SetString("pairingAuthToken", "");
- just_works->SetString("pairingAction", "");
- just_works->SetInteger("classValue", kJustWorksClass);
- just_works->SetBoolean("isTrusted", false);
- just_works->SetBoolean("discoverable", false);
- just_works->SetBoolean("paired", false);
- just_works->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(just_works));
-
- std::unique_ptr<base::DictionaryValue> low_energy(new base::DictionaryValue);
- low_energy->SetString("path", kLowEnergyPath);
- low_energy->SetString("address", kLowEnergyAddress);
- low_energy->SetString("name", kLowEnergyName);
- low_energy->SetString("alias", kLowEnergyName);
- low_energy->SetString("pairingMethod", "");
- low_energy->SetString("pairingAuthToken", "");
- low_energy->SetString("pairingAction", "");
- low_energy->SetInteger("classValue", kLowEnergyClass);
- low_energy->SetBoolean("isTrusted", false);
- low_energy->SetBoolean("discoverable", false);
- low_energy->SetBoolean("paireed", false);
- low_energy->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(low_energy));
-
- std::unique_ptr<base::DictionaryValue> paired_unconnectable(
- new base::DictionaryValue);
- paired_unconnectable->SetString("path", kPairedUnconnectableDevicePath);
- paired_unconnectable->SetString("address", kPairedUnconnectableDeviceAddress);
- paired_unconnectable->SetString("name", kPairedUnconnectableDeviceName);
- paired_unconnectable->SetString("pairingMethod", "");
- paired_unconnectable->SetString("pairingAuthToken", "");
- paired_unconnectable->SetString("pairingAction", "");
- paired_unconnectable->SetString("alias", kPairedUnconnectableDeviceName);
- paired_unconnectable->SetInteger("classValue",
- kPairedUnconnectableDeviceClass);
- paired_unconnectable->SetBoolean("isTrusted", false);
- paired_unconnectable->SetBoolean("discoverable", true);
- paired_unconnectable->SetBoolean("paired", true);
- paired_unconnectable->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(paired_unconnectable));
-
- std::unique_ptr<base::DictionaryValue> connected_trusted_not_paired(
- new base::DictionaryValue);
- connected_trusted_not_paired->SetString("path",
- kConnectedTrustedNotPairedDevicePath);
- connected_trusted_not_paired->SetString(
+base::Value FakeBluetoothDeviceClient::GetBluetoothDevicesAsDictionaries()
+ const {
+ base::Value::ListStorage predefined_devices;
+
+ base::Value paired_device(base::Value::Type::DICTIONARY);
+ paired_device.SetStringKey("path", kPairedDevicePath);
+ paired_device.SetStringKey("address", kPairedDeviceAddress);
+ paired_device.SetStringKey("name", kPairedDeviceName);
+ paired_device.SetStringKey("alias", kPairedDeviceName);
+ paired_device.SetStringKey("pairingMethod", "");
+ paired_device.SetStringKey("pairingAuthToken", "");
+ paired_device.SetStringKey("pairingAction", "");
+ paired_device.SetIntKey("classValue", kPairedDeviceClass);
+ paired_device.SetBoolKey("discoverable", true);
+ paired_device.SetBoolKey("isTrusted", true);
+ paired_device.SetBoolKey("paired", true);
+ paired_device.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(paired_device));
+
+ base::Value legacy_device(base::Value::Type::DICTIONARY);
+ legacy_device.SetStringKey("path", kLegacyAutopairPath);
+ legacy_device.SetStringKey("address", kLegacyAutopairAddress);
+ legacy_device.SetStringKey("name", kLegacyAutopairName);
+ legacy_device.SetStringKey("alias", kLegacyAutopairName);
+ legacy_device.SetStringKey("pairingMethod", "");
+ legacy_device.SetStringKey("pairingAuthToken", "");
+ legacy_device.SetStringKey("pairingAction", "");
+ legacy_device.SetIntKey("classValue", kLegacyAutopairClass);
+ legacy_device.SetBoolKey("isTrusted", true);
+ legacy_device.SetBoolKey("discoverable", false);
+ legacy_device.SetBoolKey("paired", false);
+ legacy_device.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(legacy_device));
+
+ base::Value pin(base::Value::Type::DICTIONARY);
+ pin.SetStringKey("path", kDisplayPinCodePath);
+ pin.SetStringKey("address", kDisplayPinCodeAddress);
+ pin.SetStringKey("name", kDisplayPinCodeName);
+ pin.SetStringKey("alias", kDisplayPinCodeName);
+ pin.SetStringKey("pairingMethod", kPairingMethodPinCode);
+ pin.SetStringKey("pairingAuthToken", kTestPinCode);
+ pin.SetStringKey("pairingAction", kPairingActionDisplay);
+ pin.SetIntKey("classValue", kDisplayPinCodeClass);
+ pin.SetBoolKey("isTrusted", false);
+ pin.SetBoolKey("discoverable", false);
+ pin.SetBoolKey("paired", false);
+ pin.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(pin));
+
+ base::Value vanishing(base::Value::Type::DICTIONARY);
+ vanishing.SetStringKey("path", kVanishingDevicePath);
+ vanishing.SetStringKey("address", kVanishingDeviceAddress);
+ vanishing.SetStringKey("name", kVanishingDeviceName);
+ vanishing.SetStringKey("alias", kVanishingDeviceName);
+ vanishing.SetStringKey("pairingMethod", "");
+ vanishing.SetStringKey("pairingAuthToken", "");
+ vanishing.SetStringKey("pairingAction", "");
+ vanishing.SetIntKey("classValue", kVanishingDeviceClass);
+ vanishing.SetBoolKey("isTrusted", false);
+ vanishing.SetBoolKey("discoverable", false);
+ vanishing.SetBoolKey("paired", false);
+ vanishing.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(vanishing));
+
+ base::Value connect_unpairable(base::Value::Type::DICTIONARY);
+ connect_unpairable.SetStringKey("path", kConnectUnpairablePath);
+ connect_unpairable.SetStringKey("address", kConnectUnpairableAddress);
+ connect_unpairable.SetStringKey("name", kConnectUnpairableName);
+ connect_unpairable.SetStringKey("pairingMethod", "");
+ connect_unpairable.SetStringKey("pairingAuthToken", "");
+ connect_unpairable.SetStringKey("pairingAction", "");
+ connect_unpairable.SetStringKey("alias", kConnectUnpairableName);
+ connect_unpairable.SetIntKey("classValue", kConnectUnpairableClass);
+ connect_unpairable.SetBoolKey("isTrusted", false);
+ connect_unpairable.SetBoolKey("discoverable", false);
+ connect_unpairable.SetBoolKey("paired", false);
+ connect_unpairable.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(connect_unpairable));
+
+ base::Value passkey(base::Value::Type::DICTIONARY);
+ passkey.SetStringKey("path", kDisplayPasskeyPath);
+ passkey.SetStringKey("address", kDisplayPasskeyAddress);
+ passkey.SetStringKey("name", kDisplayPasskeyName);
+ passkey.SetStringKey("alias", kDisplayPasskeyName);
+ passkey.SetStringKey("pairingMethod", kPairingMethodPassKey);
+ passkey.SetIntKey("pairingAuthToken", kTestPassKey);
+ passkey.SetStringKey("pairingAction", kPairingActionDisplay);
+ passkey.SetIntKey("classValue", kDisplayPasskeyClass);
+ passkey.SetBoolKey("isTrusted", false);
+ passkey.SetBoolKey("discoverable", false);
+ passkey.SetBoolKey("paired", false);
+ passkey.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(passkey));
+
+ base::Value request_pin(base::Value::Type::DICTIONARY);
+ request_pin.SetStringKey("path", kRequestPinCodePath);
+ request_pin.SetStringKey("address", kRequestPinCodeAddress);
+ request_pin.SetStringKey("name", kRequestPinCodeName);
+ request_pin.SetStringKey("alias", kRequestPinCodeName);
+ request_pin.SetStringKey("pairingMethod", "");
+ request_pin.SetStringKey("pairingAuthToken", "");
+ request_pin.SetStringKey("pairingAction", kPairingActionRequest);
+ request_pin.SetIntKey("classValue", kRequestPinCodeClass);
+ request_pin.SetBoolKey("isTrusted", false);
+ request_pin.SetBoolKey("discoverable", false);
+ request_pin.SetBoolKey("paired", false);
+ request_pin.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(request_pin));
+
+ base::Value confirm(base::Value::Type::DICTIONARY);
+ confirm.SetStringKey("path", kConfirmPasskeyPath);
+ confirm.SetStringKey("address", kConfirmPasskeyAddress);
+ confirm.SetStringKey("name", kConfirmPasskeyName);
+ confirm.SetStringKey("alias", kConfirmPasskeyName);
+ confirm.SetStringKey("pairingMethod", "");
+ confirm.SetIntKey("pairingAuthToken", kTestPassKey);
+ confirm.SetStringKey("pairingAction", kPairingActionConfirmation);
+ confirm.SetIntKey("classValue", kConfirmPasskeyClass);
+ confirm.SetBoolKey("isTrusted", false);
+ confirm.SetBoolKey("discoverable", false);
+ confirm.SetBoolKey("paired", false);
+ confirm.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(confirm));
+
+ base::Value request_passkey(base::Value::Type::DICTIONARY);
+ request_passkey.SetStringKey("path", kRequestPasskeyPath);
+ request_passkey.SetStringKey("address", kRequestPasskeyAddress);
+ request_passkey.SetStringKey("name", kRequestPasskeyName);
+ request_passkey.SetStringKey("alias", kRequestPasskeyName);
+ request_passkey.SetStringKey("pairingMethod", kPairingMethodPassKey);
+ request_passkey.SetStringKey("pairingAction", kPairingActionRequest);
+ request_passkey.SetIntKey("pairingAuthToken", kTestPassKey);
+ request_passkey.SetIntKey("classValue", kRequestPasskeyClass);
+ request_passkey.SetBoolKey("isTrusted", false);
+ request_passkey.SetBoolKey("discoverable", false);
+ request_passkey.SetBoolKey("paired", false);
+ request_passkey.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(request_passkey));
+
+ base::Value unconnectable(base::Value::Type::DICTIONARY);
+ unconnectable.SetStringKey("path", kUnconnectableDevicePath);
+ unconnectable.SetStringKey("address", kUnconnectableDeviceAddress);
+ unconnectable.SetStringKey("name", kUnconnectableDeviceName);
+ unconnectable.SetStringKey("alias", kUnconnectableDeviceName);
+ unconnectable.SetStringKey("pairingMethod", "");
+ unconnectable.SetStringKey("pairingAuthToken", "");
+ unconnectable.SetStringKey("pairingAction", "");
+ unconnectable.SetIntKey("classValue", kUnconnectableDeviceClass);
+ unconnectable.SetBoolKey("isTrusted", true);
+ unconnectable.SetBoolKey("discoverable", false);
+ unconnectable.SetBoolKey("paired", false);
+ unconnectable.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(unconnectable));
+
+ base::Value unpairable(base::Value::Type::DICTIONARY);
+ unpairable.SetStringKey("path", kUnpairableDevicePath);
+ unpairable.SetStringKey("address", kUnpairableDeviceAddress);
+ unpairable.SetStringKey("name", kUnpairableDeviceName);
+ unpairable.SetStringKey("alias", kUnpairableDeviceName);
+ unpairable.SetStringKey("pairingMethod", "");
+ unpairable.SetStringKey("pairingAuthToken", "");
+ unpairable.SetStringKey("pairingAction", kPairingActionFail);
+ unpairable.SetIntKey("classValue", kUnpairableDeviceClass);
+ unpairable.SetBoolKey("isTrusted", false);
+ unpairable.SetBoolKey("discoverable", false);
+ unpairable.SetBoolKey("paired", false);
+ unpairable.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(unpairable));
+
+ base::Value just_works(base::Value::Type::DICTIONARY);
+ just_works.SetStringKey("path", kJustWorksPath);
+ just_works.SetStringKey("address", kJustWorksAddress);
+ just_works.SetStringKey("name", kJustWorksName);
+ just_works.SetStringKey("alias", kJustWorksName);
+ just_works.SetStringKey("pairingMethod", "");
+ just_works.SetStringKey("pairingAuthToken", "");
+ just_works.SetStringKey("pairingAction", "");
+ just_works.SetIntKey("classValue", kJustWorksClass);
+ just_works.SetBoolKey("isTrusted", false);
+ just_works.SetBoolKey("discoverable", false);
+ just_works.SetBoolKey("paired", false);
+ just_works.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(just_works));
+
+ base::Value low_energy(base::Value::Type::DICTIONARY);
+ low_energy.SetStringKey("path", kLowEnergyPath);
+ low_energy.SetStringKey("address", kLowEnergyAddress);
+ low_energy.SetStringKey("name", kLowEnergyName);
+ low_energy.SetStringKey("alias", kLowEnergyName);
+ low_energy.SetStringKey("pairingMethod", "");
+ low_energy.SetStringKey("pairingAuthToken", "");
+ low_energy.SetStringKey("pairingAction", "");
+ low_energy.SetIntKey("classValue", kLowEnergyClass);
+ low_energy.SetBoolKey("isTrusted", false);
+ low_energy.SetBoolKey("discoverable", false);
+ low_energy.SetBoolKey("paireed", false);
+ low_energy.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(low_energy));
+
+ base::Value paired_unconnectable(base::Value::Type::DICTIONARY);
+ paired_unconnectable.SetStringKey("path", kPairedUnconnectableDevicePath);
+ paired_unconnectable.SetStringKey("address",
+ kPairedUnconnectableDeviceAddress);
+ paired_unconnectable.SetStringKey("name", kPairedUnconnectableDeviceName);
+ paired_unconnectable.SetStringKey("pairingMethod", "");
+ paired_unconnectable.SetStringKey("pairingAuthToken", "");
+ paired_unconnectable.SetStringKey("pairingAction", "");
+ paired_unconnectable.SetStringKey("alias", kPairedUnconnectableDeviceName);
+ paired_unconnectable.SetIntKey("classValue", kPairedUnconnectableDeviceClass);
+ paired_unconnectable.SetBoolKey("isTrusted", false);
+ paired_unconnectable.SetBoolKey("discoverable", true);
+ paired_unconnectable.SetBoolKey("paired", true);
+ paired_unconnectable.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(paired_unconnectable));
+
+ base::Value connected_trusted_not_paired(base::Value::Type::DICTIONARY);
+ connected_trusted_not_paired.SetStringKey(
+ "path", kConnectedTrustedNotPairedDevicePath);
+ connected_trusted_not_paired.SetStringKey(
"address", kConnectedTrustedNotPairedDeviceAddress);
- connected_trusted_not_paired->SetString("name",
- kConnectedTrustedNotPairedDeviceName);
- connected_trusted_not_paired->SetString("pairingMethod", "");
- connected_trusted_not_paired->SetString("pairingAuthToken", "");
- connected_trusted_not_paired->SetString("pairingAction", "");
- connected_trusted_not_paired->SetString("alias",
- kConnectedTrustedNotPairedDeviceName);
- connected_trusted_not_paired->SetInteger(
- "classValue", kConnectedTrustedNotPairedDeviceClass);
- connected_trusted_not_paired->SetBoolean("isTrusted", true);
- connected_trusted_not_paired->SetBoolean("discoverable", true);
- connected_trusted_not_paired->SetBoolean("paired", false);
- connected_trusted_not_paired->SetBoolean("incoming", false);
- predefined_devices->Append(std::move(connected_trusted_not_paired));
-
- return predefined_devices;
+ connected_trusted_not_paired.SetStringKey(
+ "name", kConnectedTrustedNotPairedDeviceName);
+ connected_trusted_not_paired.SetStringKey("pairingMethod", "");
+ connected_trusted_not_paired.SetStringKey("pairingAuthToken", "");
+ connected_trusted_not_paired.SetStringKey("pairingAction", "");
+ connected_trusted_not_paired.SetStringKey(
+ "alias", kConnectedTrustedNotPairedDeviceName);
+ connected_trusted_not_paired.SetIntKey("classValue",
+ kConnectedTrustedNotPairedDeviceClass);
+ connected_trusted_not_paired.SetBoolKey("isTrusted", true);
+ connected_trusted_not_paired.SetBoolKey("discoverable", true);
+ connected_trusted_not_paired.SetBoolKey("paired", false);
+ connected_trusted_not_paired.SetBoolKey("incoming", false);
+ predefined_devices.push_back(std::move(connected_trusted_not_paired));
+
+ return base::Value(std::move(predefined_devices));
}
void FakeBluetoothDeviceClient::RemoveDevice(
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h
index 66db5320ea0..98a9676382a 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_device_client.h
@@ -140,7 +140,7 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
// Creates and returns a list of std::unique_ptr<base::DictionaryValue>
// objects, which contain all the data from the constants for devices with
// predefined behavior.
- std::unique_ptr<base::ListValue> GetBluetoothDevicesAsDictionaries() const;
+ base::Value GetBluetoothDevicesAsDictionaries() const;
SimulatedPairingOptions* GetPairingOptions(
const dbus::ObjectPath& object_path);
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
index ab1c641f56b..41e00e93a88 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -206,6 +207,7 @@ void FakeBluetoothGattCharacteristicClient::ReadValue(
void FakeBluetoothGattCharacteristicClient::WriteValue(
const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
+ base::StringPiece type_option,
base::OnceClosure callback,
ErrorCallback error_callback) {
if (!authenticated_) {
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h b/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
index 217636c5389..bb17ba3f958 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_characteristic_client.h
@@ -57,6 +57,7 @@ class DEVICE_BLUETOOTH_EXPORT FakeBluetoothGattCharacteristicClient
ErrorCallback error_callback) override;
void WriteValue(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value,
+ base::StringPiece type_option,
base::OnceClosure callback,
ErrorCallback error_callback) override;
void PrepareWriteValue(const dbus::ObjectPath& object_path,
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
index 5441071b4bd..1dfd30aa534 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_gatt_service_client.cc
@@ -6,6 +6,7 @@
#include "base/bind.h"
#include "base/location.h"
+#include "base/logging.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc
index 52d3239f925..a4a3ba97129 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.cc
@@ -4,6 +4,7 @@
#include "device/bluetooth/dbus/fake_bluetooth_le_advertisement_service_provider.h"
+#include "base/logging.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_le_advertising_manager_client.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_media_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_media_client.cc
index 7e67ac7a86e..fd693399dd6 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_media_client.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_media_client.cc
@@ -6,6 +6,7 @@
#include <string>
+#include "base/logging.h"
#include "base/stl_util.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_adapter_client.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
index faf04dc0363..4a0b7c33695 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.cc
@@ -4,6 +4,7 @@
#include "device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h"
+#include "base/logging.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_media_client.h"
#include "device/bluetooth/dbus/fake_bluetooth_media_transport_client.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h b/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
index f907e4da732..43b72422101 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_media_endpoint_service_provider.h
@@ -9,7 +9,6 @@
#include <vector>
-#include "base/logging.h"
#include "base/macros.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_export.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
index d7b267d8cc7..7d4c63a468e 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_media_transport_client.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/file_descriptor_posix.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "device/bluetooth/dbus/bluetooth_media_client.h"
diff --git a/chromium/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc b/chromium/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
index f684ecb112a..508e833fb3e 100644
--- a/chromium/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
+++ b/chromium/device/bluetooth/dbus/fake_bluetooth_profile_service_provider.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "base/logging.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
#include "device/bluetooth/dbus/fake_bluetooth_profile_manager_client.h"
diff --git a/chromium/device/bluetooth/device.cc b/chromium/device/bluetooth/device.cc
index d155f38ee65..fd3df58d5de 100644
--- a/chromium/device/bluetooth/device.cc
+++ b/chromium/device/bluetooth/device.cc
@@ -180,7 +180,7 @@ void Device::WriteValueForCharacteristic(
}
auto copyable_callback = base::AdaptCallbackForRepeating(std::move(callback));
- characteristic->WriteRemoteCharacteristic(
+ characteristic->DeprecatedWriteRemoteCharacteristic(
value,
base::BindOnce(&Device::OnWriteRemoteCharacteristic,
weak_ptr_factory_.GetWeakPtr(), copyable_callback),
diff --git a/chromium/device/bluetooth/public/mojom/BUILD.gn b/chromium/device/bluetooth/public/mojom/BUILD.gn
index beed96c8d44..a8229236120 100644
--- a/chromium/device/bluetooth/public/mojom/BUILD.gn
+++ b/chromium/device/bluetooth/public/mojom/BUILD.gn
@@ -58,7 +58,10 @@ mojom("deprecated_experimental_interfaces") {
# Implementation of the mojom interfaces:
"//device/bluetooth:deprecated_experimental_mojo",
- # Single approved client of the interfaces:
+ # Bluetooth internals page
"//chrome/browser/ui/webui/bluetooth_internals:*",
+
+ # Nearby Sharing feature
+ "//chrome/services/sharing/public/mojom:*",
]
}
diff --git a/chromium/device/bluetooth/public/mojom/test/fake_bluetooth.mojom b/chromium/device/bluetooth/public/mojom/test/fake_bluetooth.mojom
index 710be64b77d..cd133119570 100644
--- a/chromium/device/bluetooth/public/mojom/test/fake_bluetooth.mojom
+++ b/chromium/device/bluetooth/public/mojom/test/fake_bluetooth.mojom
@@ -38,6 +38,14 @@ enum CentralState {
POWERED_OFF,
};
+// GATT characteristic write type.
+enum WriteType {
+ kNone,
+ kWriteDefaultDeprecated,
+ kWriteWithResponse,
+ kWriteWithoutResponse,
+};
+
// Stores the external appearance description of the device.
struct Appearance {
bool has_value;
@@ -323,7 +331,8 @@ interface FakeCentral {
GetLastWrittenCharacteristicValue(
string characteristic_id,
string service_id,
- string peripheral_address) => (bool success, array<uint8>? value);
+ string peripheral_address) => (bool success, array<uint8>? value,
+ WriteType write_type);
// Sets the next read response for descriptor with |descriptor_id| in
// |characteristics_id| in |service_id| and in |peripheral_address| to |code|