Commit eaada24f authored by Lorn Potter's avatar Lorn Potter

[connectionagent] add tethering functionality

parent e6292a78
......@@ -28,6 +28,9 @@
<signal name="roamingAskChanged">
<arg name="askRoaming" type="b" direction="out"/>
</signal>
<signal name="tetheringFinished">
<arg name="success" type="b" direction="out"/>
</signal>
<method name="connectToType">
<arg name="in0" type="s" direction="in"/>
</method>
......@@ -39,5 +42,11 @@
<arg name="input" type="a{sv}" direction="in"/>
<annotation name="org.qtproject.QtDBus.QtTypeName.In0" value="QVariantMap"/>
</method>
<method name="startTethering">
<arg name="in0" type="s" direction="in"/>
</method>
<method name="stopTethering">
</method>
</interface>
</node>
......@@ -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<NetworkTechnology *>(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<NetworkTechnology *>(sender());
if (on && delayedTethering && technology) {
QVector <NetworkService *> 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 <NetworkService *> 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);
}
......@@ -61,6 +61,7 @@ Q_SIGNALS:
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 @@ private:
bool isBestService(NetworkService *service);
QString findBestConnectableService();
void removeAllTypes(const QString &type);
bool tetheringStarted;
bool delayedTethering;
private slots:
void onScanFinished();
......
......@@ -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();
}
......@@ -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 @@ signals:
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());
......
......@@ -63,6 +63,19 @@ public Q_SLOTS: // METHODS
return asyncCallWithArgumentList(QLatin1String("sendUserReply"), argumentList);
}
inline QDBusPendingReply<> startTethering(const QString &in0)
{
QList<QVariant> 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 @@ Q_SIGNALS: // SIGNALS
void roamingAskChanged(bool askRoaming);
void userInputCanceled();
void userInputRequested(const QString &service, const QVariantMap &fields);
void tetheringFinished(bool);
};
namespace com {
......
......@@ -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 <NetworkService *>wifiServices = netman->getServices("wifi");
QVERIFY(wifiServices.count() > 0);
Q_FOREACH (wlanService, wifiServices) {
if (wlanService->autoConnect()) {
break;
}
}
bool wlanOnline = wlanService->connected();
QVector <NetworkService *>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<QVariant> 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"
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment