qconnectionagent.cpp 22.8 KB
Newer Older
1 2
/****************************************************************************
**
3
** Copyright (C) 2014-2017 Jolla Ltd
4 5 6 7 8 9 10 11 12 13 14 15 16
** Contact: lorn.potter@gmail.com
**
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
****************************************************************************/

#include "qconnectionagent.h"
17
#include "connectiond_adaptor.h"
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42

#include <connman-qt5/useragent.h>
#include <connman-qt5/networkmanager.h>
#include <connman-qt5/networktechnology.h>
#include <connman-qt5/networkservice.h>

#include <QtDBus/QDBusConnection>

#include <QObject>
#include <QSettings>

#define CONND_SERVICE "com.jolla.Connectiond"
#define CONND_PATH "/Connectiond"
#define CONND_SESSION_PATH = "/ConnectionSession"

QConnectionAgent::QConnectionAgent(QObject *parent) :
    QObject(parent),
    ua(0),
    netman(NetworkManagerFactory::createInstance()),
    currentNetworkState(QString()),
    isEthernet(false),
    connmanAvailable(false),
    tetheringWifiTech(0),
    tetheringEnabled(false),
    flightModeSuppression(false),
43
    scanTimeoutInterval(1),
44 45
    delayedTethering(false),
    valid(true)
46
{
47
    new ConnAdaptor(this);
48 49
    QDBusConnection dbus = QDBusConnection::sessionBus();

50
    if (!dbus.registerObject(CONND_PATH, this)) {
51
        qDebug() << "QConnectionAgent: Could not register object to path" << CONND_PATH;
52
        valid = false;
53 54
    }

55
    if (!dbus.registerService(CONND_SERVICE)) {
56
        qDebug() << "QConnectionAgent: could not register service" << CONND_SERVICE;
57
        valid = false;
58 59
    }

60
    connect(this, &QConnectionAgent::configurationNeeded, this, &QConnectionAgent::openConnectionDialog);
61

62 63 64 65 66 67 68 69
    connect(netman, &NetworkManager::availabilityChanged, this, &QConnectionAgent::connmanAvailabilityChanged);
    connect(netman, &NetworkManager::servicesListChanged, this, &QConnectionAgent::servicesListChanged);
    connect(netman, &NetworkManager::stateChanged, this, &QConnectionAgent::networkStateChanged);
    connect(netman, &NetworkManager::offlineModeChanged, this, &QConnectionAgent::offlineModeChanged);
    connect(netman, &NetworkManager::servicesChanged, this, [=]() {
        updateServices();
    });
    connect(netman, &NetworkManager::technologiesChanged, this, &QConnectionAgent::techChanged);
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

    QFile connmanConf("/etc/connman/main.conf");
    if (connmanConf.open(QIODevice::ReadOnly | QIODevice::Text)) {
        while (!connmanConf.atEnd()) {
            QString line = connmanConf.readLine();
            if (line.startsWith("DefaultAutoConnectTechnologies")) {
                QString token = line.section(" = ",1,1).simplified();
                techPreferenceList = token.split(",");
                break;
            }
        }
        connmanConf.close();
    }
    if (techPreferenceList.isEmpty())
        //ethernet,bluetooth,cellular,wifi is default
        techPreferenceList << "bluetooth" << "wifi" << "cellular" << "ethernet";

    connmanAvailable = QDBusConnection::systemBus().interface()->isServiceRegistered("net.connman");

    scanTimer = new QTimer(this);
90
    connect(scanTimer, &QTimer::timeout, this, &QConnectionAgent::scanTimeout);
91
    scanTimer->setSingleShot(true);
92
    if (connmanAvailable && valid)
93 94 95 96 97 98 99
        setup();
}

QConnectionAgent::~QConnectionAgent()
{
}

100
bool QConnectionAgent::isValid() const
101
{
102
    return valid;
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
}

// from useragent
void QConnectionAgent::onUserInputRequested(const QString &servicePath, const QVariantMap &fields)
{
    qDebug() << servicePath;
    // gets called when a connman service gets called to connect and needs more configurations.
    Q_EMIT userInputRequested(servicePath, fields);
}

// from useragent
void QConnectionAgent::onUserInputCanceled()
{
    Q_EMIT userInputCanceled();
}

// from useragent
void QConnectionAgent::onErrorReported(const QString &servicePath, const QString &error)
{
122
    if (shouldSuppressError(error, servicePath.contains("cellular")))
123 124
        return;

125
    if (!tetheringWifiTech) return;
126 127 128 129
    // Suppress errors when switching to tethering mode
    if ((delayedTethering || tetheringWifiTech->tethering()) && servicePath.contains(QStringLiteral("wifi")))
        return;

130 131 132 133 134 135 136 137 138
    qDebug() << "<<<<<<<<<<<<<<<<<<<<" << servicePath << error;
    Q_EMIT errorReported(servicePath, error);
}

