Commit 1feb34d3 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS MultiDevice] Add DeviceConnectedStateChanged() observer callback.

This callback allows Bluetooth clients on Chrome OS to listen for
connection state changes (i.e., when a device goes from connected to
disconnected or vice versa).

A follow-up CL will add handling for this event in the SecureChannel
service to prevent us from accidentally attempting to connect to a
disconnecting device (see https://crbug.com/898334).

Bug: 898334
Change-Id: Icc18f44106d12a881518f0ece3f0a6e9dd715c0b
Reviewed-on: https://chromium-review.googlesource.com/c/1347204Reviewed-by: default avatarGiovanni Ortuño Urquidi <ortuno@chromium.org>
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610307}
parent d32f4c9f
......@@ -152,6 +152,13 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapter
BluetoothDevice* device,
int16_t rssi,
const std::vector<uint8_t>& eir) {}
// This function is implemented for ChromeOS only.
// Called when |device|'s state has changed from connected to not connected
// or vice versa.
virtual void DeviceConnectedStateChanged(BluetoothAdapter* adapter,
BluetoothDevice* device,
bool is_now_connected) {}
#endif
// Called when the device |device| is removed from the adapter |adapter|,
......
......@@ -690,6 +690,10 @@ void BluetoothAdapterBlueZ::DevicePropertyChanged(
NotifyDeviceAdvertisementReceived(device_bluez, properties->rssi.value(),
properties->eir.value());
if (property_name == properties->connected.name())
NotifyDeviceConnectedStateChanged(device_bluez,
properties->connected.value());
if (property_name == properties->services_resolved.name() &&
properties->services_resolved.value()) {
device_bluez->UpdateGattServices(object_path);
......@@ -1152,6 +1156,16 @@ void BluetoothAdapterBlueZ::NotifyDeviceAdvertisementReceived(
observer.DeviceAdvertisementReceived(this, device, rssi, eir);
}
void BluetoothAdapterBlueZ::NotifyDeviceConnectedStateChanged(
BluetoothDeviceBlueZ* device,
bool is_now_connected) {
DCHECK_EQ(device->adapter_, this);
DCHECK_EQ(device->IsConnected(), is_now_connected);
for (auto& observer : observers_)
observer.DeviceConnectedStateChanged(this, device, is_now_connected);
}
void BluetoothAdapterBlueZ::UseProfile(
const BluetoothUUID& uuid,
const dbus::ObjectPath& device_path,
......
......@@ -172,6 +172,10 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothAdapterBlueZ
int16_t rssi,
const std::vector<uint8_t>& eir);
// Announce to observers that |device| has changed its connected state.
void NotifyDeviceConnectedStateChanged(BluetoothDeviceBlueZ* device,
bool is_now_connected);
// Returns the object path of the adapter.
const dbus::ObjectPath& object_path() const { return object_path_; }
......
......@@ -2438,6 +2438,36 @@ TEST_F(BluetoothBlueZTest, DeviceAdvertisementReceived) {
EXPECT_EQ(1, observer.device_advertisement_received_count());
EXPECT_EQ(eir, observer.device_eir());
}
TEST_F(BluetoothBlueZTest, DeviceConnectedStateChanged) {
GetAdapter();
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);
// Install an observer; expect DeviceConnectedStateChanged method to be
// called.
TestBluetoothAdapterObserver observer(adapter_);
bluez::FakeBluetoothDeviceClient::Properties* properties =
fake_bluetooth_device_client_->GetProperties(
dbus::ObjectPath(bluez::FakeBluetoothDeviceClient::kLowEnergyPath));
// The device starts out disconnected.
EXPECT_FALSE(device->IsConnected());
properties->connected.ReplaceValue(true);
EXPECT_EQ(1u, observer.device_connected_state_changed_values().size());
EXPECT_TRUE(observer.device_connected_state_changed_values()[0]);
properties->connected.ReplaceValue(false);
EXPECT_EQ(2u, observer.device_connected_state_changed_values().size());
EXPECT_FALSE(observer.device_connected_state_changed_values()[1]);
}
#endif
TEST_F(BluetoothBlueZTest, DeviceUuidsChanged) {
......
......@@ -44,6 +44,7 @@ void TestBluetoothAdapterObserver::Reset() {
device_mtu_ = 0;
device_advertisement_received_count_ = 0;
device_eir_.clear();
device_connected_state_changed_values_.clear();
#endif
device_removed_count_ = 0;
last_device_ = NULL;
......@@ -172,6 +173,16 @@ void TestBluetoothAdapterObserver::DeviceAdvertisementReceived(
QuitMessageLoop();
}
void TestBluetoothAdapterObserver::DeviceConnectedStateChanged(
device::BluetoothAdapter* adapter,
device::BluetoothDevice* device,
bool is_now_connected) {
last_device_ = device;
device_connected_state_changed_values_.push_back(is_now_connected);
QuitMessageLoop();
}
#endif
void TestBluetoothAdapterObserver::DeviceRemoved(BluetoothAdapter* adapter,
......
......@@ -49,6 +49,9 @@ class TestBluetoothAdapterObserver : public BluetoothAdapter::Observer {
device::BluetoothDevice* device,
int16_t rssi,
const std::vector<uint8_t>& eir) override;
void DeviceConnectedStateChanged(device::BluetoothAdapter* adapter,
device::BluetoothDevice* device,
bool is_now_connected) override;
#endif
void DeviceRemoved(BluetoothAdapter* adapter,
BluetoothDevice* device) override;
......@@ -110,6 +113,9 @@ class TestBluetoothAdapterObserver : public BluetoothAdapter::Observer {
return device_advertisement_received_count_;
}
const std::vector<uint8_t>& device_eir() const { return device_eir_; }
const std::vector<bool>& device_connected_state_changed_values() const {
return device_connected_state_changed_values_;
}
#endif
int device_removed_count() const { return device_removed_count_; }
BluetoothDevice* last_device() const { return last_device_; }
......@@ -197,6 +203,7 @@ class TestBluetoothAdapterObserver : public BluetoothAdapter::Observer {
uint16_t device_mtu_;
int device_advertisement_received_count_;
std::vector<uint8_t> device_eir_;
std::vector<bool> device_connected_state_changed_values_;
#endif
int device_removed_count_;
BluetoothDevice* last_device_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment