#ifndef CORE_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_ #define CORE_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_ #include #include #include "core/internal/mediums/bluetooth_radio.h" #include "core/internal/mediums/utils.h" #include "platform/api/bluetooth_adapter.h" #include "platform/api/bluetooth_classic.h" #include "platform/api/lock.h" #include "platform/api/multi_thread_executor.h" #include "platform/byte_array.h" #include "platform/port/string.h" #include "platform/ptr.h" #include "platform/runnable.h" namespace location { namespace nearby { namespace connections { template class BluetoothClassic { public: explicit BluetoothClassic(Ptr> bluetooth_radio); ~BluetoothClassic(); bool isAvailable(); bool turnOnDiscoverability(const string& device_name); void turnOffDiscoverability(); // Callback that is invoked when a nearby Bluetooth device is discovered. class DiscoveredDeviceCallback { public: virtual ~DiscoveredDeviceCallback() {} virtual void onDeviceDiscovered(Ptr device) = 0; virtual void onDeviceNameChanged(Ptr device) = 0; virtual void onDeviceLost(Ptr device) = 0; }; bool startDiscovery(Ptr discovered_device_callback); void stopDiscovery(); // Callback that is invoked when a new connection is accepted. class AcceptedConnectionCallback { public: virtual ~AcceptedConnectionCallback() {} virtual void onConnectionAccepted(Ptr socket) = 0; }; bool startAcceptingConnections( const string& service_name, Ptr accepted_connection_callback); bool isAcceptingConnections(const string& service_name); void stopAcceptingConnections(const string& service_name); Ptr connect(Ptr bluetooth_device, const string& service_name); private: class BluetoothDiscoveryCallback : public BluetoothClassicMedium::DiscoveryCallback { public: explicit BluetoothDiscoveryCallback( Ptr discovered_device_callback) : discovered_device_callback_(discovered_device_callback) {} ~BluetoothDiscoveryCallback() override { // Nothing to do. } void onDeviceDiscovered(Ptr bluetooth_device) override { discovered_device_callback_->onDeviceDiscovered(bluetooth_device); } void onDeviceNameChanged(Ptr bluetooth_device) override { discovered_device_callback_->onDeviceNameChanged(bluetooth_device); } void onDeviceLost(Ptr bluetooth_device) override { discovered_device_callback_->onDeviceLost(bluetooth_device); } private: // This could well have been a ScopedPtr, with BluetoothDiscoveryCallback in // turn being owned by ScanInfo (and it would have been cleaner overall, // since the chain of wrapped callbacks starting from // BluetoothDiscoveryCallback would then destruct like a stack of dominoes // falling, triggered by the destruction of ScanInfo), but we instead give // ownership of this DiscoveredDeviceCallback *and* // BluetoothDiscoveryCallback to ScanInfo, to maintain compatibility with // the Java code. Ptr discovered_device_callback_; }; struct ScanInfo { ScanInfo(Ptr discovered_device_callback, Ptr bluetooth_discovery_callback) : discovered_device_callback(discovered_device_callback), bluetooth_discovery_callback(bluetooth_discovery_callback) {} ~ScanInfo() { // Nothing to do (the ScopedPtr members take care of themselves). } // Stores the DiscoveredDeviceCallback passed in to startDiscovery() by // clients so that we can internally stop and start Bluetooth scans // transparently as needed (for example, when a call to connect() is // invoked). ScopedPtr> discovered_device_callback; // The ordering of bluetooth_discovery_callback_ coming after // discovered_device_callback_ is very deliberate -- // bluetooth_discovery_callback_ contains a reference to // discovered_device_callback_, so it should be destroyed first. ScopedPtr> bluetooth_discovery_callback; }; static string generateUUIDFromString(const string& data); static const std::int32_t kMaxConcurrentAcceptLoops; bool isDiscoverable() const; bool modifyDeviceName(const string& device_name); bool modifyScanMode(BluetoothAdapter::ScanMode::Value scan_mode); void restoreScanMode(); void restoreDeviceName(); bool isDiscovering() const; // ------------ GENERAL ------------ ScopedPtr> lock_; // ------------ CORE BLUETOOTH ------------ Ptr> bluetooth_radio_; ScopedPtr> bluetooth_adapter_; // The underlying, per-platform implementation. ScopedPtr> bluetooth_classic_medium_; // ------------ DISCOVERY ------------ // A bundle of state required to do a Bluetooth Classic scan. When non-null, // we are currently performing a Bluetooth scan. Ptr scan_info_; // ------------ ADVERTISING ------------ // The original scan mode (that controls visibility to scanners) of the device // before we modified it. Restored when we stop advertising. BluetoothAdapter::ScanMode::Value original_scan_mode_; // The original Bluetooth device name, before we modified it. If non-null, we // are currently Bluetooth discoverable. Restored when we stop advertising. Ptr original_device_name_; // A thread pool dedicated to running all the accept loops from // startAcceptingConnections(). ScopedPtr> accept_loops_thread_pool_; // A map of service name -> ServerSocket. While this map is non-empty, we // are currently listening for incoming connections. typedef std::map> BluetoothServerSocketMap; BluetoothServerSocketMap bluetooth_server_sockets_; }; } // namespace connections } // namespace nearby } // namespace location #include "core/internal/mediums/bluetooth_classic.cc" #endif // CORE_INTERNAL_MEDIUMS_BLUETOOTH_CLASSIC_H_