// from useragent
void QConnectionAgent::onConnectionRequest()
{
    sendConnectReply("Suppress", 15);
    qDebug() << flightModeSuppression;
139
    bool okToRequest = true;
140 141 142
    Q_FOREACH (Service elem, orderedServicesList) {
        qDebug() << "checking" << elem.service->name() << elem.service->autoConnect();
        if (elem.service->autoConnect()) {
143 144 145 146 147
            okToRequest = false;
            break;
        }
    }
    if (!flightModeSuppression && okToRequest) {
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
        Q_EMIT connectionRequest();
    }
}

void QConnectionAgent::sendConnectReply(const QString &in0, int in1)
{
    ua->sendConnectReply(in0, in1);
}

void QConnectionAgent::sendUserReply(const QVariantMap &input)
{
    qDebug() << Q_FUNC_INFO;
    ua->sendUserReply(input);
}

void QConnectionAgent::servicesListChanged(const QStringList &list)
{
165 166 167 168 169
    bool changed = false;

    Q_FOREACH(const QString &path, list) {
        if (orderedServicesList.indexOf(path) == -1) {
            //added
170
            qDebug() << Q_FUNC_INFO << "added" << path;
171 172
            changed = true;
            break;
173 174 175
        }
    }

176 177 178 179 180 181 182 183
    if (!changed)
        Q_FOREACH (Service elem, orderedServicesList) {
            if (list.indexOf(elem.path) == -1) {
                //removed
                qDebug() << Q_FUNC_INFO << "removed" << elem.path;
                changed = true;
                break;
            }
184
        }
185 186 187

    if (changed)
        updateServices();
188 189 190 191 192
}

void QConnectionAgent::serviceErrorChanged(const QString &error)
{
    NetworkService *service = static_cast<NetworkService *>(sender());
193
    if (shouldSuppressError(error, service->type() == QLatin1String("cellular")))
194 195
        return;

196
    Q_EMIT errorReported(service->path(), error);
197 198 199 200 201
}

void QConnectionAgent::serviceStateChanged(const QString &state)
{
    NetworkService *service = static_cast<NetworkService *>(sender());
202 203
    if (!service)
        return;
204 205 206
    qDebug() << state << service->name() << service->strength();
    qDebug() << "currentNetworkState" << currentNetworkState;

207 208 209 210 211 212
    if (state == "ready" && service->type() == "wifi"
            && !delayedTethering
            && netman->defaultRoute()->type() == "cellular") {
        netman->defaultRoute()->requestDisconnect();
    }

213 214
    if (!service->favorite() || !netman->getTechnology(service->type())
            || !netman->getTechnology(service->type())->powered()) {
215 216 217 218 219 220
        qDebug() << "not fav or not powered";
        return;
    }
    if (state == "disconnect") {
        ua->sendConnectReply("Clear");
    }
221 222 223 224 225
    if (state == "failure") {
        if (delayedTethering && service->type() == "cellular" && tetheringWifiTech->tethering()) {
            Q_EMIT tetheringFinished(false);
        }
    }
226

227 228 229
    if (delayedTethering && service->type() == "wifi" && state == "association") {
        service->requestDisconnect();
    }
230

231 232 233
    if (state == "online") {
        Q_EMIT connectionState(state, service->type());

234 235 236 237 238 239 240 241 242
        if (service->type() == "wifi" && delayedTethering) {
            netman->getTechnology(service->type())->setTethering(true);
        }
        if (service->type() == "cellular" && delayedTethering) {
            if (!tetheringWifiTech->tethering()) {
                tetheringWifiTech->setTethering(true);
            }
        }
    }
243 244
    //auto migrate
    if (state == "idle") {
245 246 247 248
        if (service->type() == "wifi" && delayedTethering) {
            netman->getTechnology(service->type())->setTethering(true);
        }
    } else {
249
        updateServices();
250 251 252 253 254 255 256 257 258 259
    }
    currentNetworkState = state;
    QSettings confFile;
    confFile.beginGroup("Connectionagent");
    confFile.setValue("connected",currentNetworkState);
}

