Skip to content

Commit

Permalink
[mer][qtnetwork] Make qconnman bearer to tolerate late connman start.…
Browse files Browse the repository at this point in the history
… Contributes to JB#39489

This fixes a QNetworkConfigurationManager issue when/if
QNetworkConfigurationManager has been instantiated before connman
has been stared. Now QNetworkConfigurationManager updates its
network configuration state once connman service is registered to the
system bus.

Also restarting connman is now handled.

Signed-off-by: Raine Makelainen <raine.makelainen@jolla.com>
  • Loading branch information
rainemak authored and denexter committed Jun 5, 2018
1 parent 32407ba commit 575611b
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 41 deletions.
6 changes: 1 addition & 5 deletions src/plugins/bearer/connman/main.cpp
Expand Up @@ -69,11 +69,7 @@ QConnmanEnginePlugin::~QConnmanEnginePlugin()
QBearerEngine *QConnmanEnginePlugin::create(const QString &key) const
{
if (key == QLatin1String("connman")) {
QConnmanEngine *engine = new QConnmanEngine;
if (engine->connmanAvailable())
return engine;
else
delete engine;
return new QConnmanEngine;
}
return 0;
}
Expand Down
198 changes: 164 additions & 34 deletions src/plugins/bearer/connman/qconnmanengine.cpp
Expand Up @@ -56,47 +56,75 @@

QT_BEGIN_NAMESPACE

Q_LOGGING_CATEGORY(qLcLibBearer, "qt.qpa.bearer.connman", QtWarningMsg)

QConnmanEngine::QConnmanEngine(QObject *parent)
: QBearerEngineImpl(parent),
connmanManager(new QConnmanManagerInterface(this)),
ofonoManager(new QOfonoManagerInterface(this)),
connmanManager(0),
ofonoManager(0),
ofonoNetwork(0),
ofonoContextManager(0)
ofonoContextManager(0),
connmanAvailable(false)

{
qDBusRegisterMetaType<ConnmanMap>();
qDBusRegisterMetaType<ConnmanMapList>();
qRegisterMetaType<ConnmanMapList>("ConnmanMapList");
}

QConnmanEngine::~QConnmanEngine()
{
connmanWatcher = new QDBusServiceWatcher(QLatin1String(CONNMAN_SERVICE), QDBusConnection::systemBus(),
QDBusServiceWatcher::WatchForRegistration |
QDBusServiceWatcher::WatchForUnregistration, this);
connect(connmanWatcher, SIGNAL(serviceRegistered(QString)),
this, SLOT(connmanRegistered(QString)));
connect(connmanWatcher, SIGNAL(serviceUnregistered(QString)),
this, SLOT(connmanUnRegistered(QString)));

ofonoWatcher = new QDBusServiceWatcher(QLatin1String(OFONO_SERVICE), QDBusConnection::systemBus(),
QDBusServiceWatcher::WatchForRegistration |
QDBusServiceWatcher::WatchForUnregistration, this);
connect(ofonoWatcher, SIGNAL(serviceRegistered(QString)),
this, SLOT(ofonoRegistered(QString)));
connect(ofonoWatcher, SIGNAL(serviceUnregistered(QString)),
this, SLOT(ofonoUnRegistered(QString)));

QDBusConnectionInterface *interface = QDBusConnection::systemBus().interface();
if (!interface) {
qCCritical(qLcLibBearer) << "QConnmanEngine: something is badly wrong, no system bus interface.";
return;
}

if (interface->isServiceRegistered(QLatin1String(OFONO_SERVICE))) {
QMetaObject::invokeMethod(this, "ofonoRegistered", Qt::QueuedConnection, Q_ARG(QString, OFONO_SERVICE));
} else {
qCDebug(qLcLibBearer) << "QConnmanEngine:" << OFONO_SERVICE << "dbus service is not registered";
}

if (interface->isServiceRegistered(QLatin1String(CONNMAN_SERVICE))) {
QMetaObject::invokeMethod(this, "connmanRegistered", Qt::QueuedConnection, Q_ARG(QString, CONNMAN_SERVICE));
} else {
qCDebug(qLcLibBearer) << "QConnmanEngine:" << CONNMAN_SERVICE << "dbus service is not registered";
}
}

bool QConnmanEngine::connmanAvailable() const
QConnmanEngine::~QConnmanEngine()
{
QMutexLocker locker(&mutex);
return connmanManager->isValid();
qCDebug(qLcLibBearer) << "QConnmanEngine: destroyed";
}

