[BLE Refactor] Impl Start/Stop Advertising function in medium layer.

PiperOrigin-RevId: 432185275
This commit is contained in:
edwinwu
2022-03-03 07:04:32 -08:00
committed by Copybara-Service
parent 450c536889
commit 91dfdefb9f
15 changed files with 774 additions and 29 deletions
+1
View File
@@ -90,6 +90,7 @@ cc_test(
size = "small",
srcs = [
"ble_test.cc",
"ble_v2_test.cc",
"bluetooth_classic_test.cc",
"bluetooth_radio_test.cc",
"lost_entity_tracker_test.cc",
+202 -4
View File
@@ -17,11 +17,15 @@
#include <string>
#include <string_view>
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "connections/implementation/mediums/ble_v2/ble_advertisement.h"
#include "connections/implementation/mediums/ble_v2/ble_advertisement_header.h"
#include "connections/implementation/mediums/ble_v2/bloom_filter.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "connections/implementation/mediums/utils.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
#include "internal/platform/prng.h"
namespace location {
@@ -30,7 +34,13 @@ namespace connections {
namespace {
using ::location::nearby::api::ble_v2::BleAdvertisementData;
using ::location::nearby::api::ble_v2::PowerMode;
constexpr int kMaxAdvertisementLength = 512;
constexpr int kDummyServiceIdLength = 128;
constexpr absl::string_view kCopresenceServiceUuid =
"0000FEF3-0000-1000-8000-00805F9B34FB";
ByteArray GenerateAdvertisementHash(const ByteArray& advertisement_bytes) {
return Utils::Sha256Hash(
@@ -38,11 +48,201 @@ ByteArray GenerateAdvertisementHash(const ByteArray& advertisement_bytes) {
mediums::BleAdvertisementHeader::kAdvertisementHashLength);
}
ByteArray GenerateHash(const std::string& source, size_t size) {
return Utils::Sha256Hash(source, size);
}
ByteArray GenerateDeviceToken() {
return Utils::Sha256Hash(std::to_string(Prng().NextUint32()),
mediums::BleAdvertisement::kDeviceTokenLength);
}
} // namespace
BleV2::BleV2(BluetoothRadio& radio)
: radio_(radio), adapter_(radio_.GetBluetoothAdapter()) {}
bool BleV2::IsAvailable() const {
MutexLock lock(&mutex_);
return IsAvailableLocked();
}
// TODO(edwinwu): Break down the function.
bool BleV2::StartAdvertising(
const std::string& service_id, const ByteArray& advertisement_bytes,
PowerLevel power_level,
const std::string& fast_advertisement_service_uuid) {
MutexLock lock(&mutex_);
if (advertisement_bytes.Empty()) {
NEARBY_LOGS(INFO)
<< "Refusing to turn on BLE advertising. Empty advertisement data.";
return false;
}
if (advertisement_bytes.size() > kMaxAdvertisementLength) {
NEARBY_LOG(INFO,
"Refusing to start BLE advertising because the advertisement "
"was too long. Expected at most %d bytes but received %d.",
kMaxAdvertisementLength, advertisement_bytes.size());
return false;
}
if (IsAdvertisingLocked(service_id)) {
NEARBY_LOGS(INFO)
<< "Failed to BLE advertise because we're already advertising.";
return false;
}
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO)
<< "Can't start BLE scanning because Bluetooth was never turned on";
return false;
}
if (!IsAvailableLocked()) {
NEARBY_LOGS(INFO) << "Can't turn on BLE advertising. BLE is not available.";
return false;
}
// Wrap the connections advertisement to the medium advertisement.
const bool is_fast_advertisement = !fast_advertisement_service_uuid.empty();
ByteArray service_id_hash{GenerateHash(
service_id, mediums::BleAdvertisement::kServiceIdHashLength)};
ByteArray medium_advertisement_bytes{mediums::BleAdvertisement{
mediums::BleAdvertisement::Version::kV2,
mediums::BleAdvertisement::SocketVersion::kV2,
/* service_id_hash= */
is_fast_advertisement ? ByteArray{} : service_id_hash,
advertisement_bytes, GenerateDeviceToken()}};
if (medium_advertisement_bytes.Empty()) {
NEARBY_LOGS(INFO) << "Failed to BLE advertise because we could not wrap a "
"connection advertisement to medium advertisement.";
return false;
}
// Stop any existing advertisement GATT servers. We don't stop it in
// StopAdvertising() to avoid GATT issues with BLE sockets.
if (IsAdvertisementGattServerRunning()) {
StopAdvertisementGattServer();
}
// Assemble AdvertisingData and ScanResponseData.
BleAdvertisementData advertising_data;
BleAdvertisementData scan_response_data;
if (is_fast_advertisement) {
advertising_data.service_data.insert(
{fast_advertisement_service_uuid, medium_advertisement_bytes});
scan_response_data.service_uuids.insert(fast_advertisement_service_uuid);
} else {
// Start a GATT server to deliver the full advertisement data. If fail to
// advertise the header, we must shut this down before the method returns.
if (!StartAdvertisementGattServer(service_id, medium_advertisement_bytes)) {
NEARBY_LOGS(INFO) << "Failed to BLE advertise because the "
"advertisement GATT server failed to start.";
return false;
}
ByteArray advertisement_header_bytes(CreateAdvertisementHeader());
if (advertisement_header_bytes.Empty()) {
NEARBY_LOGS(INFO) << "Failed to BLE advertise because we could not "
"create an advertisement header.";
// Failed to start BLE advertising, so stop the advertisement GATT
// server.
StopAdvertisementGattServer();
return false;
}
advertising_data.is_connectable = true;
advertising_data.tx_power_level =
BleAdvertisementData::kUnspecifiedTxPowerLevel;
scan_response_data.is_connectable = true;
scan_response_data.tx_power_level =
BleAdvertisementData::kUnspecifiedTxPowerLevel;
scan_response_data.service_uuids.insert(
std::string(kCopresenceServiceUuid));
scan_response_data.service_data.insert(
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
}
// Convert power_mode from power_level.
PowerMode power_mode = PowerMode::kUnknown;
switch (power_level) {
case PowerLevel::kHighPower:
power_mode = PowerMode::kHigh;
break;
case PowerLevel::kLowPower:
// Medium power is about the size of a conference room. Any lower power
// it won't be visible at a distance.
power_mode = PowerMode::kMedium;
break;
default:
power_mode = PowerMode::kUnknown;
}
if (!medium_.StartAdvertising(advertising_data, scan_response_data,
power_mode)) {
NEARBY_LOGS(ERROR)
<< "Failed to turn on BLE advertising with advertisement bytes="
<< absl::BytesToHexString(advertisement_bytes.data())
<< ", size=" << advertisement_bytes.size()
<< ", fast advertisement service uuid="
<< fast_advertisement_service_uuid;
// If BLE advertising was not successful, stop the advertisement GATT
// server.
StopAdvertisementGattServer();
return false;
}
NEARBY_LOGS(INFO) << "Started BLE advertising with advertisement bytes="
<< absl::BytesToHexString(advertisement_bytes.data())
<< " for service_id=" << service_id;
advertising_info_.Add(service_id);
return true;
}
bool BleV2::StopAdvertising(const std::string& service_id) {
MutexLock lock(&mutex_);
if (!IsAdvertisingLocked(service_id)) {
NEARBY_LOGS(INFO) << "Can't turn off BLE advertising; it is already off";
return false;
}
NEARBY_LOGS(INFO) << "Turned off BLE advertising with service id="
<< service_id;
bool can_stop = medium_.StopAdvertising();
// Reset our bundle of advertising state to mark that we're no longer
// advertising.
advertising_info_.Remove(service_id);
return can_stop;
}
bool BleV2::IsAdvertising(const std::string& service_id) const {
MutexLock lock(&mutex_);
return IsAdvertisingLocked(service_id);
}
bool BleV2::IsAvailableLocked() const { return medium_.IsValid(); }
bool BleV2::IsAdvertisingLocked(const std::string& service_id) const {
return advertising_info_.Existed(service_id);
}
// TODO(b/213835576): Implement GattServer
bool BleV2::IsAdvertisementGattServerRunning() { return false; }
bool BleV2::StartAdvertisementGattServer(const std::string& service_id,
const ByteArray& advertisement) {
return false;
}
bool BleV2::StopAdvertisementGattServer() { return false; }
ByteArray BleV2::CreateAdvertisementHeader() {
// Create a randomized dummy service id to anonymize the header with.
ByteArray dummy_service_id_bytes =
@@ -63,10 +263,8 @@ ByteArray BleV2::CreateAdvertisementHeader() {
// Compute the next hash according to the algorithm in
// https://source.corp.google.com/piper///depot/google3/java/com/google/android/gmscore/integ/modules/nearby/src/com/google/android/gms/nearby/mediums/bluetooth/BluetoothLowEnergy.java;rcl=428397891;l=1043
ByteArray previous_advertisement_hash = advertisement_hash;
std::string advertisement_bodies =
absl::StrCat(previous_advertisement_hash.AsStringView(),
gatt_advertisement.AsStringView());
std::string advertisement_bodies = absl::StrCat(
advertisement_hash.AsStringView(), gatt_advertisement.AsStringView());
advertisement_hash =
GenerateAdvertisementHash(ByteArray(std::move(advertisement_bodies)));
+59 -4
View File
@@ -20,27 +20,82 @@
#include <utility>
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "connections/advertising_options.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/mutex.h"
#include "internal/platform/mutex_lock.h"
namespace location {
namespace nearby {
namespace connections {
// TODO(b/213691253): Add BleV2 medium tests after more functions are ready.
// Provides the operations that can be performed on the Bluetooth Low Energy
// (BLE) medium.
class BleV2 {
// Provides the operations that can be performed on the Bluetooth Low Energy
// (BLE) medium.
class BleV2 final {
public:
explicit BleV2(BluetoothRadio& bluetooth_radio);
// Returns true, if BLE communications are supported by a platform.
bool IsAvailable() const ABSL_LOCKS_EXCLUDED(mutex_);
// Starts BLE advertising, delivering additional information if the platform
// supports it.
bool StartAdvertising(const std::string& service_id,
const ByteArray& advertisement_bytes,
PowerLevel power_level,
const std::string& fast_advertisement_service_uuid)
ABSL_LOCKS_EXCLUDED(mutex_);
// Disables BLE advertising.
bool StopAdvertising(const std::string& service_id)
ABSL_LOCKS_EXCLUDED(mutex_);
bool IsAdvertising(const std::string& service_id) 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();
}
private:
struct AdvertisingInfo {
bool Empty() const { return service_ids.empty(); }
void Clear() { service_ids.clear(); }
void Add(const std::string& service_id) { service_ids.insert(service_id); }
void Remove(const std::string& service_id) {
service_ids.erase(service_id);
}
bool Existed(const std::string& service_id) const {
return service_ids.contains(service_id);
}
absl::flat_hash_set<std::string> service_ids;
};
// Same as IsAvailable(), but must be called with `mutex_` held.
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Same as IsAdvertising(), but must be called with `mutex_` held.
bool IsAdvertisingLocked(const std::string& service_id) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool IsAdvertisementGattServerRunning();
bool StartAdvertisementGattServer(const std::string& service_id,
const ByteArray& advertisement);
bool StopAdvertisementGattServer();
ByteArray CreateAdvertisementHeader() ABSL_SHARED_LOCKS_REQUIRED(mutex_);
mutable Mutex mutex_;
BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_);
BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_);
BleV2Medium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_map<int, std::pair<std::string, ByteArray>>
gatt_advertisements_ ABSL_GUARDED_BY(mutex_);
};
@@ -0,0 +1,78 @@
// Copyright 2022 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 "connections/implementation/mediums/ble_v2.h"
#include <string>
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "internal/platform/ble.h"
#include "internal/platform/count_down_latch.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
namespace location {
namespace nearby {
namespace connections {
namespace {
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kAdvertisementString{"\x0a\x0b\x0c\x0d"};
constexpr absl::string_view kFastAdvertisementServiceUuid{"\xf3\xfe"};
class BleV2Test : public testing::Test {
protected:
BleV2Test() { env_.Stop(); }
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
TEST_F(BleV2Test, CanConstructValidObject) {
env_.Start();
BluetoothRadio radio_a;
BluetoothRadio radio_b;
BleV2 ble_a{radio_a};
BleV2 ble_b{radio_b};
EXPECT_TRUE(ble_a.IsMediumValid());
EXPECT_TRUE(ble_a.IsAvailable());
EXPECT_TRUE(ble_b.IsMediumValid());
EXPECT_TRUE(ble_b.IsAvailable());
EXPECT_NE(&radio_a.GetBluetoothAdapter(), &radio_b.GetBluetoothAdapter());
env_.Stop();
}
TEST_F(BleV2Test, CanStartAdvertising) {
env_.Start();
BluetoothRadio radio;
BleV2 ble{radio};
radio.Enable();
std::string service_id(kServiceID);
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid);
PowerLevel power_level = PowerLevel::kHighPower;
EXPECT_TRUE(ble.StartAdvertising(service_id, advertisement_bytes, power_level,
fast_advertisement_service_uuid));
EXPECT_TRUE(ble.StopAdvertising(service_id));
env_.Stop();
}
} // namespace
} // namespace connections
} // namespace nearby
} // namespace location
+3
View File
@@ -304,12 +304,14 @@ cc_library(
name = "comm",
srcs = [
"ble.cc",
"ble_v2.cc",
"bluetooth_classic.cc",
"file.cc",
"wifi_lan.cc",
],
hdrs = [
"ble.h",
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
"wifi_lan.h",
@@ -342,6 +344,7 @@ cc_test(
"atomic_boolean_test.cc",
"atomic_reference_test.cc",
"ble_test.cc",
"ble_v2_test.cc",
"bluetooth_adapter_test.cc",
"bluetooth_classic_test.cc",
"cancelable_alarm_test.cc",
+36
View File
@@ -0,0 +1,36 @@
// Copyright 2022 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 "internal/platform/ble_v2.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
namespace location {
namespace nearby {
using ::location::nearby::api::ble_v2::BleAdvertisementData;
using ::location::nearby::api::ble_v2::PowerMode;
bool BleV2Medium::StartAdvertising(
const BleAdvertisementData& advertising_data,
const BleAdvertisementData& scan_response_data, PowerMode power_mode) {
return impl_->StartAdvertising(advertising_data, scan_response_data,
power_mode);
}
bool BleV2Medium::StopAdvertising() { return impl_->StopAdvertising(); }
} // namespace nearby
} // namespace location
+59
View File
@@ -0,0 +1,59 @@
// Copyright 2022 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 PLATFORM_PUBLIC_BLE_V2_H_
#define PLATFORM_PUBLIC_BLE_V2_H_
#include "absl/container/flat_hash_map.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/cancellation_flag.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/platform.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/mutex.h"
#include "internal/platform/output_stream.h"
namespace location {
namespace nearby {
// Container of operations that can be performed over the BLE medium.
class BleV2Medium final {
public:
explicit BleV2Medium(BluetoothAdapter& adapter)
: impl_(
api::ImplementationPlatform::CreateBleV2Medium(adapter.GetImpl())),
adapter_(adapter) {}
// Returns true once the BLE advertising has been initiated.
bool StartAdvertising(
const api::ble_v2::BleAdvertisementData& advertising_data,
const api::ble_v2::BleAdvertisementData& scan_response_data,
api::ble_v2::PowerMode power_mode);
bool StopAdvertising();
bool IsValid() const { return impl_ != nullptr; }
api::ble_v2::BleMedium& GetImpl() const { return *impl_; }
private:
Mutex mutex_;
std::unique_ptr<api::ble_v2::BleMedium> impl_;
BluetoothAdapter& adapter_;
};
} // namespace nearby
} // namespace location
#endif // PLATFORM_PUBLIC_BLE_V2_H_
+76
View File
@@ -0,0 +1,76 @@
// Copyright 2020 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 "internal/platform/ble_v2.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "internal/platform/medium_environment.h"
namespace location {
namespace nearby {
namespace {
using ::location::nearby::api::ble_v2::BleAdvertisementData;
using ::location::nearby::api::ble_v2::PowerMode;
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kAdvertisementString{"\x0a\x0b\x0c\x0d"};
constexpr absl::string_view kFastAdvertisementServiceUuid{"\xf3\xfe"};
constexpr PowerMode kPowerMode(PowerMode::kHigh);
class BleV2MediumTest : public testing::Test {
protected:
BleV2MediumTest() { env_.Stop(); }
MediumEnvironment& env_{MediumEnvironment::Instance()};
};
TEST_F(BleV2MediumTest, ConstructorDestructorWorks) {
env_.Start();
BluetoothAdapter adapter_a_;
BluetoothAdapter adapter_b_;
BleV2Medium ble_a{adapter_a_};
BleV2Medium ble_b{adapter_b_};
// Make sure we can create functional mediums.
ASSERT_TRUE(ble_a.IsValid());
ASSERT_TRUE(ble_b.IsValid());
// Make sure we can create 2 distinct mediums.
EXPECT_NE(&ble_a.GetImpl(), &ble_b.GetImpl());
env_.Stop();
}
TEST_F(BleV2MediumTest, CanStartAdvertising) {
env_.Start();
BluetoothAdapter adapter_;
BleV2Medium ble{adapter_};
std::string service_id(kServiceID);
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
std::string fast_advertisement_service_uuid(kFastAdvertisementServiceUuid);
BleAdvertisementData advertising_data;
BleAdvertisementData scan_response_data;
ble.StartAdvertising(advertising_data, scan_response_data, kPowerMode);
EXPECT_TRUE(ble.StopAdvertising());
env_.Stop();
}
} // namespace
} // namespace nearby
} // namespace location
@@ -52,12 +52,14 @@ cc_library(
testonly = True,
srcs = [
"ble.cc",
"ble_v2.cc",
"bluetooth_adapter.cc",
"bluetooth_classic.cc",
"wifi_lan.cc",
],
hdrs = [
"ble.h",
"ble_v2.h",
"bluetooth_adapter.h",
"bluetooth_classic.h",
"wifi_lan.h",
@@ -0,0 +1,93 @@
// Copyright 2022 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 "internal/platform/implementation/g3/ble_v2.h"
#include <iostream>
#include <memory>
#include <string>
#include "absl/synchronization/mutex.h"
#include "internal/platform/implementation/shared/count_down_latch.h"
#include "internal/platform/logging.h"
#include "internal/platform/medium_environment.h"
namespace location {
namespace nearby {
namespace g3 {
using ::location::nearby::api::ble_v2::BleAdvertisementData;
using ::location::nearby::api::ble_v2::BleSocket;
using ::location::nearby::api::ble_v2::BleSocketLifeCycleCallback;
using ::location::nearby::api::ble_v2::ClientGattConnection;
using ::location::nearby::api::ble_v2::PowerMode;
using ::location::nearby::api::ble_v2::ServerGattConnectionCallback;
BleV2Medium::BleV2Medium(api::BluetoothAdapter& adapter)
: adapter_(static_cast<BluetoothAdapter*>(&adapter)) {
auto& env = MediumEnvironment::Instance();
env.RegisterBleV2Medium(*this);
}
BleV2Medium::~BleV2Medium() {
auto& env = MediumEnvironment::Instance();
env.UnregisterBleV2Medium(*this);
}
bool BleV2Medium::StartAdvertising(
const BleAdvertisementData& advertising_data,
const BleAdvertisementData& scan_response_data, PowerMode power_mode) {
return true;
}
bool BleV2Medium::StopAdvertising() {
NEARBY_LOGS(INFO) << "G3 Ble StopAdvertising";
return true;
}
bool BleV2Medium::StartScanning(const std::vector<std::string>& service_uuids,
PowerMode power_mode,
ScanCallback scan_callback) {
return false;
}
bool BleV2Medium::StopScanning() { return false; }
std::unique_ptr<api::ble_v2::GattServer> BleV2Medium::StartGattServer(
ServerGattConnectionCallback callback) {
return nullptr;
}
bool BleV2Medium::StartListeningForIncomingBleSockets(
const api::ble_v2::ServerBleSocketLifeCycleCallback& callback) {
return false;
}
void BleV2Medium::StopListeningForIncomingBleSockets() {}
std::unique_ptr<ClientGattConnection> BleV2Medium::ConnectToGattServer(
api::ble_v2::BlePeripheral& peripheral, Mtu mtu, PowerMode power_mode,
api::ble_v2::ClientGattConnectionCallback callback) {
return nullptr;
}
std::unique_ptr<BleSocket> BleV2Medium::EstablishBleSocket(
api::ble_v2::BlePeripheral* peripheral,
const BleSocketLifeCycleCallback& callback) {
return nullptr;
}
} // namespace g3
} // namespace nearby
} // namespace location
@@ -0,0 +1,94 @@
// Copyright 2022 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 PLATFORM_IMPL_G3_BLE_V2_H_
#define PLATFORM_IMPL_G3_BLE_V2_H_
#include <memory>
#include <string>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/escaping.h"
#include "absl/synchronization/mutex.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
#include "internal/platform/implementation/g3/bluetooth_classic.h"
#include "internal/platform/implementation/g3/multi_thread_executor.h"
#include "internal/platform/implementation/g3/pipe.h"
#include "internal/platform/input_stream.h"
#include "internal/platform/output_stream.h"
namespace location {
namespace nearby {
namespace g3 {
// TODO(b/213691253): Add g3 BleV2 medium tests after more functions are ready.
// Container of operations that can be performed over the BLE medium.
class BleV2Medium : public api::ble_v2::BleMedium {
public:
explicit BleV2Medium(api::BluetoothAdapter& adapter);
~BleV2Medium() override;
// Returns true once the Ble advertising has been initiated.
bool StartAdvertising(
const api::ble_v2::BleAdvertisementData& advertising_data,
const api::ble_v2::BleAdvertisementData& scan_response_data,
api::ble_v2::PowerMode power_mode) override ABSL_LOCKS_EXCLUDED(mutex_);
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(mutex_);
bool StartScanning(const std::vector<std::string>& service_uuids,
api::ble_v2::PowerMode power_mode,
ScanCallback callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
bool StopScanning() override ABSL_LOCKS_EXCLUDED(mutex_);
std::unique_ptr<api::ble_v2::GattServer> StartGattServer(
api::ble_v2::ServerGattConnectionCallback callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
bool StartListeningForIncomingBleSockets(
const api::ble_v2::ServerBleSocketLifeCycleCallback& callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
void StopListeningForIncomingBleSockets() override
ABSL_LOCKS_EXCLUDED(mutex_);
std::unique_ptr<api::ble_v2::ClientGattConnection> ConnectToGattServer(
api::ble_v2::BlePeripheral& peripheral, Mtu mtu,
api::ble_v2::PowerMode power_mode,
api::ble_v2::ClientGattConnectionCallback callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
std::unique_ptr<api::ble_v2::BleSocket> EstablishBleSocket(
api::ble_v2::BlePeripheral* peripheral,
const api::ble_v2::BleSocketLifeCycleCallback& callback) override
ABSL_LOCKS_EXCLUDED(mutex_);
BluetoothAdapter& GetAdapter() { return *adapter_; }
private:
struct AdvertisingInfo {
bool Empty() const { return service_id.empty(); }
void Clear() { service_id.clear(); }
std::string service_id;
};
absl::Mutex mutex_;
BluetoothAdapter* adapter_; // Our device adapter; read-only.
AdvertisingInfo advertising_info_ ABSL_GUARDED_BY(mutex_);
};
} // namespace g3
} // namespace nearby
} // namespace location
#endif // PLATFORM_IMPL_G3_BLE_V2_H_
+19 -19
View File
@@ -23,15 +23,14 @@
#include "absl/time/time.h"
#include "internal/platform/implementation/atomic_boolean.h"
#include "internal/platform/implementation/atomic_reference.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#include "internal/platform/implementation/condition_variable.h"
#include "internal/platform/implementation/shared/count_down_latch.h"
#include "internal/platform/implementation/log_message.h"
#include "internal/platform/implementation/mutex.h"
#include "internal/platform/implementation/scheduled_executor.h"
#include "internal/platform/implementation/server_sync.h"
#include "internal/platform/implementation/shared/count_down_latch.h"
#include "internal/platform/implementation/submittable_executor.h"
#ifndef NO_WEBRTC
#include "internal/platform/implementation/g3/webrtc.h"
@@ -40,6 +39,7 @@
#include "internal/platform/implementation/g3/atomic_boolean.h"
#include "internal/platform/implementation/g3/atomic_reference.h"
#include "internal/platform/implementation/g3/ble.h"
#include "internal/platform/implementation/g3/ble_v2.h"
#include "internal/platform/implementation/g3/bluetooth_adapter.h"
#include "internal/platform/implementation/g3/bluetooth_classic.h"
#include "internal/platform/implementation/g3/condition_variable.h"
@@ -70,37 +70,37 @@ int GetCurrentTid() {
std::unique_ptr<SubmittableExecutor>
ImplementationPlatform::CreateSingleThreadExecutor() {
return absl::make_unique<g3::SingleThreadExecutor>();
return std::make_unique<g3::SingleThreadExecutor>();
}
std::unique_ptr<SubmittableExecutor>
ImplementationPlatform::CreateMultiThreadExecutor(int max_concurrency) {
return absl::make_unique<g3::MultiThreadExecutor>(max_concurrency);
return std::make_unique<g3::MultiThreadExecutor>(max_concurrency);
}
std::unique_ptr<ScheduledExecutor>
ImplementationPlatform::CreateScheduledExecutor() {
return absl::make_unique<g3::ScheduledExecutor>();
return std::make_unique<g3::ScheduledExecutor>();
}
std::unique_ptr<AtomicUint32> ImplementationPlatform::CreateAtomicUint32(
std::uint32_t value) {
return absl::make_unique<g3::AtomicUint32>(value);
return std::make_unique<g3::AtomicUint32>(value);
}
std::unique_ptr<BluetoothAdapter>
ImplementationPlatform::CreateBluetoothAdapter() {
return absl::make_unique<g3::BluetoothAdapter>();
return std::make_unique<g3::BluetoothAdapter>();
}
std::unique_ptr<CountDownLatch> ImplementationPlatform::CreateCountDownLatch(
std::int32_t count) {
return absl::make_unique<shared::CountDownLatch>(count);
return std::make_unique<shared::CountDownLatch>(count);
}
std::unique_ptr<AtomicBoolean> ImplementationPlatform::CreateAtomicBoolean(
bool initial_value) {
return absl::make_unique<g3::AtomicBoolean>(initial_value);
return std::make_unique<g3::AtomicBoolean>(initial_value);
}
std::unique_ptr<InputFile> ImplementationPlatform::CreateInputFile(
@@ -116,23 +116,23 @@ std::unique_ptr<OutputFile> ImplementationPlatform::CreateOutputFile(
std::unique_ptr<LogMessage> ImplementationPlatform::CreateLogMessage(
const char* file, int line, LogMessage::Severity severity) {
return absl::make_unique<g3::LogMessage>(file, line, severity);
return std::make_unique<g3::LogMessage>(file, line, severity);
}
std::unique_ptr<BluetoothClassicMedium>
ImplementationPlatform::CreateBluetoothClassicMedium(
api::BluetoothAdapter& adapter) {
return absl::make_unique<g3::BluetoothClassicMedium>(adapter);
return std::make_unique<g3::BluetoothClassicMedium>(adapter);
}
std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(
api::BluetoothAdapter& adapter) {
return absl::make_unique<g3::BleMedium>(adapter);
return std::make_unique<g3::BleMedium>(adapter);
}
std::unique_ptr<ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium(
api::BluetoothAdapter& adapter) {
return std::unique_ptr<ble_v2::BleMedium>();
std::unique_ptr<api::ble_v2::BleMedium>
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) {
return std::make_unique<g3::BleV2Medium>(adapter);
}
std::unique_ptr<ServerSyncMedium>
@@ -145,13 +145,13 @@ std::unique_ptr<WifiMedium> ImplementationPlatform::CreateWifiMedium() {
}
std::unique_ptr<WifiLanMedium> ImplementationPlatform::CreateWifiLanMedium() {
return absl::make_unique<g3::WifiLanMedium>();
return std::make_unique<g3::WifiLanMedium>();
}
#ifndef NO_WEBRTC
std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
if (MediumEnvironment::Instance().GetEnvironmentConfig().webrtc_enabled) {
return absl::make_unique<g3::WebRtcMedium>();
return std::make_unique<g3::WebRtcMedium>();
} else {
return nullptr;
}
@@ -160,9 +160,9 @@ std::unique_ptr<WebRtcMedium> ImplementationPlatform::CreateWebRtcMedium() {
std::unique_ptr<Mutex> ImplementationPlatform::CreateMutex(Mutex::Mode mode) {
if (mode == Mutex::Mode::kRecursive)
return absl::make_unique<g3::RecursiveMutex>();
return std::make_unique<g3::RecursiveMutex>();
else
return absl::make_unique<g3::Mutex>(mode == Mutex::Mode::kRegular);
return std::make_unique<g3::Mutex>(mode == Mutex::Mode::kRegular);
}
std::unique_ptr<ConditionVariable>
@@ -129,8 +129,8 @@ std::unique_ptr<BleMedium> ImplementationPlatform::CreateBleMedium(api::Bluetoot
return nullptr;
}
std::unique_ptr<ble_v2::BleMedium> ImplementationPlatform::CreateBleV2Medium(
api::BluetoothAdapter& adapter) {
std::unique_ptr<ble_v2::BleMedium>
ImplementationPlatform::CreateBleV2Medium(api::BluetoothAdapter& adapter) {
return nullptr;
}
+26
View File
@@ -59,6 +59,7 @@ void MediumEnvironment::Reset() {
bluetooth_adapters_.clear();
bluetooth_mediums_.clear();
ble_mediums_.clear();
ble_v2_mediums_.clear();
#ifndef NO_WEBRTC
webrtc_signaling_message_callback_.clear();
webrtc_signaling_complete_callback_.clear();
@@ -477,6 +478,31 @@ void MediumEnvironment::CallBleAcceptedConnectionCallback(
info.accepted_connection_callback.accepted_cb(socket, service_id);
});
}
void MediumEnvironment::RegisterBleV2Medium(api::ble_v2::BleMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
ble_v2_mediums_.insert({&medium, BleV2MediumContext{}});
NEARBY_LOGS(INFO) << "Registered: medium:" << &medium;
});
}
// TODO(b/213691253): Add g3 BleV2 medium tests after more functions are ready.
void MediumEnvironment::UpdateBleV2MediumForAdvertising(
api::ble_v2::BleMedium& medium, api::ble_v2::BlePeripheral& peripheral,
const std::string& service_id, bool fast_advertisement, bool enabled) {
if (!enabled_) return;
}
void MediumEnvironment::UnregisterBleV2Medium(api::ble_v2::BleMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium]() {
auto item = ble_v2_mediums_.extract(&medium);
if (item.empty()) return;
NEARBY_LOGS(INFO) << "Unregistered Ble medium";
});
}
#ifndef NO_WEBRTC
void MediumEnvironment::RegisterWebRtcSignalingMessenger(
absl::string_view self_id, OnSignalingMessageCallback message_callback,
+24
View File
@@ -21,6 +21,7 @@
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "internal/platform/implementation/ble.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/implementation/bluetooth_adapter.h"
#include "internal/platform/implementation/bluetooth_classic.h"
#ifndef NO_WEBRTC
@@ -204,6 +205,21 @@ class MediumEnvironment {
api::BleSocket& socket,
const std::string& service_id);
// Adds medium-related info to allow for scanning/advertising to work.
// This provides acccess to this medium from other mediums, when protocol
// expects they should communicate.
void RegisterBleV2Medium(api::ble_v2::BleMedium& medium);
// Updates advertising info to indicate the current medium is exposing
// advertising event.
void UpdateBleV2MediumForAdvertising(api::ble_v2::BleMedium& medium,
api::ble_v2::BlePeripheral& peripheral,
const std::string& service_id,
bool fast_advertisement, bool enabled);
// Removes medium-related info. This should correspond to device power off.
void UnregisterBleV2Medium(api::ble_v2::BleMedium& mediumum);
// Adds medium-related info to allow for discovery/advertising to work.
// This provides acccess to this medium from other mediums, when protocol
// expects they should communicate.
@@ -255,6 +271,9 @@ class MediumEnvironment {
bool fast_advertisement = false;
};
struct BleV2MediumContext {
};
struct WifiLanMediumContext {
// advertising service type vs NsdServiceInfo map.
absl::flat_hash_map<std::string, NsdServiceInfo> advertising_services;
@@ -303,6 +322,10 @@ class MediumEnvironment {
bluetooth_mediums_;
absl::flat_hash_map<api::BleMedium*, BleMediumContext> ble_mediums_;
absl::flat_hash_map<api::ble_v2::BleMedium*, BleV2MediumContext>
ble_v2_mediums_;
#ifndef NO_WEBRTC
// Maps peer id to callback for receiving signaling messages.
absl::flat_hash_map<std::string, OnSignalingMessageCallback>
@@ -312,6 +335,7 @@ class MediumEnvironment {
absl::flat_hash_map<std::string, OnSignalingCompleteCallback>
webrtc_signaling_complete_callback_;
#endif
absl::flat_hash_map<api::WifiLanMedium*, WifiLanMediumContext>
wifi_lan_mediums_;