// from plugin/qml
void QConnectionAgent::connectToType(const QString &type)
{
260 261
    if (!netman)
        return;
262

263
    if (netman->technologyPathForType(type).isEmpty()) {
264 265 266 267
        Q_EMIT errorReported("","Type not valid");
        return;
    }

268
    // Connman is using "cellular" and "wifi" as part of the service path
269 270 271 272 273 274 275 276 277
    QString convType;
    if (type.contains("mobile")) {
        convType="cellular";
    } else if (type.contains("wlan")) {
        convType="wifi";
    } else {
        convType=type;
    }

278
    bool found = false;
279
    Q_FOREACH (Service elem, orderedServicesList) {
280
        if (elem.path.contains(convType)) {
281 282
            if (!isStateOnline(elem.service->state())) {
                if (elem.service->autoConnect()) {
283
                    qDebug() << "<<<<<<<<<<< requestConnect() >>>>>>>>>>>>";
284
                    elem.service->requestConnect();
285
                    return;
286 287 288
                } else if (!elem.path.contains("cellular")) {
                    // ignore cellular that are not on autoconnect
                    found = true;
289
                }
290 291
            } else {
                return;
292 293 294
            }
        }
    }
295

296 297 298 299 300 301
    // Can't connect to the service of a type that doesn't exist
    if (!found)
        return;

    // Substitute "wifi" with "wlan" for lipstick
    if (type.contains("wifi"))
302 303 304
        convType="wlan";

    Q_EMIT configurationNeeded(convType);
305 306
}

307
void QConnectionAgent::updateServices()
308 309
{
    qDebug() << Q_FUNC_INFO;
310
    ServiceList oldServices = orderedServicesList;
311 312 313 314 315 316 317 318 319 320
    orderedServicesList.clear();

    Q_FOREACH (const QString &tech,techPreferenceList) {
        QVector<NetworkService*> services = netman->getServices(tech);

        Q_FOREACH (NetworkService *serv, services) {
            const QString servicePath = serv->path();

            qDebug() << "known service:" << serv->name() << serv->strength();

321 322 323 324
            Service elem;
            elem.path = servicePath;
            elem.service = serv;
            orderedServicesList << elem;
325 326 327

            if (!oldServices.contains(servicePath)) {
                //new!
328
                qDebug() <<"new service"<< servicePath;
329

330 331 332 333 334 335 336 337
                QObject::connect(serv, &NetworkService::stateChanged,
                                 this, &QConnectionAgent::serviceStateChanged, Qt::UniqueConnection);
                QObject::connect(serv, &NetworkService::connectRequestFailed,
                                 this, &QConnectionAgent::serviceErrorChanged, Qt::UniqueConnection);
                QObject::connect(serv, &NetworkService::errorChanged,
                                 this, &QConnectionAgent::servicesError, Qt::UniqueConnection);
                QObject::connect(serv, &NetworkService::autoConnectChanged,
                                 this, &QConnectionAgent::serviceAutoconnectChanged, Qt::UniqueConnection);
338 339 340 341 342 343 344 345 346 347 348
            }
        }
    }
}

void QConnectionAgent::servicesError(const QString &errorMessage)
{
    if (errorMessage.isEmpty())
        return;
    NetworkService *serv = static_cast<NetworkService *>(sender());
    qDebug() << serv->name() << errorMessage;
349
    onErrorReported(serv->path(), errorMessage);
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
}

void QConnectionAgent::networkStateChanged(const QString &state)
{
    qDebug() << state;

    QSettings confFile;
    confFile.beginGroup("Connectionagent");
    if (state != "online")
        confFile.setValue("connected","offline");
    else
        confFile.setValue("connected","online");

    if ((state == "online" && netman->defaultRoute()->type() == "cellular")
            || (state == "idle")) {
365 366 367 368

        if (tetheringWifiTech && tetheringWifiTech->powered()
                && !tetheringWifiTech->tethering())
                tetheringWifiTech->scan();
369 370 371 372
        // on gprs, scan wifi every scanTimeoutInterval minutes
        if (scanTimeoutInterval != 0)
            scanTimer->start(scanTimeoutInterval * 60 * 1000);
    }
373 374 375 376 377 378 379 380 381 382 383 384

    if (delayedTethering && state == "online") {

        if (tetheringWifiTech->tethering()) {
            if (netman->defaultRoute()->type() == "cellular") {
                delayedTethering = false;
                Q_EMIT tetheringFinished(true);
            }
        } else {
            tetheringWifiTech->setTethering(true);
        }
    }
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406
}

void QConnectionAgent::connmanAvailabilityChanged(bool b)
{
    qDebug() << Q_FUNC_INFO;
    connmanAvailable = b;
    if (b) {
        setup();
        currentNetworkState = netman->state();
    } else {
        currentNetworkState = "error";
    }
}

