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 committed Sep 15, 2017
1 parent fc88164 commit dc6bd03
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 44 deletions.
6 changes: 1 addition & 5 deletions src/plugins/bearer/connman/main.cpp
Expand Up @@ -63,11 +63,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
194 changes: 157 additions & 37 deletions src/plugins/bearer/connman/qconnmanengine.cpp
Expand Up @@ -50,47 +50,67 @@

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()
{
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)));

foreach (const QString &servPath, connmanManager->getServices()) {
addServiceConfiguration(servPath);
qCDebug(qLcLibBearer) << "QConnmanEngine: initialize";
if (connmanAvailable) {
setupConfigurations();
}
Q_EMIT updateCompleted();
}

void QConnmanEngine::changedModem()
Expand Down Expand Up @@ -197,8 +217,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 @@ -324,10 +343,12 @@ QNetworkSessionPrivate *QConnmanEngine::createSessionBackend()
QNetworkConfigurationPrivatePointer QConnmanEngine::defaultConfiguration()
{
const QMutexLocker locker(&mutex);
Q_FOREACH (const QString &servPath, connmanManager->getServices()) {
if (connmanServiceInterfaces.contains(servPath)) {
if (accessPointConfigurations.contains(servPath))
return accessPointConfigurations.value(servPath);
if (connmanManager) {
Q_FOREACH (const QString &servPath, connmanManager->getServices()) {
if (connmanServiceInterfaces.contains(servPath)) {
if (accessPointConfigurations.contains(servPath))
return accessPointConfigurations.value(servPath);
}
}
}
return QNetworkConfigurationPrivatePointer();
Expand Down Expand Up @@ -472,9 +493,11 @@ QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QS

bool QConnmanEngine::isRoamingAllowed(const QString &context)
{
foreach (const QString &dcPath, ofonoContextManager->contexts()) {
if (dcPath.contains(context.section("_",-1))) {
return ofonoContextManager->roamingAllowed();
if (ofonoContextManager) {
foreach (const QString &dcPath, ofonoContextManager->contexts()) {
if (dcPath.contains(context.section("_",-1))) {
return ofonoContextManager->roamingAllowed();
}
}
}
return false;
Expand Down Expand Up @@ -561,16 +584,113 @@ 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)));

foreach (const QString &servPath, connmanManager->getServices()) {
addServiceConfiguration(servPath);
}
Q_EMIT updateCompleted();
}

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

void QConnmanEngine::reEvaluateCellular()
{
Q_FOREACH (const QString &servicePath, connmanManager->getServices()) {
if (servicePath.contains("cellular") && accessPointConfigurations.contains(servicePath)) {
configurationChange(connmanServiceInterfaces.value(servicePath));
if (connmanManager) {
Q_FOREACH (const QString &servicePath, connmanManager->getServices()) {
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.
QList<QString> keys = accessPointConfigurations.uniqueKeys();
Q_FOREACH (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 @@ -65,8 +65,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 @@ -99,6 +97,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 @@ -113,6 +118,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 @@ -124,6 +132,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 dc6bd03

Please sign in to comment.