mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
Implement BluetoothClassic Medium for fast pair windows
PiperOrigin-RevId: 531299637
This commit is contained in:
committed by
Copybara-Service
parent
6958edb8cc
commit
b19d4fb279
@@ -19,11 +19,13 @@ cc_library(
|
||||
srcs = [
|
||||
"ble.cc",
|
||||
"ble_v2.cc",
|
||||
"bluetooth_classic.cc",
|
||||
"bluetooth_radio.cc",
|
||||
],
|
||||
hdrs = [
|
||||
"ble.h",
|
||||
"ble_v2.h",
|
||||
"bluetooth_classic.h",
|
||||
"bluetooth_radio.h",
|
||||
"mediums.h",
|
||||
],
|
||||
@@ -105,3 +107,21 @@ cc_test(
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
cc_test(
|
||||
name = "bluetooth_classic_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"bluetooth_classic_test.cc",
|
||||
],
|
||||
shard_count = 16,
|
||||
deps = [
|
||||
":mediums",
|
||||
"//internal/platform:comm",
|
||||
"//internal/platform:test_util",
|
||||
"//internal/platform/implementation/g3", # build_cleaner: keep
|
||||
"@com_github_protobuf_matchers//protobuf-matchers",
|
||||
"@com_google_absl//absl/strings",
|
||||
"@com_google_googletest//:gtest_main",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -54,7 +54,7 @@ class Ble {
|
||||
bool IsScanning() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Return BleMedium
|
||||
BleMedium& getMedium() { return medium_; }
|
||||
BleMedium& GetMedium() { return medium_; }
|
||||
|
||||
private:
|
||||
// Same as IsAvailable(), but must be called with mutex_ held.
|
||||
|
||||
@@ -50,7 +50,7 @@ TEST(BleTest, CanStartDiscovery) {
|
||||
std::string fast_pair_service_uuid(kFastPairServiceUuid);
|
||||
CountDownLatch accept_latch(1);
|
||||
CountDownLatch lost_latch(1);
|
||||
ble_b.getMedium().StartAdvertising(service_id, advertisement_bytes,
|
||||
ble_b.GetMedium().StartAdvertising(service_id, advertisement_bytes,
|
||||
fast_pair_service_uuid);
|
||||
|
||||
EXPECT_TRUE(ble_a.StartScanning(
|
||||
@@ -69,7 +69,7 @@ TEST(BleTest, CanStartDiscovery) {
|
||||
}));
|
||||
EXPECT_TRUE(ble_a.IsScanning());
|
||||
EXPECT_TRUE(accept_latch.Await(kWaitDuration).result());
|
||||
ble_b.getMedium().StopAdvertising(service_id);
|
||||
ble_b.GetMedium().StopAdvertising(service_id);
|
||||
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
|
||||
EXPECT_TRUE(ble_a.StopScanning(service_id));
|
||||
EXPECT_FALSE(ble_a.IsScanning());
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
// 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/internal/mediums/bluetooth_classic.h"
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
BluetoothClassic::BluetoothClassic(BluetoothRadio& radio) : radio_(radio) {}
|
||||
|
||||
bool BluetoothClassic::IsAvailable() const {
|
||||
MutexLock lock(&mutex_);
|
||||
return IsAvailableLocked();
|
||||
}
|
||||
|
||||
bool BluetoothClassic::IsAvailableLocked() const {
|
||||
return medium_.IsValid() && adapter_.IsValid() && adapter_.IsEnabled();
|
||||
}
|
||||
|
||||
std::unique_ptr<BluetoothPairing> BluetoothClassic::CreatePairing(
|
||||
absl::string_view public_address) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (!radio_.IsEnabled()) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< __func__
|
||||
<< "Can't create bluetooth pairing because Bluetooth was NOT enabled";
|
||||
return nullptr;
|
||||
}
|
||||
if (!IsAvailableLocked()) {
|
||||
NEARBY_LOGS(VERBOSE) << __func__
|
||||
<< "Can't create bluetooth pairing because "
|
||||
"BluetoothClassic isn't available.";
|
||||
return nullptr;
|
||||
}
|
||||
BluetoothDevice device = medium_.GetRemoteDevice(std::string(public_address));
|
||||
if (!device.IsValid()) {
|
||||
NEARBY_LOGS(INFO) << __func__
|
||||
<< "Can't create bluetooth pairing because Bluetooth "
|
||||
"device was NOT found";
|
||||
return nullptr;
|
||||
}
|
||||
return medium_.CreatePairing(device);
|
||||
}
|
||||
|
||||
BluetoothClassicMedium& BluetoothClassic::GetMedium() { return medium_; }
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
@@ -0,0 +1,56 @@
|
||||
// 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_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_
|
||||
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "fastpair/internal/mediums/bluetooth_radio.h"
|
||||
#include "internal/platform/bluetooth_classic.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
|
||||
class BluetoothClassic {
|
||||
public:
|
||||
explicit BluetoothClassic(BluetoothRadio& bluetooth_radio);
|
||||
~BluetoothClassic() = default;
|
||||
|
||||
// Returns true, if BT communications are supported by a platform.
|
||||
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Returns a new BluetoothPairing instance to handle the pairing process
|
||||
// with the remote device.
|
||||
std::unique_ptr<BluetoothPairing> CreatePairing(
|
||||
absl::string_view public_address);
|
||||
|
||||
BluetoothClassicMedium& GetMedium() ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
private:
|
||||
// Same as IsAvailable(), but must be called with mutex_ held.
|
||||
bool IsAvailableLocked() 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_};
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
|
||||
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_
|
||||
@@ -0,0 +1,89 @@
|
||||
// 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/internal/mediums/bluetooth_classic.h"
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/strings/escaping.h"
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/medium_environment.h"
|
||||
|
||||
namespace nearby {
|
||||
namespace fastpair {
|
||||
namespace {
|
||||
|
||||
TEST(BluetoothClassicTest, CanCreatePairing) {
|
||||
MediumEnvironment::Instance().Start();
|
||||
BluetoothRadio radio;
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
BluetoothAdapter provider_adapter;
|
||||
provider_adapter.SetStatus(BluetoothAdapter::Status::kEnabled);
|
||||
BluetoothClassicMedium bt_provider(provider_adapter);
|
||||
|
||||
EXPECT_TRUE(bluetooth_classic.IsAvailable());
|
||||
EXPECT_TRUE(bluetooth_classic.CreatePairing(
|
||||
absl::BytesToHexString(provider_adapter.GetMacAddress())));
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, RemoteDeviceNotFound) {
|
||||
MediumEnvironment::Instance().Start();
|
||||
BluetoothRadio radio;
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
BluetoothAdapter provider_adapter;
|
||||
provider_adapter.SetStatus(BluetoothAdapter::Status::kEnabled);
|
||||
BluetoothClassicMedium bt_provider(provider_adapter);
|
||||
|
||||
EXPECT_TRUE(bluetooth_classic.IsAvailable());
|
||||
EXPECT_FALSE(
|
||||
bluetooth_classic.CreatePairing(absl::BytesToHexString("bleaddress")));
|
||||
MediumEnvironment::Instance().Stop();
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, RadioDisable) {
|
||||
BluetoothRadio radio;
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
BluetoothAdapter provider_adapter;
|
||||
provider_adapter.SetStatus(BluetoothAdapter::Status::kEnabled);
|
||||
BluetoothClassicMedium bt_provider(provider_adapter);
|
||||
radio.Disable();
|
||||
|
||||
EXPECT_FALSE(bluetooth_classic.IsAvailable());
|
||||
EXPECT_FALSE(bluetooth_classic.CreatePairing(
|
||||
absl::BytesToHexString(provider_adapter.GetMacAddress())));
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, BluetoothAdapterDisable) {
|
||||
BluetoothRadio radio;
|
||||
radio.GetBluetoothAdapter().SetStatus(BluetoothAdapter::Status::kDisabled);
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
BluetoothAdapter adapter_provider;
|
||||
adapter_provider.SetStatus(BluetoothAdapter::Status::kEnabled);
|
||||
BluetoothClassicMedium bt_provider(adapter_provider);
|
||||
|
||||
EXPECT_FALSE(bluetooth_classic.IsAvailable());
|
||||
EXPECT_FALSE(bluetooth_classic.CreatePairing(
|
||||
absl::BytesToHexString(adapter_provider.GetMacAddress())));
|
||||
}
|
||||
|
||||
TEST(BluetoothClassicTest, GetMedium) {
|
||||
BluetoothRadio radio;
|
||||
BluetoothClassic bluetooth_classic(radio);
|
||||
|
||||
EXPECT_TRUE(bluetooth_classic.GetMedium().IsValid());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
} // namespace nearby
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
#include "fastpair/internal/mediums/ble.h"
|
||||
#include "fastpair/internal/mediums/ble_v2.h"
|
||||
#include "fastpair/internal/mediums/bluetooth_classic.h"
|
||||
#include "fastpair/internal/mediums/bluetooth_radio.h"
|
||||
|
||||
namespace nearby {
|
||||
@@ -37,6 +38,8 @@ class Mediums {
|
||||
// Returns a handle to the Ble medium.
|
||||
BleV2& GetBleV2() { return ble_v2_; }
|
||||
|
||||
BluetoothClassic& GetBluetoothClassic() { return bluetooth_classic_; }
|
||||
|
||||
private:
|
||||
// The order of declaration is critical for both construction and
|
||||
// destruction.
|
||||
@@ -49,6 +52,7 @@ class Mediums {
|
||||
BluetoothRadio bluetooth_radio_;
|
||||
Ble ble_{bluetooth_radio_};
|
||||
BleV2 ble_v2_{bluetooth_radio_};
|
||||
BluetoothClassic bluetooth_classic_{bluetooth_radio_};
|
||||
};
|
||||
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -25,6 +25,7 @@ TEST(MediumTest, ConstructorWorks) {
|
||||
EXPECT_TRUE(medium.GetBluetoothRadio().IsAdapterValid());
|
||||
EXPECT_FALSE(medium.GetBle().IsScanning());
|
||||
EXPECT_TRUE(medium.GetBleV2().ConnectToGattServer("ble_address"));
|
||||
EXPECT_TRUE(medium.GetBluetoothClassic().IsAvailable());
|
||||
}
|
||||
} // namespace
|
||||
} // namespace fastpair
|
||||
|
||||
@@ -79,7 +79,7 @@ TEST_F(FastPairScannerImplTest, StartScanning) {
|
||||
std::string service_id(kServiceID);
|
||||
ByteArray advertisement_bytes{absl::HexStringToBytes(kModelId)};
|
||||
std::string fast_pair_service_uuid(kFastPairServiceUuid);
|
||||
mediums_2.GetBle().getMedium().StartAdvertising(
|
||||
mediums_2.GetBle().GetMedium().StartAdvertising(
|
||||
service_id, advertisement_bytes, fast_pair_service_uuid);
|
||||
|
||||
// Fast Pair scanner startScanning
|
||||
@@ -88,7 +88,7 @@ TEST_F(FastPairScannerImplTest, StartScanning) {
|
||||
EXPECT_TRUE(accept_latch.Await(kTaskWaitTimeout).result());
|
||||
|
||||
// Advertiser stopAdvertising
|
||||
mediums_2.GetBle().getMedium().StopAdvertising(service_id);
|
||||
mediums_2.GetBle().GetMedium().StopAdvertising(service_id);
|
||||
// Notify device lost
|
||||
EXPECT_TRUE(lost_latch.Await(kTaskWaitTimeout).result());
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ TEST_F(ScannerBrokerImplTest, CanStartScanning) {
|
||||
std::string service_id(kServiceID);
|
||||
ByteArray advertisement_bytes{absl::HexStringToBytes(kModelId)};
|
||||
std::string fast_pair_service_uuid(kFastPairServiceUuid);
|
||||
mediums_2.GetBle().getMedium().StartAdvertising(
|
||||
mediums_2.GetBle().GetMedium().StartAdvertising(
|
||||
service_id, advertisement_bytes, fast_pair_service_uuid);
|
||||
|
||||
// Fast Pair scanner startScanning
|
||||
@@ -102,7 +102,7 @@ TEST_F(ScannerBrokerImplTest, CanStartScanning) {
|
||||
EXPECT_TRUE(accept_latch.Await(kTaskWaitTimeout).result());
|
||||
|
||||
// Advertiser stopAdvertising
|
||||
mediums_2.GetBle().getMedium().StopAdvertising(service_id);
|
||||
mediums_2.GetBle().GetMedium().StopAdvertising(service_id);
|
||||
|
||||
// Notify device lost
|
||||
EXPECT_TRUE(lost_latch.Await(kTaskWaitTimeout).result());
|
||||
|
||||
Reference in New Issue
Block a user