void QConnectionAgent::setup()
{
    qDebug() << Q_FUNC_INFO
             << connmanAvailable;

    if (connmanAvailable) {
        qDebug() << Q_FUNC_INFO
                 << netman->state();
407
        delete ua;
408 409
        ua = new UserAgent(this);

410 411
        connect(ua, &UserAgent::userInputRequested,
                this, &QConnectionAgent::onUserInputRequested);
412

413 414 415 416 417 418 419
        connect(ua, &UserAgent::connectionRequest, this, &QConnectionAgent::onConnectionRequest);
        connect(ua, &UserAgent::errorReported, this, &QConnectionAgent::onErrorReported);
        connect(ua, &UserAgent::userInputCanceled, this, &QConnectionAgent::onUserInputCanceled);
        connect(ua, &UserAgent::userInputRequested,
                this, &QConnectionAgent::onUserInputRequested, Qt::UniqueConnection);
        connect(ua, &UserAgent::browserRequested,
                this, &QConnectionAgent::browserRequest, Qt::UniqueConnection);
420

421
        updateServices();
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
        offlineModeChanged(netman->offlineMode());

        QSettings confFile;
        confFile.beginGroup("Connectionagent");
        scanTimeoutInterval = confFile.value("scanTimerInterval", "1").toUInt(); //in minutes

        if (isStateOnline(netman->state())) {
            qDebug() << "default route type:" << netman->defaultRoute()->type();
            if (netman->defaultRoute()->type() == "ethernet")
                isEthernet = true;
            if (netman->defaultRoute()->type() == "cellular" && scanTimeoutInterval != 0)
                scanTimer->start(scanTimeoutInterval * 60 * 1000);

        }
        qDebug() << "config file says" << confFile.value("connected", "online").toString();
    }
}

440
void QConnectionAgent::technologyPowerChanged(bool powered)
441 442
{
    NetworkTechnology *tech = static_cast<NetworkTechnology *>(sender());
443 444
    if (tech->type() != "wifi")
        return;
445 446 447 448
    if (tetheringWifiTech)
        qDebug() << tetheringWifiTech->name() << powered;
    else
        qDebug() << "tetheringWifiTech is null";
449

450 451
    if (netman && powered && delayedTethering) {
        // wifi tech might not be ready, so delay this
452
        QTimer::singleShot(1000, this, &QConnectionAgent::setWifiTetheringEnabled);
453
    }
454 455 456 457
}

void QConnectionAgent::techChanged()
{
458 459
    if (!netman)
        return;
460 461 462 463
    if (netman->getTechnologies().isEmpty()) {
        knownTechnologies.clear();
    }
    if (!netman->getTechnology("wifi")) {
464
        delayedTethering = false;
465 466 467 468 469 470 471 472 473 474 475 476
        tetheringWifiTech = 0;
        return;
    }
    if (tetheringWifiTech) {
        tetheringEnabled = tetheringWifiTech->tethering();
    }

    Q_FOREACH(NetworkTechnology *technology,netman->getTechnologies()) {
        if (!knownTechnologies.contains(technology->path())) {
            knownTechnologies << technology->path();
            if (technology->type() == "wifi") {
                tetheringWifiTech = technology;
477 478 479
                connect(tetheringWifiTech, &NetworkTechnology::poweredChanged, this, &QConnectionAgent::technologyPowerChanged);
                connect(tetheringWifiTech, &NetworkTechnology::tetheringChanged,
                        this, &QConnectionAgent::techTetheringChanged, Qt::UniqueConnection);
480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
            }
        } else {
            knownTechnologies.removeOne(technology->path());
        }
    }
}

void QConnectionAgent::browserRequest(const QString &servicePath, const QString &url)
{
    Q_UNUSED(servicePath)
    qDebug() << servicePath;
    qDebug() << url;

    Q_EMIT requestBrowser(url);
}

bool QConnectionAgent::isStateOnline(const QString &state)
{
    if (state == "online" || state == "ready")
        return true;
    return false;
}

503
void QConnectionAgent::techTetheringChanged(bool on)
504
{
505 506 507 508 509 510 511 512 513 514 515
    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") {
516
                qDebug() << "<<<<<<<<<<< requestConnect() >>>>>>>>>>>>";
517 518 519 520 521 522 523 524 525
                cellService->requestConnect();
            } else if (cellService->connected()) {
                delayedTethering = false;
                Q_EMIT tetheringFinished(true);
            }
        } else {
            stopTethering();
        }
    }
526 527
}

528 529 530 531
void QConnectionAgent::offlineModeChanged(bool b)
{
    flightModeSuppression = b;
    if (b) {
532
        QTimer::singleShot(5 * 1000 * 60, this, &QConnectionAgent::flightModeDialogSuppressionTimeout); //5 minutes
533 534 535 536 537
    }
}

