From c7eab0f99e3cd3f447d8e23bc9cd614148d4e6ce Mon Sep 17 00:00:00 2001 From: Nisarg Jhaveri Date: Wed, 27 Mar 2024 00:42:48 +0530 Subject: [PATCH] Add dongle mode connection strategy --- .../board/common/rootfs_overlay/etc/aawgd.env | 8 +- aa_wireless_dongle/package/aawg/src/Makefile | 2 +- aa_wireless_dongle/package/aawg/src/aawgd.cpp | 20 +++- .../aawg/src/bluetoothAdvertisement.cpp | 22 +++++ .../package/aawg/src/bluetoothAdvertisement.h | 17 ++++ .../package/aawg/src/bluetoothHandler.cpp | 91 +++++++++++++++---- .../package/aawg/src/bluetoothHandler.h | 8 ++ .../package/aawg/src/common.cpp | 20 ++++ aa_wireless_dongle/package/aawg/src/common.h | 10 ++ .../package/aawg/src/proxyHandler.cpp | 2 +- 10 files changed, 175 insertions(+), 25 deletions(-) create mode 100644 aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.cpp create mode 100644 aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.h diff --git a/aa_wireless_dongle/board/common/rootfs_overlay/etc/aawgd.env b/aa_wireless_dongle/board/common/rootfs_overlay/etc/aawgd.env index 3b8b5bb..8131192 100644 --- a/aa_wireless_dongle/board/common/rootfs_overlay/etc/aawgd.env +++ b/aa_wireless_dongle/board/common/rootfs_overlay/etc/aawgd.env @@ -1,3 +1,5 @@ -# Uncomment this setting to wait for the usb to connect first. -# By default, we try to connect and wait for the phone to connect first regardless of the usb connection. -#AAWG_CONNECTION_WAIT_FOR_ACCESSORY=1 +# Set the connection strategy to use +# 0 - Dongle mode (default). Waits for both dongle and headunit bluetooth connections and then starts the wifi and usb connections. +# 1 - Phone first. Waits for the phone bluetooth and wifi to connect first, and then starts the usb connection. +# 2 - Usb first. Waits for the usb to connect first, and then starts the bluetooth and wifi connection with phone. +AAWG_CONNECTION_STRATEGY=0 diff --git a/aa_wireless_dongle/package/aawg/src/Makefile b/aa_wireless_dongle/package/aawg/src/Makefile index 410fb5c..3484f29 100644 --- a/aa_wireless_dongle/package/aawg/src/Makefile +++ b/aa_wireless_dongle/package/aawg/src/Makefile @@ -8,7 +8,7 @@ PROTO_HEADERS = $(PROTO_FILES:proto=pb.h) ALL_HEADERS = $(wildcard *.h) $(PROTO_HEADERS) -aawgd: aawgd.o bluetoothHandler.o bluetoothProfiles.o proxyHandler.o uevent.o usb.o common.o proto/WifiInfoResponse.pb.o proto/WifiStartRequest.pb.o +aawgd: aawgd.o bluetoothHandler.o bluetoothProfiles.o bluetoothAdvertisement.o proxyHandler.o uevent.o usb.o common.o proto/WifiInfoResponse.pb.o proto/WifiStartRequest.pb.o $(CXX) $(CXXFLAGS) $(EXTRA_CXXFLAGS) -o '$@' $^ %.o: %.cpp diff --git a/aa_wireless_dongle/package/aawg/src/aawgd.cpp b/aa_wireless_dongle/package/aawg/src/aawgd.cpp index 3f222c6..0f2098f 100644 --- a/aa_wireless_dongle/package/aawg/src/aawgd.cpp +++ b/aa_wireless_dongle/package/aawg/src/aawgd.cpp @@ -15,9 +15,16 @@ int main(void) { UsbManager::instance().init(); BluetoothHandler::instance().init(); + ConnectionStrategy connectionStrategy = Config::instance()->getConnectionStrategy(); + if (connectionStrategy == ConnectionStrategy::DONGLE_MODE) { + BluetoothHandler::instance().powerOn(); + } + while (true) { + Logger::instance()->info("Connection Strategy: %d\n", connectionStrategy); + // Per connection setup and processing - if (std::getenv("AAWG_CONNECTION_WAIT_FOR_ACCESSORY") != nullptr) { + if (connectionStrategy == ConnectionStrategy::USB_FIRST) { Logger::instance()->info("Waiting for the accessory to connect first\n"); UsbManager::instance().enableDefaultAndWaitForAccessory(); } @@ -29,7 +36,10 @@ int main(void) { return 1; } - BluetoothHandler::instance().powerOn(); + if (connectionStrategy != ConnectionStrategy::DONGLE_MODE) { + BluetoothHandler::instance().powerOn(); + } + std::optional btConnectionThread = BluetoothHandler::instance().connectWithRetry(); proxyThread->join(); @@ -41,8 +51,10 @@ int main(void) { UsbManager::instance().disableGadget(); - // sleep for a couple of seconds before retrying - sleep(2); + if (connectionStrategy != ConnectionStrategy::DONGLE_MODE) { + // sleep for a couple of seconds before retrying + sleep(2); + } } ueventThread->join(); diff --git a/aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.cpp b/aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.cpp new file mode 100644 index 0000000..8947fcb --- /dev/null +++ b/aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.cpp @@ -0,0 +1,22 @@ +#include + +#include "common.h" +#include "bluetoothAdvertisement.h" + +static constexpr const char* INTERFACE_BLUEZ_LE_ADVERTISEMENT = "org.bluez.LEAdvertisement1"; + +/* static */ std::shared_ptr BLEAdvertisement::create(DBus::Path path) { + return std::shared_ptr(new BLEAdvertisement(path)); +} + +BLEAdvertisement::BLEAdvertisement(DBus::Path path): DBus::Object(path) { + this->create_method(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "Release", sigc::mem_fun(*this, &BLEAdvertisement::Release)); + + type = this->create_property(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "Type", DBus::PropertyAccess::ReadOnly); + serviceUUIDs = this->create_property>(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "ServiceUUIDs"); + localName = this->create_property(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "LocalName"); +} + +void BLEAdvertisement::Release() { + Logger::instance()->info("Bluetooth LE Advertisement released\n"); +} diff --git a/aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.h b/aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.h new file mode 100644 index 0000000..e63fe28 --- /dev/null +++ b/aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.h @@ -0,0 +1,17 @@ +#pragma once + +#include "bluetoothCommon.h" + +class BLEAdvertisement: public DBus::Object { +public: + static std::shared_ptr create(DBus::Path path); + + std::shared_ptr> type; + std::shared_ptr>> serviceUUIDs; + std::shared_ptr> localName; + +protected: + BLEAdvertisement(DBus::Path path); + + void Release(); +}; diff --git a/aa_wireless_dongle/package/aawg/src/bluetoothHandler.cpp b/aa_wireless_dongle/package/aawg/src/bluetoothHandler.cpp index 31f143b..fb9bec8 100644 --- a/aa_wireless_dongle/package/aawg/src/bluetoothHandler.cpp +++ b/aa_wireless_dongle/package/aawg/src/bluetoothHandler.cpp @@ -3,17 +3,23 @@ #include "common.h" #include "bluetoothHandler.h" #include "bluetoothProfiles.h" +#include "bluetoothAdvertisement.h" static constexpr const char* ADAPTER_ALIAS = "AA Wireless Dongle"; +static constexpr const char* ADAPTER_ALIAS_DONGLE = "AndroidAuto-Dongle"; static constexpr const char* BLUEZ_BUS_NAME = "org.bluez"; static constexpr const char* BLUEZ_ROOT_OBJECT_PATH = "/"; static constexpr const char* BLUEZ_OBJECT_PATH = "/org/bluez"; static constexpr const char* INTERFACE_BLUEZ_ADAPTER = "org.bluez.Adapter1"; +static constexpr const char* INTERFACE_BLUEZ_LE_ADVERTISING_MANAGER = "org.bluez.LEAdvertisingManager1"; + static constexpr const char* INTERFACE_BLUEZ_DEVICE = "org.bluez.Device1"; static constexpr const char* INTERFACE_BLUEZ_PROFILE_MANAGER = "org.bluez.ProfileManager1"; +static constexpr const char* LE_ADVERTISEMENT_OBJECT_PATH = "/com/aawgd/bluetooth/advertisement"; + static constexpr const char* AAWG_PROFILE_OBJECT_PATH = "/com/aawgd/bluetooth/aawg"; static constexpr const char* AAWG_PROFILE_UUID = "4de17a00-52cb-11e6-bdf4-0800200c9a66"; @@ -28,6 +34,9 @@ class BluezAdapterProxy: private DBus::ObjectProxy { powered = this->create_property(INTERFACE_BLUEZ_ADAPTER, "Powered"); discoverable = this->create_property(INTERFACE_BLUEZ_ADAPTER, "Discoverable"); pairable = this->create_property(INTERFACE_BLUEZ_ADAPTER, "Pairable"); + + registerAdvertisement = this->create_method(INTERFACE_BLUEZ_LE_ADVERTISING_MANAGER, "RegisterAdvertisement"); + unregisterAdvertisement = this->create_method(INTERFACE_BLUEZ_LE_ADVERTISING_MANAGER, "UnregisterAdvertisement"); } public: @@ -40,6 +49,9 @@ class BluezAdapterProxy: private DBus::ObjectProxy { std::shared_ptr> powered; std::shared_ptr> discoverable; std::shared_ptr> pairable; + + std::shared_ptr> registerAdvertisement; + std::shared_ptr> unregisterAdvertisement; }; @@ -77,7 +89,7 @@ void BluetoothHandler::initAdapter() { } else { m_adapter = BluezAdapterProxy::create(m_connection, adapter_path); - m_adapter->alias->set_value(ADAPTER_ALIAS); + m_adapter->alias->set_value(m_adapterAlias); } } @@ -117,15 +129,46 @@ void BluetoothHandler::exportProfiles() { }); Logger::instance()->info("Bluetooth AA Wireless profile active\n"); - // Register HSP Handset profile - m_hspProfile = HSPHSProfile::create(HSP_HS_PROFILE_OBJECT_PATH); - if (m_connection->register_object(m_hspProfile, DBus::ThreadForCalling::DispatcherThread) != DBus::RegistrationStatus::Success) { - Logger::instance()->info("Failed to register HSP Handset profile\n"); + if (Config::instance()->getConnectionStrategy() != ConnectionStrategy::DONGLE_MODE) { + // Register HSP Handset profile + m_hspProfile = HSPHSProfile::create(HSP_HS_PROFILE_OBJECT_PATH); + if (m_connection->register_object(m_hspProfile, DBus::ThreadForCalling::DispatcherThread) != DBus::RegistrationStatus::Success) { + Logger::instance()->info("Failed to register HSP Handset profile\n"); + } + registerProfile(HSP_HS_PROFILE_OBJECT_PATH, HSP_HS_UUID, { + {"Name", DBus::Variant("HSP HS")}, + }); + Logger::instance()->info("HSP Handset profile active\n"); } - registerProfile(HSP_HS_PROFILE_OBJECT_PATH, HSP_HS_UUID, { - {"Name", DBus::Variant("HSP HS")}, - }); - Logger::instance()->info("HSP Handset profile active\n"); +} + +void BluetoothHandler::startAdvertising() { + if (!m_adapter) { + return; + } + + // Register Advertisement Object + m_leAdvertisement = BLEAdvertisement::create(LE_ADVERTISEMENT_OBJECT_PATH); + + m_leAdvertisement->type->set_value("peripheral"); + m_leAdvertisement->serviceUUIDs->set_value(std::vector{AAWG_PROFILE_UUID}); + m_leAdvertisement->localName->set_value(m_adapterAlias); + + if (m_connection->register_object(m_leAdvertisement, DBus::ThreadForCalling::DispatcherThread) != DBus::RegistrationStatus::Success) { + Logger::instance()->info("Failed to register BLE Advertisement\n"); + } + + (*m_adapter->registerAdvertisement)(LE_ADVERTISEMENT_OBJECT_PATH, {}); + Logger::instance()->info("BLE Advertisement started\n"); +} + +void BluetoothHandler::stopAdvertising() { + if (!m_adapter) { + return; + } + + (*m_adapter->unregisterAdvertisement)(LE_ADVERTISEMENT_OBJECT_PATH); + Logger::instance()->info("BLE Advertisement stopped\n"); } void BluetoothHandler::connectDevice() { @@ -145,6 +188,8 @@ void BluetoothHandler::connectDevice() { return; } + const bool isDongleMode = (Config::instance()->getConnectionStrategy() == ConnectionStrategy::DONGLE_MODE); + Logger::instance()->info("Found %d bluetooth devices\n", device_paths.size()); for (const std::string &device_path: device_paths) { @@ -161,16 +206,21 @@ void BluetoothHandler::connectDevice() { Logger::instance()->info("Bluetooth device already connected, disconnecting\n"); disconnect(); } - connectProfile(HSP_AG_UUID); + connectProfile(isDongleMode ? "" : HSP_AG_UUID); Logger::instance()->info("Bluetooth connected to the device\n"); - return; + if (!isDongleMode) { + return; + } } catch (DBus::Error& e) { - Logger::instance()->info("Failed to connect device at path: %s\n", device_path.c_str()); + if (!isDongleMode) { + Logger::instance()->info("Failed to connect device at path: %s\n", device_path.c_str()); + } } } - Logger::instance()->info("Failed to connect to any known bluetooth device\n"); - + if (!isDongleMode) { + Logger::instance()->info("Failed to connect to any known bluetooth device\n"); + } } void BluetoothHandler::retryConnectLoop() { @@ -186,7 +236,9 @@ void BluetoothHandler::retryConnectLoop() { } } - BluetoothHandler::instance().powerOff(); + if (Config::instance()->getConnectionStrategy() != ConnectionStrategy::DONGLE_MODE) { + BluetoothHandler::instance().powerOff(); + } } void BluetoothHandler::init() { @@ -196,7 +248,7 @@ void BluetoothHandler::init() { m_dispatcher = DBus::StandaloneDispatcher::create(); m_connection = m_dispatcher->create_connection( DBus::BusType::SYSTEM ); - Logger::instance()->info("Unique Name: %s\n", m_connection->unique_name().c_str()); + m_adapterAlias = (Config::instance()->getConnectionStrategy() == ConnectionStrategy::DONGLE_MODE) ? ADAPTER_ALIAS_DONGLE : ADAPTER_ALIAS; initAdapter(); exportProfiles(); @@ -209,6 +261,10 @@ void BluetoothHandler::powerOn() { setPower(true); setPairable(true); + + if (Config::instance()->getConnectionStrategy() == ConnectionStrategy::DONGLE_MODE) { + startAdvertising(); + } } std::optional BluetoothHandler::connectWithRetry() { @@ -231,5 +287,8 @@ void BluetoothHandler::powerOff() { return; } + if (Config::instance()->getConnectionStrategy() == ConnectionStrategy::DONGLE_MODE) { + stopAdvertising(); + } setPower(false); } \ No newline at end of file diff --git a/aa_wireless_dongle/package/aawg/src/bluetoothHandler.h b/aa_wireless_dongle/package/aawg/src/bluetoothHandler.h index f49b89a..9b0a969 100644 --- a/aa_wireless_dongle/package/aawg/src/bluetoothHandler.h +++ b/aa_wireless_dongle/package/aawg/src/bluetoothHandler.h @@ -8,6 +8,7 @@ class BluezAdapterProxy; class AAWirelessProfile; class HSPHSProfile; +class BLEAdvertisement; class BluetoothHandler { public: @@ -33,6 +34,9 @@ class BluetoothHandler { void exportProfiles(); void connectDevice(); + void startAdvertising(); + void stopAdvertising(); + void retryConnectLoop(); std::shared_ptr> connectWithRetryPromise; @@ -43,4 +47,8 @@ class BluetoothHandler { std::shared_ptr m_aawProfile; std::shared_ptr m_hspProfile; + + std::shared_ptr m_leAdvertisement; + + std::string m_adapterAlias; }; diff --git a/aa_wireless_dongle/package/aawg/src/common.cpp b/aa_wireless_dongle/package/aawg/src/common.cpp index ae137cc..4423948 100644 --- a/aa_wireless_dongle/package/aawg/src/common.cpp +++ b/aa_wireless_dongle/package/aawg/src/common.cpp @@ -48,6 +48,26 @@ WifiInfo Config::getWifiInfo() { getenv("AAWG_PROXY_PORT", 5288), }; } + +ConnectionStrategy Config::getConnectionStrategy() { + if (!connectionStrategy.has_value()) { + const int32_t connectionStrategyEnv = getenv("AAWG_CONNECTION_STRATEGY", 0); + + switch (connectionStrategyEnv) { + case 1: + connectionStrategy = ConnectionStrategy::PHONE_FIRST; + break; + case 2: + connectionStrategy = ConnectionStrategy::USB_FIRST; + break; + default: + connectionStrategy = ConnectionStrategy::DONGLE_MODE; + break; + } + } + + return connectionStrategy.value(); +} #pragma endregion Config #pragma region Logger diff --git a/aa_wireless_dongle/package/aawg/src/common.h b/aa_wireless_dongle/package/aawg/src/common.h index ce29b89..77bde6f 100644 --- a/aa_wireless_dongle/package/aawg/src/common.h +++ b/aa_wireless_dongle/package/aawg/src/common.h @@ -2,6 +2,7 @@ #include #include +#include enum SecurityMode: int; enum AccessPointType: int; @@ -16,11 +17,18 @@ struct WifiInfo { int32_t port; }; +enum class ConnectionStrategy { + DONGLE_MODE = 0, + PHONE_FIRST = 1, + USB_FIRST = 2 +}; + class Config { public: static Config* instance(); WifiInfo getWifiInfo(); + ConnectionStrategy getConnectionStrategy(); private: Config() = default; @@ -28,6 +36,8 @@ class Config { std::string getenv(std::string name, std::string defaultValue); std::string getMacAddress(std::string interface); + + std::optional connectionStrategy; }; class Logger { diff --git a/aa_wireless_dongle/package/aawg/src/proxyHandler.cpp b/aa_wireless_dongle/package/aawg/src/proxyHandler.cpp index e7d494e..34e6c03 100644 --- a/aa_wireless_dongle/package/aawg/src/proxyHandler.cpp +++ b/aa_wireless_dongle/package/aawg/src/proxyHandler.cpp @@ -168,7 +168,7 @@ void AAWProxy::handleClient(int server_sock) { // Phone connected via TCP, we can stop retrying bluetooth connection BluetoothHandler::instance().stopConnectWithRetry(); - if (std::getenv("AAWG_CONNECTION_WAIT_FOR_ACCESSORY") == nullptr) { + if (Config::instance()->getConnectionStrategy() != ConnectionStrategy::USB_FIRST) { if (!UsbManager::instance().enableDefaultAndWaitForAccessory(std::chrono::seconds(10))) { return; }