summaryrefslogtreecommitdiffstats
path: root/src/plugins/bearer/symbian
diff options
context:
space:
mode:
authorAaron McCarthy <aaron.mccarthy@nokia.com>2010-03-24 03:45:52 (GMT)
committerAaron McCarthy <aaron.mccarthy@nokia.com>2010-03-24 03:45:52 (GMT)
commit06188c60bfd530a5f1d6ef954a45d31bccb2e987 (patch)
treeb4b4ee53d52ab0d82dfebc759801384f22863832 /src/plugins/bearer/symbian
parent63d9c7d545489ba34c8c34d91ff06a682127acb2 (diff)
downloadQt-06188c60bfd530a5f1d6ef954a45d31bccb2e987.zip
Qt-06188c60bfd530a5f1d6ef954a45d31bccb2e987.tar.gz
Qt-06188c60bfd530a5f1d6ef954a45d31bccb2e987.tar.bz2
Bearer management changes from Qt Mobility (6fb31d1e).
6fb31d1e287d7def45c115eb56bcb9b0c5cb3c40.
Diffstat (limited to 'src/plugins/bearer/symbian')
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp67
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.h7
-rw-r--r--src/plugins/bearer/symbian/symbianengine.cpp79
-rw-r--r--src/plugins/bearer/symbian/symbianengine.h6
4 files changed, 127 insertions, 32 deletions
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
index 0737942..8910efe 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -241,15 +241,24 @@ void QNetworkSessionPrivateImpl::open()
// => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
iConnectionMonitor.CancelNotifications();
- // Configuration must be at least in Discovered - state for connecting purposes.
- if ((publicConfig.state() & QNetworkConfiguration::Discovered) !=
- QNetworkConfiguration::Discovered) {
+ // Configuration may have been invalidated after session creation by platform
+ // (e.g. configuration has been deleted).
+ if (!publicConfig.isValid()) {
newState(QNetworkSession::Invalid);
iError = QNetworkSession::InvalidConfigurationError;
emit QNetworkSessionPrivate::error(iError);
syncStateWithInterface();
return;
}
+ // If opening a (un)defined configuration, session emits error and enters
+ // NotAvailable -state.
+ if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+ publicConfig.state() == QNetworkConfiguration::Defined) {
+ newState(QNetworkSession::NotAvailable);
+ iError = QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(iError);
+ return;
+ }
TInt error = iSocketServ.Connect();
if (error != KErrNone) {
@@ -450,15 +459,49 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
void QNetworkSessionPrivateImpl::stop()
{
- if (!isOpen) {
- return;
+ if (!isOpen &&
+ publicConfig.isValid() &&
+ publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ // If the publicConfig is type of IAP, enumerate through connections at
+ // connection monitor. If publicConfig is active in that list, stop it.
+ // Otherwise there is nothing to stop. Note: because this QNetworkSession is not open,
+ // activeConfig is not usable.
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return;
+ }
+ TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f
+ TUint connectionId;
+ for (TInt i = 1; i <= count; ++i) {
+ // Get (connection monitor's assigned) connection ID
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+ QMutexLocker configLocker(&symbianConfig->mutex);
+
+ // See if connection Id matches with our Id. If so, stop() it.
+ if (symbianConfig->connectionId == connectionId) {
+ ret = iConnectionMonitor.SetBoolAttribute(connectionId,
+ 0, // subConnectionId don't care
+ KConnectionStop,
+ ETrue);
+ }
+ }
+ }
+ } else if (isOpen) {
+ // Since we are open, use RConnection to stop the interface
+ isOpen = false;
+ newState(QNetworkSession::Closing);
+ iConnection.Stop(RConnection::EStopAuthoritative);
+ isOpen = true;
+ close(false);
+ emit closed();
}
- isOpen = false;
- newState(QNetworkSession::Closing);
- iConnection.Stop(RConnection::EStopAuthoritative);
- isOpen = true;
- close(false);
- emit closed();
}
void QNetworkSessionPrivateImpl::migrate()
@@ -794,7 +837,7 @@ void QNetworkSessionPrivateImpl::RunL()
TInt statusCode = iStatus.Int();
switch (statusCode) {
- case KErrNone: // Connection created succesfully
+ case KErrNone: // Connection created successfully
{
TInt error = KErrNone;
QNetworkConfiguration newActiveConfig = activeConfiguration();
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
index 98d4222..35e2c58 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.h
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -72,12 +72,11 @@ QT_BEGIN_NAMESPACE
class ConnectionProgressNotifier;
class SymbianEngine;
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive,
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
-class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MMobilityProtocolResp,
- public MConnectionMonitorObserver
-#else
-class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MConnectionMonitorObserver
+ public MMobilityProtocolResp,
#endif
+ public MConnectionMonitorObserver
{
Q_OBJECT
public:
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
index 4d65b80..440f463 100644
--- a/src/plugins/bearer/symbian/symbianengine.cpp
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -45,6 +45,16 @@
#include <commdb.h>
#include <cdbcols.h>
#include <d32dbms.h>
+#include <QEventLoop>
+#include <QTimer>
+#include <QTime> // For randgen seeding
+#include <QtCore> // For randgen seeding
+
+// #define QT_BEARERMGMT_CONFIGMGR_DEBUG
+
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+#include <QDebug>
+#endif
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
#include <cmdestination.h>
@@ -100,10 +110,15 @@ QString SymbianNetworkConfigurationPrivate::bearerName() const
}
SymbianEngine::SymbianEngine(QObject *parent)
-: QBearerEngine(parent), CActive(CActive::EPriorityIdle), iFirstUpdate(true), iInitOk(true)
+: QBearerEngine(parent), CActive(CActive::EPriorityIdle), iFirstUpdate(true), iInitOk(true),
+ iIgnoringUpdates(false), iTimeToWait(0), iIgnoreEventLoop(0)
{
CActiveScheduler::Add(this);
+ // Seed the randomgenerator
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
+ iIgnoreEventLoop = new QEventLoop(this);
+
TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
if (error != KErrNone) {
iInitOk = false;
@@ -138,9 +153,7 @@ SymbianEngine::SymbianEngine(QObject *parent)
updateConfigurations();
updateStatesToSnaps();
-
updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans)
-
// Start monitoring IAP and/or SNAP changes in Symbian CommsDB
startCommsDatabaseNotifications();
iFirstUpdate = false;
@@ -231,7 +244,7 @@ void SymbianEngine::updateConfigurationsL()
QList<QString> knownConfigs = accessPointConfigurations.keys();
QList<QString> knownSnapConfigs = snapConfigurations.keys();
-
+
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
// S60 version is >= Series60 3rd Edition Feature Pack 2
TInt error = KErrNone;
@@ -738,8 +751,7 @@ void SymbianEngine::updateStatesToSnaps()
QMutexLocker locker(&mutex);
// Go through SNAPs and set correct state to SNAPs
- QList<QString> snapConfigIdents = snapConfigurations.keys();
- foreach (QString iface, snapConfigIdents) {
+ foreach (const QString &iface, snapConfigurations.keys()) {
bool discovered = false;
bool active = false;
QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
@@ -874,6 +886,13 @@ void SymbianEngine::RunL()
{
QMutexLocker locker(&mutex);
+ if (iIgnoringUpdates) {
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
+#endif
+ return;
+ }
+
if (iStatus != KErrCancel) {
RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
switch (event) {
@@ -881,16 +900,32 @@ void SymbianEngine::RunL()
case RDbNotifier::ECommit: /** A transaction has been committed. */
case RDbNotifier::ERollback: /** A transaction has been rolled back */
case RDbNotifier::ERecover: /** The database has been recovered */
- // Note that if further database events occur while a client is handling
- // a request completion, the notifier records the most significant database
- // event and this is signalled as soon as the client issues the next
- // RequestNotification() request.
- // => Stop recording notifications
- stopCommsDatabaseNotifications();
- TRAPD(error, updateConfigurationsL());
- if (error == KErrNone) {
- updateStatesToSnaps();
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#endif
+ iIgnoringUpdates = true;
+ // Other events than ECommit get lower priority. In practice with those events,
+ // we delay_before_updating methods, whereas
+ // with ECommit we _update_before_delaying the reaction to next event.
+ // Few important notes: 1) listening to only ECommit does not seem to be adequate,
+ // but updates will be missed. Hence other events are reacted upon too.
+ // 2) RDbNotifier records the most significant event, and that will be returned once
+ // we issue new RequestNotification, and hence updates will not be missed even
+ // when we are 'not reacting to them' for few seconds.
+ if (event == RDbNotifier::ECommit) {
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
+ waitRandomTime();
+ } else {
+ waitRandomTime();
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
}
+ iIgnoringUpdates = false; // Wait time done, allow updating again
iWaitingCommsDatabaseNotifications = true;
break;
default:
@@ -1015,6 +1050,20 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
}
}
+// Waits for 1..4 seconds.
+void SymbianEngine::waitRandomTime()
+{
+ iTimeToWait = (qAbs(qrand()) % 5) * 1000;
+ if (iTimeToWait < 1000) {
+ iTimeToWait = 1000;
+ }
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
+#endif
+ QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
+ iIgnoreEventLoop->exec();
+}
+
QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
{
QMutexLocker locker(&mutex);
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
index e6af908..2e7ae60 100644
--- a/src/plugins/bearer/symbian/symbianengine.h
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -53,6 +53,7 @@
#endif
class CCommsDatabase;
+class QEventLoop;
QT_BEGIN_NAMESPACE
class QTimer;
@@ -148,6 +149,7 @@ private:
void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo);
void startCommsDatabaseNotifications();
void stopCommsDatabaseNotifications();
+ void waitRandomTime();
QNetworkConfigurationPrivatePointer defaultConfigurationL();
TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const;
@@ -170,8 +172,10 @@ private: // Data
TBool iOnline;
TBool iInitOk;
TBool iUpdateGoingOn;
+ TBool iIgnoringUpdates;
+ TUint iTimeToWait;
+ QEventLoop* iIgnoreEventLoop;
-
AccessPointsAvailabilityScanner* ipAccessPointsAvailabilityScanner;
friend class QNetworkSessionPrivate;