void QConnectionAgent::flightModeDialogSuppressionTimeout()
{
Pekka Vuorela's avatar
Pekka Vuorela committed
538
    flightModeSuppression = false;
539 540 541 542 543
}

void QConnectionAgent::serviceAutoconnectChanged(bool on)
{
    NetworkService *service = qobject_cast<NetworkService *>(sender());
544 545
    if (!service)
        return;
546
    qDebug() << service->path() << "AutoConnect is" << on;
547

548
    if (!on) {
549 550
        if (service->state() != "idle")
            service->requestDisconnect();
551 552 553 554 555
    }
}

void QConnectionAgent::scanTimeout()
{
556
    if (!tetheringWifiTech || tetheringWifiTech->tethering())
Pekka Vuorela's avatar
Pekka Vuorela committed
557
        return;
558 559

    if (tetheringWifiTech->powered() && !tetheringWifiTech->connected() && netman->defaultRoute()->type() != "wifi" ) {
560 561 562 563 564 565 566
        tetheringWifiTech->scan();
        qDebug() << "start scanner" << scanTimeoutInterval;
        if (scanTimeoutInterval != 0) {
            scanTimer->start(scanTimeoutInterval * 60 * 1000);
        }
    }
}
567 568 569

void QConnectionAgent::removeAllTypes(const QString &type)
{
570 571
    Q_FOREACH (Service elem, orderedServicesList) {
        if (elem.path.contains(type))
572
            orderedServicesList.remove(elem.path);
573 574
    }
}
575

576 577 578 579 580 581
bool QConnectionAgent::shouldSuppressError(const QString &error, bool cellular) const
{
    if (error.isEmpty())
        return true;
    if (error == QLatin1String("Operation aborted"))
        return true;
582 583
    if (error == QLatin1String("No carrier") && cellular) // Don't report cellular carrier lost.
        return true;
584 585 586 587 588 589 590 591
    if (error == QLatin1String("connect-failed") && cellular && netman->offlineMode()) // Suppress errors when switching to offline mode
        return true;
    if (error == QLatin1String("In progress") || error.contains(QLatin1String("Method"))) // Catch dbus errors and discard
        return true;

    return false;
}

592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
void QConnectionAgent::openConnectionDialog(const QString &type)
{
    // open Connection Selector
    QDBusInterface *connSelectorInterface = new QDBusInterface(QStringLiteral("com.jolla.lipstick.ConnectionSelector"),
                                                               QStringLiteral("/"),
                                                               QStringLiteral("com.jolla.lipstick.ConnectionSelectorIf"),
                                                               QDBusConnection::sessionBus(),
                                                               this);

    connSelectorInterface->connection().connect(QStringLiteral("com.jolla.lipstick.ConnectionSelector"),
                                                QStringLiteral("/"),
                                                QStringLiteral("com.jolla.lipstick.ConnectionSelectorIf"),
                                                QStringLiteral("connectionSelectorClosed"),
                                                this,
                                                SLOT(connectionSelectorClosed(bool)));

    QList<QVariant> args;
    args.append(type);
    QDBusMessage reply = connSelectorInterface->callWithArgumentList(QDBus::NoBlock,
                                                                     QStringLiteral("openConnection"), args);
}
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654

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;
655 656
    tetheringWifiTech = tetherTech;

657 658 659 660 661 662 663
    if (!techPowered) {
        tetherTech->setPowered(true);
    } else {
        tetherTech->setTethering(true);
    }
}

664
void QConnectionAgent::stopTethering(bool keepPowered)
665 666 667 668 669 670 671 672 673 674 675 676
{
    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();

677 678 679
    Q_FOREACH (Service elem, orderedServicesList) {
        if (elem.path.contains("cellular")) {
            if (isStateOnline(elem.service->state())) {
680 681
                qDebug() << "disconnect mobile data";
                if (!b)
682
                    elem.service->requestDisconnect();
683
                if (!ab)
684
                    elem.service->setAutoConnect(false);
685 686 687 688 689
            }
        }
    }

    b = confFile.value("tetheringTechPowered").toBool();
690
    if (!b && tetherTech && !keepPowered) {
691 692 693 694
        tetherTech->setPowered(false);
    }
    Q_EMIT tetheringFinished(false);
}
695 696 697 698 699 700 701 702

void QConnectionAgent::setWifiTetheringEnabled()
{
    if (tetheringWifiTech) {
        qDebug() << "set tethering";
        tetheringWifiTech->setTethering(delayedTethering);
    }
}