void QConnmanEngine::initialize()
{
qCDebug(qLcLibBearer) << "QConnmanEngine: initialize";

QMutexLocker locker(&mutex);
connect(ofonoManager,SIGNAL(modemChanged()),this,SLOT(changedModem()));

ofonoNetwork = new QOfonoNetworkRegistrationInterface(ofonoManager->currentModem(),this);
ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this);
connect(ofonoContextManager,SIGNAL(roamingAllowedChanged(bool)),this,SLOT(reEvaluateCellular()));

connect(connmanManager,SIGNAL(servicesChanged(ConnmanMapList,QList<QDBusObjectPath>)),
this, SLOT(updateServices(ConnmanMapList,QList<QDBusObjectPath>)));

connect(connmanManager,SIGNAL(servicesReady(QStringList)),this,SLOT(servicesReady(QStringList)));
connect(connmanManager,SIGNAL(scanFinished(bool)),this,SLOT(finishedScan(bool)));

const auto servPaths = connmanManager->getServices();
for (const QString &servPath : servPaths)
addServiceConfiguration(servPath);
Q_EMIT updateCompleted();
if (connmanAvailable) {
setupConfigurations();
}
}

void QConnmanEngine::changedModem()
Expand Down Expand Up @@ -202,8 +230,7 @@ void QConnmanEngine::requestUpdate()

void QConnmanEngine::doRequestUpdate()
{
bool scanned = connmanManager->requestScan("wifi");
if (!scanned)
if (connmanManager && connmanManager->requestScan("wifi"))
Q_EMIT updateCompleted();
}

