Skip to content

Commit

Permalink
Add dongle mode connection strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
nisargjhaveri committed Mar 27, 2024
1 parent 8d9c947 commit c7eab0f
Show file tree
Hide file tree
Showing 10 changed files with 175 additions and 25 deletions.
8 changes: 5 additions & 3 deletions aa_wireless_dongle/board/common/rootfs_overlay/etc/aawgd.env
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion aa_wireless_dongle/package/aawg/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
20 changes: 16 additions & 4 deletions aa_wireless_dongle/package/aawg/src/aawgd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand All @@ -29,7 +36,10 @@ int main(void) {
return 1;
}

BluetoothHandler::instance().powerOn();
if (connectionStrategy != ConnectionStrategy::DONGLE_MODE) {
BluetoothHandler::instance().powerOn();
}

std::optional<std::thread> btConnectionThread = BluetoothHandler::instance().connectWithRetry();

proxyThread->join();
Expand All @@ -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();
Expand Down
22 changes: 22 additions & 0 deletions aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <stdio.h>

#include "common.h"
#include "bluetoothAdvertisement.h"

static constexpr const char* INTERFACE_BLUEZ_LE_ADVERTISEMENT = "org.bluez.LEAdvertisement1";

/* static */ std::shared_ptr<BLEAdvertisement> BLEAdvertisement::create(DBus::Path path) {
return std::shared_ptr<BLEAdvertisement>(new BLEAdvertisement(path));
}

BLEAdvertisement::BLEAdvertisement(DBus::Path path): DBus::Object(path) {
this->create_method<void(void)>(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "Release", sigc::mem_fun(*this, &BLEAdvertisement::Release));

type = this->create_property<std::string>(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "Type", DBus::PropertyAccess::ReadOnly);
serviceUUIDs = this->create_property<std::vector<std::string>>(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "ServiceUUIDs");
localName = this->create_property<std::string>(INTERFACE_BLUEZ_LE_ADVERTISEMENT, "LocalName");
}

void BLEAdvertisement::Release() {
Logger::instance()->info("Bluetooth LE Advertisement released\n");
}
17 changes: 17 additions & 0 deletions aa_wireless_dongle/package/aawg/src/bluetoothAdvertisement.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#pragma once

#include "bluetoothCommon.h"

class BLEAdvertisement: public DBus::Object {
public:
static std::shared_ptr<BLEAdvertisement> create(DBus::Path path);

std::shared_ptr<DBus::Property<std::string>> type;
std::shared_ptr<DBus::Property<std::vector<std::string>>> serviceUUIDs;
std::shared_ptr<DBus::Property<std::string>> localName;

protected:
BLEAdvertisement(DBus::Path path);

void Release();
};
91 changes: 75 additions & 16 deletions aa_wireless_dongle/package/aawg/src/bluetoothHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand All @@ -28,6 +34,9 @@ class BluezAdapterProxy: private DBus::ObjectProxy {
powered = this->create_property<bool>(INTERFACE_BLUEZ_ADAPTER, "Powered");
discoverable = this->create_property<bool>(INTERFACE_BLUEZ_ADAPTER, "Discoverable");
pairable = this->create_property<bool>(INTERFACE_BLUEZ_ADAPTER, "Pairable");

registerAdvertisement = this->create_method<void(DBus::Path, DBus::Properties)>(INTERFACE_BLUEZ_LE_ADVERTISING_MANAGER, "RegisterAdvertisement");
unregisterAdvertisement = this->create_method<void(DBus::Path)>(INTERFACE_BLUEZ_LE_ADVERTISING_MANAGER, "UnregisterAdvertisement");
}

public:
Expand All @@ -40,6 +49,9 @@ class BluezAdapterProxy: private DBus::ObjectProxy {
std::shared_ptr<DBus::PropertyProxy<bool>> powered;
std::shared_ptr<DBus::PropertyProxy<bool>> discoverable;
std::shared_ptr<DBus::PropertyProxy<bool>> pairable;

std::shared_ptr<DBus::MethodProxy<void(DBus::Path, DBus::Properties)>> registerAdvertisement;
std::shared_ptr<DBus::MethodProxy<void(DBus::Path)>> unregisterAdvertisement;
};


Expand Down Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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<std::string>{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() {
Expand All @@ -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) {
Expand All @@ -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() {
Expand All @@ -186,7 +236,9 @@ void BluetoothHandler::retryConnectLoop() {
}
}

BluetoothHandler::instance().powerOff();
if (Config::instance()->getConnectionStrategy() != ConnectionStrategy::DONGLE_MODE) {
BluetoothHandler::instance().powerOff();
}
}

void BluetoothHandler::init() {
Expand All @@ -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();
Expand All @@ -209,6 +261,10 @@ void BluetoothHandler::powerOn() {

setPower(true);
setPairable(true);

if (Config::instance()->getConnectionStrategy() == ConnectionStrategy::DONGLE_MODE) {
startAdvertising();
}
}

std::optional<std::thread> BluetoothHandler::connectWithRetry() {
Expand All @@ -231,5 +287,8 @@ void BluetoothHandler::powerOff() {
return;
}

if (Config::instance()->getConnectionStrategy() == ConnectionStrategy::DONGLE_MODE) {
stopAdvertising();
}
setPower(false);
}
8 changes: 8 additions & 0 deletions aa_wireless_dongle/package/aawg/src/bluetoothHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
class BluezAdapterProxy;
class AAWirelessProfile;
class HSPHSProfile;
class BLEAdvertisement;

class BluetoothHandler {
public:
Expand All @@ -33,6 +34,9 @@ class BluetoothHandler {
void exportProfiles();
void connectDevice();

void startAdvertising();
void stopAdvertising();

void retryConnectLoop();

std::shared_ptr<std::promise<void>> connectWithRetryPromise;
Expand All @@ -43,4 +47,8 @@ class BluetoothHandler {

std::shared_ptr<AAWirelessProfile> m_aawProfile;
std::shared_ptr<HSPHSProfile> m_hspProfile;

std::shared_ptr<BLEAdvertisement> m_leAdvertisement;

std::string m_adapterAlias;
};
20 changes: 20 additions & 0 deletions aa_wireless_dongle/package/aawg/src/common.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
10 changes: 10 additions & 0 deletions aa_wireless_dongle/package/aawg/src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <string>
#include <cstdint>
#include <optional>

enum SecurityMode: int;
enum AccessPointType: int;
Expand All @@ -16,18 +17,27 @@ 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;

int32_t getenv(std::string name, int32_t defaultValue);
std::string getenv(std::string name, std::string defaultValue);

std::string getMacAddress(std::string interface);

std::optional<ConnectionStrategy> connectionStrategy;
};

class Logger {
Expand Down
2 changes: 1 addition & 1 deletion aa_wireless_dongle/package/aawg/src/proxyHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down

0 comments on commit c7eab0f

Please sign in to comment.