1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the plugins of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include "qconnmanengine.h" |
41 | #include "qconnmanservice_linux_p.h" |
42 | #include "../qnetworksession_impl.h" |
43 | |
44 | #include <QtNetwork/private/qnetworkconfiguration_p.h> |
45 | |
46 | #include <QtNetwork/qnetworksession.h> |
47 | |
48 | #include <QtCore/qdebug.h> |
49 | #include <QtCore/private/qlocking_p.h> |
50 | |
51 | #include <QtDBus/QtDBus> |
52 | #include <QtDBus/QDBusConnection> |
53 | #include <QtDBus/QDBusInterface> |
54 | #include <QtDBus/QDBusMessage> |
55 | #include <QtDBus/QDBusReply> |
56 | #ifndef QT_NO_DBUS |
57 | |
58 | QT_BEGIN_NAMESPACE |
59 | |
60 | QConnmanEngine::QConnmanEngine(QObject *parent) |
61 | : QBearerEngineImpl(parent), |
62 | connmanManager(new QConnmanManagerInterface(this)), |
63 | ofonoManager(new QOfonoManagerInterface(this)), |
64 | ofonoNetwork(0), |
65 | ofonoContextManager(0) |
66 | { |
67 | qDBusRegisterMetaType<ConnmanMap>(); |
68 | qDBusRegisterMetaType<ConnmanMapList>(); |
69 | qRegisterMetaType<ConnmanMapList>(typeName: "ConnmanMapList" ); |
70 | } |
71 | |
72 | QConnmanEngine::~QConnmanEngine() |
73 | { |
74 | } |
75 | |
76 | bool QConnmanEngine::connmanAvailable() const |
77 | { |
78 | const auto locker = qt_scoped_lock(mutex); |
79 | return connmanManager->isValid(); |
80 | } |
81 | |
82 | void QConnmanEngine::initialize() |
83 | { |
84 | const auto locker = qt_scoped_lock(mutex); |
85 | connect(sender: ofonoManager,SIGNAL(modemChanged()),receiver: this,SLOT(changedModem())); |
86 | |
87 | ofonoNetwork = new QOfonoNetworkRegistrationInterface(ofonoManager->currentModem(),this); |
88 | ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this); |
89 | connect(sender: ofonoContextManager,SIGNAL(roamingAllowedChanged(bool)),receiver: this,SLOT(reEvaluateCellular())); |
90 | |
91 | connect(sender: connmanManager,SIGNAL(servicesChanged(ConnmanMapList,QList<QDBusObjectPath>)), |
92 | receiver: this, SLOT(updateServices(ConnmanMapList,QList<QDBusObjectPath>))); |
93 | |
94 | connect(sender: connmanManager,SIGNAL(servicesReady(QStringList)),receiver: this,SLOT(servicesReady(QStringList))); |
95 | connect(sender: connmanManager,SIGNAL(scanFinished(bool)),receiver: this,SLOT(finishedScan(bool))); |
96 | |
97 | const auto servPaths = connmanManager->getServices(); |
98 | for (const QString &servPath : servPaths) |
99 | addServiceConfiguration(servicePath: servPath); |
100 | Q_EMIT updateCompleted(); |
101 | } |
102 | |
103 | void QConnmanEngine::changedModem() |
104 | { |
105 | const auto locker = qt_scoped_lock(mutex); |
106 | if (ofonoNetwork) |
107 | delete ofonoNetwork; |
108 | |
109 | ofonoNetwork = new QOfonoNetworkRegistrationInterface(ofonoManager->currentModem(),this); |
110 | |
111 | if (ofonoContextManager) |
112 | delete ofonoContextManager; |
113 | ofonoContextManager = new QOfonoDataConnectionManagerInterface(ofonoManager->currentModem(),this); |
114 | } |
115 | |
116 | void QConnmanEngine::servicesReady(const QStringList &list) |
117 | { |
118 | const auto locker = qt_scoped_lock(mutex); |
119 | for (const QString &servPath : list) |
120 | addServiceConfiguration(servicePath: servPath); |
121 | |
122 | Q_EMIT updateCompleted(); |
123 | } |
124 | |
125 | QList<QNetworkConfigurationPrivate *> QConnmanEngine::getConfigurations() |
126 | { |
127 | const auto locker = qt_scoped_lock(mutex); |
128 | QList<QNetworkConfigurationPrivate *> fetchedConfigurations; |
129 | QNetworkConfigurationPrivate* cpPriv = 0; |
130 | const int numFoundConfigurations = foundConfigurations.count(); |
131 | fetchedConfigurations.reserve(alloc: numFoundConfigurations); |
132 | |
133 | for (int i = 0; i < numFoundConfigurations; ++i) { |
134 | QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate; |
135 | cpPriv = foundConfigurations.at(i); |
136 | |
137 | config->name = cpPriv->name; |
138 | config->isValid = cpPriv->isValid; |
139 | config->id = cpPriv->id; |
140 | config->state = cpPriv->state; |
141 | config->type = cpPriv->type; |
142 | config->roamingSupported = cpPriv->roamingSupported; |
143 | config->purpose = cpPriv->purpose; |
144 | config->bearerType = cpPriv->bearerType; |
145 | |
146 | fetchedConfigurations.append(t: config); |
147 | delete config; |
148 | } |
149 | return fetchedConfigurations; |
150 | } |
151 | |
152 | QString QConnmanEngine::getInterfaceFromId(const QString &id) |
153 | { |
154 | const auto locker = qt_scoped_lock(mutex); |
155 | return configInterfaces.value(akey: id); |
156 | } |
157 | |
158 | bool QConnmanEngine::hasIdentifier(const QString &id) |
159 | { |
160 | const auto locker = qt_scoped_lock(mutex); |
161 | return accessPointConfigurations.contains(akey: id); |
162 | } |
163 | |
164 | void QConnmanEngine::connectToId(const QString &id) |
165 | { |
166 | const auto locker = qt_scoped_lock(mutex); |
167 | |
168 | QConnmanServiceInterface *serv = connmanServiceInterfaces.value(akey: id); |
169 | |
170 | if (!serv || !serv->isValid()) { |
171 | emit connectionError(id, error: QBearerEngineImpl::InterfaceLookupError); |
172 | } else { |
173 | if (serv->type() == QLatin1String("cellular" )) { |
174 | if (serv->roaming()) { |
175 | if (!isRoamingAllowed(context: serv->path())) { |
176 | emit connectionError(id, error: QBearerEngineImpl::OperationNotSupported); |
177 | return; |
178 | } |
179 | } |
180 | } |
181 | if (serv->autoConnect()) |
182 | serv->connect(); |
183 | } |
184 | } |
185 | |
186 | void QConnmanEngine::disconnectFromId(const QString &id) |
187 | { |
188 | const auto locker = qt_scoped_lock(mutex); |
189 | QConnmanServiceInterface *serv = connmanServiceInterfaces.value(akey: id); |
190 | |
191 | if (!serv || !serv->isValid()) { |
192 | emit connectionError(id, error: DisconnectionError); |
193 | } else { |
194 | serv->disconnect(); |
195 | } |
196 | } |
197 | |
198 | void QConnmanEngine::requestUpdate() |
199 | { |
200 | const auto locker = qt_scoped_lock(mutex); |
201 | QTimer::singleShot(msec: 0, receiver: this, SLOT(doRequestUpdate())); |
202 | } |
203 | |
204 | void QConnmanEngine::doRequestUpdate() |
205 | { |
206 | bool scanned = connmanManager->requestScan(type: "wifi" ); |
207 | if (!scanned) |
208 | Q_EMIT updateCompleted(); |
209 | } |
210 | |
211 | void QConnmanEngine::finishedScan(bool error) |
212 | { |
213 | if (error) |
214 | Q_EMIT updateCompleted(); |
215 | } |
216 | |
217 | void QConnmanEngine::updateServices(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed) |
218 | { |
219 | const auto locker = qt_scoped_lock(mutex); |
220 | |
221 | foreach (const QDBusObjectPath &objectPath, removed) { |
222 | removeConfiguration(servicePath: objectPath.path()); |
223 | } |
224 | |
225 | foreach (const ConnmanMap &connmanMap, changed) { |
226 | const QString id = connmanMap.objectPath.path(); |
227 | if (accessPointConfigurations.contains(akey: id)) { |
228 | configurationChange(service: connmanServiceInterfaces.value(akey: id)); |
229 | } else { |
230 | addServiceConfiguration(servicePath: connmanMap.objectPath.path()); |
231 | } |
232 | } |
233 | Q_EMIT updateCompleted(); |
234 | } |
235 | |
236 | QNetworkSession::State QConnmanEngine::sessionStateForId(const QString &id) |
237 | { |
238 | const auto locker = qt_scoped_lock(mutex); |
239 | |
240 | QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(akey: id); |
241 | |
242 | if (!ptr || !ptr->isValid) |
243 | return QNetworkSession::Invalid; |
244 | |
245 | QString service = id; |
246 | QConnmanServiceInterface *serv = connmanServiceInterfaces.value(akey: service); |
247 | if (!serv) |
248 | return QNetworkSession::Invalid; |
249 | |
250 | QString servState = serv->state(); |
251 | |
252 | if (serv->favorite() && (servState == QLatin1String("idle" ) || servState == QLatin1String("failure" ))) { |
253 | return QNetworkSession::Disconnected; |
254 | } |
255 | |
256 | if (servState == QLatin1String("association" ) || servState == QLatin1String("configuration" )) { |
257 | return QNetworkSession::Connecting; |
258 | } |
259 | |
260 | if (servState == QLatin1String("online" ) || servState == QLatin1String("ready" )) { |
261 | return QNetworkSession::Connected; |
262 | } |
263 | |
264 | if ((ptr->state & QNetworkConfiguration::Discovered) == |
265 | QNetworkConfiguration::Discovered) { |
266 | return QNetworkSession::Disconnected; |
267 | } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { |
268 | return QNetworkSession::NotAvailable; |
269 | } else if ((ptr->state & QNetworkConfiguration::Undefined) == |
270 | QNetworkConfiguration::Undefined) { |
271 | return QNetworkSession::NotAvailable; |
272 | } |
273 | |
274 | return QNetworkSession::Invalid; |
275 | } |
276 | |
277 | quint64 QConnmanEngine::bytesWritten(const QString &id) |
278 | {//TODO use connman counter API |
279 | const auto locker = qt_scoped_lock(mutex); |
280 | quint64 result = 0; |
281 | QString devFile = getInterfaceFromId(id); |
282 | QFile tx("/sys/class/net/" +devFile+"/statistics/tx_bytes" ); |
283 | if (tx.open(flags: QIODevice::ReadOnly | QIODevice::Text)) { |
284 | QTextStream in(&tx); |
285 | in >> result; |
286 | tx.close(); |
287 | } |
288 | |
289 | return result; |
290 | } |
291 | |
292 | quint64 QConnmanEngine::bytesReceived(const QString &id) |
293 | {//TODO use connman counter API |
294 | const auto locker = qt_scoped_lock(mutex); |
295 | quint64 result = 0; |
296 | QString devFile = getInterfaceFromId(id); |
297 | QFile rx("/sys/class/net/" +devFile+"/statistics/rx_bytes" ); |
298 | if (rx.open(flags: QIODevice::ReadOnly | QIODevice::Text)) { |
299 | QTextStream in(&rx); |
300 | in >> result; |
301 | rx.close(); |
302 | } |
303 | return result; |
304 | } |
305 | |
306 | quint64 QConnmanEngine::startTime(const QString &/*id*/) |
307 | { |
308 | // TODO |
309 | const auto locker = qt_scoped_lock(mutex); |
310 | if (activeTime.isNull()) { |
311 | return 0; |
312 | } |
313 | return activeTime.secsTo(QDateTime::currentDateTime()); |
314 | } |
315 | |
316 | QNetworkConfigurationManager::Capabilities QConnmanEngine::capabilities() const |
317 | { |
318 | return QNetworkConfigurationManager::ForcedRoaming | |
319 | QNetworkConfigurationManager::DataStatistics | |
320 | QNetworkConfigurationManager::CanStartAndStopInterfaces | |
321 | QNetworkConfigurationManager::NetworkSessionRequired; |
322 | } |
323 | |
324 | QNetworkSessionPrivate *QConnmanEngine::createSessionBackend() |
325 | { |
326 | return new QNetworkSessionPrivateImpl; |
327 | } |
328 | |
329 | QNetworkConfigurationPrivatePointer QConnmanEngine::defaultConfiguration() |
330 | { |
331 | const auto locker = qt_scoped_lock(mutex); |
332 | const auto servPaths = connmanManager->getServices(); |
333 | for (const QString &servPath : servPaths) { |
334 | if (connmanServiceInterfaces.contains(akey: servPath)) { |
335 | if (accessPointConfigurations.contains(akey: servPath)) |
336 | return accessPointConfigurations.value(akey: servPath); |
337 | } |
338 | } |
339 | return QNetworkConfigurationPrivatePointer(); |
340 | } |
341 | |
342 | void QConnmanEngine::serviceStateChanged(const QString &state) |
343 | { |
344 | QConnmanServiceInterface *service = qobject_cast<QConnmanServiceInterface *>(object: sender()); |
345 | configurationChange(service); |
346 | |
347 | if (state == QLatin1String("failure" )) { |
348 | emit connectionError(id: service->path(), error: ConnectError); |
349 | } |
350 | } |
351 | |
352 | void QConnmanEngine::configurationChange(QConnmanServiceInterface *serv) |
353 | { |
354 | if (!serv) |
355 | return; |
356 | auto locker = qt_unique_lock(mutex); |
357 | QString id = serv->path(); |
358 | |
359 | if (accessPointConfigurations.contains(akey: id)) { |
360 | bool changed = false; |
361 | QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(akey: id); |
362 | QString networkName = serv->name(); |
363 | QNetworkConfiguration::StateFlags curState = getStateForService(service: serv->path()); |
364 | ptr->mutex.lock(); |
365 | |
366 | if (!ptr->isValid) { |
367 | ptr->isValid = true; |
368 | } |
369 | |
370 | if (ptr->name != networkName) { |
371 | ptr->name = networkName; |
372 | changed = true; |
373 | } |
374 | |
375 | if (ptr->state != curState) { |
376 | ptr->state = curState; |
377 | changed = true; |
378 | } |
379 | |
380 | ptr->mutex.unlock(); |
381 | |
382 | if (changed) { |
383 | locker.unlock(); |
384 | emit configurationChanged(config: ptr); |
385 | locker.lock(); |
386 | } |
387 | } |
388 | |
389 | locker.unlock(); |
390 | emit updateCompleted(); |
391 | } |
392 | |
393 | QNetworkConfiguration::StateFlags QConnmanEngine::getStateForService(const QString &service) |
394 | { |
395 | const auto locker = qt_scoped_lock(mutex); |
396 | QConnmanServiceInterface *serv = connmanServiceInterfaces.value(akey: service); |
397 | if (!serv) |
398 | return QNetworkConfiguration::Undefined; |
399 | |
400 | QString state = serv->state(); |
401 | QNetworkConfiguration::StateFlags flag = QNetworkConfiguration::Defined; |
402 | |
403 | if (serv->type() == QLatin1String("cellular" )) { |
404 | |
405 | if (!serv->autoConnect()|| (serv->roaming() |
406 | && !isRoamingAllowed(context: serv->path()))) { |
407 | flag = (flag | QNetworkConfiguration::Defined); |
408 | } else { |
409 | flag = (flag | QNetworkConfiguration::Discovered); |
410 | } |
411 | } else { |
412 | if (serv->favorite()) { |
413 | if (serv->autoConnect()) { |
414 | flag = (flag | QNetworkConfiguration::Discovered); |
415 | } |
416 | } else { |
417 | flag = QNetworkConfiguration::Undefined; |
418 | } |
419 | } |
420 | if (state == QLatin1String("online" ) || state == QLatin1String("ready" )) { |
421 | flag = (flag | QNetworkConfiguration::Active); |
422 | } |
423 | |
424 | return flag; |
425 | } |
426 | |
427 | QNetworkConfiguration::BearerType QConnmanEngine::typeToBearer(const QString &type) |
428 | { |
429 | if (type == QLatin1String("wifi" )) |
430 | return QNetworkConfiguration::BearerWLAN; |
431 | if (type == QLatin1String("ethernet" )) |
432 | return QNetworkConfiguration::BearerEthernet; |
433 | if (type == QLatin1String("bluetooth" )) |
434 | return QNetworkConfiguration::BearerBluetooth; |
435 | if (type == QLatin1String("cellular" )) { |
436 | return ofonoTechToBearerType(type); |
437 | } |
438 | if (type == QLatin1String("wimax" )) |
439 | return QNetworkConfiguration::BearerWiMAX; |
440 | |
441 | return QNetworkConfiguration::BearerUnknown; |
442 | } |
443 | |
444 | QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QString &/*type*/) |
445 | { |
446 | if (ofonoNetwork) { |
447 | QString currentTechnology = ofonoNetwork->getTechnology(); |
448 | if (currentTechnology == QLatin1String("gsm" )) { |
449 | return QNetworkConfiguration::Bearer2G; |
450 | } else if (currentTechnology == QLatin1String("edge" )) { |
451 | return QNetworkConfiguration::BearerCDMA2000; //wrong, I know |
452 | } else if (currentTechnology == QLatin1String("umts" )) { |
453 | return QNetworkConfiguration::BearerWCDMA; |
454 | } else if (currentTechnology == QLatin1String("hspa" )) { |
455 | return QNetworkConfiguration::BearerHSPA; |
456 | } else if (currentTechnology == QLatin1String("lte" )) { |
457 | return QNetworkConfiguration::BearerLTE; |
458 | } |
459 | } |
460 | return QNetworkConfiguration::BearerUnknown; |
461 | } |
462 | |
463 | bool QConnmanEngine::isRoamingAllowed(const QString &context) |
464 | { |
465 | const auto dcPaths = ofonoContextManager->contexts(); |
466 | for (const QString &dcPath : dcPaths) { |
467 | if (dcPath.contains(s: context.section(in_sep: "_" ,start: -1))) { |
468 | return ofonoContextManager->roamingAllowed(); |
469 | } |
470 | } |
471 | return false; |
472 | } |
473 | |
474 | void QConnmanEngine::removeConfiguration(const QString &id) |
475 | { |
476 | auto locker = qt_unique_lock(mutex); |
477 | |
478 | if (accessPointConfigurations.contains(akey: id)) { |
479 | |
480 | disconnect(sender: connmanServiceInterfaces.value(akey: id),SIGNAL(stateChanged(QString)), |
481 | receiver: this,SLOT(serviceStateChanged(QString))); |
482 | serviceNetworks.removeOne(t: id); |
483 | QConnmanServiceInterface *service = connmanServiceInterfaces.take(akey: id); |
484 | delete service; |
485 | QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(akey: id); |
486 | foundConfigurations.removeOne(t: ptr.data()); |
487 | locker.unlock(); |
488 | emit configurationRemoved(config: ptr); |
489 | } |
490 | } |
491 | |
492 | void QConnmanEngine::addServiceConfiguration(const QString &servicePath) |
493 | { |
494 | auto locker = qt_unique_lock(mutex); |
495 | if (!connmanServiceInterfaces.contains(akey: servicePath)) { |
496 | QConnmanServiceInterface *serv = new QConnmanServiceInterface(servicePath, this); |
497 | connmanServiceInterfaces.insert(akey: serv->path(),avalue: serv); |
498 | } |
499 | |
500 | if (!accessPointConfigurations.contains(akey: servicePath)) { |
501 | |
502 | serviceNetworks.append(t: servicePath); |
503 | |
504 | connect(sender: connmanServiceInterfaces.value(akey: servicePath),SIGNAL(stateChanged(QString)), |
505 | receiver: this,SLOT(serviceStateChanged(QString))); |
506 | |
507 | QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); |
508 | QConnmanServiceInterface *service = connmanServiceInterfaces.value(akey: servicePath); |
509 | |
510 | QString networkName = service->name(); |
511 | |
512 | const QString connectionType = service->type(); |
513 | if (connectionType == QLatin1String("ethernet" )) { |
514 | cpPriv->bearerType = QNetworkConfiguration::BearerEthernet; |
515 | } else if (connectionType == QLatin1String("wifi" )) { |
516 | cpPriv->bearerType = QNetworkConfiguration::BearerWLAN; |
517 | } else if (connectionType == QLatin1String("cellular" )) { |
518 | cpPriv->bearerType = ofonoTechToBearerType(QLatin1String("cellular" )); |
519 | cpPriv->roamingSupported = service->roaming() && isRoamingAllowed(context: servicePath); |
520 | } else if (connectionType == QLatin1String("wimax" )) { |
521 | cpPriv->bearerType = QNetworkConfiguration::BearerWiMAX; |
522 | } else { |
523 | cpPriv->bearerType = QNetworkConfiguration::BearerUnknown; |
524 | } |
525 | |
526 | cpPriv->name = networkName; |
527 | cpPriv->isValid = true; |
528 | cpPriv->id = servicePath; |
529 | cpPriv->type = QNetworkConfiguration::InternetAccessPoint; |
530 | |
531 | if (service->security() == QLatin1String("none" )) { |
532 | cpPriv->purpose = QNetworkConfiguration::PublicPurpose; |
533 | } else { |
534 | cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; |
535 | } |
536 | |
537 | cpPriv->state = getStateForService(service: servicePath); |
538 | |
539 | QNetworkConfigurationPrivatePointer ptr(cpPriv); |
540 | accessPointConfigurations.insert(akey: ptr->id, avalue: ptr); |
541 | if (connectionType == QLatin1String("cellular" )) { |
542 | foundConfigurations.append(t: cpPriv); |
543 | } else { |
544 | foundConfigurations.prepend(t: cpPriv); |
545 | } |
546 | configInterfaces[cpPriv->id] = service->serviceInterface(); |
547 | |
548 | locker.unlock(); |
549 | Q_EMIT configurationAdded(config: ptr); |
550 | } |
551 | } |
552 | |
553 | bool QConnmanEngine::requiresPolling() const |
554 | { |
555 | return false; |
556 | } |
557 | |
558 | void QConnmanEngine::reEvaluateCellular() |
559 | { |
560 | const auto servicePaths = connmanManager->getServices(); |
561 | for (const QString &servicePath : servicePaths) { |
562 | if (servicePath.contains(s: "cellular" ) && accessPointConfigurations.contains(akey: servicePath)) { |
563 | configurationChange(serv: connmanServiceInterfaces.value(akey: servicePath)); |
564 | } |
565 | } |
566 | } |
567 | |
568 | QT_END_NAMESPACE |
569 | |
570 | #endif // QT_NO_DBUS |
571 | |