BlackBerry QNetworkConfiguration: Keep track of bearer type

I.e. let the user know whether he is on 2G / 3G / 4G.

Since usually apps are rather interested whether they are on Wifi or
cellular, change of cellular type (i.e. transition from 3G to 4G etc.)
will not trigger emission of the
"QNetworkConfigurationManager::configurationChanged" signal. The
cellular type check will only be performed if the user queries it by
calling the respective member methods (bearerType() and
bearerTypeName()).

Reading the cellular type takes around 1-2 milliseconds.

In addition, add new fields "BearerEVDO" and "BearerLTE" to the public
API for QNetworkConfiguration.

Change-Id: I4c4ec52926f862b84487c91a88b1e20e590dd793
Reviewed-by: Kevin Krammer <kevin.krammer@kdab.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Reviewed-by: Thomas McGuire <thomas.mcguire@kdab.com>
This commit is contained in:
Peter Hartmann 2013-06-07 14:59:39 +02:00 committed by The Qt Project
parent 5defb3a36a
commit 687f002352
6 changed files with 245 additions and 5 deletions

View File

@ -42,6 +42,12 @@
#include "qnetworkconfiguration.h"
#include "qnetworkconfiguration_p.h"
#ifdef Q_OS_BLACKBERRY
#include "private/qcore_unix_p.h" // qt_safe_open
#include <QDebug>
#include <sys/pps.h>
#endif // Q_OS_BLACKBERRY
QT_BEGIN_NAMESPACE
/*!
@ -198,8 +204,81 @@ QT_BEGIN_NAMESPACE
\value BearerHSPA The configuration is for High Speed Packet Access (HSPA) interface.
\value BearerBluetooth The configuration is for a Bluetooth interface.
\value BearerWiMAX The configuration is for a WiMAX interface.
\value BearerEVDO The configuration is for an EVDO (3G) interface.
\value BearerLTE The configuration is for a LTE (4G) interface.
*/
#ifdef Q_OS_BLACKBERRY
static const char cellularStatusFile[] = "/pps/services/radioctrl/modem0/status_public";
static QNetworkConfiguration::BearerType cellularStatus()
{
QNetworkConfiguration::BearerType ret = QNetworkConfiguration::BearerUnknown;
int cellularStatusFD;
if ((cellularStatusFD = qt_safe_open(cellularStatusFile, O_RDONLY)) == -1) {
qWarning() << Q_FUNC_INFO << "failed to open" << cellularStatusFile;
return ret;
}
char buf[2048];
if (qt_safe_read(cellularStatusFD, &buf, sizeof(buf)) == -1) {
qWarning() << Q_FUNC_INFO << "read from PPS file failed:" << strerror(errno);
qt_safe_close(cellularStatusFD);
return ret;
}
pps_decoder_t ppsDecoder;
if (pps_decoder_initialize(&ppsDecoder, buf) != PPS_DECODER_OK) {
qWarning() << Q_FUNC_INFO << "failed to initialize PPS decoder";
qt_safe_close(cellularStatusFD);
return ret;
}
pps_decoder_error_t err;
if ((err = pps_decoder_push(&ppsDecoder, 0)) != PPS_DECODER_OK) {
qWarning() << Q_FUNC_INFO << "pps_decoder_push failed" << err;
pps_decoder_cleanup(&ppsDecoder);
qt_safe_close(cellularStatusFD);
return ret;
}
if (!pps_decoder_is_integer(&ppsDecoder, "network_technology")) {
qWarning() << Q_FUNC_INFO << "field has not the expected data type";
pps_decoder_cleanup(&ppsDecoder);
qt_safe_close(cellularStatusFD);
return ret;
}
int type;
if (!pps_decoder_get_int(&ppsDecoder, "network_technology", &type)
== PPS_DECODER_OK) {
qWarning() << Q_FUNC_INFO << "could not read bearer type from PPS";
pps_decoder_cleanup(&ppsDecoder);
qt_safe_close(cellularStatusFD);
return ret;
}
switch (type) {
case 0: // 0 == NONE
break; // unhandled
case 1: // fallthrough, 1 == GSM
case 4: // 4 == CDMA_1X
ret = QNetworkConfiguration::Bearer2G;
break;
case 2: // 2 == UMTS
ret = QNetworkConfiguration::BearerWCDMA;
break;
case 8: // 8 == EVDO
ret = QNetworkConfiguration::BearerEVDO;
break;
case 16: // 16 == LTE
ret = QNetworkConfiguration::BearerLTE;
break;
default:
qWarning() << Q_FUNC_INFO << "unhandled bearer type" << type;
break;
}
pps_decoder_cleanup(&ppsDecoder);
qt_safe_close(cellularStatusFD);
return ret;
}
#endif // Q_OS_BLACKBERRY
/*!
Constructs an invalid configuration object.
@ -420,6 +499,18 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const
QMutexLocker locker(&d->mutex);
#ifdef Q_OS_BLACKBERRY
// for cellular configurations, we need to determine the exact
// type right now, because it might have changed after the last scan
if (d->bearerType == QNetworkConfiguration::Bearer2G) {
QNetworkConfiguration::BearerType type = cellularStatus();
// if reading the status failed for some reason, just
// fall back to 2G
return (type == QNetworkConfiguration::BearerUnknown)
? QNetworkConfiguration::Bearer2G : type;
}
#endif // Q_OS_BLACKBERRY
return d->bearerType;
}
@ -464,6 +555,12 @@ QNetworkConfiguration::BearerType QNetworkConfiguration::bearerType() const
\row
\li BearerWiMAX
\li WiMAX
\row
\li BearerEVDO
\li EVDO
\row
\li BearerLTE
\li LTE
\endtable
This function returns an empty string if this is an invalid configuration, a network
@ -489,6 +586,20 @@ QString QNetworkConfiguration::bearerTypeName() const
case BearerWLAN:
return QStringLiteral("WLAN");
case Bearer2G:
#ifdef Q_OS_BLACKBERRY
{
// for cellular configurations, we need to determine the exact
// type right now, because it might have changed after the last scan
QNetworkConfiguration::BearerType type = cellularStatus();
if (type == QNetworkConfiguration::BearerWCDMA) {
return QStringLiteral("WCDMA");
} else if (type == QNetworkConfiguration::BearerEVDO) {
return QStringLiteral("EVDO");
}else if (type == QNetworkConfiguration::BearerLTE) {
return QStringLiteral("LTE");
}
}
#endif // Q_OS_BLACKBERRY
return QStringLiteral("2G");
case BearerCDMA2000:
return QStringLiteral("CDMA2000");
@ -500,6 +611,10 @@ QString QNetworkConfiguration::bearerTypeName() const
return QStringLiteral("Bluetooth");
case BearerWiMAX:
return QStringLiteral("WiMAX");
case BearerEVDO:
return QStringLiteral("EVDO");
case BearerLTE:
return QStringLiteral("LTE");
case BearerUnknown:
break;
}

View File

@ -97,7 +97,9 @@ public:
BearerWCDMA,
BearerHSPA,
BearerBluetooth,
BearerWiMAX
BearerWiMAX,
BearerEVDO,
BearerLTE
};
StateFlags state() const;

View File

@ -98,10 +98,9 @@ interfaceType(netstatus_interface_type_t type)
return QNetworkConfiguration::BearerBluetooth;
case NETSTATUS_INTERFACE_TYPE_CELLULAR:
//### TODO not sure which BearerType would be the best
//to return here. We need to be able to get more
//information on the bearer type in order to return
//the exact match.
// The exact bearer type is determined in QNetworkConfiguration
// at the time this info is queried, because opposed to the
// information here the type might change quickly.
return QNetworkConfiguration::Bearer2G;
case NETSTATUS_INTERFACE_TYPE_VPN:

View File

@ -19,6 +19,7 @@ qlayout \
qlocale \
qnetworkaccessmanager/qget \
qnetworkconfigurationmanager \
qnetworkconfiguration \
qnetworkreply \
qpainfo \
qscreen \

View File

@ -0,0 +1,116 @@
/****************************************************************************
**
** Copyright (C) 2013 Research in Motion.
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights. These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QDebug>
#include <qtest.h>
#include <QtTest/QtTest>
#include <QtNetwork/qnetworkconfiguration.h>
#include <QtNetwork/qnetworkconfigmanager.h>
class tst_qnetworkconfiguration : public QObject
{
Q_OBJECT
private slots:
void bearerType();
};
void tst_qnetworkconfiguration::bearerType()
{
QNetworkConfigurationManager m;
QList<QNetworkConfiguration> allConfs = m.allConfigurations();
QElapsedTimer timer;
for (int a = 0; a < allConfs.count(); a++) {
timer.start();
QNetworkConfiguration::BearerType type = allConfs.at(a).bearerType();
qint64 elapsed = timer.elapsed();
QString typeString;
switch (type) {
case QNetworkConfiguration::BearerUnknown:
typeString = QLatin1String("Unknown");
break;
case QNetworkConfiguration::BearerEthernet:
typeString = QLatin1String("Ethernet");
break;
case QNetworkConfiguration::BearerWLAN:
typeString = QLatin1String("WLAN");
break;
case QNetworkConfiguration::Bearer2G:
typeString = QLatin1String("2G");
break;
case QNetworkConfiguration::BearerCDMA2000:
typeString = QLatin1String("CDMA2000");
break;
case QNetworkConfiguration::BearerWCDMA:
typeString = QLatin1String("WCDMA");
break;
case QNetworkConfiguration::BearerHSPA:
typeString = QLatin1String("HSPA");
break;
case QNetworkConfiguration::BearerBluetooth:
typeString = QLatin1String("Bluetooth");
break;
case QNetworkConfiguration::BearerWiMAX:
typeString = QLatin1String("WiMAX");
break;
case QNetworkConfiguration::BearerEVDO:
typeString = QLatin1String("EVDO");
break;
case QNetworkConfiguration::BearerLTE:
typeString = QLatin1String("LTE");
break;
default:
typeString = "unknown bearer (?)";
}
const char *isDefault = (allConfs.at(a) == m.defaultConfiguration())
? "*DEFAULT*" : "";
qDebug() << isDefault << "identifier:" << allConfs.at(a).identifier()
<< "bearer type name:" << allConfs.at(a).bearerTypeName()
<< "bearer type:" << type << "(" << typeString << ")"
<< "elapsed:" << elapsed;
QCOMPARE(allConfs.at(a).bearerTypeName(), typeString);
}
}
QTEST_MAIN(tst_qnetworkconfiguration)
#include "main.moc"

View File

@ -0,0 +1,7 @@
TEMPLATE = app
TARGET = tst_qnetworkconfiguration
QT -= gui
QT += network testlib
SOURCES += main.cpp