diff --git a/connections/implementation/mediums/BUILD b/connections/implementation/mediums/BUILD index 7086ad26..1f777773 100644 --- a/connections/implementation/mediums/BUILD +++ b/connections/implementation/mediums/BUILD @@ -172,6 +172,7 @@ cc_test( "//internal/platform:cancellation_flag", "//internal/platform:comm", "//internal/platform:logging", + "//internal/platform:mac_address", "//internal/platform:test_util", "//internal/platform:types", "//internal/platform/implementation:types", diff --git a/connections/implementation/mediums/ble.h b/connections/implementation/mediums/ble.h index 8b24ca8c..582bfcb9 100644 --- a/connections/implementation/mediums/ble.h +++ b/connections/implementation/mediums/ble.h @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -28,8 +29,8 @@ #include "absl/functional/any_invocable.h" #include "absl/strings/string_view.h" #include "connections/implementation/mediums/ble/advertisement_read_result.h" -#include "connections/implementation/mediums/ble/ble_socket.h" #include "connections/implementation/mediums/ble/ble_advertisement.h" +#include "connections/implementation/mediums/ble/ble_socket.h" #include "connections/implementation/mediums/ble/discovered_peripheral_callback.h" #include "connections/implementation/mediums/ble/discovered_peripheral_tracker.h" #include "connections/implementation/mediums/ble/instant_on_lost_manager.h" @@ -235,6 +236,16 @@ class Ble final { return medium_.IsExtendedAdvertisementsAvailable(); }; + // Retrieves a BlePeripheral from a native BLE peripheral ID. + // On Apple platform, the native ID is NSUUID in string format like + // "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", other platform will be MAC address + // as string format like "0C:24:7A:3E:6E:5F". + std::optional RetrieveBlePeripheralFromNativeId( + const std::string& ble_peripheral_native_id) { + MutexLock lock(&mutex_); + return medium_.RetrieveBlePeripheralFromNativeId(ble_peripheral_native_id); + } + private: struct AdvertisingInfo { mediums::BleAdvertisement medium_advertisement; diff --git a/connections/implementation/mediums/ble_test.cc b/connections/implementation/mediums/ble_test.cc index dc110999..13f80d64 100644 --- a/connections/implementation/mediums/ble_test.cc +++ b/connections/implementation/mediums/ble_test.cc @@ -37,6 +37,7 @@ #include "internal/platform/feature_flags.h" #include "internal/platform/implementation/system_clock.h" #include "internal/platform/logging.h" +#include "internal/platform/mac_address.h" #include "internal/platform/medium_environment.h" namespace nearby { @@ -286,8 +287,7 @@ TEST_P(BleTest, CanCancelConnect2) { })); ble_server.StartAdvertising(service_id, PowerLevel::kHighPower, - Ble::AdvertisingType::kFast, - advertisement_bytes); + Ble::AdvertisingType::kFast, advertisement_bytes); BlePeripheral discovered_peripheral; ble_client.StartScanning( @@ -1400,6 +1400,20 @@ TEST_F(BleTest, StartMultipleAsyncScanningDiscoverAndLostPeripheral) { env_.Stop(); } +TEST_F(BleTest, RetrieveBlePeripheralIdFromNativeId) { + env_.Start(); + BluetoothRadio radio; + MacAddress mac_address = radio.GetBluetoothAdapter().GetAddress(); + Ble ble(radio); + env_.Sync(false); + EXPECT_TRUE(ble.RetrieveBlePeripheralFromNativeId(mac_address.ToString()) + .has_value()); + + EXPECT_FALSE( + ble.RetrieveBlePeripheralFromNativeId("FF:FF:FF:FF:FF:DE").has_value()); + env_.Stop(); +} + } // namespace } // namespace connections } // namespace nearby diff --git a/internal/platform/ble.cc b/internal/platform/ble.cc index ab0bce21..2db9b6d9 100644 --- a/internal/platform/ble.cc +++ b/internal/platform/ble.cc @@ -284,4 +284,19 @@ bool BleMedium::IsExtendedAdvertisementsAvailable() { bool BlePeripheral::IsValid() const { return unique_id_.has_value(); } +std::optional BleMedium::RetrieveBlePeripheralFromNativeId( + const std::string& ble_peripheral_native_id) { + if (!IsValid()) { + return std::nullopt; + } + + std::optional id = + impl_->RetrieveBlePeripheralIdFromNativeId(ble_peripheral_native_id); + if (id.has_value()) { + return BlePeripheral(*this, id.value()); + } + + return std::nullopt; +} + } // namespace nearby diff --git a/internal/platform/ble.h b/internal/platform/ble.h index 82360d28..7aafbce6 100644 --- a/internal/platform/ble.h +++ b/internal/platform/ble.h @@ -570,6 +570,13 @@ class BleMedium final { impl_->AddAlternateUuidForService(uuid, service_id); } + // Retrieves a BlePeripheral from a native BLE peripheral ID. + // On Apple platform, the native ID is NSUUID in string format like + // "E621E1F8-C36C-495A-93FC-0C247A3E6E5F", other platform will be MAC address + // as string format like "0C:24:7A:3E:6E:5F". + std::optional RetrieveBlePeripheralFromNativeId( + const std::string& ble_peripheral_native_id); + private: Mutex mutex_; std::unique_ptr impl_; diff --git a/internal/platform/implementation/g3/ble.cc b/internal/platform/implementation/g3/ble.cc index 6ce570ea..9e1282b5 100644 --- a/internal/platform/implementation/g3/ble.cc +++ b/internal/platform/implementation/g3/ble.cc @@ -38,6 +38,7 @@ #include "internal/platform/implementation/bluetooth_adapter.h" #include "internal/platform/implementation/g3/bluetooth_adapter.h" #include "internal/platform/logging.h" +#include "internal/platform/mac_address.h" #include "internal/platform/medium_environment.h" #include "internal/platform/prng.h" #include "internal/platform/uuid.h" @@ -352,6 +353,23 @@ bool BleMedium::IsExtendedAdvertisementsAvailable() { return is_extended_advertisements_available_; } +std::optional +BleMedium::RetrieveBlePeripheralIdFromNativeId( + const std::string& ble_peripheral_native_id) { + MacAddress mac_address; + if (!MacAddress::FromString(ble_peripheral_native_id, mac_address)) { + return std::nullopt; + } + + if (MediumEnvironment::Instance() + .FindBlePeripheral(mac_address.address()) + .IsSet()) { + return mac_address.address(); + } + + return std::nullopt; +} + BleMedium::GattServer::GattServer( BleMedium& medium, api::ble::ServerGattConnectionCallback callback) : medium_(medium), callback_(std::move(callback)) { diff --git a/internal/platform/implementation/g3/ble.h b/internal/platform/implementation/g3/ble.h index d54dc974..86c6daf8 100644 --- a/internal/platform/implementation/g3/ble.h +++ b/internal/platform/implementation/g3/ble.h @@ -189,6 +189,10 @@ class BleMedium : public api::ble::BleMedium { BluetoothAdapter& GetAdapter() { return adapter_; } + std::optional + RetrieveBlePeripheralIdFromNativeId( + const std::string& ble_peripheral_native_id) override; + private: class GattClient; // A concrete implementation for GattServer. diff --git a/internal/platform/medium_environment.cc b/internal/platform/medium_environment.cc index 24d65303..cbbf246a 100644 --- a/internal/platform/medium_environment.cc +++ b/internal/platform/medium_environment.cc @@ -60,7 +60,6 @@ std::string LastAddressCandidateToString( } } // namespace - MediumEnvironment& MediumEnvironment::Instance() { alignas(MediumEnvironment) static char storage[sizeof(MediumEnvironment)]; static MediumEnvironment* env = new (&storage) MediumEnvironment(); @@ -274,6 +273,27 @@ api::ble::BleMedium* MediumEnvironment::FindBleMedium( return device; } +api::ble::BlePeripheral MediumEnvironment::FindBlePeripheral( + api::ble::BlePeripheral::UniqueId id) { + api::ble::BlePeripheral peripheral; + CountDownLatch latch(1); + RunOnMediumEnvironmentThread([&]() { + for (auto& item : ble_mediums_) { + if (item.second.ble_peripheral_id == id) { + peripheral = api::ble::BlePeripheral(item.second.ble_peripheral_id); + break; + } + } + latch.CountDown(); + }); + latch.Await(); + if (!peripheral.IsSet()) { + LOG(INFO) << "FindBlePeripheral, not found: " << id; + } + + return peripheral; +} + void MediumEnvironment::OnBlePeripheralStateChanged( bool enabled, BleMediumContext& context, const Uuid& service_id, const api::ble::BleAdvertisementData& ble_advertisement_data, diff --git a/internal/platform/medium_environment.h b/internal/platform/medium_environment.h index 9346a8f1..a5bf530d 100644 --- a/internal/platform/medium_environment.h +++ b/internal/platform/medium_environment.h @@ -338,6 +338,9 @@ class MediumEnvironment { api::ble::BleMedium* FindBleMedium(api::ble::BlePeripheral::UniqueId id); + api::ble::BlePeripheral FindBlePeripheral( + api::ble::BlePeripheral::UniqueId id); + void RegisterGattServer(api::ble::BleMedium& medium, api::ble::BlePeripheral::UniqueId peripheral_id, Borrowable gatt_server);