#ifndef CORE_INTERNAL_MEDIUMS_BLE_V2_H_ #define CORE_INTERNAL_MEDIUMS_BLE_V2_H_ #include #include "core/internal/mediums/advertisement_read_result.h" #include "core/internal/mediums/ble_advertisement.h" #include "core/internal/mediums/bluetooth_radio.h" #include "core/internal/mediums/discovered_peripheral_callback.h" #include "core/internal/mediums/discovered_peripheral_tracker.h" #include "platform/api/ble_v2.h" #include "platform/api/bluetooth_adapter.h" #include "platform/api/hash_utils.h" #include "platform/api/lock.h" #include "platform/byte_array.h" #include "platform/cancelable_alarm.h" #include "platform/port/string.h" #include "platform/prng.h" #include "platform/ptr.h" namespace location { namespace nearby { namespace connections { namespace mediums { namespace ble_v2 { template class ProcessOnLostRunnable; template class OnAdvertisementFoundRunnable; } // namespace ble_v2 template class BLEV2 { public: explicit BLEV2(Ptr> bluetooth_radio); ~BLEV2(); bool isAvailable(); // While the start* functions for each action (advertising, scanning, // accepting connections) take in a service_id, the stop* and is* functions do // not. This is because the service_id isn't used. In the java code, shutdown // calls all the stop* functions w/ a null service_id. The service_id is just // passed through to the corresponding is* function, which ignores it. // service_id should be added back in when C++ supports multi-client. bool startAdvertising(const string& service_id, ConstPtr advertisement, BLEMediumV2::PowerMode::Value power_mode, const string& fast_advertisement_service_uuid); void stopAdvertising(); bool startScanning( const string& service_id, Ptr discovered_peripheral_callback, BLEMediumV2::PowerMode::Value power_mode, const string& fast_advertisement_service_uuid); void stopScanning(); class AcceptedConnectionCallback { public: virtual ~AcceptedConnectionCallback() {} // TODO(ahlee): Add in connecting logic. }; bool isAcceptingConnections(); bool startAcceptingConnections( const string& service_id, Ptr accepted_connection_callback); void stopAcceptingConnections(); private: template friend class ble_v2::ProcessOnLostRunnable; template friend class ble_v2::OnAdvertisementFoundRunnable; class GATTAdvertisementFetcherFacade : public DiscoveredPeripheralTracker::GattAdvertisementFetcher { public: explicit GATTAdvertisementFetcherFacade(Ptr> impl) : impl_(impl) {} ~GATTAdvertisementFetcherFacade() override {} Ptr> fetchGattAdvertisements( Ptr ble_peripheral, std::int32_t num_slots, Ptr> advertisement_read_result) override { return impl_->processFetchGattAdvertisementsRequest( ble_peripheral, num_slots, advertisement_read_result); } private: Ptr> impl_; }; class ScanCallbackFacade : public BLEMediumV2::ScanCallback { public: explicit ScanCallbackFacade(Ptr> impl) : impl_(impl) {} ~ScanCallbackFacade() override {} void onAdvertisementFound( Ptr peripheral, ConstPtr advertisement_data) override { impl_->onAdvertisementFoundImpl(peripheral, advertisement_data); } private: Ptr> impl_; }; class ClientGATTConnectionLifecycleCallbackFacade : public ClientGATTConnectionLifecycleCallback { public: explicit ClientGATTConnectionLifecycleCallbackFacade( Ptr> impl) : impl_(impl) {} ~ClientGATTConnectionLifecycleCallbackFacade() override {} void onDisconnected(Ptr connection) override { // Avoid leaks. ScopedPtr> scoped_connection(connection); // Nothing else to do for now. } private: Ptr> impl_; }; class ServerGATTConnectionLifecycleCallbackFacade : public ServerGATTConnectionLifecycleCallback { public: explicit ServerGATTConnectionLifecycleCallbackFacade( Ptr> impl) : impl_(impl) {} ~ServerGATTConnectionLifecycleCallbackFacade() override {} void onCharacteristicSubscription( Ptr connection, Ptr characteristic) override { // Avoid leaks. Do not scope the characteristic because it is ref counted // by the per-platform ble_v2 implementation. ScopedPtr> scoped_connection(connection); // Nothing else to do for now. } void onCharacteristicUnsubscription( Ptr connection, Ptr characteristic) override { // Avoid leaks. Do not scope the characteristic because it is ref counted // by the per-platform ble_v2 implementation. ScopedPtr> scoped_connection(connection); // Nothing else to do for now. } private: Ptr> impl_; }; struct ScanningInfo { ScanningInfo(const string& service_id, Ptr scan_callback_facade, Ptr on_lost_alarm) : service_id(service_id), scan_callback_facade(scan_callback_facade), on_lost_alarm(on_lost_alarm) {} ~ScanningInfo() { // Nothing to do (the ScopedPtr members take care of themselves). } const string service_id; ScopedPtr> scan_callback_facade; // TODO(ahlee): Change to recurring cancelable alarm ScopedPtr> on_lost_alarm; }; struct AdvertisingInfo { explicit AdvertisingInfo(const string& service_id) : service_id(service_id) {} ~AdvertisingInfo() {} const string service_id; }; struct GATTServerInfo { GATTServerInfo(Ptr gatt_server, Ptr connection_lifecycle_callback) : gatt_server(gatt_server), connection_lifecycle_callback(connection_lifecycle_callback) {} ~GATTServerInfo() { // Nothing to do (the ScopedPtr members take care of themselves). } ScopedPtr> gatt_server; ScopedPtr> connection_lifecycle_callback; }; struct AcceptingConnectionsInfo { explicit AcceptingConnectionsInfo(const string& service_id) : service_id(service_id) {} ~AcceptingConnectionsInfo() { // Nothing to do (the ScopedPtr members take care of themselves). } const string service_id; // TODO(ahlee): Fill in. }; static const std::int32_t kNumAdvertisementSlots; static const std::int32_t kMaxAdvertisementLength; static const std::int32_t kDummyServiceIdLength; static const char* kCopresenceServiceUuid; static const std::int64_t kOnLostTimeoutMillis; static const std::int64_t kGattAdvertisementOperationTimeoutMillis; static const std::int64_t kMinConnectionAttemptRecoveryDurationMillis; static const std::int32_t kMaxConnectionAttemptRecoveryFuzzDurationMillis; static const std::uint32_t kDefaultMtu; static const std::int64_t kAdvertisementUuidMsb; static const std::int64_t kAdvertisementUuidLsb; bool isAdvertising(); ConstPtr createAdvertisementHeader( const string& service_id, ConstPtr advertisement_bytes, bool is_fast_advertisement); bool isScanning(); void onAdvertisementFoundImpl( Ptr ble_peripheral, ConstPtr advertisement_data); void processOnLostTimeout(); Ptr createOnLostAlarm(); bool isAdvertisementGattServerRunning(); bool startAdvertisementGattServer(const string& service_id, ConstPtr advertisement); bool internalStartAdvertisementGattServer( ConstPtr legacy_ble_advertisement_bytes, ConstPtr ble_advertisement_bytes); bool generateAdvertisementCharacteristic( std::int32_t slot, ConstPtr advertisement, Ptr gatt_server); void stopAdvertisementGattServer(); Ptr> processFetchGattAdvertisementsRequest( Ptr peripheral, std::int32_t num_slots, Ptr> advertisement_read_result); Ptr> internalReadFromAdvertisementGattServer( Ptr ble_peripheral, std::int32_t num_slots, Ptr> advertisement_read_result); void offloadFromPlatformThread(Ptr runnable); // TODO(ahlee): Move these out to utils (also used by // DiscoveredPeripheralTracker). ConstPtr generateAdvertisementHash( ConstPtr advertisement_bytes); ConstPtr generateServiceIdHash( BLEAdvertisement::Version::Value version, const string& service_id); // This maps to a helper function found in bluetoothlowenergy/Utils.java. In // the C++ code we moved it because it's only used here. string generateAdvertisementUuid(std::int32_t slot); // ------------ GENERAL ------------ ScopedPtr> lock_; // Where we throw potentially blocking work off of the platform thread. ScopedPtr> platform_thread_offloader_; ScopedPtr> prng_; ScopedPtr> hash_utils_; // ------------ CORE BLE ------------ Ptr> bluetooth_radio_; ScopedPtr> bluetooth_adapter_; // The underlying, per-platform implementation. ScopedPtr> ble_medium_; // ------------ DISCOVERY ------------ // scanning_info_ is not scoped because it's nullable. Ptr scanning_info_; ScopedPtr>> discovered_peripheral_tracker_; ScopedPtr> on_lost_executor_; // ------------ ADVERTISING ------------ // advertising_info_, gatt_server_info_, and accepting_connections_info_ are // not scoped because they are nullable. Ptr advertising_info_; Ptr gatt_server_info_; Ptr accepting_connections_info_; std::shared_ptr self_{this, [](void*){}}; }; } // namespace mediums } // namespace connections } // namespace nearby } // namespace location #include "core/internal/mediums/ble_v2.cc" #endif // CORE_INTERNAL_MEDIUMS_BLE_V2_H_