[BLE Refactor] Impl Start/Stop Scanning and DiscoveredPeripheral callback function in medium layer and ScanCallback in platform layer.

PiperOrigin-RevId: 438293171
This commit is contained in:
edwinwu
2022-03-30 07:08:05 -07:00
committed by Copybara-Service
parent d65e41cc4a
commit 190d3ebafc
15 changed files with 520 additions and 132 deletions
+1
View File
@@ -102,6 +102,7 @@ cc_test(
deps = [
":mediums",
":utils",
"//connections/implementation/mediums/ble_v2",
"//internal/platform:base",
"//internal/platform:comm",
"//internal/platform:test_util",
+114 -19
View File
@@ -207,23 +207,8 @@ bool BleV2::StartAdvertising(
{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)) {
PowerLevelToPowerMode(power_level))) {
NEARBY_LOGS(ERROR)
<< "Failed to turn on BLE advertising with advertisement bytes="
<< absl::BytesToHexString(advertisement_bytes.data())
@@ -239,7 +224,7 @@ bool BleV2::StartAdvertising(
NEARBY_LOGS(INFO) << "Started BLE advertising with advertisement bytes="
<< absl::BytesToHexString(advertisement_bytes.data())
<< " for service_id=" << service_id;
advertising_info_.Add(service_id);
advertising_service_ids_.insert(service_id);
return true;
}
@@ -281,7 +266,7 @@ bool BleV2::StopAdvertising(const std::string& service_id) {
NEARBY_LOGS(INFO) << "Turned off BLE advertising with service_id="
<< service_id;
advertising_info_.Remove(service_id);
advertising_service_ids_.erase(service_id);
return medium_.StopAdvertising();
}
@@ -291,10 +276,107 @@ bool BleV2::IsAdvertising(const std::string& service_id) const {
return IsAdvertisingLocked(service_id);
}
bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level,
DiscoveredPeripheralCallback callback,
const std::string& fast_advertisement_service_uuid) {
MutexLock lock(&mutex_);
if (service_id.empty()) {
NEARBY_LOGS(INFO) << "Can not start BLE scanning with empty service id.";
return false;
}
if (IsScanningLocked(service_id)) {
NEARBY_LOGS(INFO) << "Cannot start scan of BLE peripherals because "
"scanning is already in-progress.";
return false;
}
if (!radio_.IsEnabled()) {
NEARBY_LOGS(INFO)
<< "Can't start BLE scanning because Bluetooth is disabled";
return false;
}
if (!IsAvailableLocked()) {
NEARBY_LOGS(INFO)
<< "Can't scan BLE peripherals because BLE isn't available.";
return false;
}
// TODO(edwinwu): Start discovered peripheral tracking.
// Check if scan has been activated, if yes, no need to notify client
// to scan again.
if (!scanned_service_ids_.empty()) {
scanned_service_ids_.insert(service_id);
NEARBY_LOGS(INFO) << "Turned on BLE scanning with service id=" << service_id
<< " without start client scanning";
return true;
}
scanned_service_ids_.insert(service_id);
// TODO(b/213835576): We should re-start scanning once the power level is
// changed.
std::vector<std::string> service_uuids{std::string(kCopresenceServiceUuid)};
if (!medium_.StartScanning(
service_uuids, PowerLevelToPowerMode(power_level),
{
.advertisement_found_cb =
[](BleV2Peripheral peripheral,
const BleAdvertisementData& advertisement_data) {
// TODO(b/213835576): Move (or Copy at fallback) the
// BleV2Peripheral.
// TODO(b/216629800): Track the found advertisement.
},
})) {
NEARBY_LOGS(INFO) << "Failed to start client scan of BLE services.";
// Erase the service id that is just added.
scanned_service_ids_.erase(service_id);
return false;
}
NEARBY_LOGS(INFO) << "Turned on BLE scanning with service id=" << service_id;
return true;
}
bool BleV2::StopScanning(const std::string& service_id) {
MutexLock lock(&mutex_);
if (!IsScanningLocked(service_id)) {
NEARBY_LOGS(INFO) << "Can't turn off BLE scanning because we never "
"started scanning.";
return false;
}
// TODO(b/213835576): Cancel lost alarm and Stop tracking.
scanned_service_ids_.erase(service_id);
NEARBY_LOGS(INFO) << "Turned off BLE scanning with service id=" << service_id;
// If still has scanner, don't stop the client scanning.
if (!scanned_service_ids_.empty()) {
return true;
}
NEARBY_LOGS(INFO) << "Turned off BLE client scanning";
return medium_.StopScanning();
}
bool BleV2::IsScanning(const std::string& service_id) const {
MutexLock lock(&mutex_);
return IsScanningLocked(service_id);
}
bool BleV2::IsAvailableLocked() const { return medium_.IsValid(); }
bool BleV2::IsAdvertisingLocked(const std::string& service_id) const {
return advertising_info_.Existed(service_id);
return advertising_service_ids_.contains(service_id);
}
bool BleV2::IsScanningLocked(const std::string& service_id) const {
return scanned_service_ids_.contains(service_id);
}
bool BleV2::IsAdvertisementGattServerRunningLocked() {
@@ -422,6 +504,19 @@ std::string BleV2::GenerateAdvertisementUuid(int slot) {
return std::string(Uuid(kAdvertisementUuidMsb, kAdvertisementUuidLsb | slot));
}
PowerMode BleV2::PowerLevelToPowerMode(PowerLevel power_level) {
switch (power_level) {
case PowerLevel::kHighPower:
return PowerMode::kHigh;
case PowerLevel::kLowPower:
// Medium power is about the size of a conference room.
// Any lower and we won't be visible at a distance.
return PowerMode::kMedium;
default:
return PowerMode::kUnknown;
}
}
} // namespace connections
} // namespace nearby
} // namespace location
+30 -15
View File
@@ -24,6 +24,7 @@
#include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h"
#include "connections/advertising_options.h"
#include "connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "internal/platform/ble_v2.h"
#include "internal/platform/byte_array.h"
@@ -38,6 +39,10 @@ namespace connections {
// (BLE) medium.
class BleV2 final {
public:
using ServerGattConnectionCallback =
BleV2Medium::ServerGattConnectionCallback;
using DiscoveredPeripheralCallback = mediums::DiscoveredPeripheralCallback;
explicit BleV2(BluetoothRadio& bluetooth_radio);
// Returns true, if BLE communications are supported by a platform.
@@ -58,6 +63,22 @@ class BleV2 final {
bool IsAdvertising(const std::string& service_id) const
ABSL_LOCKS_EXCLUDED(mutex_);
// Enables BLE scanning for a service id. Will report any discoverable
// advertisement data through a callback.
// Returns true, if the scanning is successfully enabled, false otherwise.
bool StartScanning(const std::string& service_id, PowerLevel power_level,
DiscoveredPeripheralCallback callback,
const std::string& fast_advertisement_service_uuid)
ABSL_LOCKS_EXCLUDED(mutex_);
// Disables BLE scanning for a service id.
// Returns true, if the scanning was previously enabled, false otherwise.
bool StopScanning(const std::string& service_id) ABSL_LOCKS_EXCLUDED(mutex_);
// Returns true if the scanning for service id is enabled.
bool IsScanning(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_);
@@ -65,20 +86,6 @@ class BleV2 final {
}
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_);
@@ -86,6 +93,10 @@ class BleV2 final {
bool IsAdvertisingLocked(const std::string& service_id) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Same as IsScanning(), but must be called with `mutex_` held.
bool IsScanningLocked(const std::string& service_id) const
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool IsAdvertisementGattServerRunningLocked()
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
bool StartAdvertisementGattServerLocked(const std::string& service_id,
@@ -101,16 +112,20 @@ class BleV2 final {
ByteArray CreateAdvertisementHeader() ABSL_SHARED_LOCKS_REQUIRED(mutex_);
std::string GenerateAdvertisementUuid(int slot);
api::ble_v2::PowerMode PowerLevelToPowerMode(PowerLevel power_level);
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_set<std::string> advertising_service_ids_
ABSL_GUARDED_BY(mutex_);
std::unique_ptr<GattServer> gatt_server_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_map<int, std::pair<std::string, ByteArray>>
gatt_advertisements_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_set<api::ble_v2::GattCharacteristic>
subscribed_gatt_characteristics_ ABSL_GUARDED_BY(mutex_);
absl::flat_hash_set<std::string> scanned_service_ids_ ABSL_GUARDED_BY(mutex_);
};
} // namespace connections
@@ -22,6 +22,11 @@ namespace nearby {
namespace connections {
namespace mediums {
// TODO(b/213835576): The peripheral class is for NearbyConnections to transmit
// "advertisement byte array" when peripheral discovered in
// 'discovered_peripheral_track' class, which is not the same as the one in
// BluetoothAdapter. We need to see how to differentiate between this
// BlePeripheral and BleV2Peripheral in BluetoothAdapter.
class BlePeripheral {
public:
BlePeripheral() = default;
@@ -36,8 +41,8 @@ class BlePeripheral {
ByteArray GetId() const { return id_; }
private:
// A unique identifier for this peripheral. It can be the BLE advertisement it
// was found on, or even simply the BLE MAC address.
// A unique identifier for this peripheral. It is the BLE advertisement it
// was found on.
ByteArray id_;
};
@@ -19,6 +19,7 @@
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "connections/implementation/mediums/ble_v2/discovered_peripheral_callback.h"
#include "connections/implementation/mediums/bluetooth_radio.h"
#include "internal/platform/ble.h"
#include "internal/platform/count_down_latch.h"
@@ -30,7 +31,10 @@ namespace nearby {
namespace connections {
namespace {
constexpr absl::string_view kServiceID{"com.google.location.nearby.apps.test"};
constexpr absl::string_view kServiceIDA{
"com.google.location.nearby.apps.test.a"};
constexpr absl::string_view kServiceIDB{
"com.google.location.nearby.apps.test.b"};
constexpr absl::string_view kAdvertisementString{"\x0a\x0b\x0c\x0d"};
constexpr absl::string_view kFastAdvertisementServiceUuid{"FAST"};
@@ -61,18 +65,16 @@ TEST_F(BleV2Test, CanStartFastAdvertising) {
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.StartAdvertising(std::string(kServiceIDA),
advertisement_bytes, PowerLevel::kHighPower,
std::string(kFastAdvertisementServiceUuid)));
// Can't advertise twice for the same service_id.
EXPECT_FALSE(ble.StartAdvertising(service_id, advertisement_bytes,
power_level,
fast_advertisement_service_uuid));
EXPECT_TRUE(ble.StopAdvertising(service_id));
EXPECT_FALSE(ble.StartAdvertising(
std::string(kServiceIDA), advertisement_bytes, PowerLevel::kHighPower,
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble.StopAdvertising(std::string(kServiceIDA)));
env_.Stop();
}
@@ -81,14 +83,65 @@ TEST_F(BleV2Test, CanStartAdvertising) {
BluetoothRadio radio;
BleV2 ble{radio};
radio.Enable();
std::string service_id(kServiceID);
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
std::string no_fast_advertisement_service_uuid = {};
PowerLevel power_level = PowerLevel::kHighPower;
EXPECT_TRUE(ble.StartAdvertising(service_id, advertisement_bytes, power_level,
EXPECT_TRUE(ble.StartAdvertising(std::string(kServiceIDA),
advertisement_bytes, PowerLevel::kHighPower,
no_fast_advertisement_service_uuid));
EXPECT_TRUE(ble.StopAdvertising(service_id));
EXPECT_TRUE(ble.StopAdvertising(std::string(kServiceIDA)));
env_.Stop();
}
TEST_F(BleV2Test, CanStartDiscovery) {
env_.Start();
BluetoothRadio radio;
BleV2 ble{radio};
radio.Enable();
EXPECT_TRUE(ble.StartScanning(std::string(kServiceIDA),
PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{
.peripheral_discovered_cb =
[](mediums::BlePeripheral& peripheral,
const std::string& service_id,
const ByteArray& advertisement_bytes,
bool fast_advertisement) {
// nothing to do for now
},
.peripheral_lost_cb =
[](mediums::BlePeripheral& peripheral,
const std::string& service_id) {
// nothing to do for now
},
},
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble.StopScanning(std::string(kServiceIDA)));
env_.Stop();
}
TEST_F(BleV2Test, CanStartStopMultipleScanningWithDifferentServiceIds) {
env_.Start();
BluetoothRadio radio;
BleV2 ble{radio};
radio.Enable();
EXPECT_TRUE(ble.StartScanning(std::string(kServiceIDA),
PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{},
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble.StartScanning(std::string(kServiceIDB),
PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{},
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble.StopScanning(std::string(kServiceIDA)));
EXPECT_TRUE(ble.StartScanning(std::string(kServiceIDA),
PowerLevel::kHighPower,
mediums::DiscoveredPeripheralCallback{},
std::string(kFastAdvertisementServiceUuid)));
EXPECT_TRUE(ble.StopScanning(std::string(kServiceIDA)));
EXPECT_TRUE(ble.StopScanning(std::string(kServiceIDB)));
env_.Stop();
}
+55
View File
@@ -16,6 +16,7 @@
#include <memory>
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
@@ -36,6 +37,60 @@ bool BleV2Medium::StartAdvertising(
bool BleV2Medium::StopAdvertising() { return impl_->StopAdvertising(); }
bool BleV2Medium::StartScanning(const std::vector<std::string>& service_uuids,
PowerMode power_mode, ScanCallback callback) {
MutexLock lock(&mutex_);
if (scanning_enabled_) {
NEARBY_LOGS(INFO) << "Ble Scanning already enabled; impl=" << GetImpl();
return false;
}
bool success = impl_->StartScanning(
service_uuids, power_mode,
{
.advertisement_found_cb =
[this](api::ble_v2::BlePeripheral& peripheral,
const BleAdvertisementData& advertisement_data) {
MutexLock lock(&mutex_);
if (peripherals_.contains(&peripheral)) {
NEARBY_LOGS(INFO)
<< "There is no need to callback due to peripheral impl="
<< &peripheral << ", which already exists.";
return;
}
peripherals_.insert(&peripheral);
BleV2Peripheral proxy(&peripheral);
NEARBY_LOGS(INFO)
<< "New peripheral imp=" << &peripheral
<< ", callback the proxy peripheral=" << &proxy;
if (!scanning_enabled_) return;
scan_callback_.advertisement_found_cb(std::move(proxy),
advertisement_data);
},
});
if (success) {
scan_callback_ = std::move(callback);
// Clear the `peripherals_` after succeeded in StartScanning and before the
// advertisement_found callback has been reached. This prevents deleting the
// existing `peripherals_` if the scanning is not started successfully. If
// sanning is started successfully, we need to clear `peripherals_` to
// prevent the stale data in cache.
peripherals_.clear();
scanning_enabled_ = true;
NEARBY_LOG(INFO, "Ble Scanning enabled; impl=%p", GetImpl());
}
return success;
}
bool BleV2Medium::StopScanning() {
MutexLock lock(&mutex_);
if (!scanning_enabled_) return true;
scanning_enabled_ = false;
peripherals_.clear();
scan_callback_ = {};
NEARBY_LOG(INFO, "Ble Scanning disabled: impl=%p", GetImpl());
return impl_->StopScanning();
}
std::unique_ptr<GattServer> BleV2Medium::StartGattServer(
ServerGattConnectionCallback callback) {
{
+26
View File
@@ -16,6 +16,7 @@
#define PLATFORM_PUBLIC_BLE_V2_H_
#include <memory>
#include "absl/container/flat_hash_map.h"
#include "internal/platform/bluetooth_adapter.h"
#include "internal/platform/byte_array.h"
@@ -94,6 +95,22 @@ class GattServer final {
// Container of operations that can be performed over the BLE medium.
class BleV2Medium final {
public:
// A wrapper callback for BLE scan results.
//
// The peripheral is a wrapper object which stores the real impl of
// api::BlePeripheral.
// The reference will remain valid while api::BlePeripheral object is
// itself valid. Typically peripheral lifetime matches duration of the
// connection, and is controlled by primitive client, since they hold the
// instance.
struct ScanCallback {
std::function<void(
BleV2Peripheral peripheral,
const api::ble_v2::BleAdvertisementData& advertisement_data)>
advertisement_found_cb = location::nearby::DefaultCallback<
BleV2Peripheral, const api::ble_v2::BleAdvertisementData&>();
};
struct ServerGattConnectionCallback {
std::function<void(ServerGattConnection& connection,
const api::ble_v2::GattCharacteristic& characteristic)>
@@ -117,6 +134,11 @@ class BleV2Medium final {
api::ble_v2::PowerMode power_mode);
bool StopAdvertising();
// Returns true once the BLE scan has been initiated.
bool StartScanning(const std::vector<std::string>& service_uuids,
api::ble_v2::PowerMode power_mode, ScanCallback callback);
bool StopScanning();
std::unique_ptr<GattServer> StartGattServer(
ServerGattConnectionCallback callback);
@@ -130,6 +152,10 @@ class BleV2Medium final {
BluetoothAdapter& adapter_;
ServerGattConnectionCallback server_gatt_connection_callback_
ABSL_GUARDED_BY(mutex_);
absl::flat_hash_set<api::ble_v2::BlePeripheral*> peripherals_
ABSL_GUARDED_BY(mutex_);
ScanCallback scan_callback_ ABSL_GUARDED_BY(mutex_);
bool scanning_enabled_ ABSL_GUARDED_BY(mutex_) = false;
};
} // namespace nearby
+20 -2
View File
@@ -30,7 +30,7 @@ using ::location::nearby::api::ble_v2::GattCharacteristic;
using ::location::nearby::api::ble_v2::PowerMode;
constexpr absl::string_view kAdvertisementString{"\x0a\x0b\x0c\x0d"};
constexpr absl::string_view kCoprsenseServiceUuid{"F3FE"};
constexpr absl::string_view kCopresenceServiceUuid{"F3FE"};
constexpr absl::string_view kFastAdvertisementServiceUuid{"FAST"};
constexpr PowerMode kPowerMode(PowerMode::kHigh);
@@ -128,7 +128,7 @@ TEST_F(BleV2MediumTest, CanStartGattServer) {
std::vector<GattCharacteristic::Property> properties{
GattCharacteristic::Property::kRead};
absl::optional<GattCharacteristic> gatt_characteristic =
gatt_server->CreateCharacteristic(std::string(kCoprsenseServiceUuid),
gatt_server->CreateCharacteristic(std::string(kCopresenceServiceUuid),
characteristic_uuid, permissions,
properties);
@@ -144,6 +144,24 @@ TEST_F(BleV2MediumTest, CanStartGattServer) {
env_.Stop();
}
TEST_F(BleV2MediumTest, CanStartScanning) {
env_.Start();
BluetoothAdapter adapter_;
BleV2Medium ble{adapter_};
EXPECT_TRUE(ble.StartScanning(
{std::string(kCopresenceServiceUuid)}, kPowerMode,
{
.advertisement_found_cb =
[](BleV2Peripheral peripheral,
const BleAdvertisementData& advertisement_data) {
// nothing to do for now
},
}));
EXPECT_TRUE(ble.StopScanning());
env_.Stop();
}
} // namespace
} // namespace nearby
} // namespace location
+20
View File
@@ -48,6 +48,26 @@ class BlePeripheral final {
api::BlePeripheral* impl_;
};
// Opaque wrapper over a BLE peripheral.
class BleV2Peripheral final {
public:
BleV2Peripheral() = default;
BleV2Peripheral(const BleV2Peripheral&) = default;
BleV2Peripheral& operator=(const BleV2Peripheral&) = default;
explicit BleV2Peripheral(api::ble_v2::BlePeripheral* peripheral)
: impl_(peripheral) {}
std::string GetId() const { return impl_->GetId(); }
// Returns reference to platform implementation.
// This is used to communicate with platform code, and for debugging purposes.
api::ble_v2::BlePeripheral& GetImpl() { return *impl_; }
bool IsValid() const { return impl_ != nullptr; }
private:
api::ble_v2::BlePeripheral* impl_;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice final {
public:
+6 -4
View File
@@ -329,11 +329,13 @@ class BleMedium {
// Every discovery of an advertisement should be reported, even if the
// advertisement was discovered before.
//
// Ownership of the BleAdvertisementData transfers to the caller at this
// point.
// The peripheral is owned by platform implementation and it should outlive
// for the whole peripheral(device) connection life cycle.
struct ScanCallback {
std::function<void(const BleAdvertisementData& advertisement_data)>
advertisement_found_cb = DefaultCallback<const BleAdvertisementData&>();
std::function<void(BlePeripheral& peripheral,
const BleAdvertisementData& advertisement_data)>
advertisement_found_cb =
DefaultCallback<BlePeripheral&, const BleAdvertisementData&>();
};
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#startScan(java.util.List%3Candroid.bluetooth.le.ScanFilter%3E,%20android.bluetooth.le.ScanSettings,%20android.bluetooth.le.ScanCallback)
+20 -23
View File
@@ -76,21 +76,8 @@ bool BleV2Medium::StartAdvertising(
<< ", power_mode=" << PowerModeToName(power_mode);
absl::MutexLock lock(&mutex_);
auto& env = MediumEnvironment::Instance();
// If `advertising_data.service_uuids` is empty, then it is fast
// advertisement. In real case, this should be the CopresenceServiceUuid or
// the fastAdvertisementUuid.
bool is_fast_advertisement = !advertising_data.service_uuids.empty();
for (const auto& service_data : scan_response_data.service_data) {
// Interested item found in the first index.
advertisement_byte_ = service_data.second;
if (!advertisement_byte_.Empty()) {
break;
}
}
if (advertisement_byte_.Empty()) return false;
env.UpdateBleV2MediumForAdvertising(is_fast_advertisement, true, *this,
&advertisement_byte_);
MediumEnvironment::Instance().UpdateBleV2MediumForAdvertising(
/*enabled=*/true, *this, adapter_->GetPeripheralV2(), scan_response_data);
return true;
}
@@ -99,20 +86,30 @@ bool BleV2Medium::StopAdvertising() {
absl::MutexLock lock(&mutex_);
advertisement_byte_ = {};
auto& env = MediumEnvironment::Instance();
env.UpdateBleV2MediumForAdvertising(
/*is_fast_advertisement=*/false,
/*enabled=*/false, *this, &advertisement_byte_);
BleAdvertisementData empty_advertisement_data = {};
MediumEnvironment::Instance().UpdateBleV2MediumForAdvertising(
/*enabled=*/false, *this, /*mutable=*/adapter_->GetPeripheralV2(),
empty_advertisement_data);
return true;
}
bool BleV2Medium::StartScanning(const std::vector<std::string>& service_uuids,
PowerMode power_mode,
ScanCallback scan_callback) {
return false;
PowerMode power_mode, ScanCallback callback) {
NEARBY_LOGS(INFO) << "G3 Ble StartScanning";
absl::MutexLock lock(&mutex_);
MediumEnvironment::Instance().UpdateBleV2MediumForScanning(
true, std::move(callback), *this);
return true;
}
bool BleV2Medium::StopScanning() { return false; }
bool BleV2Medium::StopScanning() {
NEARBY_LOGS(INFO) << "G3 Ble StopScanning";
absl::MutexLock lock(&mutex_);
MediumEnvironment::Instance().UpdateBleV2MediumForScanning(false, {}, *this);
return true;
}
std::unique_ptr<api::ble_v2::GattServer> BleV2Medium::StartGattServer(
ServerGattConnectionCallback callback) {
@@ -16,9 +16,9 @@
#include <string>
#include "internal/platform/implementation/g3/bluetooth_classic.h"
#include "internal/platform/medium_environment.h"
#include "internal/platform/prng.h"
#include "internal/platform/implementation/g3/bluetooth_classic.h"
namespace location {
namespace nearby {
@@ -38,10 +38,16 @@ void BlePeripheral::SetAdvertisementBytes(
advertisement_bytes_ = advertisement_bytes;
}
BleV2Peripheral::BleV2Peripheral(BluetoothAdapter* adapter)
: adapter_(*adapter) {}
std::string BleV2Peripheral::GetId() const { return adapter_.GetMacAddress(); }
BluetoothDevice::BluetoothDevice(BluetoothAdapter* adapter)
: adapter_(*adapter) {}
std::string BluetoothDevice::GetName() const { return adapter_.GetName(); }
std::string BluetoothDevice::GetMacAddress() const {
return adapter_.GetMacAddress();
}
@@ -21,6 +21,7 @@
#include "absl/strings/string_view.h"
#include "absl/synchronization/mutex.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"
#include "internal/platform/implementation/g3/single_thread_executor.h"
@@ -54,6 +55,21 @@ class BlePeripheral : public api::BlePeripheral {
ByteArray advertisement_bytes_;
};
// BlePeripheral implementation.
class BleV2Peripheral : public api::ble_v2::BlePeripheral {
public:
std::string GetId() const override;
BluetoothAdapter& GetAdapter() { return adapter_; }
private:
// Only BluetoothAdapter may instantiate BlePeripheral.
friend class BluetoothAdapter;
explicit BleV2Peripheral(BluetoothAdapter* adapter);
BluetoothAdapter& adapter_;
};
// https://developer.android.com/reference/android/bluetooth/BluetoothDevice.html.
class BluetoothDevice : public api::BluetoothDevice {
public:
@@ -117,6 +133,7 @@ class BluetoothAdapter : public api::BluetoothAdapter {
}
BlePeripheral& GetPeripheral() { return peripheral_; }
BleV2Peripheral& GetPeripheralV2() { return peripheral_v2_; }
void SetBleMedium(api::BleMedium* medium);
api::BleMedium* GetBleMedium() { return ble_medium_; }
@@ -127,6 +144,7 @@ class BluetoothAdapter : public api::BluetoothAdapter {
mutable absl::Mutex mutex_;
BluetoothDevice device_{this};
BlePeripheral peripheral_{this};
BleV2Peripheral peripheral_v2_{this};
api::BluetoothClassicMedium* bluetooth_classic_medium_ = nullptr;
api::BleMedium* ble_medium_ = nullptr;
std::string mac_address_;
+93 -33
View File
@@ -22,10 +22,11 @@
#include <type_traits>
#include <utility>
#include "internal/platform/count_down_latch.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/ble_v2.h"
#include "internal/platform/logging.h"
#include "internal/platform/prng.h"
#include "internal/platform/count_down_latch.h"
namespace location {
namespace nearby {
@@ -230,12 +231,21 @@ void MediumEnvironment::OnBlePeripheralStateChanged(
}
void MediumEnvironment::OnBleV2PeripheralStateChanged(
bool is_fast_advertisement, bool enabled, BleV2MediumContext& info) {
bool enabled, BleV2MediumContext& context,
const api::ble_v2::BleAdvertisementData& ble_advertisement_data,
api::ble_v2::BlePeripheral& peripheral) {
if (!enabled_) return;
NEARBY_LOGS(INFO) << "G3 OnBleServiceStateChanged, context=" << &info
<< ", notify=" << enable_notifications_.load();
NEARBY_LOGS(INFO) << "G3 OnBleServiceStateChanged [peripheral impl="
<< &peripheral << "]; medium_context=" << &context
<< "; notify=" << enable_notifications_.load();
if (!enable_notifications_) return;
// TODO(edwinwu): Report Advertisement found
NEARBY_LOGS(INFO) << "G3 [Run] OnBleServiceStateChanged [peripheral impl="
<< &peripheral << "]; context=" << &context
<< "; notify=" << enabled;
if (enabled) {
context.scan_callback.advertisement_found_cb(peripheral,
ble_advertisement_data);
}
}
void MediumEnvironment::OnWifiLanServiceStateChanged(
@@ -492,38 +502,88 @@ 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;
NEARBY_LOGS(INFO) << "G3 Registered: medium:" << &medium;
});
}
// TODO(b/213691253): Add g3 BleV2 medium tests after more functions are ready.
void MediumEnvironment::UpdateBleV2MediumForAdvertising(
bool is_fast_advertisement, bool enabled, api::ble_v2::BleMedium& medium,
ByteArray* advertisement_byte) {
bool enabled, api::ble_v2::BleMedium& medium,
api::ble_v2::BlePeripheral& peripheral,
const api::ble_v2::BleAdvertisementData& advertisement_data) {
if (!enabled_) return;
RunOnMediumEnvironmentThread([this, &medium, advertisement_byte,
is_fast_advertisement, enabled]() {
auto it = ble_v2_mediums_.find(&medium);
if (it == ble_v2_mediums_.end()) {
NEARBY_LOGS(INFO) << "UpdateBleMediumForAdvertising failed. There is no "
"medium registered.";
return;
}
auto& context = it->second;
context.advertisement_byte = advertisement_byte;
context.is_fast_advertisement = is_fast_advertisement;
NEARBY_LOGS(INFO) << "Update Ble medium for advertising: this=" << this
<< ", medium=" << &medium
<< ", is_fast_advertisement=" << is_fast_advertisement
<< ", enabled=" << enabled;
for (auto& medium_info : ble_v2_mediums_) {
auto& local_medium = medium_info.first;
auto& info = medium_info.second;
// Do not send notification to the same medium.
if (local_medium == &medium) continue;
OnBleV2PeripheralStateChanged(is_fast_advertisement, enabled, info);
}
});
RunOnMediumEnvironmentThread(
[this, &medium, &peripheral, advertisement_data = advertisement_data,
enabled]() {
auto it = ble_v2_mediums_.find(&medium);
if (it == ble_v2_mediums_.end()) {
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForAdvertising failed. There is no "
"medium registered.";
return;
}
auto& context = it->second;
context.ble_peripheral = &peripheral;
context.advertising = enabled;
context.advertisement_data = advertisement_data;
NEARBY_LOGS(INFO) << "G3 UpdateBleV2MediumForAdvertising: this=" << this
<< ", medium=" << &medium
<< ", medium_context=" << &context
<< ", peripheral=" << &peripheral
<< ", enabled=" << enabled;
for (auto& medium_info : ble_v2_mediums_) {
const api::ble_v2::BleMedium* remote_medium = medium_info.first;
const BleV2MediumContext& remote_context = medium_info.second;
// Do not send notification to the same medium.
if (remote_medium == &medium) continue;
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForAdvertising, found other medium="
<< remote_medium << ", remote_medium_context=" << &remote_context
<< ", remote_context.peripheral=" << remote_context.ble_peripheral
<< ". Ready to call OnBleV2PeripheralStateChanged.";
OnBleV2PeripheralStateChanged(enabled, context,
context.advertisement_data,
*context.ble_peripheral);
}
});
}
void MediumEnvironment::UpdateBleV2MediumForScanning(
bool enabled, BleScanCallback callback, api::ble_v2::BleMedium& medium) {
if (!enabled_) return;
RunOnMediumEnvironmentThread(
[this, &medium, callback = std::move(callback), enabled]() {
auto it = ble_v2_mediums_.find(&medium);
if (it == ble_v2_mediums_.end()) {
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForScanning failed. There is no medium "
"registered.";
return;
}
BleV2MediumContext& context = it->second;
context.scan_callback = std::move(callback);
NEARBY_LOGS(INFO) << "G3 UpdateBleV2MediumForScanning: this=" << this
<< ", medium=" << &medium
<< ", medium_context=" << &context
<< ", enabled=" << enabled;
if (enabled) {
for (const auto& medium_info : ble_v2_mediums_) {
const api::ble_v2::BleMedium* remote_medium = medium_info.first;
const BleV2MediumContext& remote_context = medium_info.second;
// Do not send notification to the same or the non-advertising
// medium.
if (remote_medium == &medium || !remote_context.advertising)
continue;
NEARBY_LOGS(INFO)
<< "G3 UpdateBleV2MediumForScanning, found other medium="
<< remote_medium
<< ", remote_medium_context=" << &remote_context
<< ". Ready to call OnBleV2PeripheralStateChanged.";
OnBleV2PeripheralStateChanged(enabled, context,
remote_context.advertisement_data,
*remote_context.ble_peripheral);
}
}
});
}
void MediumEnvironment::UnregisterBleV2Medium(api::ble_v2::BleMedium& medium) {
@@ -531,7 +591,7 @@ void MediumEnvironment::UnregisterBleV2Medium(api::ble_v2::BleMedium& medium) {
RunOnMediumEnvironmentThread([this, &medium]() {
auto item = ble_v2_mediums_.extract(&medium);
if (item.empty()) return;
NEARBY_LOGS(INFO) << "Unregistered Ble medium";
NEARBY_LOGS(INFO) << "G3 Unregistered Ble medium";
});
}
+36 -19
View File
@@ -27,9 +27,9 @@
#ifndef NO_WEBRTC
#include "internal/platform/implementation/webrtc.h"
#endif
#include "internal/platform/implementation/wifi_lan.h"
#include "internal/platform/byte_array.h"
#include "internal/platform/feature_flags.h"
#include "internal/platform/implementation/wifi_lan.h"
#include "internal/platform/listeners.h"
#include "internal/platform/nsd_service_info.h"
#include "internal/platform/single_thread_executor.h"
@@ -59,6 +59,7 @@ class MediumEnvironment {
api::BleMedium::DiscoveredPeripheralCallback;
using BleAcceptedConnectionCallback =
api::BleMedium::AcceptedConnectionCallback;
using BleScanCallback = api::ble_v2::BleMedium::ScanCallback;
#ifndef NO_WEBRTC
using OnSignalingMessageCallback =
api::WebRtcSignalingMessenger::OnSignalingMessageCallback;
@@ -116,15 +117,14 @@ class MediumEnvironment {
void RegisterBluetoothMedium(api::BluetoothClassicMedium& medium,
api::BluetoothAdapter& medium_adapter);
// Updates callback info to allow for dispatch of discovery events.
// Updates discovery callback info to allow for dispatch of discovery events.
//
// Invokes callback asynchronously when any changes happen to discoverable
// devices, or if the defice is turned off, whether or not it is discoverable,
// if it was ever reported as discoverable.
// devices if it is turned on.
//
// This should be called when discoverable state changes.
// with user-specified callback when discovery is enabled, and with default
// (empty) callback otherwise.
// A valid callback should be assigned when discovery `enabled` as true; or
// an empty callback is assigned with discovery `enabled` as false.
void UpdateBluetoothMedium(api::BluetoothClassicMedium& medium,
BluetoothDiscoveryCallback callback);
@@ -179,12 +179,11 @@ class MediumEnvironment {
// Updates discovery callback info to allow for dispatch of discovery events.
//
// Invokes callback asynchronously when any changes happen to discoverable
// devices, or if the defice is turned off, whether or not it is discoverable,
// if it was ever reported as discoverable.
// devices if it is turned on.
//
// This should be called when discoverable state changes.
// with user-specified callback when discovery is enabled, and with default
// (empty) callback otherwise.
// A valid callback should be assigned when discovery `enabled` as true; or
// an empty callback is assigned with discovery `enabled` as false.
void UpdateBleMediumForScanning(
api::BleMedium& medium, const std::string& service_id,
const std::string& fast_advertisement_service_uuid,
@@ -208,13 +207,27 @@ class MediumEnvironment {
// 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.
// The registered `medium` must refer to a valid instance that outlives this
// object.
void RegisterBleV2Medium(api::ble_v2::BleMedium& medium);
// Updates advertising info to indicate the current medium is exposing
// advertising event.
void UpdateBleV2MediumForAdvertising(bool is_fast_advertisement, bool enabled,
api::ble_v2::BleMedium& medium,
ByteArray* advertisement_byte);
void UpdateBleV2MediumForAdvertising(
bool enabled, api::ble_v2::BleMedium& medium,
api::ble_v2::BlePeripheral& peripheral,
const api::ble_v2::BleAdvertisementData& advertisement_data);
// Updates discovery callback info to allow for dispatch of discovery events.
//
// Invokes callback asynchronously when any changes happen to discoverable
// devices if it is turned on.
//
// This should be called when discoverable state changes.
// The `callback` argument should be non-empty if `enabled` is true or empty
// if `enabled` is false.
void UpdateBleV2MediumForScanning(bool enabled, BleScanCallback callback,
api::ble_v2::BleMedium& medium);
// Removes medium-related info. This should correspond to device power off.
void UnregisterBleV2Medium(api::ble_v2::BleMedium& mediumum);
@@ -233,8 +246,8 @@ class MediumEnvironment {
// Updates discovery callback info to allow for dispatch of discovery events.
//
// This should be called when discoverable state changes.
// with user-specified callback when discovery is enabled, and with default
// (empty) callback otherwise.
// A valid callback should be assigned when discovery `enabled` as true; or
// an empty callback is assigned with discovery `enabled` as false.
void UpdateWifiLanMediumForDiscovery(
api::WifiLanMedium& medium, WifiLanDiscoveredServiceCallback callback,
const std::string& service_type, bool enabled);
@@ -271,8 +284,10 @@ class MediumEnvironment {
};
struct BleV2MediumContext {
ByteArray* advertisement_byte;
bool is_fast_advertisement = false;
BleScanCallback scan_callback = {};
api::ble_v2::BlePeripheral* ble_peripheral = nullptr;
api::ble_v2::BleAdvertisementData advertisement_data;
bool advertising = false;
};
struct WifiLanMediumContext {
@@ -303,8 +318,10 @@ class MediumEnvironment {
const std::string& service_id,
bool fast_advertisement, bool enabled);
void OnBleV2PeripheralStateChanged(bool is_fast_advertisement, bool enabled,
BleV2MediumContext& info);
void OnBleV2PeripheralStateChanged(
bool enabled, BleV2MediumContext& context,
const api::ble_v2::BleAdvertisementData& ble_advertisement_data,
api::ble_v2::BlePeripheral& peripheral);
void OnWifiLanServiceStateChanged(WifiLanMediumContext& info,
const NsdServiceInfo& service_info,