mirror of
https://github.com/kidfromjupiter/nearby.git
synced 2026-09-14 14:46:12 -04:00
[BLE Refactor] Add Extended advertisement support.
PiperOrigin-RevId: 449619994
This commit is contained in:
committed by
Copybara-Service
parent
8f1623d293
commit
01f439b9ad
@@ -50,6 +50,7 @@ cc_library(
|
||||
"//internal/platform:logging",
|
||||
"//internal/platform:types",
|
||||
"//proto/mediums:web_rtc_signaling_frames_cc_proto",
|
||||
"@com_google_absl//absl/container:btree",
|
||||
"@com_google_absl//absl/container:flat_hash_map",
|
||||
"@com_google_absl//absl/container:flat_hash_set",
|
||||
"@com_google_absl//absl/functional:bind_front",
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
#include <utility>
|
||||
|
||||
#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/ble_utils.h"
|
||||
@@ -40,7 +39,7 @@ namespace {
|
||||
|
||||
using ::location::nearby::api::ble_v2::BleAdvertisementData;
|
||||
using ::location::nearby::api::ble_v2::GattCharacteristic;
|
||||
using ::location::nearby::api::ble_v2::PowerMode;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
|
||||
constexpr int kMaxAdvertisementLength = 512;
|
||||
constexpr int kDummyServiceIdLength = 128;
|
||||
@@ -62,8 +61,8 @@ BleV2::~BleV2() {
|
||||
while (!scanned_service_ids_.empty()) {
|
||||
StopScanning(*scanned_service_ids_.begin());
|
||||
}
|
||||
while (!advertising_service_ids_.empty()) {
|
||||
StopAdvertising(*advertising_service_ids_.begin());
|
||||
while (!advertising_infos_.empty()) {
|
||||
StopAdvertising(advertising_infos_.begin()->first);
|
||||
}
|
||||
|
||||
serial_executor_.Shutdown();
|
||||
@@ -76,7 +75,6 @@ bool BleV2::IsAvailable() const {
|
||||
return IsAvailableLocked();
|
||||
}
|
||||
|
||||
// TODO(edwinwu): Break down the function.
|
||||
bool BleV2::StartAdvertising(const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
PowerLevel power_level,
|
||||
@@ -117,152 +115,99 @@ bool BleV2::StartAdvertising(const std::string& service_id,
|
||||
// Wrap the connections advertisement to the medium advertisement.
|
||||
ByteArray service_id_hash = mediums::bleutils::GenerateHash(
|
||||
service_id, mediums::BleAdvertisement::kServiceIdHashLength);
|
||||
ByteArray medium_advertisement_bytes{mediums::BleAdvertisement{
|
||||
// Get psm value from L2CAP server if L2CAP is supported. Now just use the
|
||||
// default value.
|
||||
int psm = mediums::BleAdvertisementHeader::kDefaultPsmValue;
|
||||
mediums::BleAdvertisement medium_advertisement = {
|
||||
mediums::BleAdvertisement::Version::kV2,
|
||||
mediums::BleAdvertisement::SocketVersion::kV2,
|
||||
/*service_id_hash=*/is_fast_advertisement ? ByteArray{} : service_id_hash,
|
||||
advertisement_bytes, mediums::bleutils::GenerateDeviceToken(),
|
||||
mediums::BleAdvertisementHeader::kDefaultPsmValue}};
|
||||
if (medium_advertisement_bytes.Empty()) {
|
||||
advertisement_bytes,
|
||||
mediums::bleutils::GenerateDeviceToken(),
|
||||
psm};
|
||||
if (!medium_advertisement.IsValid()) {
|
||||
NEARBY_LOGS(INFO) << "Failed to BLE advertise because we could not wrap a "
|
||||
"connection advertisement to medium advertisement.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assemble AdvertisingData and ScanResponseData.
|
||||
BleAdvertisementData advertising_data;
|
||||
BleAdvertisementData scan_response_data;
|
||||
if (is_fast_advertisement) {
|
||||
advertising_data.is_connectable = true;
|
||||
advertising_data.tx_power_level =
|
||||
BleAdvertisementData::kUnspecifiedTxPowerLevel;
|
||||
advertising_data.service_uuids.insert(
|
||||
std::string(mediums::bleutils::kCopresenceServiceUuid));
|
||||
advertising_infos_.insert(
|
||||
{service_id,
|
||||
AdvertisingInfo{.medium_advertisement = medium_advertisement,
|
||||
.power_level = power_level,
|
||||
.is_fast_advertisement = is_fast_advertisement}});
|
||||
|
||||
scan_response_data.is_connectable = true;
|
||||
scan_response_data.tx_power_level =
|
||||
BleAdvertisementData::kUnspecifiedTxPowerLevel;
|
||||
scan_response_data.service_data.insert(
|
||||
{std::string(mediums::bleutils::kCopresenceServiceUuid),
|
||||
medium_advertisement_bytes});
|
||||
} else {
|
||||
// Stop the current advertisement GATT server if there are no incoming
|
||||
// sockets connected to this device.
|
||||
//
|
||||
// The reason for aggressively restarting a GATT server is to make sure this
|
||||
// class is not using a stale server object that may not be actually running
|
||||
// anymore (possibly due to Bluetooth being turned off).
|
||||
//
|
||||
// Changing one's GATT server while a remote device is connected to it leads
|
||||
// to a loss of GATT callbacks for that remote device. The only time a
|
||||
// remote device is indefinitely connected to this device's GATT server is
|
||||
// when it has a BLE socket connection.
|
||||
// TODO(b/213835576): Check the BLE Connections is off. We set the fake
|
||||
// value for the time being till connections is implemented.
|
||||
bool no_incoming_ble_sockets = true;
|
||||
if (no_incoming_ble_sockets) {
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< "Aggressively stopping any pre-existing advertisement GATT "
|
||||
"servers because no incoming BLE sockets are connected";
|
||||
StopAdvertisementGattServerLocked();
|
||||
}
|
||||
// Stop the pre-existing BLE advertisement if there is one.
|
||||
medium_.StopAdvertising();
|
||||
|
||||
// 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 (!IsAdvertisementGattServerRunningLocked()) {
|
||||
if (!StartAdvertisementGattServerLocked(service_id,
|
||||
medium_advertisement_bytes)) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to start BLE advertising for service_id=" << service_id
|
||||
<< " 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.
|
||||
StopAdvertisementGattServerLocked();
|
||||
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(mediums::bleutils::kCopresenceServiceUuid));
|
||||
scan_response_data.service_data.insert(
|
||||
{std::string(mediums::bleutils::kCopresenceServiceUuid),
|
||||
advertisement_header_bytes});
|
||||
}
|
||||
|
||||
if (!medium_.StartAdvertising(advertising_data, scan_response_data,
|
||||
PowerLevelToPowerMode(power_level))) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to turn on BLE advertising with advertisement bytes="
|
||||
<< absl::BytesToHexString(advertisement_bytes.data())
|
||||
<< ", is_fast_advertisement=" << is_fast_advertisement;
|
||||
|
||||
// If BLE advertising was not successful, stop the advertisement GATT
|
||||
// server.
|
||||
StopAdvertisementGattServerLocked();
|
||||
if (!StartAdvertisingLocked(service_id)) {
|
||||
advertising_infos_.erase(service_id);
|
||||
return false;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Started BLE advertising with advertisement bytes="
|
||||
<< absl::BytesToHexString(advertisement_bytes.data())
|
||||
<< " for service_id=" << service_id;
|
||||
advertising_service_ids_.insert(service_id);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2::StopAdvertising(const std::string& service_id) {
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
if (!IsAdvertisingLocked(service_id)) {
|
||||
NEARBY_LOGS(INFO) << "Cannot stop BLE advertising for service_id="
|
||||
<< service_id << " because it never started.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Stop the BLE advertisement. We will restart it later if necessary.
|
||||
NEARBY_LOGS(INFO) << "Turned off BLE advertising with service_id="
|
||||
<< service_id;
|
||||
advertising_infos_.erase(service_id);
|
||||
medium_.StopAdvertising();
|
||||
|
||||
// Remove the GATT advertisements.
|
||||
gatt_advertisements_.clear();
|
||||
|
||||
// Restart the BLE advertisement if there is still an advertiser.
|
||||
// TODO(b/213835576): Check the BLE Connections is off. We set the fake
|
||||
// value for the time being till connections is implemented.
|
||||
bool no_incoming_ble_sockets = true;
|
||||
// Set the value of characteristic to empty if there is still an advertiser.
|
||||
if (!hosted_gatt_characteristics_.empty()) {
|
||||
ByteArray empty_value = {};
|
||||
for (const auto& characteristic : hosted_gatt_characteristics_) {
|
||||
if (!gatt_server_->UpdateCharacteristic(characteristic, empty_value)) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to clear characteristic uuid=" << characteristic.uuid
|
||||
<< " after stopping BLE advertisement for service_id="
|
||||
<< service_id;
|
||||
if (advertising_infos_.empty() && !no_incoming_ble_sockets) {
|
||||
return true;
|
||||
}
|
||||
if (!advertising_infos_.empty()) {
|
||||
if (!hosted_gatt_characteristics_.empty()) {
|
||||
// Set the value of characteristic to empty if there is still an
|
||||
// advertiser.
|
||||
ByteArray empty_value = {};
|
||||
for (const auto& characteristic : hosted_gatt_characteristics_) {
|
||||
if (!gatt_server_->UpdateCharacteristic(characteristic, empty_value)) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to clear characteristic uuid=" << characteristic.uuid
|
||||
<< " after stopping BLE advertisement for service_id="
|
||||
<< service_id;
|
||||
}
|
||||
}
|
||||
hosted_gatt_characteristics_.clear();
|
||||
}
|
||||
hosted_gatt_characteristics_.clear();
|
||||
} else if (no_incoming_ble_sockets) {
|
||||
// Otherwise, if we aren't restarting the BLE advertisement, then shutdown
|
||||
// the gatt server if it's not in use.
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< "Aggressively stopping any pre-existing advertisement GATT servers "
|
||||
"because no incoming BLE sockets are connected.";
|
||||
StopAdvertisementGattServerLocked();
|
||||
// Get the next service_id to restart BLE advertisement.
|
||||
const std::string& service_id = advertising_infos_.begin()->first;
|
||||
if (!StartAdvertisingLocked(service_id)) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to restart BLE advertisement after stopping "
|
||||
"BLE advertisement for service_id="
|
||||
<< service_id;
|
||||
advertising_infos_.erase(service_id);
|
||||
return false;
|
||||
}
|
||||
NEARBY_LOGS(INFO) << "Restart BLE advertising with service_id="
|
||||
<< service_id;
|
||||
return true;
|
||||
}
|
||||
|
||||
NEARBY_LOGS(INFO) << "Turned off BLE advertising with service_id="
|
||||
<< service_id;
|
||||
advertising_service_ids_.erase(service_id);
|
||||
return medium_.StopAdvertising();
|
||||
// If we aren't restarting the BLE advertisement, then shutdown
|
||||
// the gatt server if it's not in use.
|
||||
NEARBY_LOGS(VERBOSE) << "Aggressively stopping any pre-existing "
|
||||
"advertisement GATT servers "
|
||||
"because no incoming BLE sockets are connected.";
|
||||
StopAdvertisementGattServerLocked();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2::IsAdvertising(const std::string& service_id) const {
|
||||
@@ -317,7 +262,7 @@ bool BleV2::StartScanning(const std::string& service_id, PowerLevel power_level,
|
||||
// changed.
|
||||
if (!medium_.StartScanning(
|
||||
std::string(mediums::bleutils::kCopresenceServiceUuid),
|
||||
PowerLevelToPowerMode(power_level),
|
||||
PowerLevelToTxPowerLevel(power_level),
|
||||
{
|
||||
.advertisement_found_cb =
|
||||
[this](BleV2Peripheral peripheral,
|
||||
@@ -406,7 +351,7 @@ bool BleV2::IsScanning(const std::string& service_id) const {
|
||||
bool BleV2::IsAvailableLocked() const { return medium_.IsValid(); }
|
||||
|
||||
bool BleV2::IsAdvertisingLocked(const std::string& service_id) const {
|
||||
return advertising_service_ids_.contains(service_id);
|
||||
return advertising_infos_.contains(service_id);
|
||||
}
|
||||
|
||||
bool BleV2::IsScanningLocked(const std::string& service_id) const {
|
||||
@@ -499,7 +444,7 @@ void BleV2::ProcessFetchGattAdvertisementsRequest(
|
||||
// from the GATT server.
|
||||
bool read_success = true;
|
||||
std::unique_ptr<GattClient> gatt_client = medium_.ConnectToGattServer(
|
||||
std::move(peripheral), PowerLevelToPowerMode(PowerLevel::kHighPower),
|
||||
std::move(peripheral), PowerLevelToTxPowerLevel(PowerLevel::kHighPower),
|
||||
/*ClientGattConnectionCallback=*/{});
|
||||
if (!gatt_client || !gatt_client->IsValid()) {
|
||||
advertisement_read_result.RecordLastReadStatus(false);
|
||||
@@ -565,7 +510,8 @@ bool BleV2::StopAdvertisementGattServerLocked() {
|
||||
return true;
|
||||
}
|
||||
|
||||
ByteArray BleV2::CreateAdvertisementHeader() {
|
||||
ByteArray BleV2::CreateAdvertisementHeader(
|
||||
int psm, bool extended_advertisement_advertised) {
|
||||
// Create a randomized dummy service id to anonymize the header with.
|
||||
ByteArray dummy_service_id_bytes =
|
||||
Utils::GenerateRandomBytes(kDummyServiceIdLength);
|
||||
@@ -583,8 +529,7 @@ ByteArray BleV2::CreateAdvertisementHeader() {
|
||||
const ByteArray& gatt_advertisement = item.second.second;
|
||||
bloom_filter.Add(service_id);
|
||||
|
||||
// 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
|
||||
// Compute the next hash.
|
||||
std::string advertisement_bodies = absl::StrCat(
|
||||
advertisement_hash.AsStringView(), gatt_advertisement.AsStringView());
|
||||
|
||||
@@ -594,21 +539,183 @@ ByteArray BleV2::CreateAdvertisementHeader() {
|
||||
|
||||
return ByteArray(mediums::BleAdvertisementHeader(
|
||||
mediums::BleAdvertisementHeader::Version::kV2,
|
||||
/*extended_advertisement=*/false,
|
||||
extended_advertisement_advertised,
|
||||
/*num_slots=*/gatt_advertisements_.size(), ByteArray(bloom_filter),
|
||||
advertisement_hash, /*psm=*/0));
|
||||
advertisement_hash, psm));
|
||||
}
|
||||
|
||||
PowerMode BleV2::PowerLevelToPowerMode(PowerLevel power_level) {
|
||||
bool BleV2::StartAdvertisingLocked(const std::string& service_id) {
|
||||
const auto it = advertising_infos_.find(service_id);
|
||||
if (it == advertising_infos_.end()) {
|
||||
NEARBY_LOGS(WARNING) << "Failed to BLE advertise with service_id="
|
||||
<< service_id;
|
||||
return false;
|
||||
}
|
||||
|
||||
const AdvertisingInfo& info = it->second;
|
||||
if (info.is_fast_advertisement) {
|
||||
return StartFastAdvertisingLocked(info.power_level,
|
||||
info.medium_advertisement);
|
||||
} else {
|
||||
return StartRegularAdvertisingLocked(service_id, info.power_level,
|
||||
info.medium_advertisement);
|
||||
}
|
||||
}
|
||||
|
||||
bool BleV2::StartFastAdvertisingLocked(
|
||||
PowerLevel power_level,
|
||||
const mediums::BleAdvertisement& medium_advertisement) {
|
||||
// Begin building the fast BLE advertisement.
|
||||
BleAdvertisementData advertising_data;
|
||||
ByteArray medium_advertisement_bytes = ByteArray(medium_advertisement);
|
||||
advertising_data.is_extended_advertisement = false;
|
||||
advertising_data.service_data.insert(
|
||||
{std::string(mediums::bleutils::kCopresenceServiceUuid),
|
||||
medium_advertisement_bytes});
|
||||
|
||||
// Finally, start the fast advertising operation.
|
||||
if (!medium_.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = PowerLevelToTxPowerLevel(power_level),
|
||||
.is_connectable = true})) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to turn on BLE fast advertising with "
|
||||
"advertisement bytes="
|
||||
<< absl::BytesToHexString(
|
||||
medium_advertisement_bytes.data());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BleV2::StartRegularAdvertisingLocked(
|
||||
const std::string& service_id, PowerLevel power_level,
|
||||
const mediums::BleAdvertisement& medium_advertisement) {
|
||||
// Begin building the regular BLE advertisement.
|
||||
BleAdvertisementData advertising_data;
|
||||
ByteArray medium_advertisement_bytes =
|
||||
medium_.IsExtendedAdvertisementsAvailable()
|
||||
? medium_advertisement.ByteArrayWithExtraField()
|
||||
: ByteArray(medium_advertisement);
|
||||
|
||||
// Start extended advertisement first if available.
|
||||
bool extended_regular_advertisement_success = false;
|
||||
if (medium_.IsExtendedAdvertisementsAvailable()) {
|
||||
advertising_data.is_extended_advertisement = true;
|
||||
advertising_data.service_data.insert(
|
||||
{std::string(mediums::bleutils::kCopresenceServiceUuid),
|
||||
medium_advertisement_bytes});
|
||||
|
||||
// Start the extended regular advertising operation.
|
||||
extended_regular_advertisement_success = medium_.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = PowerLevelToTxPowerLevel(power_level),
|
||||
.is_connectable = true});
|
||||
if (!extended_regular_advertisement_success) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to turn on BLE extended regular advertising with "
|
||||
"advertisement bytes="
|
||||
<< absl::BytesToHexString(medium_advertisement_bytes.data());
|
||||
}
|
||||
}
|
||||
|
||||
// Start GATT advertisement no matter extended advertisment succeeded or not.
|
||||
// This is to ensure that legacy devices which don't support extended
|
||||
// advertisement can get the advertisement via GATT connection.
|
||||
bool gatt_advertisement_success = StartGattAdvertisingLocked(
|
||||
service_id, power_level, medium_advertisement.GetPsm(),
|
||||
medium_advertisement_bytes, extended_regular_advertisement_success);
|
||||
|
||||
return extended_regular_advertisement_success || gatt_advertisement_success;
|
||||
}
|
||||
|
||||
bool BleV2::StartGattAdvertisingLocked(
|
||||
const std::string& service_id, PowerLevel power_level, int psm,
|
||||
const ByteArray& medium_advertisement_bytes,
|
||||
bool extended_advertisement_advertised) {
|
||||
// Begin building the GATT BLE advertisement header.
|
||||
BleAdvertisementData advertising_data;
|
||||
advertising_data.is_extended_advertisement = false;
|
||||
|
||||
// Stop the current advertisement GATT server if there are no incoming
|
||||
// sockets connected to this device.
|
||||
//
|
||||
// The reason for aggressively restarting a GATT server is to make sure this
|
||||
// class is not using a stale server object that may not be actually running
|
||||
// anymore (possibly due to Bluetooth being turned off).
|
||||
//
|
||||
// Changing one's GATT server while a remote device is connected to it leads
|
||||
// to a loss of GATT callbacks for that remote device. The only time a
|
||||
// remote device is indefinitely connected to this device's GATT server is
|
||||
// when it has a BLE socket connection.
|
||||
// TODO(b/213835576): Check the BLE Connections is off. We set the fake
|
||||
// value for the time being till connections is implemented.
|
||||
bool no_incoming_ble_sockets = true;
|
||||
if (no_incoming_ble_sockets) {
|
||||
NEARBY_LOGS(VERBOSE)
|
||||
<< "Aggressively stopping any pre-existing advertisement GATT "
|
||||
"servers because no incoming BLE sockets are connected";
|
||||
StopAdvertisementGattServerLocked();
|
||||
}
|
||||
|
||||
// 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 (!IsAdvertisementGattServerRunningLocked()) {
|
||||
if (!StartAdvertisementGattServerLocked(service_id,
|
||||
medium_advertisement_bytes)) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to turn on BLE GATT advertising for service_id="
|
||||
<< service_id
|
||||
<< " because the advertisement GATT server failed to start.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Begin building the regular BLE advertisement (backed by a GATT server).
|
||||
// Add the advertisement header.
|
||||
ByteArray advertisement_header_bytes =
|
||||
CreateAdvertisementHeader(psm, extended_advertisement_advertised);
|
||||
if (advertisement_header_bytes.Empty()) {
|
||||
NEARBY_LOGS(ERROR)
|
||||
<< "Failed to turn on BLE GATT advertising because we could not "
|
||||
"create an advertisement header.";
|
||||
// Failed to create an advertisement header, so stop the advertisement
|
||||
// GATT server.
|
||||
StopAdvertisementGattServerLocked();
|
||||
return false;
|
||||
}
|
||||
|
||||
advertising_data.service_data.insert(
|
||||
{std::string(mediums::bleutils::kCopresenceServiceUuid),
|
||||
advertisement_header_bytes});
|
||||
|
||||
// Finally, start the regular advertising operation.
|
||||
if (!medium_.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = PowerLevelToTxPowerLevel(power_level),
|
||||
.is_connectable = true})) {
|
||||
NEARBY_LOGS(ERROR) << "Failed to turn on BLE GATT advertising with "
|
||||
"advertisement bytes="
|
||||
<< absl::BytesToHexString(
|
||||
medium_advertisement_bytes.data());
|
||||
// If BLE advertising was not successful, stop the advertisement GATT
|
||||
// server.
|
||||
StopAdvertisementGattServerLocked();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
TxPowerLevel BleV2::PowerLevelToTxPowerLevel(PowerLevel power_level) {
|
||||
switch (power_level) {
|
||||
case PowerLevel::kHighPower:
|
||||
return PowerMode::kHigh;
|
||||
return TxPowerLevel::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;
|
||||
return TxPowerLevel::kMedium;
|
||||
default:
|
||||
return PowerMode::kUnknown;
|
||||
return TxPowerLevel::kUnknown;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,11 @@
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "absl/container/btree_map.h"
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "connections/implementation/mediums/ble_v2/advertisement_read_result.h"
|
||||
#include "connections/implementation/mediums/ble_v2/ble_advertisement.h"
|
||||
#include "connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.h"
|
||||
#include "connections/implementation/mediums/bluetooth_radio.h"
|
||||
#include "connections/power_level.h"
|
||||
@@ -63,8 +65,7 @@ class BleV2 final {
|
||||
// but much more efficient to discover.
|
||||
bool StartAdvertising(const std::string& service_id,
|
||||
const ByteArray& advertisement_bytes,
|
||||
PowerLevel power_level,
|
||||
bool is_fast_advertisement)
|
||||
PowerLevel power_level, bool is_fast_advertisement)
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// Disables BLE advertising.
|
||||
@@ -101,6 +102,12 @@ class BleV2 final {
|
||||
}
|
||||
|
||||
private:
|
||||
struct AdvertisingInfo {
|
||||
mediums::BleAdvertisement medium_advertisement;
|
||||
PowerLevel power_level;
|
||||
bool is_fast_advertisement;
|
||||
};
|
||||
|
||||
// Same as IsAvailable(), but must be called with `mutex_` held.
|
||||
bool IsAvailableLocked() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
@@ -129,9 +136,26 @@ class BleV2 final {
|
||||
bool StopAdvertisementGattServerLocked()
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
ByteArray CreateAdvertisementHeader() ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
ByteArray CreateAdvertisementHeader(int psm,
|
||||
bool extended_advertisement_advertised)
|
||||
ABSL_SHARED_LOCKS_REQUIRED(mutex_);
|
||||
bool StartAdvertisingLocked(const std::string& service_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool StartFastAdvertisingLocked(
|
||||
PowerLevel power_level,
|
||||
const mediums::BleAdvertisement& medium_advertisement)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool StartRegularAdvertisingLocked(
|
||||
const std::string& service_id, PowerLevel power_level,
|
||||
const mediums::BleAdvertisement& medium_advertisement)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
bool StartGattAdvertisingLocked(const std::string& service_id,
|
||||
PowerLevel power_level, int psm,
|
||||
const ByteArray& medium_advertisement_bytes,
|
||||
bool extended_advertisement_advertised)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
api::ble_v2::PowerMode PowerLevelToPowerMode(PowerLevel power_level);
|
||||
api::ble_v2::TxPowerLevel PowerLevelToTxPowerLevel(PowerLevel power_level);
|
||||
|
||||
void RunOnBleThread(Runnable runnable);
|
||||
|
||||
@@ -142,7 +166,7 @@ class BleV2 final {
|
||||
BluetoothRadio& radio_ ABSL_GUARDED_BY(mutex_);
|
||||
BluetoothAdapter& adapter_ ABSL_GUARDED_BY(mutex_);
|
||||
BleV2Medium medium_ ABSL_GUARDED_BY(mutex_){adapter_};
|
||||
absl::flat_hash_set<std::string> advertising_service_ids_
|
||||
absl::btree_map<std::string, AdvertisingInfo> advertising_infos_
|
||||
ABSL_GUARDED_BY(mutex_);
|
||||
std::unique_ptr<GattServer> gatt_server_ ABSL_GUARDED_BY(mutex_);
|
||||
absl::flat_hash_map<int, std::pair<std::string, ByteArray>>
|
||||
|
||||
@@ -98,6 +98,7 @@ class BleAdvertisement {
|
||||
const ByteArray &&GetData() const && { return std::move(data_); }
|
||||
ByteArray GetDeviceToken() const { return device_token_; }
|
||||
int GetPsm() const { return psm_; }
|
||||
void SetPsm(int psm) { psm_ = psm; }
|
||||
|
||||
private:
|
||||
// Represents the extra fields of the `BleAdvertisement` used in Advertising +
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
#include <utility>
|
||||
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
#include "internal/platform/base_input_stream.h"
|
||||
#include "internal/platform/logging.h"
|
||||
|
||||
@@ -36,7 +35,7 @@ constexpr int BleAdvertisementHeader::kDefaultPsmValue;
|
||||
constexpr int BleAdvertisementHeader::kPsmValueByteLength;
|
||||
|
||||
BleAdvertisementHeader::BleAdvertisementHeader(
|
||||
Version version, bool extended_advertisement, int num_slots,
|
||||
Version version, bool support_extended_advertisement, int num_slots,
|
||||
const ByteArray &service_id_bloom_filter,
|
||||
const ByteArray &advertisement_hash, int psm) {
|
||||
if (version != Version::kV2 || num_slots < 0 ||
|
||||
@@ -46,7 +45,7 @@ BleAdvertisementHeader::BleAdvertisementHeader(
|
||||
}
|
||||
|
||||
version_ = version;
|
||||
extended_advertisement_ = extended_advertisement;
|
||||
support_extended_advertisement_ = support_extended_advertisement;
|
||||
num_slots_ = num_slots;
|
||||
service_id_bloom_filter_ = service_id_bloom_filter;
|
||||
advertisement_hash_ = advertisement_hash;
|
||||
@@ -87,7 +86,7 @@ BleAdvertisementHeader::BleAdvertisementHeader(
|
||||
return;
|
||||
}
|
||||
// The next 1 bit is supposed to be the extended advertisement flag.
|
||||
extended_advertisement_ =
|
||||
support_extended_advertisement_ =
|
||||
((version_and_num_slots_byte & kExtendedAdvertismentBitMask) >> 4) == 1;
|
||||
// The lower 4 bits are supposed to be the number of slots.
|
||||
num_slots_ = static_cast<int>(version_and_num_slots_byte & kNumSlotsBitmask);
|
||||
@@ -120,7 +119,7 @@ BleAdvertisementHeader::operator ByteArray() const {
|
||||
(static_cast<char>(version_) << 5) & kVersionBitmask;
|
||||
// The next 1 bit is extended advertisement flag.
|
||||
version_and_num_slots_byte |=
|
||||
(static_cast<char>(extended_advertisement_) << 4) &
|
||||
(static_cast<char>(support_extended_advertisement_) << 4) &
|
||||
kExtendedAdvertismentBitMask;
|
||||
// The next 5 bits are the number of slots.
|
||||
version_and_num_slots_byte |=
|
||||
@@ -145,7 +144,8 @@ BleAdvertisementHeader::operator ByteArray() const {
|
||||
bool BleAdvertisementHeader::operator==(
|
||||
const BleAdvertisementHeader &rhs) const {
|
||||
return GetVersion() == rhs.GetVersion() &&
|
||||
IsExtendedAdvertisement() == rhs.IsExtendedAdvertisement() &&
|
||||
IsSupportExtendedAdvertisement() ==
|
||||
rhs.IsSupportExtendedAdvertisement() &&
|
||||
GetNumSlots() == rhs.GetNumSlots() &&
|
||||
GetServiceIdBloomFilter() == rhs.GetServiceIdBloomFilter() &&
|
||||
GetAdvertisementHash() == rhs.GetAdvertisementHash() &&
|
||||
|
||||
@@ -60,13 +60,14 @@ class BleAdvertisementHeader {
|
||||
bool operator==(const BleAdvertisementHeader &rhs) const;
|
||||
template <typename H>
|
||||
friend H AbslHashValue(H h, const BleAdvertisementHeader &b) {
|
||||
return H::combine(std::move(h), b.version_, b.extended_advertisement_,
|
||||
b.num_slots_, b.service_id_bloom_filter_,
|
||||
b.advertisement_hash_, b.psm_);
|
||||
return H::combine(std::move(h), b.version_,
|
||||
b.support_extended_advertisement_, b.num_slots_,
|
||||
b.service_id_bloom_filter_, b.advertisement_hash_,
|
||||
b.psm_);
|
||||
}
|
||||
|
||||
BleAdvertisementHeader() = default;
|
||||
BleAdvertisementHeader(Version version, bool extended_advertisement,
|
||||
BleAdvertisementHeader(Version version, bool support_extended_advertisement,
|
||||
int num_slots,
|
||||
const ByteArray &service_id_bloom_filter,
|
||||
const ByteArray &advertisement_hash, int psm);
|
||||
@@ -82,7 +83,9 @@ class BleAdvertisementHeader {
|
||||
|
||||
bool IsValid() const { return version_ == Version::kV2; }
|
||||
Version GetVersion() const { return version_; }
|
||||
bool IsExtendedAdvertisement() const { return extended_advertisement_; }
|
||||
bool IsSupportExtendedAdvertisement() const {
|
||||
return support_extended_advertisement_;
|
||||
}
|
||||
int GetNumSlots() const { return num_slots_; }
|
||||
ByteArray GetServiceIdBloomFilter() const { return service_id_bloom_filter_; }
|
||||
ByteArray GetAdvertisementHash() const { return advertisement_hash_; }
|
||||
@@ -99,7 +102,7 @@ class BleAdvertisementHeader {
|
||||
static constexpr int kNumSlotsBitmask = 0x00F;
|
||||
|
||||
Version version_ = Version::kUndefined;
|
||||
bool extended_advertisement_ = false;
|
||||
bool support_extended_advertisement_ = false;
|
||||
int num_slots_ = 0;
|
||||
ByteArray service_id_bloom_filter_;
|
||||
ByteArray advertisement_hash_;
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "absl/hash/hash_testing.h"
|
||||
#include "internal/platform/base64_utils.h"
|
||||
|
||||
namespace location {
|
||||
namespace nearby {
|
||||
@@ -44,7 +43,7 @@ TEST(BleAdvertisementHeaderTest, ConstructionWorks) {
|
||||
|
||||
EXPECT_TRUE(ble_advertisement_header.IsValid());
|
||||
EXPECT_EQ(kVersion, ble_advertisement_header.GetVersion());
|
||||
EXPECT_FALSE(ble_advertisement_header.IsExtendedAdvertisement());
|
||||
EXPECT_FALSE(ble_advertisement_header.IsSupportExtendedAdvertisement());
|
||||
EXPECT_EQ(kNumSlots, ble_advertisement_header.GetNumSlots());
|
||||
EXPECT_EQ(service_id_bloom_filter,
|
||||
ble_advertisement_header.GetServiceIdBloomFilter());
|
||||
@@ -161,7 +160,7 @@ TEST(BleAdvertisementHeaderTest, ConstructionFromSerializedStringWorks) {
|
||||
|
||||
EXPECT_TRUE(ble_advertisement_header.IsValid());
|
||||
EXPECT_EQ(kVersion, ble_advertisement_header.GetVersion());
|
||||
EXPECT_FALSE(ble_advertisement_header.IsExtendedAdvertisement());
|
||||
EXPECT_FALSE(ble_advertisement_header.IsSupportExtendedAdvertisement());
|
||||
EXPECT_EQ(kNumSlots, ble_advertisement_header.GetNumSlots());
|
||||
EXPECT_EQ(service_id_bloom_filter,
|
||||
ble_advertisement_header.GetServiceIdBloomFilter());
|
||||
@@ -188,7 +187,7 @@ TEST(BleAdvertisementHeaderTest, ConstructionFromExtraBytesWorks) {
|
||||
|
||||
EXPECT_TRUE(long_ble_advertisement_header.IsValid());
|
||||
EXPECT_EQ(kVersion, long_ble_advertisement_header.GetVersion());
|
||||
EXPECT_FALSE(ble_advertisement_header.IsExtendedAdvertisement());
|
||||
EXPECT_FALSE(ble_advertisement_header.IsSupportExtendedAdvertisement());
|
||||
EXPECT_EQ(kNumSlots, long_ble_advertisement_header.GetNumSlots());
|
||||
EXPECT_EQ(service_id_bloom_filter,
|
||||
long_ble_advertisement_header.GetServiceIdBloomFilter());
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "connections/implementation/mediums/ble_v2/discovered_peripheral_tracker.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@@ -84,6 +85,12 @@ void DiscoveredPeripheralTracker::ProcessFoundBleAdvertisement(
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsSkippableGattAdvertisement(advertisement_data)) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Ignore GATT advertisement and wait for extended advertisement.";
|
||||
return;
|
||||
}
|
||||
|
||||
HandleAdvertisement(peripheral, advertisement_data);
|
||||
HandleAdvertisementHeader(peripheral, advertisement_data,
|
||||
std::move(advertisement_fetcher));
|
||||
@@ -129,6 +136,21 @@ void DiscoveredPeripheralTracker::ClearDataForServiceId(
|
||||
}
|
||||
}
|
||||
|
||||
bool DiscoveredPeripheralTracker::IsSkippableGattAdvertisement(
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data) {
|
||||
if (!is_extended_advertisement_available_) {
|
||||
// Don't skip any advertisement if the scanner doesn't support extended
|
||||
// advertisement.
|
||||
return false;
|
||||
}
|
||||
|
||||
BleAdvertisementHeader advertisement_header(
|
||||
ExtractAdvertisementHeaderBytes(advertisement_data));
|
||||
|
||||
return advertisement_header.IsValid() &&
|
||||
advertisement_header.IsSupportExtendedAdvertisement();
|
||||
}
|
||||
|
||||
void DiscoveredPeripheralTracker::ClearGattAdvertisement(
|
||||
const BleAdvertisement& gatt_advertisement) {
|
||||
const auto gai_it = gatt_advertisement_infos_.find(gatt_advertisement);
|
||||
@@ -176,18 +198,17 @@ void DiscoveredPeripheralTracker::HandleAdvertisement(
|
||||
// First filter out kCopresenceServiceUuid and see if any Caller UUID
|
||||
// existed; if not then just take the kCopresenceServiceUuid as
|
||||
// |service_uuid|.
|
||||
std::vector<std::string> extracted_uuids;
|
||||
absl::flat_hash_map<std::string, location::nearby::ByteArray> extracted_uuids;
|
||||
// Filter out kCoprsence service uuid.
|
||||
std::remove_copy_if(advertisement_data.service_uuids.begin(),
|
||||
advertisement_data.service_uuids.end(),
|
||||
std::back_inserter(extracted_uuids),
|
||||
[](const std::string& advertisement_data_service_uuid) {
|
||||
return advertisement_data_service_uuid ==
|
||||
bleutils::kCopresenceServiceUuid;
|
||||
});
|
||||
std::remove_copy_if(
|
||||
advertisement_data.service_data.begin(),
|
||||
advertisement_data.service_data.end(),
|
||||
std::inserter(extracted_uuids, extracted_uuids.end()),
|
||||
[](const std::pair<const std::string, location::nearby::ByteArray>&
|
||||
pair) { return pair.first == bleutils::kCopresenceServiceUuid; });
|
||||
std::string service_uuid;
|
||||
if (!extracted_uuids.empty()) {
|
||||
service_uuid = extracted_uuids.front();
|
||||
service_uuid = extracted_uuids.begin()->first;
|
||||
} else {
|
||||
service_uuid = std::string(bleutils::kCopresenceServiceUuid);
|
||||
}
|
||||
@@ -214,9 +235,9 @@ ByteArray DiscoveredPeripheralTracker::ExtractInterestingAdvertisementBytes(
|
||||
// advertisements are contained within this BLE advertisement.
|
||||
for (const auto& item : service_id_infos_) {
|
||||
const ServiceIdInfo& service_id_info = item.second;
|
||||
// Check if there's service data for this fast advertisement
|
||||
// service UUID. If so, we can short-circuit since all BLE
|
||||
// advertisements can contain at most ONE fast advertisement.
|
||||
// Check if there's service data for this fast advertisement service UUID.
|
||||
// If so, we can short-circuit since all BLE advertisements can contain at
|
||||
// most ONE fast advertisement.
|
||||
const auto sd_it = advertisement_data.service_data.find(
|
||||
service_id_info.fast_advertisement_service_uuid);
|
||||
if (sd_it != advertisement_data.service_data.end()) {
|
||||
@@ -410,10 +431,7 @@ bool DiscoveredPeripheralTracker::ShouldRemoveHeader(
|
||||
// remove the physical header for the new incoming regular extended
|
||||
// advertisement. Otherwise, it make the device to fetch advertisement when
|
||||
// received a physical header again.
|
||||
// TODO(b/213835576) : Implement API to fetch the support for extended
|
||||
// advertisement from platform impl.
|
||||
bool is_extended_advertisement_available = false;
|
||||
if (is_extended_advertisement_available) {
|
||||
if (is_extended_advertisement_available_) {
|
||||
if (!IsDummyAdvertisementHeader(old_advertisement_header) &&
|
||||
IsDummyAdvertisementHeader(new_advertisement_header)) {
|
||||
return false;
|
||||
|
||||
@@ -59,6 +59,11 @@ class DiscoveredPeripheralTracker {
|
||||
mediums::AdvertisementReadResult&>();
|
||||
};
|
||||
|
||||
explicit DiscoveredPeripheralTracker(
|
||||
bool is_extended_advertisement_available = false)
|
||||
: is_extended_advertisement_available_(
|
||||
is_extended_advertisement_available) {}
|
||||
|
||||
// Starts tracking discoveries for a particular service Id.
|
||||
//
|
||||
// service_id - The service ID to track.
|
||||
@@ -138,6 +143,13 @@ class DiscoveredPeripheralTracker {
|
||||
void ClearDataForServiceId(const std::string& service_id)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Returns true if `advertisement_data` is AdvertisementHeader and is marked
|
||||
// as exented_advertisement. This is to avoid reading advertisement from GATT
|
||||
// connection, which has been advertised by extended advertisement.
|
||||
bool IsSkippableGattAdvertisement(
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data)
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
// Clears out all data related to the provided GATT advertisement. This
|
||||
// includes:
|
||||
// 1. Removing the corresponding GATT advertisement from
|
||||
@@ -237,6 +249,7 @@ class DiscoveredPeripheralTracker {
|
||||
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
|
||||
|
||||
Mutex mutex_;
|
||||
bool is_extended_advertisement_available_;
|
||||
|
||||
// ------------ SERVICE ID MAPS ------------
|
||||
// Entries in these maps all follow the same lifecycle. Entries are added in
|
||||
|
||||
@@ -211,8 +211,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -252,8 +250,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -298,8 +294,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -357,14 +351,10 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -406,8 +396,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
@@ -444,8 +432,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
@@ -492,8 +478,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
@@ -540,8 +524,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
@@ -585,8 +567,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
@@ -636,14 +616,10 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -700,14 +676,10 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -761,8 +733,6 @@ TEST_F(DiscoveredPeripheralTrackerTest, LostPeripheralForAdvertisementLost) {
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
@@ -841,14 +811,10 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
if (!fast_advertisement_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kFastAdvertisementServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kFastAdvertisementServiceUuid), fast_advertisement_bytes});
|
||||
}
|
||||
@@ -907,8 +873,6 @@ TEST_F(DiscoveredPeripheralTrackerTest,
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertisement_header_bytes.Empty()) {
|
||||
advertisement_data.service_uuids.insert(
|
||||
std::string(kCopresenceServiceUuid));
|
||||
advertisement_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes});
|
||||
}
|
||||
|
||||
@@ -28,26 +28,26 @@ namespace nearby {
|
||||
|
||||
using ::location::nearby::api::ble_v2::BleAdvertisementData;
|
||||
using ::location::nearby::api::ble_v2::GattCharacteristic;
|
||||
using ::location::nearby::api::ble_v2::PowerMode;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
|
||||
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);
|
||||
api::ble_v2::AdvertiseParameters advertise_parameters) {
|
||||
return impl_->StartAdvertising(advertising_data, advertise_parameters);
|
||||
}
|
||||
|
||||
bool BleV2Medium::StopAdvertising() { return impl_->StopAdvertising(); }
|
||||
|
||||
bool BleV2Medium::StartScanning(const std::string& service_uuid,
|
||||
PowerMode power_mode, ScanCallback callback) {
|
||||
TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) {
|
||||
MutexLock lock(&mutex_);
|
||||
if (scanning_enabled_) {
|
||||
NEARBY_LOGS(INFO) << "Ble Scanning already enabled; impl=" << GetImpl();
|
||||
return false;
|
||||
}
|
||||
bool success = impl_->StartScanning(
|
||||
service_uuid, power_mode,
|
||||
service_uuid, tx_power_level,
|
||||
{
|
||||
.advertisement_found_cb =
|
||||
[this](api::ble_v2::BlePeripheral& peripheral,
|
||||
@@ -119,7 +119,7 @@ std::unique_ptr<GattServer> BleV2Medium::StartGattServer(
|
||||
}
|
||||
|
||||
std::unique_ptr<GattClient> BleV2Medium::ConnectToGattServer(
|
||||
BleV2Peripheral peripheral, PowerMode power_mode,
|
||||
BleV2Peripheral peripheral, TxPowerLevel tx_power_level,
|
||||
ClientGattConnectionCallback callback) {
|
||||
{
|
||||
MutexLock lock(&mutex_);
|
||||
@@ -128,7 +128,7 @@ std::unique_ptr<GattClient> BleV2Medium::ConnectToGattServer(
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattClient> api_gatt_client =
|
||||
impl_->ConnectToGattServer(
|
||||
peripheral.GetImpl(), power_mode,
|
||||
peripheral.GetImpl(), tx_power_level,
|
||||
{
|
||||
.disconnected_cb =
|
||||
[this]() {
|
||||
@@ -139,5 +139,9 @@ std::unique_ptr<GattClient> BleV2Medium::ConnectToGattServer(
|
||||
return std::make_unique<GattClient>(std::move(api_gatt_client));
|
||||
}
|
||||
|
||||
bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
|
||||
return impl_->IsExtendedAdvertisementsAvailable();
|
||||
}
|
||||
|
||||
} // namespace nearby
|
||||
} // namespace location
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "internal/platform/bluetooth_adapter.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/platform.h"
|
||||
#include "internal/platform/mutex.h"
|
||||
|
||||
namespace location {
|
||||
@@ -153,13 +154,13 @@ class BleV2Medium final {
|
||||
// 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);
|
||||
api::ble_v2::AdvertiseParameters advertise_parameters);
|
||||
bool StopAdvertising();
|
||||
|
||||
// Returns true once the BLE scan has been initiated.
|
||||
bool StartScanning(const std::string& service_uuid,
|
||||
api::ble_v2::PowerMode power_mode, ScanCallback callback);
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanCallback callback);
|
||||
bool StopScanning();
|
||||
|
||||
// Starts Gatt Server for waiting to client connection.
|
||||
@@ -169,9 +170,11 @@ class BleV2Medium final {
|
||||
// Returns a new GattClient connection to a gatt server.
|
||||
// There is only one instance of GattServer can run at a time.
|
||||
std::unique_ptr<GattClient> ConnectToGattServer(
|
||||
BleV2Peripheral peripheral, api::ble_v2::PowerMode power_mode,
|
||||
BleV2Peripheral peripheral, api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ClientGattConnectionCallback callback);
|
||||
|
||||
bool IsExtendedAdvertisementsAvailable();
|
||||
|
||||
bool IsValid() const { return impl_ != nullptr; }
|
||||
|
||||
api::ble_v2::BleMedium* GetImpl() const { return impl_.get(); }
|
||||
|
||||
@@ -30,13 +30,14 @@ namespace {
|
||||
|
||||
using ::location::nearby::api::ble_v2::BleAdvertisementData;
|
||||
using ::location::nearby::api::ble_v2::GattCharacteristic;
|
||||
using ::location::nearby::api::ble_v2::PowerMode;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
using ::testing::Optional;
|
||||
|
||||
constexpr absl::Duration kWaitDuration = absl::Milliseconds(1000);
|
||||
constexpr absl::string_view kAdvertisementString = "\x0a\x0b\x0c\x0d";
|
||||
constexpr absl::string_view kAdvertisementHeaderString = "\x0x\x0y\x0z";
|
||||
constexpr absl::string_view kCopresenceServiceUuid = "F3FE";
|
||||
constexpr PowerMode kPowerMode(PowerMode::kHigh);
|
||||
constexpr TxPowerLevel kTxPowerLevel(TxPowerLevel::kHigh);
|
||||
|
||||
// A stub BlePeripheral implementation.
|
||||
class BlePeripheralStub : public api::ble_v2::BlePeripheral {
|
||||
@@ -80,10 +81,11 @@ TEST_F(BleV2MediumTest, CanStartFastScanningAndFastAdvertising) {
|
||||
BluetoothAdapter adapter_b;
|
||||
BleV2Medium ble_a(adapter_a);
|
||||
BleV2Medium ble_b(adapter_b);
|
||||
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
|
||||
CountDownLatch found_latch(1);
|
||||
|
||||
EXPECT_TRUE(ble_a.StartScanning(
|
||||
std::string(kCopresenceServiceUuid), kPowerMode,
|
||||
{std::string(kCopresenceServiceUuid)}, kTxPowerLevel,
|
||||
{
|
||||
.advertisement_found_cb =
|
||||
[&found_latch](BleV2Peripheral peripheral,
|
||||
@@ -92,16 +94,23 @@ TEST_F(BleV2MediumTest, CanStartFastScanningAndFastAdvertising) {
|
||||
},
|
||||
}));
|
||||
|
||||
// Assemble fast advertising and scan response data.
|
||||
// Fail to start extended advertisement due to g3 Ble medium does not support.
|
||||
BleAdvertisementData advertising_data;
|
||||
advertising_data.service_uuids.insert(std::string(kCopresenceServiceUuid));
|
||||
BleAdvertisementData scan_response_data;
|
||||
scan_response_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid),
|
||||
ByteArray(std::string(kAdvertisementString))});
|
||||
advertising_data.is_extended_advertisement = true;
|
||||
advertising_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_bytes});
|
||||
EXPECT_FALSE(ble_b.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = kTxPowerLevel, .is_connectable = true}));
|
||||
|
||||
// Succeed to start regular advertisement.
|
||||
advertising_data.is_extended_advertisement = false;
|
||||
advertising_data.service_data = {
|
||||
{std::string(kCopresenceServiceUuid), advertisement_bytes}};
|
||||
EXPECT_TRUE(ble_b.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = kTxPowerLevel, .is_connectable = true}));
|
||||
|
||||
EXPECT_TRUE(
|
||||
ble_b.StartAdvertising(advertising_data, scan_response_data, kPowerMode));
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_TRUE(ble_a.StopScanning());
|
||||
EXPECT_TRUE(ble_b.StopAdvertising());
|
||||
@@ -114,10 +123,12 @@ TEST_F(BleV2MediumTest, CanStartScanningAndAdvertising) {
|
||||
BluetoothAdapter adapter_b;
|
||||
BleV2Medium ble_a(adapter_a);
|
||||
BleV2Medium ble_b(adapter_b);
|
||||
ByteArray advertisement_bytes{std::string(kAdvertisementString)};
|
||||
ByteArray advertisement_header_bytes{std::string(kAdvertisementHeaderString)};
|
||||
CountDownLatch found_latch(1);
|
||||
|
||||
EXPECT_TRUE(ble_a.StartScanning(
|
||||
std::string(kCopresenceServiceUuid), kPowerMode,
|
||||
{std::string(kCopresenceServiceUuid)}, kTxPowerLevel,
|
||||
{
|
||||
.advertisement_found_cb =
|
||||
[&found_latch](BleV2Peripheral peripheral,
|
||||
@@ -126,16 +137,23 @@ TEST_F(BleV2MediumTest, CanStartScanningAndAdvertising) {
|
||||
},
|
||||
}));
|
||||
|
||||
// Assemble regular advertising and scan response data.
|
||||
BleAdvertisementData advertising_data = {};
|
||||
BleAdvertisementData scan_response_data;
|
||||
scan_response_data.service_uuids.insert(std::string(kCopresenceServiceUuid));
|
||||
scan_response_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid),
|
||||
ByteArray(std::string(kAdvertisementString))});
|
||||
// Fail to start extended advertisement due to g3 Ble medium does not support.
|
||||
BleAdvertisementData advertising_data;
|
||||
advertising_data.is_extended_advertisement = true;
|
||||
advertising_data.service_data.insert(
|
||||
{std::string(kCopresenceServiceUuid), advertisement_bytes});
|
||||
EXPECT_FALSE(ble_b.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = kTxPowerLevel, .is_connectable = true}));
|
||||
|
||||
// Succeed to start regular advertisement.
|
||||
advertising_data.is_extended_advertisement = false;
|
||||
advertising_data.service_data = {
|
||||
{std::string(kCopresenceServiceUuid), advertisement_header_bytes}};
|
||||
EXPECT_TRUE(ble_b.StartAdvertising(
|
||||
advertising_data,
|
||||
{.tx_power_level = kTxPowerLevel, .is_connectable = true}));
|
||||
|
||||
EXPECT_TRUE(
|
||||
ble_b.StartAdvertising(advertising_data, scan_response_data, kPowerMode));
|
||||
EXPECT_TRUE(found_latch.Await(kWaitDuration).result());
|
||||
EXPECT_TRUE(ble_a.StopScanning());
|
||||
EXPECT_TRUE(ble_b.StopAdvertising());
|
||||
@@ -145,7 +163,7 @@ TEST_F(BleV2MediumTest, CanStartScanningAndAdvertising) {
|
||||
TEST_F(BleV2MediumTest, CanStartGattServer) {
|
||||
env_.Start();
|
||||
BluetoothAdapter adapter;
|
||||
BleV2Medium ble{adapter};
|
||||
BleV2Medium ble(adapter);
|
||||
std::string characteristic_uuid = "characteristic_uuid";
|
||||
|
||||
std::unique_ptr<GattServer> gatt_server =
|
||||
@@ -157,6 +175,7 @@ TEST_F(BleV2MediumTest, CanStartGattServer) {
|
||||
GattCharacteristic::Permission::kRead};
|
||||
std::vector<GattCharacteristic::Property> properties = {
|
||||
GattCharacteristic::Property::kRead};
|
||||
// NOLINTNEXTLINE(google3-legacy-absl-backports)
|
||||
absl::optional<GattCharacteristic> gatt_characteristic =
|
||||
gatt_server->CreateCharacteristic(std::string(kCopresenceServiceUuid),
|
||||
characteristic_uuid, permissions,
|
||||
@@ -207,7 +226,7 @@ TEST_F(BleV2MediumTest, GattClientConnectToGattServerWorks) {
|
||||
auto ble_peripheral =
|
||||
std::make_unique<BlePeripheralStub>(/*mac_address=*/"ABCD");
|
||||
std::unique_ptr<GattClient> gatt_client = ble_b.ConnectToGattServer(
|
||||
BleV2Peripheral(ble_peripheral.get()), kPowerMode,
|
||||
BleV2Peripheral(ble_peripheral.get()), kTxPowerLevel,
|
||||
/*ClientGattConnectionCallback=*/{});
|
||||
|
||||
ASSERT_NE(gatt_client, nullptr);
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include <string>
|
||||
|
||||
#include "absl/container/flat_hash_map.h"
|
||||
#include "absl/container/flat_hash_set.h"
|
||||
#include "absl/strings/string_view.h"
|
||||
#include "internal/platform/byte_array.h"
|
||||
#include "internal/platform/exception.h"
|
||||
@@ -38,7 +37,7 @@ namespace api {
|
||||
namespace ble_v2 {
|
||||
|
||||
// Coarse representation of power settings throughout all BLE operations.
|
||||
enum class PowerMode {
|
||||
enum class TxPowerLevel {
|
||||
kUnknown = 0,
|
||||
kUltraLow = 1,
|
||||
kLow = 2,
|
||||
@@ -46,6 +45,16 @@ enum class PowerMode {
|
||||
kHigh = 4,
|
||||
};
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/le/AdvertisingSetParameters.Builder
|
||||
//
|
||||
// The preferences for Advertising.
|
||||
struct AdvertiseParameters {
|
||||
// The transmission power level for the advertising.
|
||||
TxPowerLevel tx_power_level;
|
||||
// Whether the advertisement type should be connectable or non-connectable.
|
||||
bool is_connectable;
|
||||
};
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/le/AdvertiseData
|
||||
//
|
||||
// Bundle of data found in a BLE advertisement.
|
||||
@@ -54,27 +63,17 @@ enum class PowerMode {
|
||||
// 0000xxxx-0000-1000-8000-00805F9B34FB. This makes it possible to store two
|
||||
// byte service UUIDs in the advertisement.
|
||||
struct BleAdvertisementData {
|
||||
using TxPowerLevel = std::int8_t;
|
||||
|
||||
static constexpr TxPowerLevel kUnspecifiedTxPowerLevel =
|
||||
std::numeric_limits<TxPowerLevel>::min();
|
||||
|
||||
bool is_connectable;
|
||||
|
||||
// If tx_power_level is not set to kUnspecifiedTxPowerLevel, platform
|
||||
// implementer needs to set the TxPowerLevel.
|
||||
TxPowerLevel tx_power_level;
|
||||
|
||||
// If the set is not empty, the platform implementer needs to add the
|
||||
// service_uuids in the advertisement data.
|
||||
absl::flat_hash_set<std::string> service_uuids;
|
||||
// Broadcasts a BLE extended advertisement if it is true.
|
||||
bool is_extended_advertisement;
|
||||
|
||||
// Maps service UUIDs to their service data.
|
||||
//
|
||||
// Note if platform can't advertise data from Data type (0x16)
|
||||
// (reaonly in iOS), then (iOS) should advertise data via LocalName data
|
||||
// type (0x08). It means the iOS should take the first index of service_data
|
||||
// as the data for LocalName type.
|
||||
// For each platform should follow to set the service UUID(key) and service
|
||||
// data(value):
|
||||
//
|
||||
// iOS : 16 bit service UUID (type=0x03) + LocalName data (type=0x08)
|
||||
// Windows: Service data (type=0x16)
|
||||
// Android: 16 bit service UUID (type=0x03) + Service data (type=0x16)
|
||||
absl::flat_hash_map<std::string, location::nearby::ByteArray> service_data;
|
||||
};
|
||||
|
||||
@@ -274,15 +273,9 @@ class BleMedium {
|
||||
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#startAdvertising(android.bluetooth.le.AdvertiseSettings,%20android.bluetooth.le.AdvertiseData,%20android.bluetooth.le.AdvertiseData,%20android.bluetooth.le.AdvertiseCallback)
|
||||
//
|
||||
// Starts BLE advertising and returns whether or not it was successful.
|
||||
//
|
||||
// Power mode should be interpreted in the following way:
|
||||
// LOW:
|
||||
// - TX power = medium
|
||||
// HIGH:
|
||||
// - TX power = high
|
||||
virtual bool StartAdvertising(const BleAdvertisementData& advertising_data,
|
||||
const BleAdvertisementData& scan_response_data,
|
||||
PowerMode power_mode) = 0;
|
||||
virtual bool StartAdvertising(
|
||||
const BleAdvertisementData& advertising_data,
|
||||
AdvertiseParameters advertise_set_parameters) = 0;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeAdvertiser.html#stopAdvertising(android.bluetooth.le.AdvertiseCallback)
|
||||
//
|
||||
@@ -312,7 +305,7 @@ class BleMedium {
|
||||
//
|
||||
// Starts scanning and returns whether or not it was successful.
|
||||
//
|
||||
// Power mode should be interpreted in the following way:
|
||||
// TX Power level should be interpreted in the following way:
|
||||
// LOW:
|
||||
// - Scan window = ~512ms
|
||||
// - Scan interval = ~5120ms
|
||||
@@ -320,7 +313,8 @@ class BleMedium {
|
||||
// - Scan window = ~4096ms
|
||||
// - Scan interval = ~4096ms
|
||||
virtual bool StartScanning(const std::string& service_uuid,
|
||||
PowerMode power_mode, ScanCallback callback) = 0;
|
||||
TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) = 0;
|
||||
|
||||
// https://developer.android.com/reference/android/bluetooth/le/BluetoothLeScanner.html#stopScan(android.bluetooth.le.ScanCallback)
|
||||
//
|
||||
@@ -347,13 +341,13 @@ class BleMedium {
|
||||
// Connects to a GATT server and negotiates the specified connection
|
||||
// parameters. Returns nullptr upon error.
|
||||
//
|
||||
// Power mode should be interpreted in the following way:
|
||||
// TX Power level should be interpreted in the following way:
|
||||
// HIGH:
|
||||
// - Connection interval = ~11.25ms - 15ms
|
||||
// LOW:
|
||||
// - Connection interval = ~100ms - 125ms
|
||||
virtual std::unique_ptr<GattClient> ConnectToGattServer(
|
||||
BlePeripheral& peripheral, PowerMode power_mode,
|
||||
BlePeripheral& peripheral, TxPowerLevel tx_power_level,
|
||||
ClientGattConnectionCallback callback) = 0;
|
||||
|
||||
// Establishes a BLE socket to the specified remote peripheral. Returns
|
||||
@@ -361,6 +355,9 @@ class BleMedium {
|
||||
virtual std::unique_ptr<BleSocket> EstablishBleSocket(
|
||||
BlePeripheral* peripheral,
|
||||
const BleSocketLifeCycleCallback& callback) = 0;
|
||||
|
||||
// Requests if support extended advertisement.
|
||||
virtual bool IsExtendedAdvertisementsAvailable() = 0;
|
||||
};
|
||||
|
||||
} // namespace ble_v2
|
||||
|
||||
@@ -35,19 +35,19 @@ namespace {
|
||||
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::PowerMode;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
|
||||
std::string PowerModeToName(PowerMode power_mode) {
|
||||
std::string TxPowerLevelToName(TxPowerLevel power_mode) {
|
||||
switch (power_mode) {
|
||||
case PowerMode::kUltraLow:
|
||||
case TxPowerLevel::kUltraLow:
|
||||
return "UltraLow";
|
||||
case PowerMode::kLow:
|
||||
case TxPowerLevel::kLow:
|
||||
return "Low";
|
||||
case PowerMode::kMedium:
|
||||
case TxPowerLevel::kMedium:
|
||||
return "Medium";
|
||||
case PowerMode::kHigh:
|
||||
case TxPowerLevel::kHigh:
|
||||
return "High";
|
||||
case PowerMode::kUnknown:
|
||||
case TxPowerLevel::kUnknown:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
@@ -67,28 +67,24 @@ BleV2Medium::~BleV2Medium() {
|
||||
|
||||
bool BleV2Medium::StartAdvertising(
|
||||
const BleAdvertisementData& advertising_data,
|
||||
const BleAdvertisementData& scan_response_data, PowerMode power_mode) {
|
||||
api::ble_v2::AdvertiseParameters advertise_parameters) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "G3 Ble StartAdvertising:, advertising_data.service_uuids size="
|
||||
<< advertising_data.service_uuids.size()
|
||||
<< ", scan_response_data.service_data size="
|
||||
<< scan_response_data.service_data.size()
|
||||
<< ", power_mode=" << PowerModeToName(power_mode);
|
||||
<< "G3 Ble StartAdvertising: advertising_data.is_extended_advertisement="
|
||||
<< advertising_data.is_extended_advertisement
|
||||
<< ", advertising_data.service_data size="
|
||||
<< advertising_data.service_data.size() << ", tx_power_level="
|
||||
<< TxPowerLevelToName(advertise_parameters.tx_power_level)
|
||||
<< ", is_connectable=" << advertise_parameters.is_connectable;
|
||||
if (advertising_data.is_extended_advertisement &&
|
||||
!is_support_extended_advertisement_) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "G3 Ble StartAdvertising does not support extended advertisement";
|
||||
return false;
|
||||
}
|
||||
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
// Reassemble advertisement data from advertising and scan response
|
||||
// data.
|
||||
api::ble_v2::BleAdvertisementData advertisement_data;
|
||||
if (!advertising_data.service_uuids.empty()) {
|
||||
advertisement_data.service_uuids = advertising_data.service_uuids;
|
||||
} else {
|
||||
advertisement_data.service_uuids = scan_response_data.service_uuids;
|
||||
}
|
||||
advertisement_data.service_data = scan_response_data.service_data;
|
||||
|
||||
MediumEnvironment::Instance().UpdateBleV2MediumForAdvertising(
|
||||
/*enabled=*/true, *this, adapter_->GetPeripheralV2(), advertisement_data);
|
||||
/*enabled=*/true, *this, adapter_->GetPeripheralV2(), advertising_data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -104,7 +100,8 @@ bool BleV2Medium::StopAdvertising() {
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartScanning(const std::string& service_uuid,
|
||||
PowerMode power_mode, ScanCallback callback) {
|
||||
TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) {
|
||||
NEARBY_LOGS(INFO) << "G3 Ble StartScanning";
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
@@ -136,7 +133,7 @@ bool BleV2Medium::StartListeningForIncomingBleSockets(
|
||||
void BleV2Medium::StopListeningForIncomingBleSockets() {}
|
||||
|
||||
std::unique_ptr<api::ble_v2::GattClient> BleV2Medium::ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral, PowerMode power_mode,
|
||||
api::ble_v2::BlePeripheral& peripheral, TxPowerLevel tx_power_level,
|
||||
api::ble_v2::ClientGattConnectionCallback callback) {
|
||||
return std::make_unique<GattClient>();
|
||||
}
|
||||
@@ -147,6 +144,10 @@ std::unique_ptr<BleSocket> BleV2Medium::EstablishBleSocket(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool BleV2Medium::IsExtendedAdvertisementsAvailable() {
|
||||
return is_support_extended_advertisement_;
|
||||
}
|
||||
|
||||
std::optional<api::ble_v2::GattCharacteristic>
|
||||
BleV2Medium::GattServer::CreateCharacteristic(
|
||||
absl::string_view service_uuid, absl::string_view characteristic_uuid,
|
||||
|
||||
@@ -38,12 +38,12 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
// 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_);
|
||||
api::ble_v2::AdvertiseParameters advertise_parameters) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool StartScanning(const std::string& service_uuid,
|
||||
api::ble_v2::PowerMode power_mode,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopScanning() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
@@ -56,7 +56,8 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
void StopListeningForIncomingBleSockets() override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::GattClient> ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral, api::ble_v2::PowerMode power_mode,
|
||||
api::ble_v2::BlePeripheral& peripheral,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
api::ble_v2::ClientGattConnectionCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::BleSocket> EstablishBleSocket(
|
||||
@@ -64,6 +65,8 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
const api::ble_v2::BleSocketLifeCycleCallback& callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool IsExtendedAdvertisementsAvailable() override;
|
||||
|
||||
BluetoothAdapter& GetAdapter() { return *adapter_; }
|
||||
|
||||
private:
|
||||
@@ -113,6 +116,8 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
|
||||
absl::Mutex mutex_;
|
||||
BluetoothAdapter* adapter_; // Our device adapter; read-only.
|
||||
// TODO(edwinwu): Adds extended advertisement for testing.
|
||||
bool is_support_extended_advertisement_ = false;
|
||||
};
|
||||
|
||||
} // namespace g3
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include "absl/synchronization/mutex.h"
|
||||
#include "internal/platform/implementation/ble_v2.h"
|
||||
#include "internal/platform/implementation/shared/count_down_latch.h"
|
||||
#include "internal/platform/logging.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.Advertisement.h"
|
||||
#include "winrt/Windows.Devices.Bluetooth.h"
|
||||
@@ -32,12 +31,13 @@ namespace windows {
|
||||
|
||||
namespace {
|
||||
|
||||
using ::location::nearby::api::ble_v2::AdvertiseParameters;
|
||||
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::GattClient;
|
||||
using ::location::nearby::api::ble_v2::PowerMode;
|
||||
using ::location::nearby::api::ble_v2::ServerGattConnectionCallback;
|
||||
using ::location::nearby::api::ble_v2::TxPowerLevel;
|
||||
using ::winrt::Windows::Devices::Bluetooth::BluetoothError;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisement;
|
||||
@@ -61,22 +61,23 @@ using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEAdvertisementWatcherStoppedEventArgs;
|
||||
using ::winrt::Windows::Devices::Bluetooth::Advertisement::
|
||||
BluetoothLEScanningMode;
|
||||
using ::winrt::Windows::Storage::Streams::Buffer;
|
||||
using ::winrt::Windows::Storage::Streams::DataWriter;
|
||||
|
||||
template <typename T>
|
||||
using IVector = winrt::Windows::Foundation::Collections::IVector<T>;
|
||||
|
||||
std::string PowerModeToName(PowerMode power_mode) {
|
||||
switch (power_mode) {
|
||||
case PowerMode::kUltraLow:
|
||||
std::string TxPowerLevelToName(TxPowerLevel tx_power_level) {
|
||||
switch (tx_power_level) {
|
||||
case TxPowerLevel::kUltraLow:
|
||||
return "UltraLow";
|
||||
case PowerMode::kLow:
|
||||
case TxPowerLevel::kLow:
|
||||
return "Low";
|
||||
case PowerMode::kMedium:
|
||||
case TxPowerLevel::kMedium:
|
||||
return "Medium";
|
||||
case PowerMode::kHigh:
|
||||
case TxPowerLevel::kHigh:
|
||||
return "High";
|
||||
case PowerMode::kUnknown:
|
||||
case TxPowerLevel::kUnknown:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
@@ -90,66 +91,33 @@ BleV2Medium::BleV2Medium(api::BluetoothAdapter& adapter)
|
||||
|
||||
BleV2Medium::~BleV2Medium() {}
|
||||
|
||||
// TODO(edwinwu): Modify advertising abstraction APIs and fit all data into one
|
||||
// advertisement packet and populate accordingly
|
||||
bool BleV2Medium::StartAdvertising(
|
||||
const BleAdvertisementData& advertising_data,
|
||||
const BleAdvertisementData& scan_response_data, PowerMode power_mode) {
|
||||
bool BleV2Medium::StartAdvertising(const BleAdvertisementData& advertising_data,
|
||||
AdvertiseParameters advertising_parameters) {
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "Windows Ble StartAdvertising:, advertising_data.service_uuids size="
|
||||
<< advertising_data.service_uuids.size()
|
||||
<< ", scan_response_data.service_data size="
|
||||
<< scan_response_data.service_data.size()
|
||||
<< ", power_mode=" << PowerModeToName(power_mode);
|
||||
<< "Windows Ble StartAdvertising:, advertising_data.service_data size="
|
||||
<< advertising_data.service_data.size() << ", tx_power_level="
|
||||
<< TxPowerLevelToName(advertising_parameters.tx_power_level);
|
||||
|
||||
if (advertising_data.service_data.empty()) return false;
|
||||
|
||||
absl::MutexLock lock(&mutex_);
|
||||
|
||||
// (AD type 0x16) Service Data
|
||||
constexpr uint8_t kCopresenceServiceUuid[] = {0xf3, 0xfe};
|
||||
DataWriter data_writer;
|
||||
auto it = advertising_data.service_data.begin();
|
||||
const std::string& service_uuid = it->first;
|
||||
const ByteArray& service_bytes = it->second;
|
||||
|
||||
// (2 bytes) 16-bit Service UUID 0xf3fe
|
||||
data_writer.WriteByte(kCopresenceServiceUuid[1]); // 0xfe
|
||||
data_writer.WriteByte(kCopresenceServiceUuid[0]); // 0xf3
|
||||
|
||||
// (1 byte) version [3-bits] + socket_version [3-bits] +
|
||||
// fast_advertisement_flag [1-bit] + reserved [1-bit]
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (1 byte) body_length
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (1 byte) Nearby Connection version [3-bits] + pcp [5-bits]
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (4 bytes) endpoint_id
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
if (service_uuid.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
data_writer.WriteByte(service_uuid[0]);
|
||||
data_writer.WriteByte(service_uuid[1]);
|
||||
|
||||
// (1 byte) endpoint_info_size
|
||||
data_writer.WriteByte(0x11); // always 17-bytes for Fast Advertisement
|
||||
|
||||
// =========endpoint_info [17-bytes]============
|
||||
// (1 byte) Nearby Share version [3-bits] + visibility [1-bit] + reserved
|
||||
// [4-bits]
|
||||
data_writer.WriteByte(0x00);
|
||||
|
||||
// (2 bytes) salt
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
|
||||
// (14 bytes) encrypted_metadata_key
|
||||
for (int i = 0; i < 14; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
// =========endpoint_info [17-bytes]============
|
||||
|
||||
// (2 bytes) device_token
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
data_writer.WriteByte(0x00);
|
||||
}
|
||||
Buffer buffer(service_bytes.size());
|
||||
std::memcpy(buffer.data(), service_bytes.data(), service_bytes.size());
|
||||
data_writer.WriteBuffer(buffer);
|
||||
|
||||
BluetoothLEAdvertisementDataSection service_data =
|
||||
BluetoothLEAdvertisementDataSection(0x16, data_writer.DetachBuffer());
|
||||
@@ -217,7 +185,8 @@ bool BleV2Medium::StopAdvertising() {
|
||||
}
|
||||
|
||||
bool BleV2Medium::StartScanning(const std::string& service_uuid,
|
||||
PowerMode power_mode, ScanCallback callback) {
|
||||
TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) {
|
||||
NEARBY_LOGS(INFO) << "Windows Ble StartScanning";
|
||||
absl::MutexLock lock(&mutex_);
|
||||
watcher_started_callback_ = [this]() {
|
||||
@@ -290,7 +259,7 @@ bool BleV2Medium::StartListeningForIncomingBleSockets(
|
||||
void BleV2Medium::StopListeningForIncomingBleSockets() {}
|
||||
|
||||
std::unique_ptr<GattClient> BleV2Medium::ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral, PowerMode power_mode,
|
||||
api::ble_v2::BlePeripheral& peripheral, TxPowerLevel tx_power_level,
|
||||
api::ble_v2::ClientGattConnectionCallback callback) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -19,9 +19,6 @@
|
||||
#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"
|
||||
@@ -49,12 +46,12 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
// 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_);
|
||||
api::ble_v2::AdvertiseParameters advertising_parameters) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopAdvertising() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
bool StartScanning(const std::string& service_uuid,
|
||||
api::ble_v2::PowerMode power_mode,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
ScanCallback callback) override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
bool StopScanning() override ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
@@ -67,13 +64,15 @@ class BleV2Medium : public api::ble_v2::BleMedium {
|
||||
void StopListeningForIncomingBleSockets() override
|
||||
ABSL_LOCKS_EXCLUDED(mutex_);
|
||||
std::unique_ptr<api::ble_v2::GattClient> ConnectToGattServer(
|
||||
api::ble_v2::BlePeripheral& peripheral, api::ble_v2::PowerMode power_mode,
|
||||
api::ble_v2::BlePeripheral& peripheral,
|
||||
api::ble_v2::TxPowerLevel tx_power_level,
|
||||
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_);
|
||||
bool IsExtendedAdvertisementsAvailable() override { return false; }
|
||||
|
||||
BluetoothAdapter& GetAdapter() { return *adapter_; }
|
||||
|
||||
|
||||
@@ -34,7 +34,8 @@ TEST(BleV2Medium, DISABLED_StartAdvertising) {
|
||||
api::ble_v2::BleAdvertisementData scan_response_data;
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartAdvertising(
|
||||
advertising_data, scan_response_data, api::ble_v2::PowerMode::kHigh));
|
||||
advertising_data, {.tx_power_level = api::ble_v2::TxPowerLevel::kHigh,
|
||||
.is_connectable = true}));
|
||||
}
|
||||
|
||||
TEST(BleV2Medium, DISABLED_StopAdvertising) {
|
||||
@@ -42,10 +43,10 @@ TEST(BleV2Medium, DISABLED_StopAdvertising) {
|
||||
BleV2Medium blev2_medium(bluetoothAdapter);
|
||||
|
||||
api::ble_v2::BleAdvertisementData advertising_data;
|
||||
api::ble_v2::BleAdvertisementData scan_response_data;
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartAdvertising(
|
||||
advertising_data, scan_response_data, api::ble_v2::PowerMode::kHigh));
|
||||
advertising_data, {.tx_power_level = api::ble_v2::TxPowerLevel::kHigh,
|
||||
.is_connectable = true}));
|
||||
EXPECT_TRUE(blev2_medium.StopAdvertising());
|
||||
}
|
||||
|
||||
@@ -67,7 +68,7 @@ TEST(BleV2Medium, DISABLED_StartScanning) {
|
||||
};
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartScanning(
|
||||
service_uuid, api::ble_v2::PowerMode::kHigh, callback));
|
||||
service_uuid, api::ble_v2::TxPowerLevel::kHigh, callback));
|
||||
|
||||
EXPECT_TRUE(scan_response_notification.WaitForNotificationWithTimeout(
|
||||
absl::Seconds(5)));
|
||||
@@ -85,7 +86,7 @@ TEST(BleV2Medium, DISABLED_StopScanning) {
|
||||
const api::ble_v2::BleAdvertisementData& advertisement_data) {};
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StartScanning(
|
||||
service_uuid, api::ble_v2::PowerMode::kHigh, callback));
|
||||
service_uuid, api::ble_v2::TxPowerLevel::kHigh, callback));
|
||||
|
||||
EXPECT_TRUE(blev2_medium.StopScanning());
|
||||
}
|
||||
|
||||
@@ -539,9 +539,9 @@ void MediumEnvironment::UpdateBleV2MediumForAdvertising(
|
||||
BleV2MediumContext& remote_context = medium_info.second;
|
||||
// Do not send notification to the same medium.
|
||||
if (remote_medium == &medium) continue;
|
||||
if (!context.advertisement_data.service_uuids.contains(
|
||||
remote_context.scanning_service_uuid))
|
||||
continue;
|
||||
auto const it = context.advertisement_data.service_data.find(
|
||||
remote_context.scanning_service_uuid);
|
||||
if (it == context.advertisement_data.service_data.end()) continue;
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "G3 UpdateBleV2MediumForAdvertising, found other medium="
|
||||
<< remote_medium << ", remote_medium_context=" << &remote_context
|
||||
@@ -583,8 +583,9 @@ void MediumEnvironment::UpdateBleV2MediumForScanning(
|
||||
// medium.
|
||||
if (remote_medium == &medium || !remote_context.advertising)
|
||||
continue;
|
||||
if (!remote_context.advertisement_data.service_uuids.contains(
|
||||
context.scanning_service_uuid))
|
||||
auto const it = remote_context.advertisement_data.service_data.find(
|
||||
context.scanning_service_uuid);
|
||||
if (it == remote_context.advertisement_data.service_data.end())
|
||||
continue;
|
||||
NEARBY_LOGS(INFO)
|
||||
<< "G3 UpdateBleV2MediumForScanning, found other medium="
|
||||
@@ -894,8 +895,8 @@ api::WifiHotspotMedium* MediumEnvironment::GetWifiHotspotMedium(
|
||||
}
|
||||
|
||||
void MediumEnvironment::UpdateWifiHotspotMediumForStartOrConnect(
|
||||
api::WifiHotspotMedium& medium, HotspotCredentials* hotspot_credentials,
|
||||
bool is_ap, bool enabled) {
|
||||
api::WifiHotspotMedium& medium, HotspotCredentials* hotspot_credentials,
|
||||
bool is_ap, bool enabled) {
|
||||
if (!enabled_) return;
|
||||
|
||||
CountDownLatch latch(1);
|
||||
@@ -913,8 +914,8 @@ void MediumEnvironment::UpdateWifiHotspotMediumForStartOrConnect(
|
||||
<< "; ssid=" << hotspot_credentials->GetSSID()
|
||||
<< "; password=" << hotspot_credentials->GetPassword();
|
||||
} else {
|
||||
NEARBY_LOGS(INFO) << "Reset WifiHotspot medium for Hotspot: this="
|
||||
<< this << "; medium=" << &medium << role_status;
|
||||
NEARBY_LOGS(INFO) << "Reset WifiHotspot medium for Hotspot: this=" << this
|
||||
<< "; medium=" << &medium << role_status;
|
||||
}
|
||||
|
||||
MutexLock lock(&mutex_);
|
||||
|
||||
Reference in New Issue
Block a user