Commit 582bff0c authored by Michael Hansen's avatar Michael Hansen Committed by Commit Bot

[Nearby] Set advertising interval.

This lowers the interval for Fast Initiation advertising, and then
restores it to a reasonable default when advertising stops.

See design document: go/nearby-chrome-bt.

Bug: b:154846208
Change-Id: I02720b0ee50ee2bd48f62c010d8da10b8aa6ed2f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2264623Reviewed-by: default avatarMiao-chen Chou <mcchou@chromium.org>
Reviewed-by: default avatarReilly Grant <reillyg@chromium.org>
Reviewed-by: default avatarRyan Hansberry <hansberry@chromium.org>
Commit-Queue: Michael Hansen <hansenmichael@google.com>
Cr-Commit-Position: refs/heads/master@{#784516}
parent 06b85d85
...@@ -11,10 +11,25 @@ ...@@ -11,10 +11,25 @@
#include "base/bind_helpers.h" #include "base/bind_helpers.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "device/bluetooth/bluetooth_adapter_factory.h" #include "device/bluetooth/bluetooth_adapter_factory.h"
#include "device/bluetooth/bluetooth_advertisement.h" #include "device/bluetooth/bluetooth_advertisement.h"
namespace { namespace {
#if defined(CHROME_OS)
constexpr base::TimeDelta kMinFastInitAdvertisingInterval =
base::TimeDelta::FromMilliseconds(100);
constexpr base::TimeDelta kMaxFastInitAdvertisingInterval =
base::TimeDelta::FromMilliseconds(100);
// A value of 0 will restore the interval to the system default.
constexpr base::TimeDelta kMinDefaultAdvertisingInterval =
base::TimeDelta::FromMilliseconds(0);
constexpr base::TimeDelta kMaxDefaultAdvertisingInterval =
base::TimeDelta::FromMilliseconds(0);
#endif
constexpr const char kNearbySharingFastInitiationServiceUuid[] = constexpr const char kNearbySharingFastInitiationServiceUuid[] =
"0000fe2c-0000-1000-8000-00805f9b34fb"; "0000fe2c-0000-1000-8000-00805f9b34fb";
const uint8_t kNearbySharingFastPairId[] = {0xfc, 0x12, 0x8e}; const uint8_t kNearbySharingFastPairId[] = {0xfc, 0x12, 0x8e};
...@@ -55,16 +70,61 @@ void FastInitiationManager::StartAdvertising( ...@@ -55,16 +70,61 @@ void FastInitiationManager::StartAdvertising(
DCHECK(adapter_->IsPresent() && adapter_->IsPowered()); DCHECK(adapter_->IsPresent() && adapter_->IsPowered());
DCHECK(!advertisement_); DCHECK(!advertisement_);
// These callbacks are instances of OnceCallback, but RegisterAdvertisement() // These callbacks are instances of OnceCallback, but BluetoothAdapter methods
// expects RepeatingCallback. Passing these as arguments is possible using // expect RepeatingCallbacks. Passing these as arguments is possible using
// Passed(), but this is dangerous so we just store them. // Passed(), but this is dangerous so we just store them to run later.
start_callback_ = std::move(callback); start_callback_ = std::move(callback);
start_error_callback_ = std::move(error_callback); start_error_callback_ = std::move(error_callback);
// TODO(hansenmichael): Lower Bluetooth advertising interval to 100ms for #if defined(CHROME_OS)
// faster discovery. Be sure to restore the interval when we stop adapter_->SetAdvertisingInterval(
// broadcasting. kMinFastInitAdvertisingInterval, kMaxFastInitAdvertisingInterval,
base::Bind(&FastInitiationManager::OnSetAdvertisingInterval,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&FastInitiationManager::OnSetAdvertisingIntervalError,
weak_ptr_factory_.GetWeakPtr()));
#else
RegisterAdvertisement();
#endif
}
void FastInitiationManager::StopAdvertising(
base::OnceCallback<void()> callback) {
stop_callback_ = std::move(callback);
if (!advertisement_) {
std::move(stop_callback_).Run();
return;
}
#if defined(CHROME_OS)
adapter_->SetAdvertisingInterval(
kMinDefaultAdvertisingInterval, kMaxDefaultAdvertisingInterval,
base::Bind(&FastInitiationManager::OnRestoreAdvertisingInterval,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&FastInitiationManager::OnRestoreAdvertisingIntervalError,
weak_ptr_factory_.GetWeakPtr()));
#else
UnregisterAdvertisement();
#endif
}
void FastInitiationManager::AdvertisementReleased(
device::BluetoothAdvertisement* advertisement) {
// TODO(hansenmichael): Handle advertisement released appropriately.
}
void FastInitiationManager::OnSetAdvertisingInterval() {
RegisterAdvertisement();
}
void FastInitiationManager::OnSetAdvertisingIntervalError(
device::BluetoothAdvertisement::ErrorCode code) {
LOG(WARNING) << "SetAdvertisingInterval() failed with error code = " << code;
RegisterAdvertisement();
}
void FastInitiationManager::RegisterAdvertisement() {
auto advertisement_data = auto advertisement_data =
std::make_unique<device::BluetoothAdvertisement::Data>( std::make_unique<device::BluetoothAdvertisement::Data>(
device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST); device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_BROADCAST);
...@@ -84,35 +144,13 @@ void FastInitiationManager::StartAdvertising( ...@@ -84,35 +144,13 @@ void FastInitiationManager::StartAdvertising(
adapter_->RegisterAdvertisement( adapter_->RegisterAdvertisement(
std::move(advertisement_data), std::move(advertisement_data),
base::Bind(&FastInitiationManager::OnAdvertisementRegistered, base::Bind(&FastInitiationManager::OnRegisterAdvertisement,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&FastInitiationManager::OnErrorRegisteringAdvertisement,
weak_ptr_factory_.GetWeakPtr()));
}
void FastInitiationManager::StopAdvertising(
base::OnceCallback<void()> callback) {
stop_callback_ = std::move(callback);
if (!advertisement_) {
std::move(stop_callback_).Run();
return;
}
advertisement_->RemoveObserver(this);
advertisement_->Unregister(
base::Bind(&FastInitiationManager::OnAdvertisementUnregistered,
weak_ptr_factory_.GetWeakPtr()), weak_ptr_factory_.GetWeakPtr()),
base::Bind(&FastInitiationManager::OnErrorUnregisteringAdvertisement, base::Bind(&FastInitiationManager::OnRegisterAdvertisementError,
weak_ptr_factory_.GetWeakPtr())); weak_ptr_factory_.GetWeakPtr()));
} }
void FastInitiationManager::AdvertisementReleased( void FastInitiationManager::OnRegisterAdvertisement(
device::BluetoothAdvertisement* advertisement) {
// TODO(hansenmichael): Handle advertisement released appropriately.
}
void FastInitiationManager::OnAdvertisementRegistered(
scoped_refptr<device::BluetoothAdvertisement> advertisement) { scoped_refptr<device::BluetoothAdvertisement> advertisement) {
advertisement_ = advertisement; advertisement_ = advertisement;
advertisement_->AddObserver(this); advertisement_->AddObserver(this);
...@@ -120,7 +158,7 @@ void FastInitiationManager::OnAdvertisementRegistered( ...@@ -120,7 +158,7 @@ void FastInitiationManager::OnAdvertisementRegistered(
start_error_callback_.Reset(); start_error_callback_.Reset();
} }
void FastInitiationManager::OnErrorRegisteringAdvertisement( void FastInitiationManager::OnRegisterAdvertisementError(
device::BluetoothAdvertisement::ErrorCode error_code) { device::BluetoothAdvertisement::ErrorCode error_code) {
LOG(ERROR) LOG(ERROR)
<< "FastInitiationManager::StartAdvertising() failed with error code = " << "FastInitiationManager::StartAdvertising() failed with error code = "
...@@ -129,12 +167,31 @@ void FastInitiationManager::OnErrorRegisteringAdvertisement( ...@@ -129,12 +167,31 @@ void FastInitiationManager::OnErrorRegisteringAdvertisement(
start_callback_.Reset(); start_callback_.Reset();
} }
void FastInitiationManager::OnAdvertisementUnregistered() { void FastInitiationManager::OnRestoreAdvertisingInterval() {
UnregisterAdvertisement();
}
void FastInitiationManager::OnRestoreAdvertisingIntervalError(
device::BluetoothAdvertisement::ErrorCode code) {
LOG(WARNING) << "SetAdvertisingInterval() failed with error code = " << code;
UnregisterAdvertisement();
}
void FastInitiationManager::UnregisterAdvertisement() {
advertisement_->RemoveObserver(this);
advertisement_->Unregister(
base::Bind(&FastInitiationManager::OnUnregisterAdvertisement,
weak_ptr_factory_.GetWeakPtr()),
base::Bind(&FastInitiationManager::OnUnregisterAdvertisementError,
weak_ptr_factory_.GetWeakPtr()));
}
void FastInitiationManager::OnUnregisterAdvertisement() {
advertisement_.reset(); advertisement_.reset();
std::move(stop_callback_).Run(); std::move(stop_callback_).Run();
} }
void FastInitiationManager::OnErrorUnregisteringAdvertisement( void FastInitiationManager::OnUnregisterAdvertisementError(
device::BluetoothAdvertisement::ErrorCode error_code) { device::BluetoothAdvertisement::ErrorCode error_code) {
LOG(WARNING) LOG(WARNING)
<< "FastInitiationManager::StopAdvertising() failed with error code = " << "FastInitiationManager::StopAdvertising() failed with error code = "
......
...@@ -55,12 +55,20 @@ class FastInitiationManager : device::BluetoothAdvertisement::Observer { ...@@ -55,12 +55,20 @@ class FastInitiationManager : device::BluetoothAdvertisement::Observer {
void AdvertisementReleased( void AdvertisementReleased(
device::BluetoothAdvertisement* advertisement) override; device::BluetoothAdvertisement* advertisement) override;
void OnAdvertisementRegistered( void OnSetAdvertisingInterval();
void OnSetAdvertisingIntervalError(
device::BluetoothAdvertisement::ErrorCode code);
void RegisterAdvertisement();
void OnRegisterAdvertisement(
scoped_refptr<device::BluetoothAdvertisement> advertisement); scoped_refptr<device::BluetoothAdvertisement> advertisement);
void OnErrorRegisteringAdvertisement( void OnRegisterAdvertisementError(
device::BluetoothAdvertisement::ErrorCode error_code); device::BluetoothAdvertisement::ErrorCode error_code);
void OnAdvertisementUnregistered(); void OnRestoreAdvertisingInterval();
void OnErrorUnregisteringAdvertisement( void OnRestoreAdvertisingIntervalError(
device::BluetoothAdvertisement::ErrorCode code);
void UnregisterAdvertisement();
void OnUnregisterAdvertisement();
void OnUnregisterAdvertisementError(
device::BluetoothAdvertisement::ErrorCode error_code); device::BluetoothAdvertisement::ErrorCode error_code);
uint8_t GenerateFastInitV1Metadata(); uint8_t GenerateFastInitV1Metadata();
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
#include <vector> #include <vector>
#include "base/memory/ptr_util.h" #include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "device/bluetooth/test/mock_bluetooth_adapter.h" #include "device/bluetooth/test/mock_bluetooth_adapter.h"
#include "device/bluetooth/test/mock_bluetooth_advertisement.h" #include "device/bluetooth/test/mock_bluetooth_advertisement.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -21,6 +23,12 @@ namespace { ...@@ -21,6 +23,12 @@ namespace {
constexpr const char kNearbySharingFastInitiationServiceUuid[] = constexpr const char kNearbySharingFastInitiationServiceUuid[] =
"0000fe2c-0000-1000-8000-00805f9b34fb"; "0000fe2c-0000-1000-8000-00805f9b34fb";
const uint8_t kNearbySharingFastPairId[] = {0xfc, 0x12, 0x8e}; const uint8_t kNearbySharingFastPairId[] = {0xfc, 0x12, 0x8e};
#if defined(CHROME_OS)
const int64_t kFastInitAdvertisingInterval = 100;
const int64_t kDefaultAdvertisingInterval = 0;
#endif
} // namespace } // namespace
struct RegisterAdvertisementArgs { struct RegisterAdvertisementArgs {
...@@ -46,6 +54,18 @@ class MockBluetoothAdapterWithAdvertisements ...@@ -46,6 +54,18 @@ class MockBluetoothAdapterWithAdvertisements
public: public:
MOCK_METHOD1(RegisterAdvertisementWithArgsStruct, MOCK_METHOD1(RegisterAdvertisementWithArgsStruct,
void(RegisterAdvertisementArgs*)); void(RegisterAdvertisementArgs*));
MOCK_METHOD2(OnSetAdvertisingInterval, void(int64_t, int64_t));
#if defined(CHROME_OS)
void SetAdvertisingInterval(
const base::TimeDelta& min,
const base::TimeDelta& max,
const base::Closure& callback,
const AdvertisementErrorCallback& error_callback) override {
callback.Run();
OnSetAdvertisingInterval(min.InMilliseconds(), max.InMilliseconds());
}
#endif
void RegisterAdvertisement( void RegisterAdvertisement(
std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data, std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement_data,
...@@ -80,6 +100,10 @@ class NearbySharingFastInitiationManagerTest : public testing::Test { ...@@ -80,6 +100,10 @@ class NearbySharingFastInitiationManagerTest : public testing::Test {
ON_CALL(*mock_adapter_, RegisterAdvertisementWithArgsStruct(_)) ON_CALL(*mock_adapter_, RegisterAdvertisementWithArgsStruct(_))
.WillByDefault(Invoke(this, &NearbySharingFastInitiationManagerTest:: .WillByDefault(Invoke(this, &NearbySharingFastInitiationManagerTest::
OnAdapterRegisterAdvertisement)); OnAdapterRegisterAdvertisement));
ON_CALL(*mock_adapter_, OnSetAdvertisingInterval(_, _))
.WillByDefault(Invoke(
this,
&NearbySharingFastInitiationManagerTest::OnSetAdvertisingInterval));
fast_initiation_manager_ = fast_initiation_manager_ =
std::make_unique<FastInitiationManager>(mock_adapter_); std::make_unique<FastInitiationManager>(mock_adapter_);
...@@ -127,11 +151,27 @@ class NearbySharingFastInitiationManagerTest : public testing::Test { ...@@ -127,11 +151,27 @@ class NearbySharingFastInitiationManagerTest : public testing::Test {
void OnStopAdvertising() { called_on_stop_advertising_ = true; } void OnStopAdvertising() { called_on_stop_advertising_ = true; }
void OnSetAdvertisingInterval(int64_t min, int64_t max) {
++set_advertising_interval_call_count_;
last_advertising_interval_min_ = min;
last_advertising_interval_max_ = max;
}
bool called_on_start_advertising() { return called_on_start_advertising_; } bool called_on_start_advertising() { return called_on_start_advertising_; }
bool called_on_start_advertising_error() { bool called_on_start_advertising_error() {
return called_on_start_advertising_error_; return called_on_start_advertising_error_;
} }
bool called_on_stop_advertising() { return called_on_stop_advertising_; } bool called_on_stop_advertising() { return called_on_stop_advertising_; }
size_t set_advertising_interval_call_count() {
return set_advertising_interval_call_count_;
}
int64_t last_advertising_interval_min() {
return last_advertising_interval_min_;
}
int64_t last_advertising_interval_max() {
return last_advertising_interval_max_;
}
scoped_refptr<NiceMock<MockBluetoothAdapterWithAdvertisements>> mock_adapter_; scoped_refptr<NiceMock<MockBluetoothAdapterWithAdvertisements>> mock_adapter_;
std::unique_ptr<FastInitiationManager> fast_initiation_manager_; std::unique_ptr<FastInitiationManager> fast_initiation_manager_;
...@@ -139,27 +179,57 @@ class NearbySharingFastInitiationManagerTest : public testing::Test { ...@@ -139,27 +179,57 @@ class NearbySharingFastInitiationManagerTest : public testing::Test {
bool called_on_start_advertising_; bool called_on_start_advertising_;
bool called_on_start_advertising_error_; bool called_on_start_advertising_error_;
bool called_on_stop_advertising_; bool called_on_stop_advertising_;
size_t set_advertising_interval_call_count_ = 0u;
int64_t last_advertising_interval_min_ = 0;
int64_t last_advertising_interval_max_ = 0;
}; };
TEST_F(NearbySharingFastInitiationManagerTest, TestStartAdvertising_Success) { TEST_F(NearbySharingFastInitiationManagerTest, TestStartAdvertising_Success) {
StartAdvertising(); StartAdvertising();
register_args_->callback.Run( register_args_->callback.Run(
base::MakeRefCounted<device::MockBluetoothAdvertisement>()); base::MakeRefCounted<device::MockBluetoothAdvertisement>());
EXPECT_TRUE(called_on_start_advertising()); EXPECT_TRUE(called_on_start_advertising());
EXPECT_FALSE(called_on_start_advertising_error()); EXPECT_FALSE(called_on_start_advertising_error());
EXPECT_FALSE(called_on_stop_advertising());
#if defined(CHROME_OS)
EXPECT_EQ(1u, set_advertising_interval_call_count());
EXPECT_EQ(kFastInitAdvertisingInterval, last_advertising_interval_min());
EXPECT_EQ(kFastInitAdvertisingInterval, last_advertising_interval_max());
#endif
} }
TEST_F(NearbySharingFastInitiationManagerTest, TestStartAdvertising_Error) { TEST_F(NearbySharingFastInitiationManagerTest, TestStartAdvertising_Error) {
StartAdvertising(); StartAdvertising();
register_args_->error_callback.Run(device::BluetoothAdvertisement::ErrorCode:: register_args_->error_callback.Run(device::BluetoothAdvertisement::ErrorCode::
INVALID_ADVERTISEMENT_ERROR_CODE); INVALID_ADVERTISEMENT_ERROR_CODE);
EXPECT_FALSE(called_on_start_advertising()); EXPECT_FALSE(called_on_start_advertising());
EXPECT_TRUE(called_on_start_advertising_error()); EXPECT_TRUE(called_on_start_advertising_error());
EXPECT_FALSE(called_on_stop_advertising());
#if defined(CHROME_OS)
EXPECT_EQ(1u, set_advertising_interval_call_count());
EXPECT_EQ(kFastInitAdvertisingInterval, last_advertising_interval_min());
EXPECT_EQ(kFastInitAdvertisingInterval, last_advertising_interval_max());
#endif
} }
TEST_F(NearbySharingFastInitiationManagerTest, TestStopAdvertising) { TEST_F(NearbySharingFastInitiationManagerTest, TestStopAdvertising) {
StartAdvertising();
register_args_->callback.Run(
base::MakeRefCounted<device::MockBluetoothAdvertisement>());
#if defined(CHROME_OS)
EXPECT_EQ(1u, set_advertising_interval_call_count());
EXPECT_EQ(kFastInitAdvertisingInterval, last_advertising_interval_min());
EXPECT_EQ(kFastInitAdvertisingInterval, last_advertising_interval_max());
#endif
StopAdvertising(); StopAdvertising();
EXPECT_TRUE(called_on_start_advertising());
EXPECT_FALSE(called_on_start_advertising_error());
EXPECT_TRUE(called_on_stop_advertising()); EXPECT_TRUE(called_on_stop_advertising());
#if defined(CHROME_OS)
EXPECT_EQ(2u, set_advertising_interval_call_count());
EXPECT_EQ(kDefaultAdvertisingInterval, last_advertising_interval_min());
EXPECT_EQ(kDefaultAdvertisingInterval, last_advertising_interval_max());
#endif
} }
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