Expand Down Expand Up @@ -329,11 +356,14 @@ QNetworkSessionPrivate *QConnmanEngine::createSessionBackend()
QNetworkConfigurationPrivatePointer QConnmanEngine::defaultConfiguration()
{
const QMutexLocker locker(&mutex);
const auto servPaths = connmanManager->getServices();
for (const QString &servPath : servPaths) {
if (connmanServiceInterfaces.contains(servPath)) {
if (accessPointConfigurations.contains(servPath))
return accessPointConfigurations.value(servPath);

if (connmanManager) {
const auto servPaths = connmanManager->getServices();
for (const QString &servPath : servPaths) {
if (connmanServiceInterfaces.contains(servPath)) {
if (accessPointConfigurations.contains(servPath))
return accessPointConfigurations.value(servPath);
}
}
}
return QNetworkConfigurationPrivatePointer();
Expand Down Expand Up @@ -478,10 +508,12 @@ QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QS

bool QConnmanEngine::isRoamingAllowed(const QString &context)
{
const auto dcPaths = ofonoContextManager->contexts();
for (const QString &dcPath : dcPaths) {
if (dcPath.contains(context.section("_",-1))) {
return ofonoContextManager->roamingAllowed();
if (ofonoContextManager) {
const auto dcPaths = ofonoContextManager->contexts();
for (const QString &dcPath : dcPaths) {
if (dcPath.contains(context.section("_",-1))) {
return ofonoContextManager->roamingAllowed();
}
}
}
return false;
Expand Down Expand Up @@ -568,17 +600,115 @@ void QConnmanEngine::addServiceConfiguration(const QString &servicePath)
}
}

void QConnmanEngine::setupConfigurations()
{
QMutexLocker locker(&mutex);
qCDebug(qLcLibBearer) << "QConnmanEngine: setup connman configurations";

if (connmanManager) {
delete connmanManager;
}

connmanManager = new QConnmanManagerInterface(this);

connect(connmanManager,SIGNAL(servicesChanged(ConnmanMapList,QList<QDBusObjectPath>)),
this, SLOT(updateServices(ConnmanMapList,QList<QDBusObjectPath>)));

connect(connmanManager,SIGNAL(servicesReady(QStringList)),this,SLOT(servicesReady(QStringList)));
connect(connmanManager,SIGNAL(scanFinished(bool)),this,SLOT(finishedScan(bool)));

const auto servPaths = connmanManager->getServices();
for (const QString &servPath : servPaths)
addServiceConfiguration(servPath);
Q_EMIT updateCompleted();
}

bool QConnmanEngine::requiresPolling() const
{
return false;
}

void QConnmanEngine::reEvaluateCellular()
{
const auto servicePaths = connmanManager->getServices();
for (const QString &servicePath : servicePaths) {
if (servicePath.contains("cellular") && accessPointConfigurations.contains(servicePath)) {
configurationChange(connmanServiceInterfaces.value(servicePath));
if (connmanManager) {
const auto servicePaths = connmanManager->getServices();
for (const QString &servicePath : servicePaths) {
if (servicePath.contains("cellular") && accessPointConfigurations.contains(servicePath)) {
configurationChange(connmanServiceInterfaces.value(servicePath));
}
}
}
}

void QConnmanEngine::connmanRegistered(const QString &serviceName)
{
qCDebug(qLcLibBearer) << "QConnmanEngine: connman dbus service registered:" << serviceName;
connmanAvailable = true;
setupConfigurations();
}

void QConnmanEngine::connmanUnRegistered(const QString &serviceName)
{
qCDebug(qLcLibBearer) << "QConnmanEngine: connman dbus service unregistered:" << serviceName;

qDeleteAll(connmanServiceInterfaces);
connmanServiceInterfaces.clear();

// Remove all configurations.
QList<QString> keys = accessPointConfigurations.uniqueKeys();
for (const QString &key : keys) {
removeConfiguration(key);
}

serviceNetworks.clear();
connmanLastKnownSessionState.clear();
configInterfaces.clear();

delete connmanManager;
connmanManager = nullptr;
connmanAvailable = false;
}

void QConnmanEngine::ofonoRegistered(const QString &serviceName)
{
qCDebug(qLcLibBearer) << "QConnmanEngine: ofono dbus service registered:" << serviceName;
if (ofonoManager) {
delete ofonoManager;
}

if (ofonoNetwork) {
delete ofonoNetwork;
}

if (ofonoContextManager) {
delete ofonoContextManager;
}

ofonoManager = new QOfonoManagerInterface(this);
ofonoNetwork = new QOfonoNetworkRegistrationInterface(ofonoManager->currentModem(),this);
ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this);

connect(ofonoManager,SIGNAL(modemChanged()),this,SLOT(changedModem()));
connect(ofonoContextManager,SIGNAL(roamingAllowedChanged(bool)),this,SLOT(reEvaluateCellular()));
}

void QConnmanEngine::ofonoUnRegistered(const QString &serviceName)
{
qCDebug(qLcLibBearer) << "QConnmanEngine: ofono dbus service unregistered:" << serviceName;
delete ofonoManager;
ofonoManager = nullptr;

delete ofonoNetwork;
ofonoNetwork = nullptr;

delete ofonoContextManager;
ofonoContextManager = nullptr;

// Remove all cellular configurations.
const auto keys = accessPointConfigurations.uniqueKeys();
for (const QString &key : keys) {
if (key.startsWith(QLatin1String("/net/connman/service/cellular"))) {
removeConfiguration(key);
}
}
}
Expand Down
17 changes: 15 additions & 2 deletions src/plugins/bearer/connman/qconnmanengine.h
Expand Up @@ -71,8 +71,6 @@ class QConnmanEngine : public QBearerEngineImpl
QConnmanEngine(QObject *parent = 0);
~QConnmanEngine();

bool connmanAvailable() const;

virtual QString getInterfaceFromId(const QString &id);
bool hasIdentifier(const QString &id);

Expand Down Expand Up @@ -105,6 +103,13 @@ private Q_SLOTS:
void serviceStateChanged(const QString &state);
void configurationChange(QConnmanServiceInterface * service);
void reEvaluateCellular();

void connmanRegistered(const QString &serviceName);
void connmanUnRegistered(const QString &serviceName);

void ofonoRegistered(const QString &serviceName);
void ofonoUnRegistered(const QString &serviceName);

private:
QConnmanManagerInterface *connmanManager;

Expand All @@ -119,6 +124,9 @@ private Q_SLOTS:

void removeConfiguration(const QString &servicePath);
void addServiceConfiguration(const QString &servicePath);

void setupConfigurations();

QDateTime activeTime;

QMap<QString,QConnmanTechnologyInterface *> technologies; // techpath, tech interface
Expand All @@ -130,6 +138,11 @@ private Q_SLOTS:
QMap <QString,QConnmanServiceInterface *> connmanServiceInterfaces;
QMap <QString,QNetworkSession::State> connmanLastKnownSessionState;

QDBusServiceWatcher *ofonoWatcher;
QDBusServiceWatcher *connmanWatcher;

bool connmanAvailable;

protected:
bool requiresPolling() const;
};
Expand Down

0 comments on commit 575611b

Please sign in to comment.