Commit e68959f4 authored by Kyle Horimoto's avatar Kyle Horimoto Committed by Commit Bot

[CrOS PhoneHub] Add BleScanner support for Nearby scan results

This CL:
(1) Updates the BleScanner::Observer interface so that scan results also
    include the associated ConnectionMedium.
(2) Changes BleConnectionManagerImpl's observer callback so that it
    ignores non-BLE scan results (which preserves its existing
    functionality).
(3) Updates BleScannerImpl to handle Nearby scan results.

Bug: 1106937
Change-Id: Idd35b4e09ec70e55bfd353841b73ecc7aba2c0a3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2401804
Commit-Queue: Kyle Horimoto <khorimoto@chromium.org>
Reviewed-by: default avatarJames Vecore <vecore@google.com>
Cr-Commit-Position: refs/heads/master@{#805534}
parent a95e1204
...@@ -337,7 +337,12 @@ void BleConnectionManagerImpl::OnFailureToGenerateAdvertisement( ...@@ -337,7 +337,12 @@ void BleConnectionManagerImpl::OnFailureToGenerateAdvertisement(
void BleConnectionManagerImpl::OnReceivedAdvertisement( void BleConnectionManagerImpl::OnReceivedAdvertisement(
multidevice::RemoteDeviceRef remote_device, multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role) { ConnectionRole connection_role) {
// Only process advertisements received as part of the BLE connection flow.
if (connection_medium != ConnectionMedium::kBluetoothLowEnergy)
return;
remote_device_id_to_timestamps_map_[remote_device.GetDeviceId()] remote_device_id_to_timestamps_map_[remote_device.GetDeviceId()]
->RecordAdvertisementReceived(); ->RecordAdvertisementReceived();
......
...@@ -134,6 +134,7 @@ class BleConnectionManagerImpl : public BleConnectionManager, ...@@ -134,6 +134,7 @@ class BleConnectionManagerImpl : public BleConnectionManager,
// BleScanner::Observer: // BleScanner::Observer:
void OnReceivedAdvertisement(multidevice::RemoteDeviceRef remote_device, void OnReceivedAdvertisement(multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role) override; ConnectionRole connection_role) override;
// SecureChannel::Observer: // SecureChannel::Observer:
......
...@@ -563,7 +563,8 @@ class SecureChannelBleConnectionManagerImplTest : public testing::Test { ...@@ -563,7 +563,8 @@ class SecureChannelBleConnectionManagerImplTest : public testing::Test {
mock_bluetooth_device.get()); mock_bluetooth_device.get());
fake_ble_scanner()->NotifyReceivedAdvertisementFromDevice( fake_ble_scanner()->NotifyReceivedAdvertisementFromDevice(
remote_device, mock_bluetooth_device.get(), connection_role); remote_device, mock_bluetooth_device.get(),
ConnectionMedium::kBluetoothLowEnergy, connection_role);
// As a result of the connection, all ongoing connection attmepts should // As a result of the connection, all ongoing connection attmepts should
// have been canceled, since a connection is in progress. // have been canceled, since a connection is in progress.
......
...@@ -62,10 +62,11 @@ DeviceIdPairSet BleScanner::GetAllDeviceIdPairs() { ...@@ -62,10 +62,11 @@ DeviceIdPairSet BleScanner::GetAllDeviceIdPairs() {
void BleScanner::NotifyReceivedAdvertisementFromDevice( void BleScanner::NotifyReceivedAdvertisementFromDevice(
const multidevice::RemoteDeviceRef& remote_device, const multidevice::RemoteDeviceRef& remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role) { ConnectionRole connection_role) {
for (auto& observer : observer_list_) { for (auto& observer : observer_list_) {
observer.OnReceivedAdvertisement(remote_device, bluetooth_device, observer.OnReceivedAdvertisement(remote_device, bluetooth_device,
connection_role); connection_medium, connection_role);
} }
} }
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#include "chromeos/services/secure_channel/connection_attempt_details.h" #include "chromeos/services/secure_channel/connection_attempt_details.h"
#include "chromeos/services/secure_channel/connection_role.h" #include "chromeos/services/secure_channel/connection_role.h"
#include "chromeos/services/secure_channel/device_id_pair.h" #include "chromeos/services/secure_channel/device_id_pair.h"
#include "chromeos/services/secure_channel/public/cpp/shared/connection_medium.h"
namespace device { namespace device {
class BluetoothDevice; class BluetoothDevice;
...@@ -36,6 +37,7 @@ class BleScanner { ...@@ -36,6 +37,7 @@ class BleScanner {
virtual void OnReceivedAdvertisement( virtual void OnReceivedAdvertisement(
multidevice::RemoteDeviceRef remote_device, multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role) = 0; ConnectionRole connection_role) = 0;
}; };
...@@ -70,6 +72,7 @@ class BleScanner { ...@@ -70,6 +72,7 @@ class BleScanner {
void NotifyReceivedAdvertisementFromDevice( void NotifyReceivedAdvertisementFromDevice(
const multidevice::RemoteDeviceRef& remote_device, const multidevice::RemoteDeviceRef& remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role); ConnectionRole connection_role);
private: private:
......
...@@ -219,26 +219,40 @@ void BleScannerImpl::HandlePotentialScanResult( ...@@ -219,26 +219,40 @@ void BleScannerImpl::HandlePotentialScanResult(
const std::string& service_data, const std::string& service_data,
const BleServiceDataHelper::DeviceWithBackgroundBool& potential_result, const BleServiceDataHelper::DeviceWithBackgroundBool& potential_result,
device::BluetoothDevice* bluetooth_device) { device::BluetoothDevice* bluetooth_device) {
// Background advertisements correspond to the listener role; foreground std::vector<std::pair<ConnectionMedium, ConnectionRole>> results;
// advertisements correspond to the initiator role.
ConnectionRole connection_role = potential_result.second
? ConnectionRole::kListenerRole
: ConnectionRole::kInitiatorRole;
// Check to see if a corresponding scan request exists. At this point, it is // Check to see if a corresponding scan request exists. At this point, it is
// possible that a scan result was received for the correct DeviceIdPair but // possible that a scan result was received for the correct DeviceIdPair but
// incorrect ConnectionRole. // incorrect ConnectionMedium and/or ConnectionRole.
bool does_corresponding_scan_request_exist = false;
for (const auto& scan_request : scan_requests()) { for (const auto& scan_request : scan_requests()) {
if (scan_request.remote_device_id() != if (scan_request.remote_device_id() !=
potential_result.first.GetDeviceId()) { potential_result.first.GetDeviceId()) {
continue; continue;
} }
// TODO(khorimoto): Also handle Nearby cases; currently, it is assumed that switch (scan_request.connection_medium()) {
// only BLE scan results are handled. // BLE scans for background advertisements in the listener role and for
if (scan_request.connection_role() == connection_role) { // foreground advertisements in the initiator role.
does_corresponding_scan_request_exist = true; case ConnectionMedium::kBluetoothLowEnergy:
if (potential_result.second &&
scan_request.connection_role() == ConnectionRole::kListenerRole) {
results.emplace_back(ConnectionMedium::kBluetoothLowEnergy,
ConnectionRole::kListenerRole);
} else if (!potential_result.second &&
scan_request.connection_role() ==
ConnectionRole::kInitiatorRole) {
results.emplace_back(ConnectionMedium::kBluetoothLowEnergy,
ConnectionRole::kInitiatorRole);
}
break;
// Nearby Connections scans for background advertisements in the initiator
// role and does not have support for the listener role.
case ConnectionMedium::kNearbyConnections:
DCHECK_EQ(ConnectionRole::kInitiatorRole,
scan_request.connection_role());
results.emplace_back(ConnectionMedium::kNearbyConnections,
ConnectionRole::kInitiatorRole);
break; break;
} }
} }
...@@ -249,7 +263,7 @@ void BleScannerImpl::HandlePotentialScanResult( ...@@ -249,7 +263,7 @@ void BleScannerImpl::HandlePotentialScanResult(
for (const auto& character : service_data) for (const auto& character : service_data)
ss << static_cast<uint32_t>(character); ss << static_cast<uint32_t>(character);
if (!does_corresponding_scan_request_exist) { if (results.empty()) {
PA_LOG(WARNING) << "BleScannerImpl::HandleDeviceUpdated(): Received scan " PA_LOG(WARNING) << "BleScannerImpl::HandleDeviceUpdated(): Received scan "
<< "result from device with ID \"" << "result from device with ID \""
<< potential_result.first.GetTruncatedDeviceIdForLogs() << potential_result.first.GetTruncatedDeviceIdForLogs()
...@@ -267,8 +281,10 @@ void BleScannerImpl::HandlePotentialScanResult( ...@@ -267,8 +281,10 @@ void BleScannerImpl::HandlePotentialScanResult(
<< ", Background advertisement: " << ", Background advertisement: "
<< (potential_result.second ? "true" : "false"); << (potential_result.second ? "true" : "false");
NotifyReceivedAdvertisementFromDevice(potential_result.first, for (const std::pair<ConnectionMedium, ConnectionRole>& result : results) {
bluetooth_device, connection_role); NotifyReceivedAdvertisementFromDevice(
potential_result.first, bluetooth_device, result.first, result.second);
}
} }
void BleScannerImpl::SetServiceDataProviderForTesting( void BleScannerImpl::SetServiceDataProviderForTesting(
......
...@@ -56,7 +56,13 @@ class FakeBluetoothDevice : public device::MockBluetoothDevice { ...@@ -56,7 +56,13 @@ class FakeBluetoothDevice : public device::MockBluetoothDevice {
DISALLOW_COPY_AND_ASSIGN(FakeBluetoothDevice); DISALLOW_COPY_AND_ASSIGN(FakeBluetoothDevice);
}; };
// const size_t kMinNumBytesInServiceData = 2; std::vector<std::pair<ConnectionMedium, ConnectionRole>>
CreateSingleBleScanResult(bool is_background_advertisement) {
return std::vector<std::pair<ConnectionMedium, ConnectionRole>>{
{ConnectionMedium::kBluetoothLowEnergy,
is_background_advertisement ? ConnectionRole::kListenerRole
: ConnectionRole::kInitiatorRole}};
}
} // namespace } // namespace
...@@ -154,7 +160,7 @@ class SecureChannelBleScannerImplTest : public testing::Test { ...@@ -154,7 +160,7 @@ class SecureChannelBleScannerImplTest : public testing::Test {
void ProcessScanResultAndVerifyNoDeviceIdentified( void ProcessScanResultAndVerifyNoDeviceIdentified(
const std::string& service_data) { const std::string& service_data) {
const FakeBleScannerObserver::ScannedResultList& results = const std::vector<FakeBleScannerObserver::Result>& results =
fake_delegate_->handled_scan_results(); fake_delegate_->handled_scan_results();
size_t num_results_before_call = results.size(); size_t num_results_before_call = results.size();
...@@ -162,11 +168,22 @@ class SecureChannelBleScannerImplTest : public testing::Test { ...@@ -162,11 +168,22 @@ class SecureChannelBleScannerImplTest : public testing::Test {
EXPECT_EQ(num_results_before_call, results.size()); EXPECT_EQ(num_results_before_call, results.size());
} }
// |expected_scan_results| contains the data expected to be provided to
// scan observers; if null, we default to a single BLE scan result.
void ProcessScanResultAndVerifyDevice( void ProcessScanResultAndVerifyDevice(
const std::string& service_data, const std::string& service_data,
multidevice::RemoteDeviceRef expected_remote_device, multidevice::RemoteDeviceRef expected_remote_device,
bool is_background_advertisement) { bool is_background_advertisement,
const FakeBleScannerObserver::ScannedResultList& results = const base::Optional<
std::vector<std::pair<ConnectionMedium, ConnectionRole>>>&
expected_scan_results = base::nullopt) {
std::vector<std::pair<ConnectionMedium, ConnectionRole>>
new_expected_results =
expected_scan_results.has_value()
? *expected_scan_results
: CreateSingleBleScanResult(is_background_advertisement);
const std::vector<FakeBleScannerObserver::Result>& results =
fake_delegate_->handled_scan_results(); fake_delegate_->handled_scan_results();
fake_ble_service_data_helper_->SetIdentifiedDevice( fake_ble_service_data_helper_->SetIdentifiedDevice(
...@@ -175,13 +192,17 @@ class SecureChannelBleScannerImplTest : public testing::Test { ...@@ -175,13 +192,17 @@ class SecureChannelBleScannerImplTest : public testing::Test {
size_t num_results_before_call = results.size(); size_t num_results_before_call = results.size();
std::unique_ptr<FakeBluetoothDevice> fake_bluetooth_device = std::unique_ptr<FakeBluetoothDevice> fake_bluetooth_device =
SimulateScanResult(service_data); SimulateScanResult(service_data);
EXPECT_EQ(num_results_before_call + 1u, results.size()); EXPECT_EQ(num_results_before_call + new_expected_results.size(),
results.size());
EXPECT_EQ(expected_remote_device, std::get<0>(results.back()));
EXPECT_EQ(fake_bluetooth_device.get(), std::get<1>(results.back())); for (size_t i = 0; i < new_expected_results.size(); ++i) {
EXPECT_EQ(is_background_advertisement ? ConnectionRole::kListenerRole const auto& result =
: ConnectionRole::kInitiatorRole, results[results.size() - new_expected_results.size() + i];
std::get<2>(results.back())); EXPECT_EQ(expected_remote_device, result.remote_device);
EXPECT_EQ(fake_bluetooth_device.get(), result.bluetooth_device);
EXPECT_EQ(new_expected_results[i].first, result.connection_medium);
EXPECT_EQ(new_expected_results[i].second, result.connection_role);
}
} }
void InvokeStartDiscoveryCallback(bool success, size_t command_index) { void InvokeStartDiscoveryCallback(bool success, size_t command_index) {
...@@ -320,6 +341,37 @@ TEST_F(SecureChannelBleScannerImplTest, IdentifyDevice_Background) { ...@@ -320,6 +341,37 @@ TEST_F(SecureChannelBleScannerImplTest, IdentifyDevice_Background) {
EXPECT_FALSE(discovery_session_is_active()); EXPECT_FALSE(discovery_session_is_active());
} }
TEST_F(SecureChannelBleScannerImplTest, IdentifyDevice_BleAndNearby) {
ConnectionAttemptDetails ble_filter(
DeviceIdPair(test_devices()[0].GetDeviceId(),
test_devices()[1].GetDeviceId()),
ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole);
ConnectionAttemptDetails nearby_filter(
DeviceIdPair(test_devices()[0].GetDeviceId(),
test_devices()[1].GetDeviceId()),
ConnectionMedium::kNearbyConnections, ConnectionRole::kInitiatorRole);
AddScanRequest(ble_filter);
InvokeStartDiscoveryCallback(true /* success */, 0u /* command_index */);
EXPECT_TRUE(discovery_session_is_active());
AddScanRequest(nearby_filter);
EXPECT_TRUE(discovery_session_is_active());
std::vector<std::pair<ConnectionMedium, ConnectionRole>> expected_results{
{ConnectionMedium::kBluetoothLowEnergy, ConnectionRole::kListenerRole},
{ConnectionMedium::kNearbyConnections, ConnectionRole::kInitiatorRole}};
ProcessScanResultAndVerifyDevice("device0ServiceData", test_devices()[0],
true /* is_background_advertisement */,
expected_results);
RemoveScanRequest(ble_filter);
RemoveScanRequest(nearby_filter);
InvokeStopDiscoveryCallback(true /* success */, 1u /* command_index */);
EXPECT_FALSE(discovery_session_is_active());
}
TEST_F(SecureChannelBleScannerImplTest, IdentifyDevice_Foreground) { TEST_F(SecureChannelBleScannerImplTest, IdentifyDevice_Foreground) {
ConnectionAttemptDetails filter(DeviceIdPair(test_devices()[0].GetDeviceId(), ConnectionAttemptDetails filter(DeviceIdPair(test_devices()[0].GetDeviceId(),
test_devices()[1].GetDeviceId()), test_devices()[1].GetDeviceId()),
......
...@@ -27,6 +27,18 @@ void FakeBleScanner::HandleScanRequestChange() { ...@@ -27,6 +27,18 @@ void FakeBleScanner::HandleScanRequestChange() {
++num_scan_request_changes_handled_; ++num_scan_request_changes_handled_;
} }
FakeBleScannerObserver::Result::Result(
multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role)
: remote_device(remote_device),
bluetooth_device(bluetooth_device),
connection_medium(connection_medium),
connection_role(connection_role) {}
FakeBleScannerObserver::Result::~Result() = default;
FakeBleScannerObserver::FakeBleScannerObserver() = default; FakeBleScannerObserver::FakeBleScannerObserver() = default;
FakeBleScannerObserver::~FakeBleScannerObserver() = default; FakeBleScannerObserver::~FakeBleScannerObserver() = default;
...@@ -34,9 +46,10 @@ FakeBleScannerObserver::~FakeBleScannerObserver() = default; ...@@ -34,9 +46,10 @@ FakeBleScannerObserver::~FakeBleScannerObserver() = default;
void FakeBleScannerObserver::OnReceivedAdvertisement( void FakeBleScannerObserver::OnReceivedAdvertisement(
multidevice::RemoteDeviceRef remote_device, multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role) { ConnectionRole connection_role) {
handled_scan_results_.push_back( handled_scan_results_.emplace_back(remote_device, bluetooth_device,
std::make_tuple(remote_device, bluetooth_device, connection_role)); connection_medium, connection_role);
} }
} // namespace secure_channel } // namespace secure_channel
......
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
#ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_SCANNER_H_ #ifndef CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_SCANNER_H_
#define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_SCANNER_H_ #define CHROMEOS_SERVICES_SECURE_CHANNEL_FAKE_BLE_SCANNER_H_
#include <tuple>
#include <vector> #include <vector>
#include "base/macros.h" #include "base/macros.h"
...@@ -44,23 +43,33 @@ class FakeBleScanner : public BleScanner { ...@@ -44,23 +43,33 @@ class FakeBleScanner : public BleScanner {
// Test BleScanner::Observer implementation. // Test BleScanner::Observer implementation.
class FakeBleScannerObserver : public BleScanner::Observer { class FakeBleScannerObserver : public BleScanner::Observer {
public: public:
struct Result {
Result(multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role);
~Result();
multidevice::RemoteDeviceRef remote_device;
device::BluetoothDevice* bluetooth_device;
ConnectionMedium connection_medium;
ConnectionRole connection_role;
};
FakeBleScannerObserver(); FakeBleScannerObserver();
~FakeBleScannerObserver() override; ~FakeBleScannerObserver() override;
using ScannedResultList = std::vector<std::tuple<multidevice::RemoteDeviceRef, const std::vector<Result>& handled_scan_results() const {
device::BluetoothDevice*,
ConnectionRole>>;
const ScannedResultList& handled_scan_results() const {
return handled_scan_results_; return handled_scan_results_;
} }
private: private:
void OnReceivedAdvertisement(multidevice::RemoteDeviceRef remote_device, void OnReceivedAdvertisement(multidevice::RemoteDeviceRef remote_device,
device::BluetoothDevice* bluetooth_device, device::BluetoothDevice* bluetooth_device,
ConnectionMedium connection_medium,
ConnectionRole connection_role) override; ConnectionRole connection_role) override;
ScannedResultList handled_scan_results_; std::vector<Result> handled_scan_results_;
DISALLOW_COPY_AND_ASSIGN(FakeBleScannerObserver); DISALLOW_COPY_AND_ASSIGN(FakeBleScannerObserver);
}; };
......
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