[chromecast][Bluetooth] Fix connect/services logic
This allows WebBT to work if we were connected before or after the WebBT
application starts.
Remove BluetoothAdapterCast::OnServicesUpdated because Connect now
implies services are discovered. Dynamic service updating is also
deprecated:
https://cs.chromium.org/chromium/src/device/bluetooth/bluetooth_adapter.h?rcl=21e8d8c8dc11cd4b8f77c47b7f37098ebde13d3a&l=142
BUG=internal b/79542125
TEST=device_unittests. Manual
Change-Id: I99ed5dc61942cb310ed76581648fdab6c31316a1
Reviewed-on: https://chromium-review.googlesource.com/1058605
Commit-Queue: Bailey Forrest <[email protected]>
Reviewed-by: Stephen Lanham <[email protected]>
Reviewed-by: Reilly Grant <[email protected]>
Cr-Commit-Position: refs/heads/master@{#558898}
diff --git a/device/BUILD.gn b/device/BUILD.gn
index 68be0c8..a5d97242 100644
--- a/device/BUILD.gn
+++ b/device/BUILD.gn
@@ -246,6 +246,7 @@
deps += [
"//chromecast/device/bluetooth:util",
"//chromecast/device/bluetooth/le",
+ "//chromecast/device/bluetooth/le:test_support",
"//chromecast/device/bluetooth/shlib:mock_shlib",
]
} else {
diff --git a/device/bluetooth/DEPS b/device/bluetooth/DEPS
index d098881..1eab793 100644
--- a/device/bluetooth/DEPS
+++ b/device/bluetooth/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+chromecast/device/bluetooth",
+ "+chromecast/public/bluetooth",
"+chromeos/dbus",
"+crypto",
"+dbus",
diff --git a/device/bluetooth/cast/bluetooth_adapter_cast.cc b/device/bluetooth/cast/bluetooth_adapter_cast.cc
index 8bf86dd..af5df4c 100644
--- a/device/bluetooth/cast/bluetooth_adapter_cast.cc
+++ b/device/bluetooth/cast/bluetooth_adapter_cast.cc
@@ -300,24 +300,6 @@
<< " mtu: " << mtu;
}
-void BluetoothAdapterCast::OnServicesUpdated(
- scoped_refptr<chromecast::bluetooth::RemoteDevice> device,
- std::vector<scoped_refptr<chromecast::bluetooth::RemoteService>> services) {
- DVLOG(1) << __func__;
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- std::string address = GetCanonicalBluetoothAddress(device->addr());
- BluetoothDeviceCast* cast_device = GetCastDevice(address);
- if (!cast_device)
- return;
-
- if (!cast_device->UpdateServices(services))
- LOG(WARNING) << "The services were not updated. Alerting anyway.";
-
- cast_device->SetGattServicesDiscoveryComplete(true);
- NotifyGattServicesDiscovered(cast_device);
-}
-
void BluetoothAdapterCast::OnCharacteristicNotification(
scoped_refptr<chromecast::bluetooth::RemoteDevice> device,
scoped_refptr<chromecast::bluetooth::RemoteCharacteristic> characteristic,
@@ -347,17 +329,19 @@
// to send an async request to |gatt_client_manager_| for a handle to the
// device.
if (devices_.find(address) == devices_.end()) {
+ bool first_time_seen =
+ pending_scan_results_.find(address) == pending_scan_results_.end();
+ // These results will be used to construct the BluetoothDeviceCast.
+ pending_scan_results_[address].push_back(result);
+
// Only send a request if this is the first time we've seen this |address|
// in a scan. This may happen if we pick up additional GAP advertisements
// while the first request is in-flight.
- if (pending_scan_results_.find(address) == pending_scan_results_.end()) {
+ if (first_time_seen) {
gatt_client_manager_->GetDevice(
result.addr, base::BindOnce(&BluetoothAdapterCast::OnGetDevice,
weak_factory_.GetWeakPtr()));
}
-
- // These results will be used to construct the BluetoothDeviceCast.
- pending_scan_results_[address].push_back(result);
return;
}
diff --git a/device/bluetooth/cast/bluetooth_adapter_cast.h b/device/bluetooth/cast/bluetooth_adapter_cast.h
index a25ee07..7dca466 100644
--- a/device/bluetooth/cast/bluetooth_adapter_cast.h
+++ b/device/bluetooth/cast/bluetooth_adapter_cast.h
@@ -137,10 +137,6 @@
bool connected) override;
void OnMtuChanged(scoped_refptr<chromecast::bluetooth::RemoteDevice> device,
int mtu) override;
- void OnServicesUpdated(
- scoped_refptr<chromecast::bluetooth::RemoteDevice> device,
- std::vector<scoped_refptr<chromecast::bluetooth::RemoteService>> services)
- override;
void OnCharacteristicNotification(
scoped_refptr<chromecast::bluetooth::RemoteDevice> device,
scoped_refptr<chromecast::bluetooth::RemoteCharacteristic> characteristic,
diff --git a/device/bluetooth/cast/bluetooth_device_cast.cc b/device/bluetooth/cast/bluetooth_device_cast.cc
index e92f3530..32ccb2a 100644
--- a/device/bluetooth/cast/bluetooth_device_cast.cc
+++ b/device/bluetooth/cast/bluetooth_device_cast.cc
@@ -14,6 +14,7 @@
#include "chromecast/device/bluetooth/bluetooth_util.h"
#include "chromecast/device/bluetooth/le/remote_characteristic.h"
#include "chromecast/device/bluetooth/le/remote_service.h"
+#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/cast/bluetooth_remote_gatt_characteristic_cast.h"
#include "device/bluetooth/cast/bluetooth_remote_gatt_service_cast.h"
#include "device/bluetooth/cast/bluetooth_utils.h"
@@ -60,7 +61,12 @@
connected_(device->IsConnected()),
remote_device_(std::move(device)),
address_(GetCanonicalBluetoothAddress(remote_device_->addr())),
- weak_factory_(this) {}
+ weak_factory_(this) {
+ if (connected_) {
+ remote_device_->GetServices(base::BindOnce(
+ &BluetoothDeviceCast::OnGetServices, weak_factory_.GetWeakPtr()));
+ }
+}
BluetoothDeviceCast::~BluetoothDeviceCast() {}
@@ -286,6 +292,8 @@
// fired.
if (!was_connected && connected) {
DidConnectGatt();
+ remote_device_->GetServices(base::BindOnce(
+ &BluetoothDeviceCast::OnGetServices, weak_factory_.GetWeakPtr()));
} else if (was_connected && !connected) {
DidDisconnectGatt();
}
@@ -294,43 +302,23 @@
return was_connected != connected;
}
-bool BluetoothDeviceCast::UpdateServices(
+void BluetoothDeviceCast::OnGetServices(
std::vector<scoped_refptr<chromecast::bluetooth::RemoteService>> services) {
DVLOG(2) << __func__;
- bool changed = false;
-
- // Create a look-up for the updated list of services.
- std::unordered_set<std::string> new_service_uuids;
- for (const auto& service : services)
- new_service_uuids.insert(GetCanonicalBluetoothUuid(service->uuid()));
-
- // Remove any services in |gatt_services_| that are not present in |services|.
- for (auto it = gatt_services_.cbegin(); it != gatt_services_.cend();) {
- if (new_service_uuids.find(it->first) == new_service_uuids.end()) {
- gatt_services_.erase(it++);
- changed = true;
- } else {
- ++it;
- }
- }
+ gatt_services_.clear();
// Add new services.
for (auto& service : services) {
auto key = GetCanonicalBluetoothUuid(service->uuid());
-
- if (gatt_services_.find(key) != gatt_services_.end())
- continue;
-
auto cast_service = std::make_unique<BluetoothRemoteGattServiceCast>(
this, std::move(service));
DCHECK_EQ(key, cast_service->GetIdentifier());
gatt_services_[key] = std::move(cast_service);
- changed = true;
}
- if (changed)
- device_uuids_.ReplaceServiceUUIDs(gatt_services_);
- return changed;
+ device_uuids_.ReplaceServiceUUIDs(gatt_services_);
+ SetGattServicesDiscoveryComplete(true);
+ adapter_->NotifyGattServicesDiscovered(this);
}
bool BluetoothDeviceCast::UpdateCharacteristicValue(
@@ -375,18 +363,14 @@
void BluetoothDeviceCast::OnConnect(bool success) {
DVLOG(2) << __func__ << " success:" << success;
pending_connect_ = false;
- if (success)
- SetConnected(true);
- else
+ if (!success)
DidFailToConnectGatt(ERROR_FAILED);
}
void BluetoothDeviceCast::OnDisconnect(bool success) {
DVLOG(2) << __func__ << " success:" << success;
pending_disconnect_ = false;
- if (success)
- SetConnected(false);
- else
+ if (!success)
LOG(ERROR) << "Request to DisconnectGatt() failed!";
}
diff --git a/device/bluetooth/cast/bluetooth_device_cast.h b/device/bluetooth/cast/bluetooth_device_cast.h
index 68ad822..0f212b1 100644
--- a/device/bluetooth/cast/bluetooth_device_cast.h
+++ b/device/bluetooth/cast/bluetooth_device_cast.h
@@ -95,13 +95,6 @@
// connection state changed as a result.
bool SetConnected(bool connected);
- // Called by BluetoothAdapterCast when the GATT services for this device are
- // updated. Updates the services in this devices to reflect |services|.
- // Returns true if a service was added or removed.
- bool UpdateServices(
- std::vector<scoped_refptr<chromecast::bluetooth::RemoteService>>
- services);
-
// Called by BluetoothAdapterCast when the value of a characteristic in one of
// this device's services has changed, resulting in a notification to the
// device. Locate the characteristc and update the underluing value. If the
@@ -132,6 +125,11 @@
// Called back from disconnect requests.
void OnDisconnect(bool success);
+ // Called in response to GetServices
+ void OnGetServices(
+ std::vector<scoped_refptr<chromecast::bluetooth::RemoteService>>
+ services);
+
bool connected_;
bool pending_connect_ = false;
bool pending_disconnect_ = false;
diff --git a/device/bluetooth/test/bluetooth_test_cast.cc b/device/bluetooth/test/bluetooth_test_cast.cc
index 31728ba..a5d9f01 100644
--- a/device/bluetooth/test/bluetooth_test_cast.cc
+++ b/device/bluetooth/test/bluetooth_test_cast.cc
@@ -7,52 +7,46 @@
#include "base/bind_helpers.h"
#include "base/task_scheduler/post_task.h"
#include "chromecast/device/bluetooth/bluetooth_util.h"
-#include "chromecast/device/bluetooth/le/gatt_client_manager_impl.h"
+#include "chromecast/device/bluetooth/le/mock_gatt_client_manager.h"
#include "chromecast/device/bluetooth/le/remote_device.h"
#include "device/bluetooth/cast/bluetooth_adapter_cast.h"
-#include "device/bluetooth/test/bluetooth_test_cast.h"
+
+using ::testing::Return;
namespace device {
-class BluetoothTestCast::FakeLeScanManager
- : public chromecast::bluetooth::LeScanManager {
+class BluetoothTestCast::GattClientManager
+ : public chromecast::bluetooth::MockGattClientManager {
public:
- FakeLeScanManager() = default;
- ~FakeLeScanManager() override = default;
+ GattClientManager() = default;
+ ~GattClientManager() override = default;
- void AddObserver(Observer* o) override {
- DCHECK(!observer_);
- observer_ = o;
- }
- void RemoveObserver(Observer* o) override {
- DCHECK_EQ(observer_, o);
- observer_ = nullptr;
- }
- void SetScanEnable(bool enable, SetScanEnableCallback cb) override {
- std::move(cb).Run(true);
- }
- void GetScanResults(GetScanResultsCallback cb,
- base::Optional<chromecast::bluetooth::ScanFilter>
- scan_filter = base::nullopt) override {}
- void ClearScanResults() override {}
+ // chromecast::bluetooth::GattClientManager implementation:
+ void GetDevice(
+ const chromecast::bluetooth_v2_shlib::Addr& addr,
+ base::OnceCallback<void(
+ scoped_refptr<chromecast::bluetooth::RemoteDevice>)> cb) override {
+ auto it = addr_to_remote_device_.find(addr);
+ if (it != addr_to_remote_device_.end()) {
+ std::move(cb).Run(it->second);
+ return;
+ }
- Observer* observer() {
- DCHECK(observer_);
- return observer_;
+ auto device =
+ base::MakeRefCounted<chromecast::bluetooth::MockRemoteDevice>(addr);
+ addr_to_remote_device_.emplace(addr, device);
+ std::move(cb).Run(device);
}
private:
- Observer* observer_ = nullptr;
+ std::map<chromecast::bluetooth_v2_shlib::Addr,
+ scoped_refptr<chromecast::bluetooth::MockRemoteDevice>>
+ addr_to_remote_device_;
};
BluetoothTestCast::BluetoothTestCast()
- : io_task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
- {base::MayBlock(), base::TaskPriority::BACKGROUND})),
- gatt_client_manager_(
- new chromecast::bluetooth::GattClientManagerImpl(&mock_gatt_client_)),
- fake_le_scan_manager_(new FakeLeScanManager()) {
- gatt_client_manager_->Initialize(io_task_runner_);
- mock_gatt_client_.SetDelegate(gatt_client_manager_.get());
+ : gatt_client_manager_(std::make_unique<GattClientManager>()) {
+ ON_CALL(le_scan_manager_, SetScanEnable).WillByDefault(Return(true));
}
BluetoothTestCast::~BluetoothTestCast() {
@@ -62,12 +56,11 @@
// Tear down adapter, which relies on members in the subclass.
adapter_ = nullptr;
- gatt_client_manager_->Finalize();
}
void BluetoothTestCast::InitWithFakeAdapter() {
- adapter_ = new BluetoothAdapterCast(gatt_client_manager_.get(),
- fake_le_scan_manager_.get());
+ adapter_ =
+ new BluetoothAdapterCast(gatt_client_manager_.get(), &le_scan_manager_);
adapter_->SetPowered(true, base::DoNothing(), base::DoNothing());
}
@@ -124,7 +117,7 @@
const std::vector<std::string>& service_uuids,
const std::map<std::string, std::vector<uint8_t>>& service_data,
const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data) {
- // Create a scan result with the desired address and name.
+ // Create a scan result with the desired values.
chromecast::bluetooth::LeScanResult result;
ASSERT_TRUE(chromecast::bluetooth::util::ParseAddr(address, &result.addr));
if (name) {
@@ -132,6 +125,18 @@
.push_back(std::vector<uint8_t>(name->begin(), name->end()));
}
+ // Add service_uuids.
+ std::vector<uint8_t> data;
+ for (const auto& uuid_str : service_uuids) {
+ chromecast::bluetooth_v2_shlib::Uuid uuid;
+ ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(uuid_str, &uuid));
+ data.insert(data.end(), uuid.rbegin(), uuid.rend());
+ }
+ result
+ .type_to_data
+ [chromecast::bluetooth::LeScanResult::kGapComplete128BitServiceUuids]
+ .push_back(std::move(data));
+
// Add service data.
for (const auto& it : service_data) {
chromecast::bluetooth_v2_shlib::Uuid uuid;
@@ -154,17 +159,7 @@
}
// Update the adapter with the ScanResult.
- fake_le_scan_manager_->observer()->OnNewScanResult(result);
- scoped_task_environment_.RunUntilIdle();
-
- // Add the services.
- std::vector<chromecast::bluetooth_v2_shlib::Gatt::Service> services;
- for (const auto& uuid : service_uuids) {
- chromecast::bluetooth_v2_shlib::Gatt::Service service;
- ASSERT_TRUE(chromecast::bluetooth::util::ParseUuid(uuid, &service.uuid));
- services.push_back(service);
- }
- mock_gatt_client_.delegate()->OnServicesAdded(result.addr, services);
+ le_scan_manager_.observer_->OnNewScanResult(result);
scoped_task_environment_.RunUntilIdle();
}
diff --git a/device/bluetooth/test/bluetooth_test_cast.h b/device/bluetooth/test/bluetooth_test_cast.h
index fb414dc..a77c10a 100644
--- a/device/bluetooth/test/bluetooth_test_cast.h
+++ b/device/bluetooth/test/bluetooth_test_cast.h
@@ -6,23 +6,20 @@
#define DEVICE_BLUETOOTH_TEST_BLUETOOTH_TEST_CAST_H_
#include <cstdint>
+#include <map>
+#include <string>
#include <vector>
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/optional.h"
-#include "chromecast/device/bluetooth/shlib/mock_gatt_client.h"
+#include "chromecast/device/bluetooth/le/mock_le_scan_manager.h"
+#include "chromecast/public/bluetooth/bluetooth_types.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_local_gatt_characteristic.h"
#include "device/bluetooth/bluetooth_local_gatt_descriptor.h"
#include "device/bluetooth/test/bluetooth_test.h"
-namespace chromecast {
-namespace bluetooth {
-class GattClientManagerImpl;
-}
-} // namespace chromecast
-
namespace device {
// Cast implementation of BluetoothTestBase.
@@ -37,8 +34,7 @@
BluetoothDevice* SimulateLowEnergyDevice(int device_ordinal) override;
private:
- class FakeGattClientManager;
- class FakeLeScanManager;
+ class GattClientManager;
void UpdateAdapter(
const std::string& address,
@@ -47,11 +43,8 @@
const std::map<std::string, std::vector<uint8_t>>& service_data,
const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data);
- scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
- chromecast::bluetooth_v2_shlib::MockGattClient mock_gatt_client_;
- std::unique_ptr<chromecast::bluetooth::GattClientManagerImpl>
- gatt_client_manager_;
- std::unique_ptr<FakeLeScanManager> fake_le_scan_manager_;
+ const std::unique_ptr<GattClientManager> gatt_client_manager_;
+ ::chromecast::bluetooth::MockLeScanManager le_scan_manager_;
DISALLOW_COPY_AND_ASSIGN(BluetoothTestCast);
};