mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-16 15:36:12 -04:00
Implement RetroactivePairingDetector
PiperOrigin-RevId: 538319791
This commit is contained in:
committed by
Copybara-Service
parent
aabc521454
commit
ba740c9a5c
@@ -119,9 +119,9 @@ cc_test(
|
||||
":mediums",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform:types",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -34,6 +34,57 @@ bool BluetoothClassic::IsAvailableLocked() const {
|
||||
return medium_.IsValid() && adapter_.IsValid() && adapter_.IsEnabled();
|
||||
}
|
||||
|
||||
void BluetoothClassic::AddObserver(BluetoothClassicMedium::Observer* observer) {
|
||||
MutexLock lock(&mutex_);
|
||||
medium_.AddObserver(observer);
|
||||
}
|
||||
|
||||
void BluetoothClassic::RemoveObserver(
|
||||
BluetoothClassicMedium::Observer* observer) {
|
||||
MutexLock lock(&mutex_);
|
||||
medium_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
bool BluetoothClassic::StartDiscovery() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!radio_.IsEnabled()) {
|
||||
NEARBY_LOGS(INFO) << "Can't discover BT devices because BT isn't enabled.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsAvailableLocked()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Can't discover BT devices because BT isn't available.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!medium_.StartDiscovery({})) {
|
||||
NEARBY_LOGS(INFO) << "Failed to start discovery of BT devices.";
|
||||
return false;
|
||||
}
|
||||
// Mark the fact that we're currently performing a Bluetooth scan.
|
||||
is_scanning = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothClassic::StopDiscovery() {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!IsDiscovering()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Can't stop discovery of BT devices because it never started.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!medium_.StopDiscovery()) {
|
||||
NEARBY_LOGS(INFO) << "Failed to stop discovery of Bluetooth devices.";
|
||||
return false;
|
||||
}
|
||||
is_scanning = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BluetoothClassic::IsDiscovering() const { return is_scanning; }
|
||||
|
||||
std::unique_ptr<BluetoothPairing> BluetoothClassic::CreatePairing(
|
||||
absl::string_view public_address) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
@@ -32,6 +32,17 @@ class BluetoothClassic {
|
||||
// Returns true, if BT communications are supported by a platform.
|
||||
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
void AddObserver(BluetoothClassicMedium::Observer* observer);
|
||||
void RemoveObserver(BluetoothClassicMedium::Observer* observer);
|
||||
|
||||
// Enables BT discovery mode to observer any discoverable device in range.
|
||||
// Returns true, if discovery mode was enabled, false otherwise.
|
||||
bool StartDiscovery() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Disables BT discovery mode.
|
||||
// Returns true, if discovery mode was previously enabled, false otherwise.
|
||||
bool StopDiscovery() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns a new BluetoothPairing instance to handle the pairing process
|
||||
// with the remote device.
|
||||
std::unique_ptr<BluetoothPairing> CreatePairing(
|
||||
@@ -43,11 +54,15 @@ class BluetoothClassic {
|
||||
// Same as IsAvailable(), but must be called with mutex_ held.
|
||||
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Returns true if device is currently in discovery mode.
|
||||
bool IsDiscovering() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
mutable Mutex mutex_;
|
||||
BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_);
|
||||
BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){
|
||||
radio_.GetBluetoothAdapter()};
|
||||
BluetoothClassicMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
|
||||
bool is_scanning ABSL_GUARDED_BY(mutex_) = false;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -16,11 +16,74 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/count_down_latch.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
class BluetoothClassicMediumObserver
|
||||
: public BluetoothClassicMedium ::Observer {
|
||||
public:
|
||||
explicit BluetoothClassicMediumObserver(
|
||||
BluetoothClassic* bluetooth_classic, CountDownLatch* device_added_latch,
|
||||
CountDownLatch* device_removed_latch,
|
||||
CountDownLatch* device_paired_changed_latch)
|
||||
: bluetooth_classic_(bluetooth_classic),
|
||||
device_added_latch_(device_added_latch),
|
||||
device_removed_latch_(device_removed_latch),
|
||||
device_paired_changed_latch_(device_paired_changed_latch) {
|
||||
bluetooth_classic_->AddObserver(this);
|
||||
}
|
||||
|
||||
~BluetoothClassicMediumObserver() override {
|
||||
bluetooth_classic_->RemoveObserver(this);
|
||||
}
|
||||
|
||||
void DeviceAdded(BluetoothDevice& device) override {
|
||||
if (!device_added_latch_) return;
|
||||
device_added_latch_->CountDown();
|
||||
}
|
||||
|
||||
void DeviceRemoved(BluetoothDevice& device) override {
|
||||
if (!device_removed_latch_) return;
|
||||
device_removed_latch_->CountDown();
|
||||
}
|
||||
|
||||
void DevicePairedChanged(BluetoothDevice& device,
|
||||
bool new_paired_status) override {
|
||||
if (!device_paired_changed_latch_) return;
|
||||
device_paired_changed_latch_->CountDown();
|
||||
}
|
||||
|
||||
BluetoothClassic* bluetooth_classic_;
|
||||
CountDownLatch* device_added_latch_;
|
||||
CountDownLatch* device_removed_latch_;
|
||||
CountDownLatch* device_paired_changed_latch_;
|
||||
};
|
||||
|
||||
TEST(BluetoothClassicTest, CanStartAndStopDiscovery) {
|
||||
MediumEnvironment::Instance().Start();
|
||||
BluetoothRadio radio;
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
BluetoothAdapter provider_adapter;
|
||||
provider_adapter.SetStatus(BluetoothAdapter::Status::kEnabled);
|
||||
provider_adapter.SetScanMode(
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable);
|
||||
BluetoothClassicMedium bt_provider(provider_adapter);
|
||||
CountDownLatch device_added_latch(1);
|
||||
CountDownLatch device_removed_latch(1);
|
||||
BluetoothClassicMediumObserver observer(
|
||||
&bluetooth_classic, &device_added_latch, &device_removed_latch, nullptr);
|
||||
|
||||
EXPECT_TRUE(bluetooth_classic.StartDiscovery());
|
||||
device_added_latch.Await();
|
||||
provider_adapter.SetStatus(BluetoothAdapter::Status::kDisabled);
|
||||
device_removed_latch.Await();
|
||||
|
||||
EXPECT_TRUE(bluetooth_classic.StopDiscovery());
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, CanCreatePairing) {
|
||||
MediumEnvironment::Instance().Start();
|
||||
@@ -36,7 +99,7 @@ TEST(BluetoothClassicTest, CanCreatePairing) {
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, RemoteDeviceNotFound) {
|
||||
TEST(BluetoothClassicTest, FailedToCreatePairingDueToRemoteDeviceNotFound) {
|
||||
MediumEnvironment::Instance().Start();
|
||||
BluetoothRadio radio;
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
@@ -60,6 +123,8 @@ TEST(BluetoothClassicTest, RadioDisable) {
|
||||
EXPECT_FALSE(bluetooth_classic.IsAvailable());
|
||||
EXPECT_FALSE(
|
||||
bluetooth_classic.CreatePairing(provider_adapter.GetMacAddress()));
|
||||
EXPECT_FALSE(bluetooth_classic.StartDiscovery());
|
||||
EXPECT_FALSE(bluetooth_classic.StopDiscovery());
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, BluetoothAdapterDisable) {
|
||||
@@ -73,6 +138,8 @@ TEST(BluetoothClassicTest, BluetoothAdapterDisable) {
|
||||
EXPECT_FALSE(bluetooth_classic.IsAvailable());
|
||||
EXPECT_FALSE(
|
||||
bluetooth_classic.CreatePairing(adapter_provider.GetMacAddress()));
|
||||
EXPECT_FALSE(bluetooth_classic.StartDiscovery());
|
||||
EXPECT_FALSE(bluetooth_classic.StopDiscovery());
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, GetMedium) {
|
||||
|
||||
@@ -18,9 +18,12 @@ cc_library(
|
||||
name = "retroactive",
|
||||
srcs = [
|
||||
"retroactive.cc",
|
||||
"retroactive_pairing_detector_impl.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"retroactive.h",
|
||||
"retroactive_pairing_detector.h",
|
||||
"retroactive_pairing_detector_impl.h",
|
||||
],
|
||||
compatible_with = ["//buildenv/target:non_prod"],
|
||||
visibility = [
|
||||
@@ -30,10 +33,14 @@ cc_library(
|
||||
deps = [
|
||||
"//fastpair:fast_pair_controller",
|
||||
"//fastpair/common",
|
||||
"//fastpair/internal/mediums",
|
||||
"//fastpair/message_stream",
|
||||
"//fastpair/pairing",
|
||||
"//internal/base",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:types",
|
||||
"//third_party/magic_enum",
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
"@com_google_absl//absl/status",
|
||||
"@com_google_absl//absl/strings",
|
||||
],
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_RETROACTIVE_RETROACTIVE_PAIRING_DETECTOR_H_
|
||||
#define THIRD_PARTY_NEARBY_FASTPAIR_RETROACTIVE_RETROACTIVE_PAIRING_DETECTOR_H_
|
||||
|
||||
#include "fastpair/common/fast_pair_device.h"
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
// A RetroactivePairingDetector instance is responsible for detecting Fast Pair
|
||||
// devices that can be paired retroactively, and notifying observers of this
|
||||
// device.
|
||||
class RetroactivePairingDetector {
|
||||
public:
|
||||
class Observer {
|
||||
public:
|
||||
virtual ~Observer() = default;
|
||||
virtual void OnRetroactivePairFound(FastPairDevice& device) = 0;
|
||||
};
|
||||
|
||||
virtual ~RetroactivePairingDetector() = default;
|
||||
|
||||
virtual void AddObserver(Observer* observer) = 0;
|
||||
virtual void RemoveObserver(Observer* observer) = 0;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_FASTPAIR_RETROACTIVE_RETROACTIVE_PAIRING_DETECTOR_H_
|
||||
@@ -0,0 +1,105 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "fastpair/retroactive/retroactive_pairing_detector_impl.h"
|
||||
|
||||
#include <ios>
|
||||
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/pairing/pairer_broker.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
RetroactivePairingDetectorImpl::RetroactivePairingDetectorImpl(
|
||||
Mediums& mediums, PairerBroker* pairer_broker)
|
||||
: mediums_(mediums) {
|
||||
pairer_broker->AddObserver(this);
|
||||
mediums_.GetBluetoothClassic().AddObserver(this);
|
||||
mediums_.GetBluetoothClassic().StartDiscovery();
|
||||
}
|
||||
|
||||
RetroactivePairingDetectorImpl::~RetroactivePairingDetectorImpl() {
|
||||
mediums_.GetBluetoothClassic().RemoveObserver(this);
|
||||
mediums_.GetBluetoothClassic().StopDiscovery();
|
||||
}
|
||||
|
||||
void RetroactivePairingDetectorImpl::AddObserver(
|
||||
RetroactivePairingDetector::Observer* observer) {
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
|
||||
void RetroactivePairingDetectorImpl::RemoveObserver(
|
||||
RetroactivePairingDetector::Observer* observer) {
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
void RetroactivePairingDetectorImpl::OnDevicePaired(FastPairDevice& device) {
|
||||
// The classic address is assigned to the Device during the
|
||||
// initial Fast Pair pairing protocol and if it doesn't exist,
|
||||
// then it wasn't properly paired during initial Fast Pair
|
||||
// pairing.
|
||||
if (!device.GetPublicAddress().has_value()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// The Bluetooth Adapter system event `DevicePairedChanged` fires before
|
||||
// Fast Pair's `OnDevicePaired`, and a Fast Pair pairing is expected to have
|
||||
// both events. If a device is Fast Paired, it is already inserted in the
|
||||
// |potential_retroactive_addresses_| in `DevicePairedChanged`; we need to
|
||||
// remove it to prevent a false positive.
|
||||
if (potential_retroactive_addresses_.contains(
|
||||
device.GetPublicAddress().value())) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< ": paired with initial pairing, removing device at address = "
|
||||
<< device.GetPublicAddress().value();
|
||||
potential_retroactive_addresses_.erase(device.GetPublicAddress().value());
|
||||
}
|
||||
}
|
||||
|
||||
void RetroactivePairingDetectorImpl::DevicePairedChanged(
|
||||
BluetoothDevice& device, bool new_paired_status) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< " Device paired changed, name = " << device.GetName()
|
||||
<< " address = " << device.GetMacAddress()
|
||||
<< " new_paired_status = " << std::boolalpha
|
||||
<< new_paired_status;
|
||||
// This event fires whenever a device pairing has changed with
|
||||
// the BluetoothClassicMedium.
|
||||
// If the |new_paired_status| is false, it means a device was unpaired,
|
||||
// so we early return since it would not be a device to retroactively pair to.
|
||||
if (!new_paired_status) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Both classic paired and Fast paired devices call this function, so we
|
||||
// have to add the device to |potential_retroactive_addresses_|. We expect
|
||||
// devices paired via Fast Pair to always call `OnDevicePaired` after calling
|
||||
// this function, which will remove the device from
|
||||
// |potential_retroactive_addresses_|.
|
||||
potential_retroactive_addresses_.insert(device.GetMacAddress());
|
||||
|
||||
// In order to confirm that this device is a retroactive pairing, we need to
|
||||
// first check if it has already been saved to the user's account. If it has
|
||||
// already been saved, we don't want to prompt the user to save a device
|
||||
// again.
|
||||
// TODO(b/285047010): check if device has already been saved to the user's
|
||||
// account
|
||||
|
||||
// TODO(Janusz) Add implementation for AttemptRetroactivePairing
|
||||
}
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,60 @@
|
||||
// Copyright 2023 Google LLC
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// https://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_RETROACTIVE_RETROACTIVE_PAIRING_DETECTOR_IMPL_H_
|
||||
#define THIRD_PARTY_NEARBY_FASTPAIR_RETROACTIVE_RETROACTIVE_PAIRING_DETECTOR_IMPL_H_
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "fastpair/internal/mediums/mediums.h"
|
||||
#include "fastpair/pairing/pairer_broker.h"
|
||||
#include "fastpair/retroactive/retroactive_pairing_detector.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
class RetroactivePairingDetectorImpl : public RetroactivePairingDetector,
|
||||
public BluetoothClassicMedium ::Observer,
|
||||
public PairerBroker::Observer {
|
||||
public:
|
||||
RetroactivePairingDetectorImpl(Mediums& mediums, PairerBroker* pairer_broker);
|
||||
RetroactivePairingDetectorImpl(const RetroactivePairingDetectorImpl&) =
|
||||
delete;
|
||||
RetroactivePairingDetectorImpl& operator=(
|
||||
const RetroactivePairingDetectorImpl&) = delete;
|
||||
~RetroactivePairingDetectorImpl() override;
|
||||
|
||||
// RetroactivePairingDetector:
|
||||
void AddObserver(RetroactivePairingDetector::Observer* observer) override;
|
||||
void RemoveObserver(RetroactivePairingDetector::Observer* observer) override;
|
||||
|
||||
// BluetoothClassicMedium :: Observer
|
||||
void DevicePairedChanged(BluetoothDevice& device,
|
||||
bool new_paired_status) override;
|
||||
|
||||
// PairerBroker::Observer
|
||||
void OnDevicePaired(FastPairDevice& device) override;
|
||||
|
||||
private:
|
||||
Mediums& mediums_;
|
||||
ObserverList<RetroactivePairingDetector::Observer> observers_;
|
||||
absl::flat_hash_set<std::string> potential_retroactive_addresses_;
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_FASTPAIR_RETROACTIVE_RETROACTIVE_PAIRING_DETECTOR_IMPL_H_
|
||||
@@ -226,6 +226,7 @@ cc_library(
|
||||
":logging",
|
||||
":types",
|
||||
":uuid",
|
||||
"//internal/base",
|
||||
"//internal/platform/implementation:comm",
|
||||
"//internal/test",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
|
||||
@@ -45,6 +45,39 @@ constexpr FeatureFlags kTestCases[] = {
|
||||
},
|
||||
};
|
||||
|
||||
class BluetoothClassicMediumObserver
|
||||
: public BluetoothClassicMedium ::Observer {
|
||||
public:
|
||||
explicit BluetoothClassicMediumObserver(
|
||||
CountDownLatch* device_added_latch, CountDownLatch* device_removed_latch,
|
||||
CountDownLatch* device_paired_changed_latch)
|
||||
: device_added_latch_(device_added_latch),
|
||||
device_removed_latch_(device_removed_latch),
|
||||
device_paired_changed_latch_(device_paired_changed_latch) {}
|
||||
|
||||
void DeviceAdded(BluetoothDevice& device) override {
|
||||
if (!device_added_latch_) return;
|
||||
device_added_latch_->CountDown();
|
||||
}
|
||||
|
||||
void DeviceRemoved(BluetoothDevice& device) override {
|
||||
if (!device_removed_latch_) return;
|
||||
device_removed_latch_->CountDown();
|
||||
}
|
||||
|
||||
void DevicePairedChanged(BluetoothDevice& device,
|
||||
bool new_paired_status) override {
|
||||
if (!device_paired_changed_latch_) return;
|
||||
paired_status_ = new_paired_status;
|
||||
device_paired_changed_latch_->CountDown();
|
||||
}
|
||||
|
||||
CountDownLatch* device_added_latch_;
|
||||
CountDownLatch* device_removed_latch_;
|
||||
CountDownLatch* device_paired_changed_latch_;
|
||||
bool paired_status_ = false;
|
||||
};
|
||||
|
||||
class BluetoothClassicMediumTest
|
||||
: public ::testing::TestWithParam<FeatureFlags> {
|
||||
protected:
|
||||
@@ -304,6 +337,12 @@ TEST_F(BluetoothClassicMediumTest, CanStartDiscovery) {
|
||||
adapter_a_->SetScanMode(BluetoothAdapter::ScanMode::kConnectable);
|
||||
CountDownLatch found_latch(1);
|
||||
CountDownLatch lost_latch(1);
|
||||
CountDownLatch device_added_latch(1);
|
||||
CountDownLatch device_removed_latch(1);
|
||||
BluetoothClassicMediumObserver observer(&device_added_latch,
|
||||
&device_removed_latch, nullptr);
|
||||
bt_a_->AddObserver(&observer);
|
||||
|
||||
bt_a_->StartDiscovery(DiscoveryCallback{
|
||||
.device_discovered_cb =
|
||||
[this, &found_latch](BluetoothDevice& device) {
|
||||
@@ -322,9 +361,11 @@ TEST_F(BluetoothClassicMediumTest, CanStartDiscovery) {
|
||||
EXPECT_EQ(adapter_b_->GetScanMode(),
|
||||
BluetoothAdapter::ScanMode::kConnectableDiscoverable);
|
||||
EXPECT_TRUE(found_latch.Await(absl::Milliseconds(1000)).result());
|
||||
EXPECT_TRUE(device_added_latch.Await(absl::Milliseconds(1000)).result());
|
||||
adapter_b_->SetStatus(BluetoothAdapter::Status::kDisabled);
|
||||
EXPECT_FALSE(adapter_b_->IsEnabled());
|
||||
EXPECT_TRUE(lost_latch.Await(absl::Milliseconds(1000)).result());
|
||||
EXPECT_TRUE(device_removed_latch.Await(absl::Milliseconds(1000)).result());
|
||||
}
|
||||
|
||||
TEST_F(BluetoothClassicMediumTest, CanStopDiscovery) {
|
||||
@@ -417,6 +458,10 @@ TEST_F(BluetoothClassicMediumTest, BluetoothPairingSuccess) {
|
||||
CountDownLatch paired_latch(1);
|
||||
CountDownLatch initiated_latch(1);
|
||||
CountDownLatch error_latch(1);
|
||||
CountDownLatch device_paired_latch(1);
|
||||
BluetoothClassicMediumObserver observer(nullptr, nullptr,
|
||||
&device_paired_latch);
|
||||
bt_a_->AddObserver(&observer);
|
||||
EXPECT_TRUE(bluetooth_pairing->InitiatePairing({
|
||||
.on_paired_cb = [&]() { paired_latch.CountDown(); },
|
||||
.on_pairing_error_cb =
|
||||
@@ -442,6 +487,8 @@ TEST_F(BluetoothClassicMediumTest, BluetoothPairingSuccess) {
|
||||
// Finishes pairing with remote device.
|
||||
EXPECT_TRUE(bluetooth_pairing->FinishPairing(received_passkey));
|
||||
paired_latch.Await();
|
||||
device_paired_latch.Await();
|
||||
EXPECT_TRUE(observer.paired_status_);
|
||||
EXPECT_TRUE(bluetooth_pairing->IsPaired());
|
||||
|
||||
// Unpairs with remote device.
|
||||
|
||||
@@ -314,11 +314,12 @@ api::BluetoothDevice* BluetoothClassicMedium::GetRemoteDevice(
|
||||
|
||||
void BluetoothClassicMedium::AddObserver(
|
||||
api::BluetoothClassicMedium::Observer* observer) {
|
||||
// TODO(b/269521993): Implement observer callbacks.
|
||||
MediumEnvironment::Instance().AddObserver(observer);
|
||||
}
|
||||
|
||||
void BluetoothClassicMedium::RemoveObserver(
|
||||
api::BluetoothClassicMedium::Observer* observer) {
|
||||
// TODO(b/269521993): Implement observer callbacks.
|
||||
MediumEnvironment::Instance().RemoveObserver(observer);
|
||||
}
|
||||
|
||||
} // namespace g3
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#include <codecvt>
|
||||
#include <fstream>
|
||||
#include <functional>
|
||||
#include <ios>
|
||||
#include <locale>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
@@ -560,11 +561,6 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
// Represents a Bluetooth device.
|
||||
// https://docs.microsoft.com/en-us/uwp/api/windows.devices.bluetooth.bluetoothdevice?view=winrt-20348
|
||||
std::unique_ptr<winrt::Windows::Devices::Bluetooth::BluetoothDevice>
|
||||
windowsBluetoothDevice;
|
||||
|
||||
// Create an iterator for the internal list
|
||||
std::map<winrt::hstring, std::unique_ptr<BluetoothDevice>>::const_iterator
|
||||
it = discovered_devices_by_id_.find(deviceInfo.Id());
|
||||
@@ -587,11 +583,14 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Added(
|
||||
|
||||
discovered_devices_by_id_[deviceInfo.Id()] = std::move(bluetoothDeviceP);
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Notifying bluetooth device added";
|
||||
if (discovery_callback_.device_discovered_cb != nullptr) {
|
||||
discovery_callback_.device_discovered_cb(
|
||||
*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceAdded(*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
@@ -619,6 +618,7 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/uwp/devices-sensors/device-information-properties#associationendpoint-properties
|
||||
if (properties.HasKey(L"System.ItemNameDisplay")) {
|
||||
// we need to really change the name of the bluetooth device
|
||||
std::string new_device_name = InspectableReader::ReadString(
|
||||
@@ -627,17 +627,29 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Updated(
|
||||
if (it->second->GetName() == new_device_name) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Device name is same as old name, ignore the update.";
|
||||
return {};
|
||||
} else {
|
||||
it->second->SetName(new_device_name);
|
||||
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Updated device name:"
|
||||
<< discovered_devices_by_id_[deviceInfoUpdate.Id()]->GetName();
|
||||
|
||||
discovery_callback_.device_name_changed_cb(
|
||||
*discovered_devices_by_id_[deviceInfoUpdate.Id()]);
|
||||
}
|
||||
}
|
||||
|
||||
it->second->SetName(new_device_name);
|
||||
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Updated device name:"
|
||||
<< discovered_devices_by_id_[deviceInfoUpdate.Id()]->GetName();
|
||||
|
||||
discovery_callback_.device_name_changed_cb(
|
||||
*discovered_devices_by_id_[deviceInfoUpdate.Id()]);
|
||||
// Indicates if the device is currently paired.
|
||||
if (properties.HasKey(L"System.Devices.Aep.IsPaired")) {
|
||||
bool new_paired_status = InspectableReader::ReadBoolean(
|
||||
properties.Lookup(L"System.Devices.Aep.IsPaired"));
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< ": Notifying device paired changed: " << std::boolalpha
|
||||
<< new_paired_status;
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DevicePairedChanged(
|
||||
*discovered_devices_by_id_[deviceInfoUpdate.Id()], new_paired_status);
|
||||
}
|
||||
}
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
@@ -662,11 +674,16 @@ winrt::fire_and_forget BluetoothClassicMedium::DeviceWatcher_Removed(
|
||||
return winrt::fire_and_forget();
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << __func__ << ": Notifying bluetooth device removed";
|
||||
if (discovery_callback_.device_lost_cb != nullptr) {
|
||||
discovery_callback_.device_lost_cb(
|
||||
*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceRemoved(*discovered_devices_by_id_[deviceInfo.Id()]);
|
||||
}
|
||||
|
||||
discovered_devices_by_id_.erase(deviceInfo.Id());
|
||||
|
||||
return winrt::fire_and_forget();
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/implementation/bluetooth_classic.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_adapter.h"
|
||||
#include "internal/platform/implementation/windows/bluetooth_classic_device.h"
|
||||
@@ -152,12 +153,12 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
api::BluetoothDevice& remote_device) override;
|
||||
|
||||
void AddObserver(Observer* observer) override {
|
||||
// TODO(b/269521993): Implement.
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
|
||||
// Removes an observer. It's OK to remove an unregistered observer.
|
||||
void RemoveObserver(Observer* observer) override {
|
||||
// TODO(b/269521993): Implement.
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -218,6 +219,7 @@ class BluetoothClassicMedium : public api::BluetoothClassicMedium {
|
||||
std::unique_ptr<BluetoothServerSocket> server_socket_ = nullptr;
|
||||
BluetoothServerSocket* raw_server_socket_ = nullptr;
|
||||
bool is_radio_discoverable_ = false;
|
||||
ObserverList<Observer> observers_;
|
||||
};
|
||||
|
||||
} // namespace windows
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace windows {
|
||||
class ConditionVariable : public api::ConditionVariable {
|
||||
public:
|
||||
explicit ConditionVariable(api::Mutex* mutex)
|
||||
: mutex_(&(static_cast<windows::Mutex*>(mutex))->mutex_) {}
|
||||
: mutex_(&(static_cast<windows::Mutex*>(mutex))->GetMutex()) {}
|
||||
~ConditionVariable() override = default;
|
||||
|
||||
Exception Wait() override {
|
||||
|
||||
@@ -167,8 +167,12 @@ void MediumEnvironment::OnBluetoothDeviceStateChanged(
|
||||
// Store device name, and report it as discovered.
|
||||
info.devices.emplace(&device, name);
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread(
|
||||
[&info, &device]() { info.callback.device_discovered_cb(device); });
|
||||
RunOnMediumEnvironmentThread([&]() {
|
||||
info.callback.device_discovered_cb(device);
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceAdded(device);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -190,8 +194,11 @@ void MediumEnvironment::OnBluetoothDeviceStateChanged(
|
||||
} else {
|
||||
// Device is in discovery mode, so we are reporting it anyway.
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread([&info, &device]() {
|
||||
RunOnMediumEnvironmentThread([&]() {
|
||||
info.callback.device_discovered_cb(device);
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceAdded(device);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -200,8 +207,12 @@ void MediumEnvironment::OnBluetoothDeviceStateChanged(
|
||||
// Known device is turned off.
|
||||
// Erase it from the map, and report as lost.
|
||||
if (enable_notifications_) {
|
||||
RunOnMediumEnvironmentThread(
|
||||
[&info, &device]() { info.callback.device_lost_cb(device); });
|
||||
RunOnMediumEnvironmentThread([&]() {
|
||||
info.callback.device_lost_cb(device);
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DeviceRemoved(device);
|
||||
}
|
||||
});
|
||||
}
|
||||
info.devices.erase(item);
|
||||
}
|
||||
@@ -1199,6 +1210,11 @@ bool MediumEnvironment::SetPairingState(api::BluetoothDevice* device,
|
||||
latch.CountDown();
|
||||
});
|
||||
latch.Await();
|
||||
if (enable_notifications_) {
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DevicePairedChanged(*device, true);
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
@@ -1262,6 +1278,11 @@ bool MediumEnvironment::FinishPairing(api::BluetoothDevice* device) {
|
||||
pairing_context->pairing_error.value());
|
||||
} else {
|
||||
pairing_context->is_paired = true;
|
||||
if (enable_notifications_) {
|
||||
for (auto& observer : observers_.GetObservers()) {
|
||||
observer->DevicePairedChanged(*device, true);
|
||||
}
|
||||
}
|
||||
pairing_context->pairing_callback.on_paired_cb();
|
||||
}
|
||||
return finshed;
|
||||
@@ -1306,4 +1327,17 @@ void MediumEnvironment::ClearBluetoothDevicesForPairing() {
|
||||
if (!enabled_) return;
|
||||
RunOnMediumEnvironmentThread([&]() { devices_pairing_contexts_.clear(); });
|
||||
}
|
||||
|
||||
void MediumEnvironment::AddObserver(
|
||||
api::BluetoothClassicMedium::Observer* observer) {
|
||||
if (!enabled_) return;
|
||||
observers_.AddObserver(observer);
|
||||
}
|
||||
|
||||
void MediumEnvironment::RemoveObserver(
|
||||
api::BluetoothClassicMedium::Observer* observer) {
|
||||
if (!enabled_) return;
|
||||
observers_.RemoveObserver(observer);
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "absl/types/optional.h"
|
||||
#include "internal/base/observer_list.h"
|
||||
#include "internal/platform/borrowable.h"
|
||||
#include "internal/platform/implementation/ble.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
@@ -384,6 +385,9 @@ class MediumEnvironment {
|
||||
// Clears the map `devices_pairing_contexts_`.
|
||||
void ClearBluetoothDevicesForPairing();
|
||||
|
||||
void AddObserver(api::BluetoothClassicMedium::Observer* observer);
|
||||
void RemoveObserver(api::BluetoothClassicMedium::Observer* observer);
|
||||
|
||||
private:
|
||||
struct BluetoothMediumContext {
|
||||
BluetoothDiscoveryCallback callback;
|
||||
@@ -514,6 +518,7 @@ class MediumEnvironment {
|
||||
bool use_valid_peer_connection_ = true;
|
||||
absl::Duration peer_connection_latency_ = absl::ZeroDuration();
|
||||
std::unique_ptr<FakeClock> simulated_clock_ ABSL_GUARDED_BY(mutex_);
|
||||
ObserverList<api::BluetoothClassicMedium::Observer> observers_;
|
||||
};
|
||||
|
||||
} // namespace nearby
|
||||
|
||||
@@ -418,4 +418,4 @@ enum PowerLevel {
|
||||
}
|
||||
// LINT.ThenChange(
|
||||
// //depot/google3/java/com/google/android/gmscore/integ/client/nearby/src/com/google/android/gms/nearby/connection/PowerLevel.java
|
||||
// )
|
||||
// )
|
||||
|
||||
Reference in New Issue
Block a user