diff --git a/connd/com.jollamobile.Connectiond.xml b/connd/com.jollamobile.Connectiond.xml
index 82dd574..b356e57 100644
--- a/connd/com.jollamobile.Connectiond.xml
+++ b/connd/com.jollamobile.Connectiond.xml
@@ -28,6 +28,9 @@
+
+
+
@@ -39,5 +42,11 @@
+
+
+
+
+
+
diff --git a/connd/qconnectionagent.cpp b/connd/qconnectionagent.cpp
index 898fc0c..af00be2 100644
--- a/connd/qconnectionagent.cpp
+++ b/connd/qconnectionagent.cpp
@@ -234,18 +234,35 @@ void QConnectionAgent::serviceStateChanged(const QString &state)
if (state == "disconnect") {
ua->sendConnectReply("Clear");
}
-// if (state == "failure") {
+ if (state == "failure") {
+ if (delayedTethering && service->type() == "cellular" && tetheringWifiTech->tethering()) {
+ Q_EMIT tetheringFinished(false);
+ }
// serviceInProgress.clear();
// // service->requestDisconnect();
-// }
+ }
+ if (delayedTethering && service->type() == "wifi" && state == "association") {
+ service->requestDisconnect();
+ }
if (state == "online") {
Q_EMIT connectionState(state, service->type());
- }
+ if (service->type() == "wifi" && delayedTethering) {
+ netman->getTechnology(service->type())->setTethering(true);
+ }
+ if (service->type() == "cellular" && delayedTethering) {
+ if (!tetheringWifiTech->tethering()) {
+ tetheringWifiTech->setTethering(true);
+ }
+ }
+ }
//auto migrate
if (state == "idle") {
- } else {
+ if (service->type() == "wifi" && delayedTethering) {
+ netman->getTechnology(service->type())->setTethering(true);
+ }
+ } else {
updateServicesMap();
}
currentNetworkState = state;
@@ -358,10 +375,26 @@ void QConnectionAgent::networkStateChanged(const QString &state)
if ((state == "online" && netman->defaultRoute()->type() == "cellular")
|| (state == "idle")) {
+
+ if (tetheringWifiTech && tetheringWifiTech->powered()
+ && !tetheringWifiTech->tethering())
+ tetheringWifiTech->scan();
// on gprs, scan wifi every scanTimeoutInterval minutes
if (scanTimeoutInterval != 0)
scanTimer->start(scanTimeoutInterval * 60 * 1000);
}
+
+ if (delayedTethering && state == "online") {
+
+ if (tetheringWifiTech->tethering()) {
+ if (netman->defaultRoute()->type() == "cellular") {
+ delayedTethering = false;
+ Q_EMIT tetheringFinished(true);
+ }
+ } else {
+ tetheringWifiTech->setTethering(true);
+ }
+ }
}
bool QConnectionAgent::askRoaming() const
@@ -457,10 +490,13 @@ void QConnectionAgent::technologyPowerChanged(bool powered)
{
NetworkTechnology *tech = static_cast(sender());
qDebug() << tech->name() << powered;
- if (tech->type() == "wifi") {
- if (powered) {
- tetheringWifiTech->scan();
- } else {
+
+ if (netman && tech->type() == "wifi" && powered && delayedTethering) {
+ tech->setTethering(true);
+ }
+
+ if (!delayedTethering && tech->type() == "wifi") {
+ if (!powered) {
removeAllTypes("wifi"); //dont wait for connman, he's too slow at this
QString bestService = findBestConnectableService();
if (!bestService.isEmpty()) {
@@ -473,7 +509,8 @@ void QConnectionAgent::technologyPowerChanged(bool powered)
void QConnectionAgent::techChanged()
{
- qDebug() << netman->getTechnology("wifi");
+ if (!netman)
+ return;
if (netman->getTechnologies().isEmpty()) {
knownTechnologies.clear();
}
@@ -483,9 +520,6 @@ void QConnectionAgent::techChanged()
}
if (tetheringWifiTech) {
tetheringEnabled = tetheringWifiTech->tethering();
- qDebug() << "tethering is" << tetheringEnabled;
- QObject::connect(tetheringWifiTech, SIGNAL(tetheringChanged(bool)),
- this,SLOT(techTetheringChanged(bool)), Qt::UniqueConnection);
}
Q_FOREACH(NetworkTechnology *technology,netman->getTechnologies()) {
@@ -495,6 +529,8 @@ void QConnectionAgent::techChanged()
tetheringWifiTech = technology;
connect(tetheringWifiTech,SIGNAL(poweredChanged(bool)),this,SLOT(technologyPowerChanged(bool)));
connect(tetheringWifiTech,SIGNAL(scanFinished()),this,SLOT(onScanFinished()));
+ connect(tetheringWifiTech, SIGNAL(tetheringChanged(bool)),
+ this,SLOT(techTetheringChanged(bool)), Qt::UniqueConnection);
}
} else {
knownTechnologies.removeOne(technology->path());
@@ -518,10 +554,28 @@ bool QConnectionAgent::isStateOnline(const QString &state)
return false;
}
-void QConnectionAgent::techTetheringChanged(bool b)
+void QConnectionAgent::techTetheringChanged(bool on)
{
- qDebug() << b;
- tetheringEnabled = b;
+ qDebug() << on;
+ tetheringEnabled = on;
+ NetworkTechnology *technology = static_cast(sender());
+
+ if (on && delayedTethering && technology) {
+ QVector services = netman->getServices("cellular");
+ if (services.isEmpty())
+ return;
+ NetworkService* cellService = services.at(0);
+ if (cellService) {
+ if (cellService->state() == "idle"|| cellService->state() == "failure") {
+ cellService->requestConnect();
+ } else if (cellService->connected()) {
+ delayedTethering = false;
+ Q_EMIT tetheringFinished(true);
+ }
+ } else {
+ stopTethering();
+ }
+ }
}
void QConnectionAgent::offlineModeChanged(bool b)
@@ -542,7 +596,7 @@ void QConnectionAgent::displayStateChanged(const QString &state)
{
if (state == "on") {
NetworkTechnology *wifiTech = netman->getTechnology("wifi");
- if (wifiTech && wifiTech->powered() && !wifiTech->connected()) {
+ if (wifiTech && wifiTech->powered() && !wifiTech->connected() && !wifiTech->tethering()) {
wifiTech->scan();
}
}
@@ -603,7 +657,10 @@ bool QConnectionAgent::isBestService(NetworkService *service)
void QConnectionAgent::scanTimeout()
{
- if (tetheringWifiTech && tetheringWifiTech->powered() && !tetheringWifiTech->connected() && netman->defaultRoute()->type() != "wifi" ) {
+ if (!tetheringWifiTech || tetheringWifiTech->tethering())
+ return;
+
+ if (tetheringWifiTech->powered() && !tetheringWifiTech->connected() && netman->defaultRoute()->type() != "wifi" ) {
tetheringWifiTech->scan();
qDebug() << "start scanner" << scanTimeoutInterval;
if (scanTimeoutInterval != 0) {
@@ -722,3 +779,83 @@ void QConnectionAgent::openConnectionDialog(const QString &type)
QDBusMessage reply = connSelectorInterface->callWithArgumentList(QDBus::NoBlock,
QStringLiteral("openConnection"), args);
}
+
+void QConnectionAgent::startTethering(const QString &type)
+{
+ if (!netman | (type != "wifi")) { //we only support wifi for now
+ Q_EMIT tetheringFinished(false);
+ return;
+ }
+
+ NetworkTechnology *tetherTech = netman->getTechnology(type);
+ if (!tetherTech) {
+ Q_EMIT tetheringFinished(false);
+ return;
+ }
+
+ QVector services = netman->getServices("cellular");
+ if (services.isEmpty()) {
+ Q_EMIT tetheringFinished(false);
+ return;
+ }
+
+ NetworkService *cellService = services.at(0);
+ if (!cellService || netman->offlineMode()) {
+ Q_EMIT tetheringFinished(false);
+ return;
+ }
+
+ QSettings confFile;
+ confFile.beginGroup("Connectionagent");
+ bool cellConnected = cellService->connected();
+ bool cellAutoconnect = cellService->autoConnect();
+
+ // save cellular connection state
+ confFile.setValue("tetheringCellularConnected",cellConnected);
+ confFile.setValue("tetheringCellularAutoconnect",cellAutoconnect);
+
+ bool techPowered = tetherTech->powered();
+
+ // save wifi powered state
+ confFile.setValue("tetheringTechPowered",techPowered);
+ confFile.setValue("tetheringType",type);
+
+ delayedTethering = true;
+ if (!techPowered) {
+ tetherTech->setPowered(true);
+ } else {
+ tetherTech->setTethering(true);
+ }
+}
+
+void QConnectionAgent::stopTethering()
+{
+ delayedTethering = false;
+ QSettings confFile;
+ confFile.beginGroup("Connectionagent");
+
+ NetworkTechnology *tetherTech = netman->getTechnology(confFile.value("tetheringType","wifi").toString());
+ if (tetherTech && tetherTech->tethering()) {
+ tetherTech->setTethering(false);
+ }
+ bool b = confFile.value("tetheringCellularConnected").toBool();
+ bool ab = confFile.value("tetheringCellularAutoconnect").toBool();
+
+ Q_FOREACH (const QString &path, servicesMap.keys()) {
+ if (path.contains("cellular")) {
+ if (isStateOnline(servicesMap.value(path)->state())) {
+ qDebug() << "disconnect mobile data";
+ if (!b)
+ servicesMap.value(path)->requestDisconnect();
+ if (!ab)
+ servicesMap.value(path)->setAutoConnect(false);
+ }
+ }
+ }
+
+ b = confFile.value("tetheringTechPowered").toBool();
+ if (!b && tetherTech) {
+ tetherTech->setPowered(false);
+ }
+ Q_EMIT tetheringFinished(false);
+}
diff --git a/connd/qconnectionagent.h b/connd/qconnectionagent.h
index f453d9d..1b6769b 100644
--- a/connd/qconnectionagent.h
+++ b/connd/qconnectionagent.h
@@ -61,6 +61,7 @@ class QConnectionAgent : public QObject
void connectNow(const QString &path);
void requestBrowser(const QString &url);
+ void tetheringFinished(bool);
public Q_SLOTS:
@@ -75,6 +76,9 @@ public Q_SLOTS:
void connectToType(const QString &type);
+ void startTethering(const QString &type);
+ void stopTethering();
+
private:
explicit QConnectionAgent(QObject *parent = 0);
static QConnectionAgent *self;
@@ -107,6 +111,8 @@ public Q_SLOTS:
bool isBestService(NetworkService *service);
QString findBestConnectableService();
void removeAllTypes(const QString &type);
+ bool tetheringStarted;
+ bool delayedTethering;
private slots:
void onScanFinished();
diff --git a/connectionagentplugin/connectionagentplugin.cpp b/connectionagentplugin/connectionagentplugin.cpp
index 2505fc1..9354c71 100644
--- a/connectionagentplugin/connectionagentplugin.cpp
+++ b/connectionagentplugin/connectionagentplugin.cpp
@@ -87,10 +87,13 @@ void ConnectionAgentPlugin::connectToConnectiond(QString)
connect(connManagerInterface,SIGNAL(userInputRequested(QString,QVariantMap)),
this,SLOT(onUserInputRequested(QString,QVariantMap)), Qt::UniqueConnection);
+
+ connect(connManagerInterface,SIGNAL(tetheringFinished(bool)),
+ this,SLOT(onTetheringFinished(bool)));
}
void ConnectionAgentPlugin::sendUserReply(const QVariantMap &input)
-{
+{
if (!connManagerInterface || !connManagerInterface->isValid()) {
Q_EMIT errorReported("","ConnectionAgent not available");
return;
@@ -179,3 +182,17 @@ void ConnectionAgentPlugin::setAskRoaming(bool value)
connManagerInterface->setAskRoaming(value);
}
+void ConnectionAgentPlugin::startTethering(const QString &type)
+{
+ connManagerInterface->startTethering(type);
+}
+
+void ConnectionAgentPlugin::onTetheringFinished(bool success)
+{
+ Q_EMIT tetheringFinished(success);
+}
+
+void ConnectionAgentPlugin::stopTethering()
+{
+ connManagerInterface->stopTethering();
+}
diff --git a/connectionagentplugin/connectionagentplugin.h b/connectionagentplugin/connectionagentplugin.h
index 0b748f3..b7fc4a0 100644
--- a/connectionagentplugin/connectionagentplugin.h
+++ b/connectionagentplugin/connectionagentplugin.h
@@ -27,7 +27,7 @@ class ConnectionAgentPlugin : public QObject
Q_PROPERTY(bool askRoaming READ askRoaming WRITE setAskRoaming)
Q_DISABLE_COPY(ConnectionAgentPlugin)
-
+
public:
explicit ConnectionAgentPlugin(QObject *parent = 0);
~ConnectionAgentPlugin();
@@ -38,6 +38,8 @@ public slots:
void sendUserReply(const QVariantMap &input);
void sendConnectReply(const QString &replyMessage, int timeout = 120);
void connectToType(const QString &type);
+ void startTethering(const QString &type);
+ void stopTethering();
signals:
void userInputRequested(const QString &servicePath, const QVariantMap &fields);
@@ -47,6 +49,7 @@ public slots:
void configurationNeeded(const QString &type);
void connectionState(const QString &state, const QString &type);
void browserRequested(const QString &url);
+ void tetheringFinished(bool);
private:
com::jolla::Connectiond *connManagerInterface;
@@ -58,6 +61,7 @@ private slots:
void onUserInputRequested(const QString &service, const QVariantMap &fields);
void onConnectionRequested();
void onConnectionState(const QString &state, const QString &type);
+ void onTetheringFinished(bool);
void connectToConnectiond(const QString = QString());
void connectiondUnregistered(const QString = QString());
diff --git a/connectionagentplugin/connectionamanagerinterface.h b/connectionagentplugin/connectionamanagerinterface.h
index 9231b4a..7462873 100644
--- a/connectionagentplugin/connectionamanagerinterface.h
+++ b/connectionagentplugin/connectionamanagerinterface.h
@@ -63,6 +63,19 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("sendUserReply"), argumentList);
}
+ inline QDBusPendingReply<> startTethering(const QString &in0)
+ {
+ QList argumentList;
+ argumentList << QVariant::fromValue(in0);
+ return asyncCallWithArgumentList(QLatin1String("startTethering"), argumentList);
+ }
+
+ inline QDBusPendingReply<> stopTethering()
+ {
+ return asyncCall(QLatin1String("stopTethering"));
+ }
+
+
Q_SIGNALS: // SIGNALS
void configurationNeeded(const QString &type);
void connectionRequest();
@@ -72,6 +85,7 @@ public Q_SLOTS: // METHODS
void roamingAskChanged(bool askRoaming);
void userInputCanceled();
void userInputRequested(const QString &service, const QVariantMap &fields);
+ void tetheringFinished(bool);
};
namespace com {
diff --git a/test/auto/tst_connectionagent_plugin/tst_connectionagent_plugintest.cpp b/test/auto/tst_connectionagent_plugin/tst_connectionagent_plugintest.cpp
index 8e3562c..743aa87 100644
--- a/test/auto/tst_connectionagent_plugin/tst_connectionagent_plugintest.cpp
+++ b/test/auto/tst_connectionagent_plugin/tst_connectionagent_plugintest.cpp
@@ -33,7 +33,7 @@
class Tst_connectionagent_pluginTest : public QObject
{
Q_OBJECT
-
+
public:
Tst_connectionagent_pluginTest();
~Tst_connectionagent_pluginTest();
@@ -44,15 +44,20 @@ private Q_SLOTS:
void testUserInputRequested_data();
void testUserInputRequested();
-
void testErrorReported();
+
+ void tst_tethering();
+
private:
ConnectionAgentPlugin *plugin;
+ NetworkManager *netman;
};
Tst_connectionagent_pluginTest::Tst_connectionagent_pluginTest()
{
plugin = new ConnectionAgentPlugin(this);
+ netman = NetworkManagerFactory::createInstance();
+ QTest::qWait(5000);
}
Tst_connectionagent_pluginTest::~Tst_connectionagent_pluginTest()
@@ -147,6 +152,70 @@ void Tst_connectionagent_pluginTest::testUserInputRequested()
}
+void Tst_connectionagent_pluginTest::tst_tethering()
+{
+ NetworkService *wlanService;
+ NetworkService *mobiledataService;
+
+ QVector wifiServices = netman->getServices("wifi");
+ QVERIFY(wifiServices.count() > 0);
+
+ Q_FOREACH (wlanService, wifiServices) {
+ if (wlanService->autoConnect()) {
+ break;
+ }
+ }
+ bool wlanOnline = wlanService->connected();
+
+ QVector cellServices = netman->getServices("cellular");
+ QVERIFY(cellServices.count() > 0);
+ mobiledataService = cellServices.at(0);
+
+ bool mdOnline = mobiledataService->connected();
+ bool mdAutoconnect = mobiledataService->autoConnect();
+
+ QSignalSpy spy(plugin, SIGNAL(tetheringFinished(bool)));
+ plugin->startTethering("wifi");
+
+ QVERIFY(spy.isValid());
+ QVERIFY(spy.wait(7000));
+
+ QCOMPARE(spy.count(),1);
+ QList arguments;
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toBool(), true);
+
+ QTest::qWait(5000);
+
+ QVERIFY(mobiledataService->state() == "online");
+
+ plugin->stopTethering();
+ QTest::qWait(2500);
+
+ QCOMPARE(spy.count(),1);
+ arguments = spy.takeFirst();
+ QCOMPARE(arguments.at(0).toBool(), false);
+
+ QTest::qWait(5000);
+
+ QVERIFY(wlanService->connected() == wlanOnline);
+ QVERIFY(mobiledataService->connected() == mdOnline);
+ QVERIFY(mobiledataService->autoConnect() == mdAutoconnect);
+
+// plugin->startTethering("wifi");
+
+
+// plugin->stopTethering();
+
+// QCOMPARE(spy.count(),1);
+// arguments = spy.takeFirst();
+// QCOMPARE(arguments.at(0).toBool(), false);
+
+// NetworkManager *netman = NetworkManagerFactory::createInstance();
+// NetworkService *cellServices = netman->getServices("cellular").at(0);
+// QVERIFY(cellServices->state() == "idle");
+}
+
QTEST_MAIN(Tst_connectionagent_pluginTest)
#include "tst_connectionagent_plugintest.moc"