Skip to content

Commit 0543d27

Browse files
Jon MannChromium LUCI CQ
Jon Mann
authored and
Chromium LUCI CQ
committed
Fast Pair: Retry metadata requests when eligible.
Retry device metadata requests on network status changes when an initial request fails in a way that could indicate a network issue. Change-Id: I87f5e781cebd60b9ac01a0159e3082fc077c6d76 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3411240 Reviewed-by: Shane Fitzpatrick <[email protected]> Commit-Queue: Jon Mann <[email protected]> Auto-Submit: Jon Mann <[email protected]> Cr-Commit-Position: refs/heads/main@{#967427}
1 parent 3d1cf1a commit 0543d27

6 files changed

+106
-5
lines changed

ash/quick_pair/repository/fake_fast_pair_repository.cc

+5
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ bool FakeFastPairRepository::HasKeyForDevice(const std::string& mac_address) {
4343
void FakeFastPairRepository::GetDeviceMetadata(
4444
const std::string& hex_model_id,
4545
DeviceMetadataCallback callback) {
46+
if (!is_network_connected_) {
47+
std::move(callback).Run(/*device=*/nullptr, /*has_retryable_error=*/true);
48+
return;
49+
}
50+
4651
std::string normalized_id = base::ToUpperASCII(hex_model_id);
4752
if (data_.contains(normalized_id)) {
4853
std::move(callback).Run(data_[normalized_id].get(),

ash/quick_pair/repository/fake_fast_pair_repository.h

+5
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ class FakeFastPairRepository : public FastPairRepository {
4545

4646
bool HasKeyForDevice(const std::string& mac_address);
4747

48+
void set_is_network_connected(bool is_connected) {
49+
is_network_connected_ = is_connected;
50+
}
51+
4852
// FastPairRepository::
4953
void GetDeviceMetadata(const std::string& hex_model_id,
5054
DeviceMetadataCallback callback) override;
@@ -64,6 +68,7 @@ class FakeFastPairRepository : public FastPairRepository {
6468
private:
6569
static void SetInstance(FastPairRepository* instance);
6670

71+
bool is_network_connected_ = true;
6772
base::flat_map<std::string, std::unique_ptr<DeviceMetadata>> data_;
6873
base::flat_map<std::string, std::vector<uint8_t>> saved_account_keys_;
6974
absl::optional<PairingMetadata> check_account_key_result_;

ash/quick_pair/scanning/BUILD.gn

+3
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ source_set("scanning") {
2929
"//ash/services/quick_pair",
3030
"//ash/services/quick_pair/public/cpp",
3131
"//base",
32+
"//chromeos/network",
3233
"//device/bluetooth",
3334
"//device/bluetooth/public/cpp",
3435
]
@@ -76,6 +77,8 @@ source_set("unit_tests") {
7677
"//ash/services/quick_pair",
7778
"//ash/services/quick_pair:test_support",
7879
"//base/test:test_support",
80+
"//chromeos/network:test_support",
81+
"//dbus:test_support",
7982
"//device/bluetooth",
8083
"//device/bluetooth:mocks",
8184
"//mojo/public/cpp/bindings",

ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner.cc

+42-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@
2525
#include "base/containers/flat_set.h"
2626
#include "base/memory/scoped_refptr.h"
2727
#include "base/strings/string_util.h"
28+
#include "chromeos/network/network_handler.h"
29+
#include "chromeos/network/network_state_handler.h"
2830
#include "device/bluetooth//bluetooth_adapter.h"
2931
#include "device/bluetooth/bluetooth_device.h"
3032
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -49,9 +51,14 @@ FastPairDiscoverableScanner::FastPairDiscoverableScanner(
4951
found_callback_(std::move(found_callback)),
5052
lost_callback_(std::move(lost_callback)) {
5153
observation_.Observe(scanner_.get());
54+
chromeos::NetworkHandler::Get()->network_state_handler()->AddObserver(
55+
this, FROM_HERE);
5256
}
5357

54-
FastPairDiscoverableScanner::~FastPairDiscoverableScanner() = default;
58+
FastPairDiscoverableScanner::~FastPairDiscoverableScanner() {
59+
chromeos::NetworkHandler::Get()->network_state_handler()->RemoveObserver(
60+
this, FROM_HERE);
61+
}
5562

5663
void FastPairDiscoverableScanner::OnDeviceFound(
5764
device::BluetoothDevice* device) {
@@ -116,18 +123,26 @@ void FastPairDiscoverableScanner::OnDeviceMetadataRetrieved(
116123
const std::string model_id,
117124
DeviceMetadata* device_metadata,
118125
bool has_retryable_error) {
126+
if (has_retryable_error) {
127+
pending_devices_address_to_model_id_[address] = model_id;
128+
QP_LOG(WARNING) << __func__
129+
<< ": Could not retrieve metadata for id: " << model_id
130+
<< ". Waiting for network change before retry.";
131+
return;
132+
}
133+
119134
if (!device_metadata) {
120135
QP_LOG(WARNING) << __func__
121-
<< ": Could not get metadata for id: " << model_id
136+
<< ": No metadata available for id: " << model_id
122137
<< ". Ignoring this advertisement";
123138
return;
124139
}
125140

126-
QP_LOG(VERBOSE) << __func__ << ": Id: " << model_id;
127-
128141
auto device = base::MakeRefCounted<Device>(model_id, address,
129142
Protocol::kFastPairInitial);
130143

144+
QP_LOG(VERBOSE) << __func__ << ": Id: " << model_id;
145+
131146
// Anti-spoofing keys were introduced in Fast Pair v2, so if this isn't
132147
// available then the device is v1.
133148
if (device_metadata->GetDetails()
@@ -182,6 +197,9 @@ void FastPairDiscoverableScanner::OnDeviceLost(
182197
device::BluetoothDevice* device) {
183198
QP_LOG(VERBOSE) << __func__ << ": " << device->GetNameForDisplay();
184199

200+
// No need to retry fetching metadata for devices that are no longer in range.
201+
pending_devices_address_to_model_id_.erase(device->GetAddress());
202+
185203
// If we have an in-progress attempt to parse for this device, removing it
186204
// from this map will ensure the result is ignored.
187205
model_id_parse_attempts_.erase(device->GetAddress());
@@ -231,5 +249,25 @@ void FastPairDiscoverableScanner::OnUtilityProcessStopped(
231249
weak_pointer_factory_.GetWeakPtr(), address));
232250
}
233251

252+
void FastPairDiscoverableScanner::DefaultNetworkChanged(
253+
const chromeos::NetworkState* network) {
254+
// Only retry when we have an active connected network.
255+
if (!network || !network->IsConnectedState()) {
256+
return;
257+
}
258+
259+
auto it = pending_devices_address_to_model_id_.begin();
260+
while (it != pending_devices_address_to_model_id_.end()) {
261+
FastPairRepository::Get()->GetDeviceMetadata(
262+
/*model_id=*/it->second,
263+
base::BindOnce(&FastPairDiscoverableScanner::OnDeviceMetadataRetrieved,
264+
weak_pointer_factory_.GetWeakPtr(),
265+
/*address=*/it->first,
266+
/*model_id=*/it->second));
267+
268+
pending_devices_address_to_model_id_.erase(it);
269+
}
270+
}
271+
234272
} // namespace quick_pair
235273
} // namespace ash

ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner.h

+8-1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "base/memory/scoped_refptr.h"
1515
#include "base/memory/weak_ptr.h"
1616
#include "base/scoped_observation.h"
17+
#include "chromeos/network/network_state_handler_observer.h"
1718
#include "third_party/abseil-cpp/absl/types/optional.h"
1819

1920
namespace device {
@@ -35,7 +36,9 @@ using DeviceCallback = base::RepeatingCallback<void(scoped_refptr<Device>)>;
3536
// and invokes the |found_callback| when it finds a device within the
3637
// appropriate range. |lost_callback| will be invoked when that device is lost
3738
// to the bluetooth adapter.
38-
class FastPairDiscoverableScanner final : public FastPairScanner::Observer {
39+
class FastPairDiscoverableScanner final
40+
: public FastPairScanner::Observer,
41+
public chromeos::NetworkStateHandlerObserver {
3942
public:
4043
FastPairDiscoverableScanner(scoped_refptr<FastPairScanner> scanner,
4144
scoped_refptr<device::BluetoothAdapter> adapter,
@@ -50,6 +53,9 @@ class FastPairDiscoverableScanner final : public FastPairScanner::Observer {
5053
void OnDeviceFound(device::BluetoothDevice* device) override;
5154
void OnDeviceLost(device::BluetoothDevice* device) override;
5255

56+
// chromeos::NetworkStateHandlerObserver:
57+
void DefaultNetworkChanged(const chromeos::NetworkState* network) override;
58+
5359
private:
5460
void OnModelIdRetrieved(const std::string& address,
5561
const absl::optional<std::string>& model_id);
@@ -68,6 +74,7 @@ class FastPairDiscoverableScanner final : public FastPairScanner::Observer {
6874
scoped_refptr<device::BluetoothAdapter> adapter_;
6975
DeviceCallback found_callback_;
7076
DeviceCallback lost_callback_;
77+
base::flat_map<std::string, std::string> pending_devices_address_to_model_id_;
7178
base::flat_map<std::string, scoped_refptr<Device>> notified_devices_;
7279
base::flat_map<std::string, int> model_id_parse_attempts_;
7380
base::ScopedObservation<FastPairScanner, FastPairScanner::Observer>

ash/quick_pair/scanning/fast_pair/fast_pair_discoverable_scanner_unittest.cc

+43
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
#include "base/test/bind.h"
2828
#include "base/test/mock_callback.h"
2929
#include "base/test/task_environment.h"
30+
#include "chromeos/network/network_handler.h"
31+
#include "chromeos/network/network_state_handler.h"
32+
#include "chromeos/network/network_state_test_helper.h"
3033
#include "device/bluetooth/bluetooth_adapter.h"
3134
#include "device/bluetooth/bluetooth_device.h"
3235
#include "device/bluetooth/test/mock_bluetooth_adapter.h"
@@ -45,6 +48,7 @@ namespace quick_pair {
4548
class FastPairDiscoverableScannerTest : public testing::Test {
4649
public:
4750
void SetUp() override {
51+
chromeos::NetworkHandler::Initialize();
4852
repository_ = std::make_unique<FakeFastPairRepository>();
4953

5054
nearby::fastpair::Device metadata;
@@ -81,6 +85,12 @@ class FastPairDiscoverableScannerTest : public testing::Test {
8185
lost_device_callback_.Get());
8286
}
8387

88+
void TearDown() override {
89+
testing::Test::TearDown();
90+
discoverable_scanner_.reset();
91+
chromeos::NetworkHandler::Shutdown();
92+
}
93+
8494
MockQuickPairProcessManager* mock_process_manager() {
8595
return static_cast<MockQuickPairProcessManager*>(process_manager_.get());
8696
}
@@ -119,6 +129,7 @@ class FastPairDiscoverableScannerTest : public testing::Test {
119129
}
120130

121131
base::test::SingleThreadTaskEnvironment task_enviornment_;
132+
chromeos::NetworkStateTestHelper helper_{/*use_defaults=*/true};
122133
scoped_refptr<FakeFastPairScanner> scanner_;
123134
std::unique_ptr<FakeFastPairRepository> repository_;
124135
std::unique_ptr<FastPairDiscoverableScanner> discoverable_scanner_;
@@ -179,6 +190,38 @@ TEST_F(FastPairDiscoverableScannerTest, InvokesLostCallbackAfterFound_v1) {
179190
base::RunLoop().RunUntilIdle();
180191
}
181192

193+
TEST_F(FastPairDiscoverableScannerTest,
194+
InvokesFoundCallback_AfterNetworkAvailable) {
195+
device::BluetoothDevice* device = GetDevice(kValidModelId);
196+
repository_->set_is_network_connected(false);
197+
198+
EXPECT_CALL(found_device_callback_, Run).Times(0);
199+
scanner_->NotifyDeviceFound(device);
200+
base::RunLoop().RunUntilIdle();
201+
202+
EXPECT_CALL(found_device_callback_, Run).Times(1);
203+
repository_->set_is_network_connected(true);
204+
discoverable_scanner_->DefaultNetworkChanged(
205+
helper_.network_state_handler()->DefaultNetwork());
206+
base::RunLoop().RunUntilIdle();
207+
}
208+
209+
TEST_F(FastPairDiscoverableScannerTest,
210+
NoFoundCallback_AfterDeviceLostAndNetworkAvailable) {
211+
device::BluetoothDevice* device = GetDevice(kValidModelId);
212+
repository_->set_is_network_connected(false);
213+
214+
EXPECT_CALL(found_device_callback_, Run).Times(0);
215+
scanner_->NotifyDeviceFound(device);
216+
base::RunLoop().RunUntilIdle();
217+
218+
scanner_->NotifyDeviceLost(device);
219+
repository_->set_is_network_connected(true);
220+
discoverable_scanner_->DefaultNetworkChanged(
221+
helper_.network_state_handler()->DefaultNetwork());
222+
base::RunLoop().RunUntilIdle();
223+
}
224+
182225
TEST_F(FastPairDiscoverableScannerTest, InvokesLostCallbackAfterFound_v2) {
183226
nearby::fastpair::Device metadata;
184227
metadata.set_trigger_distance(2);

0 commit comments

Comments
 (0)