Refactor Bluetooth Mediums

PiperOrigin-RevId: 528511969
This commit is contained in:
Qin Wang
2023-05-01 10:41:29 -07:00
committed by Copybara-Service
parent e46bfb52d0
commit 9f6e7f6b84
41 changed files with 754 additions and 499 deletions
@@ -15,12 +15,17 @@
licenses(["notice"])
cc_library(
name = "ble",
name = "mediums",
srcs = [
"ble.cc",
"ble_v2.cc",
"bluetooth_radio.cc",
],
hdrs = [
"ble.h",
"ble_v2.h",
"bluetooth_radio.h",
"mediums.h",
],
visibility = [
"//fastpair:__subpackages__",
@@ -30,13 +35,41 @@ cc_library(
"//internal/platform:comm",
"//internal/platform:logging",
"//internal/platform:types",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
],
)
cc_test(
name = "bluetooth_radio_test",
size = "small",
srcs = [
"bluetooth_radio_test.cc",
],
shard_count = 16,
deps = [
":mediums",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "mediums_test",
size = "small",
srcs = [
"mediums_test.cc",
],
shard_count = 16,
deps = [
":mediums",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "ble_test",
size = "small",
@@ -45,7 +78,7 @@ cc_test(
],
shard_count = 16,
deps = [
":ble",
":mediums",
"//internal/platform:base",
"//internal/platform:comm",
"//internal/platform:test_util",
@@ -57,3 +90,18 @@ cc_test(
"@com_google_googletest//:gtest_main",
],
)
cc_test(
name = "ble_v2_test",
size = "small",
srcs = [
"ble_v2_test.cc",
],
shard_count = 16,
deps = [
":mediums",
"//internal/platform/implementation/g3", # build_cleaner: keep
"@com_github_protobuf_matchers//protobuf-matchers",
"@com_google_googletest//:gtest_main",
],
)
@@ -12,87 +12,19 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/internal/ble/ble.h"
#include "fastpair/internal/mediums/ble.h"
#include <memory>
#include <string>
#include <utility>
#include "internal/platform/ble_v2.h"
#include "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
namespace nearby {
namespace fastpair {
namespace {
// A stub BlePeripheral implementation.
class BlePeripheralStub : public api::ble_v2::BlePeripheral {
public:
explicit BlePeripheralStub(absl::string_view ble_address) {
ble_address_ = std::string(ble_address);
}
std::string GetAddress() const override { return ble_address_; }
private:
std::string ble_address_;
};
} // namespace
Ble::~Ble() {
// We never enabled Bluetooth, nothing to do.
if (!ever_saved_state_.Get()) {
NEARBY_LOG(INFO, "BT adapter was not used. Not touching HW.");
return;
}
NEARBY_LOG(INFO, "Bring BT adapter to original state");
if (!SetBluetoothState(originally_enabled_.Get())) {
NEARBY_LOG(INFO, "Failed to restore BT adapter original state.");
}
}
bool Ble::Enable() {
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(true);
}
bool Ble::Disable() {
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(false);
}
bool Ble::IsEnabled() const {
return IsAdapterValid() && IsInDesiredState(true);
}
bool Ble::SetBluetoothState(bool enable) {
return adapter_.SetStatus(enable ? BluetoothAdapter::Status::kEnabled
: BluetoothAdapter::Status::kDisabled);
}
bool Ble::IsInDesiredState(bool should_be_enabled) const {
return adapter_.IsEnabled() == should_be_enabled;
}
bool Ble::SaveOriginalState() {
if (!IsAdapterValid()) {
return false;
}
// If we haven't saved the original state of the radio, save it.
if (!ever_saved_state_.Set(true)) {
originally_enabled_.Set(adapter_.IsEnabled());
}
return true;
}
Ble::Ble(BluetoothRadio& radio) : radio_(radio) {}
bool Ble::IsAvailable() const {
MutexLock lock(&mutex_);
@@ -122,7 +54,7 @@ bool Ble::StartScanning(const std::string& service_id,
return false;
}
if (!IsEnabled()) {
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO)
<< "Can't start BLE scanning because Bluetooth was NOT enabled";
return false;
@@ -183,18 +115,9 @@ bool Ble::StopScanning(const std::string& service_id) {
return ret;
}
std::unique_ptr<GattClient> Ble::ConnectToGattServer(
absl::string_view ble_address) {
MutexLock lock(&mutex_);
auto v2_peripheral = std::make_unique<BlePeripheralStub>(ble_address);
return v2_medium_.ConnectToGattServer(BleV2Peripheral(v2_peripheral.get()),
api::ble_v2::TxPowerLevel::kUnknown,
{});
}
bool Ble::IsScanning() {
NEARBY_LOGS(INFO) << __func__;
MutexLock lock(&mutex_);
return IsScanningLocked();
}
@@ -15,59 +15,30 @@
#ifndef THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_BLE_BLE_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_BLE_BLE_H_
#include <cstdint>
#include <memory>
#include <string>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "internal/platform/atomic_boolean.h"
#include "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/ble.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/multi_thread_executor.h"
#include "internal/platform/mutex.h"
namespace nearby {
namespace fastpair {
// Provides the operations that can be performed on the Bluetooth Low Energy
// (BLE) medium.
class Ble {
public:
using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback;
Ble() = default;
Ble(Ble&&) = default;
Ble& operator=(Ble&&) = default;
explicit Ble(BluetoothRadio& bluetooth_radio);
Ble(Ble&&) = delete;
Ble& operator=(Ble&&) = delete;
~Ble() = default;
// Reverts the Ble to its original state.
~Ble();
// Enables Bluetooth. Returns true if enabled successfully.
// This must be called before attempting to invoke any other methods of
// this class.
bool Enable();
// Disables Bluetooth. Returns true if disabled successfully.
bool Disable();
// Returns true if the Bluetooth radio is currently enabled.
bool IsEnabled() const;
// Returns true if Ble communications are supported by a platform.
// Returns true, if Ble communications are supported by a platform.
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true if this object owns a valid platform implementation.
bool IsMediumValid() const ABSL_LOCKS_EXCLUDED(mutex_) {
MutexLock lock(&mutex_);
return medium_.IsValid();
}
// Returns true if this object has a valid BluetoothAdapter reference.
bool IsAdapterValid() const { return adapter_.IsValid(); }
// Return true if Ble is currenlty scanning.
bool IsScanning() ABSL_LOCKS_EXCLUDED(mutex_);
// Enables Ble scanning mode. Will report any discoverable peripherals in
// range through a callback. Returns true, if scanning mode was enabled,
// false otherwise.
@@ -76,51 +47,29 @@ class Ble {
DiscoveredPeripheralCallback callback)
ABSL_LOCKS_EXCLUDED(mutex_);
// Returns a new GattClient connection to a gatt server.
std::unique_ptr<GattClient> ConnectToGattServer(
absl::string_view ble_address);
// Disables Ble discovery mode.
bool StopScanning(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_);
// Return true if Ble is currenlty scanning.
bool IsScanning() ABSL_LOCKS_EXCLUDED(mutex_);
// Return BleMedium
BleMedium& getMedium() { return medium_; }
// Return BluetoothAdapter
BluetoothAdapter& GetBluetoothAdapter() { return adapter_; }
private:
mutable Mutex mutex_;
// BluetoothAdapter::IsValid() will return false if BT is not supported.
BluetoothAdapter adapter_;
DiscoveredPeripheralCallback discovered_peripheral_callback_;
BleMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
BleV2Medium v2_medium_ ABSL_GUARDED_BY(mutex_){adapter_};
bool is_scanning_ = false;
// Same as IsAvailable(), but must be called with mutex_ held.
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Same as IsDiscovering(), but must be called with mutex_ held.
bool IsScanningLocked() ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool SetBluetoothState(bool enable);
bool IsInDesiredState(bool should_be_enabled) const;
// To be called in enable() and disable(). This will remember the
// original state of the ble before any ble state has been modified.
// Returns false if Bluetooth doesn't exist on the device and the state cannot
// be obtained.
bool SaveOriginalState();
// The Ble's original state, before we modified it. True if
// originally enabled, false if originally disabled.
// We restore the radio to its original state in the destructor.
AtomicBoolean originally_enabled_{false};
// false if we never modified the radio state, true otherwise.
AtomicBoolean ever_saved_state_{false};
mutable Mutex mutex_;
DiscoveredPeripheralCallback discovered_peripheral_callback_;
BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_);
BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_){
radio_.GetBluetoothAdapter()};
BleMedium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
bool is_scanning_ = false;
};
} // namespace fastpair
@@ -1,4 +1,4 @@
// Copyright 2022 Google LLC
// 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.
@@ -12,13 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#include "fastpair/internal/ble/ble.h"
#include "fastpair/internal/mediums/ble.h"
#include <string>
#include "gtest/gtest.h"
#include "internal/platform/ble.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/medium_environment.h"
@@ -26,64 +24,27 @@ namespace nearby {
namespace fastpair {
namespace {
using FeatureFlags = FeatureFlags::Flags;
using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback;
constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000);
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kAdvertisementString{"96C12E"};
constexpr absl::string_view kFastPairServiceUuid{"\x2c\xfe"};
class BleTest : public ::testing::TestWithParam<FeatureFlags> {
protected:
using DiscoveredPeripheralCallback = BleMedium::DiscoveredPeripheralCallback;
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
TEST_F(BleTest, ConstructorDestructorWorks) {
Ble ble;
EXPECT_TRUE(ble.IsAdapterValid());
TEST(BleTest, ConstructorDestructorWorks) {
BluetoothRadio radio;
Ble ble(radio);
EXPECT_TRUE(ble.IsAvailable());
EXPECT_FALSE(ble.IsScanning());
}
TEST_F(BleTest, CanEnable) {
Ble ble;
EXPECT_TRUE(ble.IsAdapterValid());
EXPECT_TRUE(ble.IsEnabled());
EXPECT_TRUE(ble.Disable());
EXPECT_FALSE(ble.IsEnabled());
EXPECT_TRUE(ble.Enable());
EXPECT_TRUE(ble.IsEnabled());
}
TEST_F(BleTest, CanDisable) {
Ble ble;
EXPECT_TRUE(ble.IsAdapterValid());
EXPECT_TRUE(ble.IsEnabled());
EXPECT_TRUE(ble.Disable());
EXPECT_FALSE(ble.IsEnabled());
}
TEST_F(BleTest, CanConstructValidObject) {
env_.Start();
Ble ble_a;
Ble ble_b;
EXPECT_TRUE(ble_a.IsMediumValid());
EXPECT_TRUE(ble_a.IsAdapterValid());
EXPECT_TRUE(ble_a.IsAvailable());
EXPECT_TRUE(ble_b.IsMediumValid());
EXPECT_TRUE(ble_b.IsAdapterValid());
EXPECT_TRUE(ble_b.IsAvailable());
EXPECT_NE(&ble_a.GetBluetoothAdapter(), &ble_b.GetBluetoothAdapter());
env_.Stop();
}
TEST_F(BleTest, CanStartDiscovery) {
env_.Start();
Ble ble_a;
Ble ble_b;
ble_a.Enable();
ble_b.Enable();
TEST(BleTest, CanStartDiscovery) {
MediumEnvironment::Instance().Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
Ble ble_a{radio_a};
Ble ble_b{radio_b};
radio_a.Enable();
radio_b.Enable();
std::string service_id(kServiceID);
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
std::string fast_pair_service_uuid(kFastPairServiceUuid);
@@ -112,16 +73,8 @@ TEST_F(BleTest, CanStartDiscovery) {
EXPECT_TRUE(lost_latch.Await(kWaitDuration).result());
EXPECT_TRUE(ble_a.StopScanning(service_id));
EXPECT_FALSE(ble_a.IsScanning());
env_.Stop();
MediumEnvironment::Instance().Stop();
}
TEST_F(BleTest, CannConnectToGattServer) {
env_.Start();
Ble ble;
EXPECT_NE(ble.ConnectToGattServer("bleaddress"), nullptr);
env_.Stop();
}
} // namespace
} // namespace fastpair
} // namespace nearby
+69
View File
@@ -0,0 +1,69 @@
// 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/ble_v2.h"
#include <memory>
#include <string>
#include "internal/platform/mutex_lock.h"
namespace nearby {
namespace fastpair {
namespace {
// A stub BlePeripheral implementation.
class BlePeripheralStub : public api::ble_v2::BlePeripheral {
public:
explicit BlePeripheralStub(absl::string_view ble_address) {
ble_address_ = std::string(ble_address);
}
std::string GetAddress() const override { return ble_address_; }
private:
std::string ble_address_;
};
} // namespace
BleV2::BleV2(BluetoothRadio& radio) : radio_(radio) {}
bool BleV2::IsAvailable() const {
MutexLock lock(&mutex_);
return IsAvailableLocked();
}
bool BleV2::IsAvailableLocked() const {
return medium_.IsValid() && adapter_.IsValid() && adapter_.IsEnabled();
}
std::unique_ptr<GattClient> BleV2::ConnectToGattServer(
absl::string_view ble_address) {
MutexLock lock(&mutex_);
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO)
<< "Can't connect to GattServer because Bluetooth was NOT enabled";
return nullptr;
}
if (!IsAvailableLocked()) {
NEARBY_LOGS(VERBOSE)
<< __func__
<< "Can't connect to GattServer because BleV2 isn't available.";
return nullptr;
}
auto v2_peripheral = std::make_unique<BlePeripheralStub>(ble_address);
return medium_.ConnectToGattServer(BleV2Peripheral(v2_peripheral.get()),
api::ble_v2::TxPowerLevel::kUnknown, {});
}
} // namespace fastpair
} // namespace nearby
+56
View File
@@ -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_BLE_V2_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLE_V2_H_
#include <memory>
#include "fastpair/internal/mediums/bluetooth_radio.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/mutex.h"
#include "internal/platform/mutex_lock.h"
namespace nearby {
namespace fastpair {
// Provides the operations that can be performed on the Bluetooth Low Energy
// (BLE_V2) medium.
class BleV2 {
public:
explicit BleV2(BluetoothRadio& bluetooth_radio);
~BleV2() = default;
// Returns true, if BleV2 communications are supported by a platform.
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
// Returns a new GattClient connection to a gatt server.
std::unique_ptr<GattClient> ConnectToGattServer(
absl::string_view ble_address);
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()};
BleV2Medium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLE_V2_H_
+46
View File
@@ -0,0 +1,46 @@
// 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/ble_v2.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(BleV2Test, IsAvailable) {
BluetoothRadio radio;
BleV2 bleV2(radio);
EXPECT_TRUE(bleV2.IsAvailable());
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(bleV2.IsAvailable());
}
TEST(BleV2Test, CanConnectToGattServer) {
BluetoothRadio radio;
BleV2 bleV2(radio);
EXPECT_TRUE(bleV2.ConnectToGattServer("bleaddress"));
}
TEST(BleV2Test, CannotConnectToGattServer) {
BluetoothRadio radio;
BleV2 bleV2(radio);
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(bleV2.ConnectToGattServer("bleaddress"));
}
} // namespace
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,86 @@
// 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_radio.h"
#include "internal/platform/logging.h"
namespace nearby {
namespace fastpair {
BluetoothRadio::BluetoothRadio() {
if (!IsAdapterValid()) {
NEARBY_LOGS(ERROR) << "Bluetooth adapter is not valid: BT is not supported";
}
}
BluetoothRadio::~BluetoothRadio() {
// We never enabled Bluetooth, nothing to do.
if (!ever_saved_state_.Get()) {
NEARBY_LOGS(INFO) << "BT adapter was not used. Not touching HW.";
return;
}
NEARBY_LOG(INFO, "Bring BT adapter to original state");
if (!SetBluetoothState(originally_enabled_.Get())) {
NEARBY_LOGS(INFO) << "Failed to restore BT adapter original state.";
}
}
bool BluetoothRadio::Enable() {
NEARBY_LOGS(INFO) << __func__;
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(true);
}
bool BluetoothRadio::Disable() {
if (!SaveOriginalState()) {
return false;
}
return SetBluetoothState(false);
}
bool BluetoothRadio::IsEnabled() const {
return IsAdapterValid() && IsInDesiredState(true);
}
bool BluetoothRadio::SetBluetoothState(bool enable) {
return bluetooth_adapter_.SetStatus(
enable ? BluetoothAdapter::Status::kEnabled
: BluetoothAdapter::Status::kDisabled);
}
bool BluetoothRadio::IsInDesiredState(bool should_be_enabled) const {
return bluetooth_adapter_.IsEnabled() == should_be_enabled;
}
bool BluetoothRadio::SaveOriginalState() {
if (!IsAdapterValid()) {
return false;
}
// If we haven't saved the original state of the radio, save it.
if (!ever_saved_state_.Set(true)) {
originally_enabled_.Set(bluetooth_adapter_.IsEnabled());
}
return true;
}
} // namespace fastpair
} // namespace nearby
@@ -0,0 +1,79 @@
// 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_RADIO_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_
#include "internal/platform/atomic_boolean.h"
#include "internal/platform/bluetooth_adapter.h"
namespace nearby {
namespace fastpair {
// Provides the operations that can be performed on the Bluetooth radio.
class BluetoothRadio {
public:
BluetoothRadio();
BluetoothRadio(BluetoothRadio&&) = default;
BluetoothRadio& operator=(BluetoothRadio&&) = default;
// Reverts the Bluetooth radio to its original state.
~BluetoothRadio();
// Enables Bluetooth.
//
// This must be called before attempting to invoke any other methods of
// this class.
//
// Returns true if enabled successfully.
bool Enable();
// Disables Bluetooth.
//
// Returns true if disabled successfully.
bool Disable();
// Returns true if the Bluetooth radio is currently enabled.
bool IsEnabled() const;
// Returns result of BluetoothAdapter::IsValid() for private adapter instance.
bool IsAdapterValid() const { return bluetooth_adapter_.IsValid(); }
BluetoothAdapter& GetBluetoothAdapter() { return bluetooth_adapter_; }
private:
bool SetBluetoothState(bool enable);
bool IsInDesiredState(bool should_be_enabled) const;
// To be called in enable() and disable(). This will remember the
// original state of the radio before any radio state has been modified.
// Returns false if Bluetooth doesn't exist on the device and the state cannot
// be obtained.
bool SaveOriginalState();
// BluetoothAdapter::IsValid() will return false if BT is not supported.
BluetoothAdapter bluetooth_adapter_;
// The Bluetooth radio's original state, before we modified it. True if
// originally enabled, false if originally disabled.
// We restore the radio to its original state in the destructor.
AtomicBoolean originally_enabled_{false};
// false if we never modified the radio state, true otherwise.
AtomicBoolean ever_saved_state_{false};
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_BLUETOOTH_RADIO_H_
@@ -0,0 +1,48 @@
// 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_radio.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(BluetoothRadioTest, ConstructorDestructorWorks) {
BluetoothRadio radio;
EXPECT_TRUE(radio.IsAdapterValid());
}
TEST(BluetoothRadioTest, CanEnable) {
BluetoothRadio radio;
EXPECT_TRUE(radio.IsAdapterValid());
EXPECT_TRUE(radio.IsEnabled());
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(radio.IsEnabled());
EXPECT_TRUE(radio.Enable());
EXPECT_TRUE(radio.IsEnabled());
}
TEST(BluetoothRadioTest, CanDisable) {
BluetoothRadio radio;
EXPECT_TRUE(radio.IsAdapterValid());
EXPECT_TRUE(radio.IsEnabled());
EXPECT_TRUE(radio.Disable());
EXPECT_FALSE(radio.IsEnabled());
}
} // namespace
} // namespace fastpair
} // namespace nearby
+56
View File
@@ -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_MEDIUMS_H_
#define THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_MEDIUMS_H_
#include "fastpair/internal/mediums/ble.h"
#include "fastpair/internal/mediums/ble_v2.h"
#include "fastpair/internal/mediums/bluetooth_radio.h"
namespace nearby {
namespace fastpair {
// Facilitates convenient and reliable usage of various wireless mediums.
class Mediums {
public:
Mediums() = default;
~Mediums() = default;
// Returns a handle to the Bluetooth radio.
BluetoothRadio& GetBluetoothRadio() { return bluetooth_radio_; }
// Returns a handle to the Ble medium.
Ble& GetBle() { return ble_; }
// Returns a handle to the Ble medium.
BleV2& GetBleV2() { return ble_v2_; }
private:
// The order of declaration is critical for both construction and
// destruction.
//
// 1) Construction: The individual mediums have a dependency on the
// corresponding radio, so the radio must be initialized first.
//
// 2) Destruction: The individual mediums should be shut down before the
// corresponding radio.
BluetoothRadio bluetooth_radio_;
Ble ble_{bluetooth_radio_};
BleV2 ble_v2_{bluetooth_radio_};
};
} // namespace fastpair
} // namespace nearby
#endif // THIRD_PARTY_NEARBY_FASTPAIR_INTERNAL_MEDIUMS_MEDIUMS_H_
+31
View File
@@ -0,0 +1,31 @@
// 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/mediums.h"
#include "gtest/gtest.h"
namespace nearby {
namespace fastpair {
namespace {
TEST(MediumTest, ConstructorWorks) {
Mediums medium;
EXPECT_TRUE(medium.GetBluetoothRadio().IsAdapterValid());
EXPECT_FALSE(medium.GetBle().IsScanning());
EXPECT_TRUE(medium.GetBleV2().ConnectToGattServer("ble_address"));
}
} // namespace
} // namespace fastpair
} // namespace nearby