From 08b6114240a6c02dbeb0297d0deeb538ebc3fde9 Mon Sep 17 00:00:00 2001
From: Aaron McCarthy <aaron.mccarthy@nokia.com>
Date: Thu, 13 May 2010 10:16:48 +1000
Subject: Cherry pick fix for MOBILITY-828 from Qt Mobility.

Change e5f8e3069d0de428a751e8a1dd88f3585f2d3f5f from Qt Mobility.
---
 .../bearer/symbian/qnetworksession_impl.cpp        | 369 ++++++++++++---------
 src/plugins/bearer/symbian/qnetworksession_impl.h  |  15 +-
 src/plugins/bearer/symbian/symbianengine.cpp       | 248 +++++++++-----
 src/plugins/bearer/symbian/symbianengine.h         |  27 +-
 tests/auto/qnetworksession/lackey/main.cpp         |  24 +-
 .../qnetworksession/test/tst_qnetworksession.cpp   | 361 ++++++++++++--------
 6 files changed, 658 insertions(+), 386 deletions(-)

diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
index 1b9c8cc..04853c4 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -53,15 +53,17 @@
 QT_BEGIN_NAMESPACE
 
 QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine)
-    : CActive(CActive::EPriorityStandard), engine(engine), ipConnectionNotifier(0),
-      iError(QNetworkSession::UnknownSessionError),
-      iALREnabled(0), iConnectInBackground(false)
+    : CActive(CActive::EPriorityStandard), engine(engine),
+      ipConnectionNotifier(0), iHandleStateNotificationsFromManager(false),
+      iFirstSync(true), iStoppedByUser(false), iClosedByUser(false), iDeprecatedConnectionId(0),
+      iError(QNetworkSession::UnknownSessionError), iALREnabled(0), iConnectInBackground(false)
 {
     CActiveScheduler::Add(this);
 
 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
     iMobility = NULL;
 #endif
+
     TRAP_IGNORE(iConnectionMonitor.ConnectL());
 }
 
@@ -90,18 +92,72 @@ QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl()
     
     // Close global 'Open C' RConnection
     setdefaultif(0);
-
-    iConnectionMonitor.CancelNotifications();
+    
     iConnectionMonitor.Close();
 }
 
+void QNetworkSessionPrivateImpl::configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState)
+{
+    if (iHandleStateNotificationsFromManager) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+                << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId)
+                << "configurationStateChanged connMon ID : " << QString::number(connMonId)
+                << " : to a state: " << newState
+                << " whereas my current state is: " << state;
+#endif
+        if (connMonId == iDeprecatedConnectionId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+            qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+                    << "however status update from manager ignored because it related to already closed connection.";
+#endif
+            return;
+        }
+        this->newState(newState, accessPointId);
+    }
+}
+
+void QNetworkSessionPrivateImpl::configurationRemoved(QNetworkConfigurationPrivatePointer config)
+{
+    if (!publicConfig.isValid())
+        return;
+
+    SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(config);
+    
+    symbianConfig->mutex.lock();
+    TUint32 configNumericId = symbianConfig->numericId;
+    symbianConfig->mutex.unlock();
+
+    symbianConfig = toSymbianConfig(privateConfiguration(publicConfig));
+
+    symbianConfig->mutex.lock();
+    TUint32 publicNumericId = symbianConfig->numericId;
+    symbianConfig->mutex.unlock();
+
+    if (configNumericId == publicNumericId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+                 << "configurationRemoved IAP: " << QString::number(publicNumericId) << " : going to State: Invalid";
+#endif
+        this->newState(QNetworkSession::Invalid, publicNumericId);
+    }
+}
+
 void QNetworkSessionPrivateImpl::syncStateWithInterface()
 {
     if (!publicConfig.isValid())
         return;
 
-    // Start monitoring changes in IAP states
-    TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+    if (iFirstSync && publicConfig.isValid()) {
+        QObject::connect(engine, SIGNAL(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)),
+                         this, SLOT(configurationStateChanged(TUint32, TUint32, QNetworkSession::State)));
+        // Listen to configuration removals, so that in case the configuration
+        // this session is based on is removed, session knows to enter Invalid -state.
+        QObject::connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)),
+                         this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
+    }
+    // Start listening IAP state changes from QNetworkConfigurationManagerPrivate
+    iHandleStateNotificationsFromManager = true;    
 
     // Check open connections to see if there is already
     // an open connection to selected IAP or SNAP
@@ -137,11 +193,8 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface()
     }
 
     if (state != QNetworkSession::Connected) {
-        // There were no open connections to used IAP or SNAP
-        if (iError == QNetworkSession::InvalidConfigurationError) {
-            newState(QNetworkSession::Invalid);
-        } else if ((publicConfig.state() & QNetworkConfiguration::Discovered) ==
-                   QNetworkConfiguration::Discovered) {
+        if ((publicConfig.state() & QNetworkConfiguration::Discovered) ==
+            QNetworkConfiguration::Discovered) {
             newState(QNetworkSession::Disconnected);
         } else {
             newState(QNetworkSession::NotAvailable);
@@ -245,13 +298,18 @@ QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
 
 void QNetworkSessionPrivateImpl::open()
 {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+                << "open() called, session state is: " << state << " and isOpen is: "
+                << isOpen;
+#endif
     if (isOpen || (state == QNetworkSession::Connecting)) {
         return;
     }
-
-    // Cancel notifications from RConnectionMonitor
+    
+    // Stop handling IAP state change signals from QNetworkConfigurationManagerPrivate
     // => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
-    iConnectionMonitor.CancelNotifications();
+    iHandleStateNotificationsFromManager = false;
 
     // Configuration may have been invalidated after session creation by platform
     // (e.g. configuration has been deleted).
@@ -259,19 +317,25 @@ void QNetworkSessionPrivateImpl::open()
         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) {
+    // If opening a undefined configuration, session emits error and enters
+    // NotAvailable -state. Note that we will try ones in 'defined' state to avoid excessive
+    // need for WLAN scans (via updateConfigurations()), because user may have walked
+    // into a WLAN range, but periodic background scan has not occurred yet -->
+    // we don't want to force application to make frequent updateConfigurations() calls
+    // to be able to try if e.g. home WLAN is available.
+    if (publicConfig.state() == QNetworkConfiguration::Undefined) {
         newState(QNetworkSession::NotAvailable);
         iError = QNetworkSession::InvalidConfigurationError;
         emit QNetworkSessionPrivate::error(iError);
         return;
     }
-    
+    // Clear possible previous states
+    iStoppedByUser = false;
+    iClosedByUser = false;
+    iDeprecatedConnectionId = 0;
+
     TInt error = iSocketServ.Connect();
     if (error != KErrNone) {
         // Could not open RSocketServ
@@ -446,9 +510,18 @@ TUint QNetworkSessionPrivateImpl::iapClientCount(TUint aIAPId) const
 
 void QNetworkSessionPrivateImpl::close(bool allowSignals)
 {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+            << "close() called, session state is: " << state << " and isOpen is : "
+            << isOpen;
+#endif
     if (!isOpen) {
         return;
     }
+    // Mark this session as closed-by-user so that we are able to report
+    // distinguish between stop() and close() state transitions
+    // when reporting.
+    iClosedByUser = true;
 
     SymbianNetworkConfigurationPrivate *symbianConfig =
         toSymbianConfig(privateConfiguration(activeConfig));
@@ -469,8 +542,10 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
     }
 #endif
 
-    if (ipConnectionNotifier) {
+    if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) {
         ipConnectionNotifier->StopNotifications();
+        // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+        iHandleStateNotificationsFromManager = true;
     }
     
     iConnection.Close();
@@ -488,7 +563,6 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
         newState(QNetworkSession::Closing);
     }
     
-    syncStateWithInterface();
     if (allowSignals) {
         if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
             newState(QNetworkSession::Disconnected);
@@ -499,9 +573,19 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
 
 void QNetworkSessionPrivateImpl::stop()
 {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+            << "stop() called, session state is: " << state << " and isOpen is : "
+            << isOpen;
+#endif
     if (!isOpen &&
         publicConfig.isValid() &&
         publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+            << "since session is not open, using RConnectionMonitor to stop() the interface";
+#endif
+        iStoppedByUser = true;
         // 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,
@@ -532,11 +616,25 @@ void QNetworkSessionPrivateImpl::stop()
                                                               ETrue);
                 }
             }
+            // Enter disconnected state right away since the session is not even open.
+            // Symbian^3 connection monitor does not emit KLinkLayerClosed when
+            // connection is stopped via connection monitor.
+            newState(QNetworkSession::Disconnected);
         }
     } else if (isOpen) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+            << "since session is open, using RConnection to stop() the interface";
+#endif
         // Since we are open, use RConnection to stop the interface
         isOpen = false;
+        iStoppedByUser = true;
         newState(QNetworkSession::Closing);
+        if (ipConnectionNotifier) {
+            ipConnectionNotifier->StopNotifications();
+            // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+            iHandleStateNotificationsFromManager = true;
+        }
         iConnection.Stop(RConnection::EStopAuthoritative);
         isOpen = true;
         close(false);
@@ -654,6 +752,10 @@ void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*
 
 void QNetworkSessionPrivateImpl::Error(TInt /*aError*/)
 {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+            << "roaming Error() occured";
+#endif
     if (isOpen) {
         isOpen = false;
         activeConfig = QNetworkConfiguration();
@@ -671,6 +773,11 @@ void QNetworkSessionPrivateImpl::Error(TInt /*aError*/)
         //    changes immediately to Disconnected.
         newState(QNetworkSession::Disconnected);
         emit closed();
+    } else if (iStoppedByUser) {
+        // If the user of this session has called the stop() and
+        // configuration is based on internet SNAP, this needs to be
+        // done here because platform might roam.
+        newState(QNetworkSession::Disconnected);
     }
 }
 #endif
@@ -975,7 +1082,12 @@ void QNetworkSessionPrivateImpl::RunL()
             isOpen = false;
             activeConfig = QNetworkConfiguration();
             serviceConfig = QNetworkConfiguration();
-            iError = QNetworkSession::UnknownSessionError;
+            if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+                publicConfig.state() == QNetworkConfiguration::Defined) {
+                iError = QNetworkSession::InvalidConfigurationError;
+            } else {
+                iError = QNetworkSession::UnknownSessionError;
+            }
             emit QNetworkSessionPrivate::error(iError);
             Cancel();
             if (ipConnectionNotifier) {
@@ -991,8 +1103,16 @@ void QNetworkSessionPrivateImpl::DoCancel()
     iConnection.Close();
 }
 
+// Enters newState if feasible according to current state.
+// AccessPointId may be given as parameter. If it is zero, state-change is assumed to
+// concern this session's configuration. If non-zero, the configuration is looked up
+// and checked if it matches the configuration this session is based on.
 bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint accessPointId)
 {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+             << "NEW STATE, IAP ID : " << QString::number(accessPointId) << " , newState : " << QString::number(newState);
+#endif
     // Make sure that activeConfig is always updated when SNAP is signaled to be
     // connected.
     if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork &&
@@ -1027,9 +1147,29 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
     if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) {
         return false;
     }
+    
+    // Make sure that Connected state is not reported when Connection is
+    // already Closing.
+    // Note: Stopping connection results sometimes KLinkLayerOpen
+    //       to be reported first (just before KLinkLayerClosed).
+    if (state == QNetworkSession::Closing && newState == QNetworkSession::Connected) {
+        return false;
+    }
+
+    // Make sure that some lagging 'closing' state-changes do not overwrite
+    // if we are already disconnected or closed.
+    if (state == QNetworkSession::Disconnected && newState == QNetworkSession::Closing) {
+        return false;
+    }
 
     bool emitSessionClosed = false;
-    if (isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) {
+
+    // If we abruptly go down and user hasn't closed the session, we've been aborted.
+    // Note that session may be in 'closing' state and not in 'connected' state, because
+    // depending on platform the platform may report KConfigDaemonStartingDeregistration
+    // event before KLinkLayerClosed
+    if ((isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) ||
+        (isOpen && !iClosedByUser && newState == QNetworkSession::Disconnected)) {
         // Active & Connected state should change directly to Disconnected state
         // only when something forces connection to close (eg. when another
         // application or session stops connection or when network drops
@@ -1043,14 +1183,17 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
         if (ipConnectionNotifier) {
             ipConnectionNotifier->StopNotifications();
         }
-        // Start monitoring changes in IAP states
-        TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+        // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+        iHandleStateNotificationsFromManager = true;
         emitSessionClosed = true; // Emit SessionClosed after state change has been reported
     }
 
     bool retVal = false;
     if (accessPointId == 0) {
         state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed A to: " << state;
+#endif
         emit stateChanged(state);
         retVal = true;
     } else {
@@ -1063,6 +1206,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
                 configLocker.unlock();
 
                 state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed B to: " << state;
+#endif
                 emit stateChanged(state);
                 retVal = true;
             }
@@ -1075,6 +1221,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
                 configLocker.unlock();
 
                 state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed C to: " << state;
+#endif
                 emit stateChanged(state);
                 retVal = true;
             }
@@ -1088,20 +1237,13 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
 
                 if (symbianConfig->numericId == accessPointId) {
                     if (newState == QNetworkSession::Connected) {
-                        // Make sure that when AccessPoint is reported to be Connected
-                        // also state of the related configuration changes to Active.
-                        symbianConfig->state = QNetworkConfiguration::Active;
-                        configLocker.unlock();
-    
                         state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                        qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D  to: " << state;
+#endif
                         emit stateChanged(state);
                         retVal = true;
                     } else {
-                        if (newState == QNetworkSession::Disconnected) {
-                            // Make sure that when AccessPoint is reported to be disconnected
-                            // also state of the related configuration changes from Active to Defined.
-                            symbianConfig->state = QNetworkConfiguration::Defined;
-                        }
                         QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
                         if ((config.state() == QNetworkConfiguration::Defined) ||
                             (config.state() == QNetworkConfiguration::Discovered)) {
@@ -1109,6 +1251,9 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
                             configLocker.unlock();
 
                             state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                            qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E  to: " << state;
+#endif
                             emit stateChanged(state);
                             retVal = true;
                         }
@@ -1121,6 +1266,19 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint
     if (emitSessionClosed) {
         emit closed();
     }
+    if (state == QNetworkSession::Disconnected) {
+        // The connection has gone down, and processing of status updates must be
+        // stopped. Depending on platform, there may come 'connecting/connected' states
+        // considerably later (almost a second). Connection id is an increasing
+        // number, so this does not affect next _real_ 'conneting/connected' states.
+
+        SymbianNetworkConfigurationPrivate *symbianConfig =
+            toSymbianConfig(privateConfiguration(publicConfig));
+
+        symbianConfig->mutex.lock();
+        iDeprecatedConnectionId = symbianConfig->connectionId;
+        symbianConfig->mutex.unlock();
+    }
 
     return retVal;
 }
@@ -1129,6 +1287,9 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
                                                                  TInt aError,
                                                                  TUint accessPointId)
 {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNS this : " << QString::number((uint)this) << " - " << QString::number(accessPointId) << " , status : " << QString::number(aConnectionStatus);
+#endif
     switch (aConnectionStatus)
         {
         // Connection unitialised
@@ -1167,6 +1328,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
         case KCsdGotLoginInfo:
             break;
 
+        case KConfigDaemonStartingRegistration:
         // Creating connection (e.g. GPRS activation)
         case KCsdStartingConnect:
         case KCsdFinishedConnect:
@@ -1193,6 +1355,7 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
         case KDataTransferTemporarilyBlocked:
             break;
 
+        case KConfigDaemonStartingDeregistration:
         // Hangup or GRPS deactivation
         case KConnectionStartingClose:
             newState(QNetworkSession::Closing,accessPointId);
@@ -1200,136 +1363,26 @@ void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConne
 
         // Connection closed
         case KConnectionClosed:
-            break;
-
         case KLinkLayerClosed:
             newState(QNetworkSession::Disconnected,accessPointId);
+            // Report manager about this to make sure this event
+            // is received by all interseted parties (mediated by
+            // manager because it does always receive all events from
+            // connection monitor).
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+            qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "reporting disconnection to manager.";
+#endif
+            if (publicConfig.isValid()) {
+                engine->configurationStateChangeReport(toSymbianConfig(privateConfiguration(publicConfig))->numericId, QNetworkSession::Disconnected);
+            }
             break;
-
         // Unhandled state
         default:
             break;
         }
 }
 
-void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent)
-{
-    switch (aEvent.EventType())
-    {
-        case EConnMonConnectionStatusChange:
-            {
-            CConnMonConnectionStatusChange* realEvent;
-            realEvent = (CConnMonConnectionStatusChange*) &aEvent;
-
-            TUint connectionId = realEvent->ConnectionId();
-            TInt connectionStatus = realEvent->ConnectionStatus();
-
-            // Try to Find IAP Id using connection Id
-            TUint apId = 0;
-            if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
-                QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
-                for (int i = 0; i < subConfigurations.count(); i++ ) {
-                    SymbianNetworkConfigurationPrivate *symbianConfig =
-                        toSymbianConfig(privateConfiguration(subConfigurations[i]));
-
-                    QMutexLocker configLocker(&symbianConfig->mutex);
-
-                    if (symbianConfig->connectionId == connectionId) {
-                        apId = symbianConfig->numericId;
-                        break;
-                    }
-                }
-            } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-                SymbianNetworkConfigurationPrivate *symbianConfig =
-                    toSymbianConfig(privateConfiguration(publicConfig));
-
-                symbianConfig->mutex.lock();
-                if (symbianConfig->connectionId == connectionId)
-                    apId = symbianConfig->numericId;
-                symbianConfig->mutex.unlock();
-            }
-
-            if (apId > 0) {
-                handleSymbianConnectionStatusChange(connectionStatus, KErrNone, apId);
-            }
-            }
-            break;
-
-        case EConnMonCreateConnection:
-            {
-            CConnMonCreateConnection* realEvent;
-            realEvent = (CConnMonCreateConnection*) &aEvent;
-            TUint apId;
-            TUint connectionId = realEvent->ConnectionId();
-            TRequestStatus status;
-            iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
-            User::WaitForRequest(status);
-            if (status.Int() == KErrNone) {
-                // Store connection id to related AccessPoint Configuration
-                if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
-                    QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
-                    for (int i = 0; i < subConfigurations.count(); i++ ) {
-                        SymbianNetworkConfigurationPrivate *symbianConfig =
-                            toSymbianConfig(privateConfiguration(subConfigurations[i]));
-
-                        QMutexLocker configLocker(&symbianConfig->mutex);
-
-                        if (symbianConfig->numericId == apId) {
-                            symbianConfig->connectionId = connectionId;
-                            break;
-                        }
-                    }
-                } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-                    SymbianNetworkConfigurationPrivate *symbianConfig =
-                        toSymbianConfig(privateConfiguration(publicConfig));
-
-                    symbianConfig->mutex.lock();
-                    if (symbianConfig->numericId == apId)
-                        symbianConfig->connectionId = connectionId;
-                    symbianConfig->mutex.unlock();
-                }
-            }
-            }
-            break;
-
-        case EConnMonDeleteConnection:
-            {
-            CConnMonDeleteConnection* realEvent;
-            realEvent = (CConnMonDeleteConnection*) &aEvent;
-            TUint connectionId = realEvent->ConnectionId();
-            // Remove connection id from related AccessPoint Configuration
-            if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
-                QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
-                for (int i = 0; i < subConfigurations.count(); i++ ) {
-                    SymbianNetworkConfigurationPrivate *symbianConfig =
-                        toSymbianConfig(privateConfiguration(subConfigurations[i]));
-
-                    QMutexLocker configLocker(&symbianConfig->mutex);
-
-                    if (symbianConfig->connectionId == connectionId) {
-                        symbianConfig->connectionId = 0;
-                        break;
-                    }
-                }
-            } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-                SymbianNetworkConfigurationPrivate *symbianConfig =
-                    toSymbianConfig(privateConfiguration(publicConfig));
-
-                symbianConfig->mutex.lock();
-                if (symbianConfig->connectionId == connectionId)
-                    symbianConfig->connectionId = 0;
-                symbianConfig->mutex.unlock();
-            }
-            }
-            break;
-
-        default:
-            // For unrecognized events
-            break;
-    }
-}
-
-ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection)
+ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection)
     : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection)
 {
     CActiveScheduler::Add(this);
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
index 7116519..9767293 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.h
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -75,9 +75,8 @@ class SymbianEngine;
 
 class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive,
 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
-                                   public MMobilityProtocolResp,
+                                   public MMobilityProtocolResp
 #endif
-                                   public MConnectionMonitorObserver
 {
     Q_OBJECT
 public:
@@ -130,8 +129,9 @@ protected: // From CActive
     void RunL();
     void DoCancel();
     
-private: // MConnectionMonitorObserver
-    void EventL(const CConnMonEventBase& aEvent);
+private Q_SLOTS:
+    void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId, QNetworkSession::State newState);
+    void configurationRemoved(QNetworkConfigurationPrivatePointer config);
     
 private:
     TUint iapClientCount(TUint aIAPId) const;
@@ -157,6 +157,13 @@ private: // data
     mutable RConnection iConnection;
     mutable RConnectionMonitor iConnectionMonitor;
     ConnectionProgressNotifier* ipConnectionNotifier;
+    
+    bool iHandleStateNotificationsFromManager;
+    bool iFirstSync;
+    bool iStoppedByUser;
+    bool iClosedByUser;
+    TUint32 iDeprecatedConnectionId;
+    
 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
     CActiveCommsMobilityApiExt* iMobility;
 #endif    
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
index 8e9675e..cea8b67 100644
--- a/src/plugins/bearer/symbian/symbianengine.cpp
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -45,14 +45,14 @@
 #include <commdb.h>
 #include <cdbcols.h>
 #include <d32dbms.h>
+#include <nifvar.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
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
 #include <QDebug>
 #endif
 
@@ -73,7 +73,9 @@
 
 QT_BEGIN_NAMESPACE
 
-static const int KValueThatWillBeAddedToSNAPId = 1000;
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+    static const int KValueThatWillBeAddedToSNAPId = 1000;
+#endif
 static const int KUserChoiceIAPId = 0;
 
 SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
@@ -657,26 +659,34 @@ void SymbianEngine::updateActiveAccessPoints()
     iConnectionMonitor.GetConnectionCount(connectionCount, status);
     User::WaitForRequest(status);
     
-    // Go through all connections and set state of related IAPs to Active
+    // Go through all connections and set state of related IAPs to Active.
+    // Status needs to be checked carefully, because ConnMon lists also e.g.
+    // WLAN connections that are being currently tried --> we don't want to
+    // state these as active.
     TUint connectionId;
     TUint subConnectionCount;
     TUint apId;
+    TInt connectionStatus;
     if (status.Int() == KErrNone) {
         for (TUint i = 1; i <= connectionCount; i++) {
             iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
             User::WaitForRequest(status);
             QString ident = QString::number(qHash(apId));
-
             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
             if (ptr) {
-                online = true;
-                inactiveConfigs.removeOne(ident);
+                iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
+                User::WaitForRequest(status);          
+                if (connectionStatus == KLinkLayerOpen) {
+                    online = true;
+                    inactiveConfigs.removeOne(ident);
 
-                toSymbianConfig(ptr)->connectionId = connectionId;
+                    QMutexLocker configLocker(&ptr->mutex);
+                    toSymbianConfig(ptr)->connectionId = connectionId;
 
-                // Configuration is Active
-                changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+                    // Configuration is Active
+                    changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+                }
             }
         }
     }
@@ -733,12 +743,12 @@ void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapIn
             }
         }
         
-        // Make sure that state of rest of the IAPs won't be Discovered or Active
+        // Make sure that state of rest of the IAPs won't be Active
         foreach (const QString &iface, unavailableConfigs) {
             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
             if (ptr) {
                 // Configuration is Defined
-                changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
+                changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
             }
         }
     }
@@ -894,21 +904,22 @@ 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).");
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug("QNCM 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) {
         case RDbNotifier::EUnlock:   /** All read locks have been removed.  */
         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    */
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
-            qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+            qDebug("QNCM 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,
@@ -957,73 +968,95 @@ void SymbianEngine::DoCancel()
     ipCommsDB->CancelRequestNotification();
 }
 
-
 void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
 {
     QMutexLocker locker(&mutex);
 
     switch (aEvent.EventType()) {
-    case EConnMonCreateConnection:
+    case EConnMonConnectionStatusChange:
         {
-        CConnMonCreateConnection* realEvent;
-        realEvent = (CConnMonCreateConnection*) &aEvent;
-        TUint subConnectionCount = 0;
-        TUint apId;            
-        TUint connectionId = realEvent->ConnectionId();
-        TRequestStatus status;
-        iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
-        User::WaitForRequest(status);
-        QString ident = QString::number(qHash(apId));
-
-        QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
-        if (ptr) {
-            toSymbianConfig(ptr)->connectionId = connectionId;
-            // Configuration is Active
-            if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active))
-                updateStatesToSnaps();
-
-            if (!iOnline) {
-                iOnline = true;
-
-                locker.unlock();
-                emit this->onlineStateChanged(iOnline);
-                locker.relock();
+        CConnMonConnectionStatusChange* realEvent;
+        realEvent = (CConnMonConnectionStatusChange*) &aEvent;
+        TInt connectionStatus = realEvent->ConnectionStatus();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId();
+#endif
+        if (connectionStatus == KConfigDaemonStartingRegistration) {
+            TUint connectionId = realEvent->ConnectionId();
+            TUint subConnectionCount = 0;
+            TUint apId;            
+            TRequestStatus status;
+            iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+            User::WaitForRequest(status);
+            QString ident = QString::number(qHash(apId));
+            QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+            if (ptr) {
+                QMutexLocker configLocker(&ptr->mutex);
+                toSymbianConfig(ptr)->connectionId = connectionId;
+                emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connecting);
             }
-        }
-        }
-        break;
-
-    case EConnMonDeleteConnection:
-        {
-        CConnMonDeleteConnection* realEvent;
-        realEvent = (CConnMonDeleteConnection*) &aEvent;
-        TUint connectionId = realEvent->ConnectionId();
-
-        QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
-        if (ptr) {
-            toSymbianConfig(ptr)->connectionId = 0;
-            // Configuration is either Defined or Discovered
-            if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered))
-                updateStatesToSnaps();
-        }
-        
-        bool online = false;
-        foreach (const QString &iface, accessPointConfigurations.keys()) {
-            QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
-            if (ptr->state == QNetworkConfiguration::Active) {
-                online = true;
-                break;
+        } else if (connectionStatus == KLinkLayerOpen) {
+            // Connection has been successfully opened
+            TUint connectionId = realEvent->ConnectionId();
+            TUint subConnectionCount = 0;
+            TUint apId;            
+            TRequestStatus status;
+            iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+            User::WaitForRequest(status);
+            QString ident = QString::number(qHash(apId));
+            QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+            if (ptr) {
+                QMutexLocker configLocker(&ptr->mutex);
+                toSymbianConfig(ptr)->connectionId = connectionId;
+                // Configuration is Active
+                if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) {
+                    updateStatesToSnaps();
+                }
+                emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connected);
+                if (!iOnline) {
+                    iOnline = true;
+                    emit this->onlineStateChanged(iOnline);
+                }
             }
-        }
-        if (iOnline != online) {
-            iOnline = online;
+        } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
+            TUint connectionId = realEvent->ConnectionId();
+            QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+            if (ptr) {
+                QMutexLocker configLocker(&ptr->mutex);
+                emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Closing);
+            }
+        } else if (connectionStatus == KLinkLayerClosed ||
+                   connectionStatus == KConnectionClosed) {
+            // Connection has been closed. Which of the above events is reported, depends on the Symbian
+            // platform.
+            TUint connectionId = realEvent->ConnectionId();
+            QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+            if (ptr) {
+                // Configuration is either Defined or Discovered
+                if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
+                    updateStatesToSnaps();
+                }
 
-            locker.unlock();
-            emit this->onlineStateChanged(iOnline);
-            locker.relock();
+                QMutexLocker configLocker(&ptr->mutex);
+                emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Disconnected);
+            }
+            
+            bool online = false;
+            foreach (const QString &iface, accessPointConfigurations.keys()) {
+                QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+                QMutexLocker configLocker(&ptr->mutex);
+                if (ptr->state == QNetworkConfiguration::Active) {
+                    online = true;
+                    break;
+                }
+            }
+            if (iOnline != online) {
+                iOnline = online;
+                emit this->onlineStateChanged(iOnline);
+            }
         }
         }
-        break;
+        break;    
 
     case EConnMonIapAvailabilityChange:
         {
@@ -1051,21 +1084,78 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
         }
         break;
 
+    case EConnMonCreateConnection:
+        {
+        // This event is caught to keep connection monitor IDs up-to-date.
+        CConnMonCreateConnection* realEvent;
+        realEvent = (CConnMonCreateConnection*) &aEvent;
+        TUint subConnectionCount = 0;
+        TUint apId;
+        TUint connectionId = realEvent->ConnectionId();
+        TRequestStatus status;
+        iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+        User::WaitForRequest(status);
+        QString ident = QString::number(qHash(apId));
+        QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+        if (ptr) {
+            QMutexLocker configLocker(&ptr->mutex);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+            qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name;
+#endif
+            toSymbianConfig(ptr)->connectionId = connectionId;
+        }
+        }
+        break;
     default:
         // For unrecognized events
         break;
     }
 }
 
-// Waits for 1..4 seconds.
+// Sessions may use this function to report configuration state changes,
+// because on some Symbian platforms (especially Symbian^3) all state changes are not
+// reported by the RConnectionMonitor, in particular in relation to stop() call,
+// whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
+// this data here so that other sessions may benefit from it too (not all sessions necessarily have
+// RConnection progress notifiers available but they relay on having e.g. disconnected information from
+// manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
+void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState;
+#endif
+    switch (newState) {
+    case QNetworkSession::Disconnected:
+        {
+            QString ident = QString::number(qHash(accessPointId));
+            QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+            if (ptr) {
+                // Configuration is either Defined or Discovered
+                if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
+                    updateStatesToSnaps();
+                }
+
+                QMutexLocker configLocker(&ptr->mutex);
+                emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId,
+                                                     toSymbianConfig(ptr)->connectionId,
+                                                     QNetworkSession::Disconnected);
+            }
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+// Waits for 2..6 seconds.
 void SymbianEngine::waitRandomTime()
 {
-    iTimeToWait = (qAbs(qrand()) % 5) * 1000;
-    if (iTimeToWait < 1000) {
-        iTimeToWait = 1000;
+    iTimeToWait = (qAbs(qrand()) % 7) * 1000;
+    if (iTimeToWait < 2000) {
+        iTimeToWait = 2000;
     }
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
-    qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug("QNCM waiting random time: %d ms", iTimeToWait);
 #endif
     QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
     iIgnoreEventLoop->exec();
@@ -1076,11 +1166,11 @@ QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aCon
     QMutexLocker locker(&mutex);
 
     QNetworkConfiguration item;
-    
     QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
             accessPointConfigurations.constBegin();
     while (i != accessPointConfigurations.constEnd()) {
         QNetworkConfigurationPrivatePointer ptr = i.value();
+        QMutexLocker configLocker(&ptr->mutex);
         if (toSymbianConfig(ptr)->connectionId == aConnectionId)
             return ptr;
 
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
index afb37de..7d565db 100644
--- a/src/plugins/bearer/symbian/symbianengine.h
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -52,6 +52,9 @@
     #include <cmmanager.h>
 #endif
 
+// Uncomment and compile QtBearer to gain detailed state tracing
+// #define QT_BEARERMGMT_SYMBIAN_DEBUG
+
 class CCommsDatabase;
 class QEventLoop;
 
@@ -90,7 +93,18 @@ public:
 
     Bearer bearer;
 
+    // So called IAP id from the platform. Remains constant as long as the
+    // platform is aware of the configuration ie. it is stored in the databases
+    // --> does not depend on whether connections are currently open or not.
+    // In practice is the same for the lifetime of the QNetworkConfiguration.
     TUint32 numericId;
+    // So called connection id, or connection monitor ID. A dynamic ID assigned
+    // by RConnectionMonitor whenever a new connection is opened. ConnectionID and
+    // numericId/IAP id have 1-to-1 mapping during the lifetime of the connection at
+    // connection monitor. Notably however it changes whenever a new connection to
+    // a given IAP is created. In a sense it is constant during the time the
+    // configuration remains between states Discovered..Active..Discovered, do not
+    // however relay on this.
     TUint connectionId;
 };
 
@@ -124,6 +138,9 @@ public:
 Q_SIGNALS:
     void onlineStateChanged(bool isOnline);
     
+    void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId,
+                                   QNetworkSession::State newState);
+    
 public Q_SLOTS:
     void updateConfigurations();
 
@@ -157,12 +174,17 @@ private:
     void startMonitoringIAPData(TUint32 aIapId);
     QNetworkConfigurationPrivatePointer dataByConnectionId(TUint aConnectionId);
 
-protected: // From CActive
+protected:
+    // From CActive
     void RunL();
     void DoCancel();
     
-private: // MConnectionMonitorObserver
+private:
+    // MConnectionMonitorObserver
     void EventL(const CConnMonEventBase& aEvent);
+    // For QNetworkSessionPrivate to indicate about state changes
+    void configurationStateChangeReport(TUint32 accessPointId,
+                                   QNetworkSession::State newState);
 
 private: // Data
     bool               iFirstUpdate; 
@@ -181,6 +203,7 @@ private: // Data
     
     friend class QNetworkSessionPrivate;
     friend class AccessPointsAvailabilityScanner;
+    friend class QNetworkSessionPrivateImpl;
 
 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
     RCmManager iCmManager;
diff --git a/tests/auto/qnetworksession/lackey/main.cpp b/tests/auto/qnetworksession/lackey/main.cpp
index 8759b52..ec2fad9 100644
--- a/tests/auto/qnetworksession/lackey/main.cpp
+++ b/tests/auto/qnetworksession/lackey/main.cpp
@@ -47,6 +47,8 @@
 #include <QtNetwork/qnetworkconfigmanager.h>
 #include <QtNetwork/qnetworksession.h>
 
+#include <QEventLoop>
+#include <QTimer>
 #include <QDebug>
 
 QT_USE_NAMESPACE
@@ -60,15 +62,14 @@ int main(int argc, char** argv)
 {
     QCoreApplication app(argc, argv);
 
-    // Cannot read/write to processes on WinCE or Symbian.
-    // Easiest alternative is to use sockets for IPC.
-
-    QLocalSocket oopSocket;
-
-    oopSocket.connectToServer("tst_qnetworksession");
-    oopSocket.waitForConnected(-1);
-
+    // Update configurations so that everything is up to date for this process too.
+    // Event loop is used to wait for awhile.
     QNetworkConfigurationManager manager;
+    manager.updateConfigurations();
+    QEventLoop iIgnoreEventLoop;
+    QTimer::singleShot(3000, &iIgnoreEventLoop, SLOT(quit()));
+    iIgnoreEventLoop.exec();
+
     QList<QNetworkConfiguration> discovered =
         manager.allConfigurations(QNetworkConfiguration::Discovered);
 
@@ -82,6 +83,13 @@ int main(int argc, char** argv)
         return NO_DISCOVERED_CONFIGURATIONS_ERROR;
     }
 
+    // Cannot read/write to processes on WinCE or Symbian.
+    // Easiest alternative is to use sockets for IPC.
+    QLocalSocket oopSocket;
+
+    oopSocket.connectToServer("tst_qnetworksession");
+    oopSocket.waitForConnected(-1);
+
     qDebug() << "Lackey started";
 
     QNetworkSession *session = 0;
diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
index 23cdc6a..8ab9da2 100644
--- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
+++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
@@ -100,6 +100,7 @@ private slots:
 
 private:
     QNetworkConfigurationManager manager;
+    QMap<QString, bool> testsToRun;
 
     int inProcessSessionManagementCount;
 
@@ -117,6 +118,7 @@ private:
 bool openSession(QNetworkSession *session);
 bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration = true);
 void updateConfigurations();
+void printConfigurations();
 QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType);
 
 void tst_QNetworkSession::initTestCase()
@@ -125,7 +127,19 @@ void tst_QNetworkSession::initTestCase()
     qRegisterMetaType<QNetworkSession::SessionError>("QNetworkSession::SessionError");
     qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
     qRegisterMetaType<QNetworkConfiguration::Type>("QNetworkConfiguration::Type");
-
+	
+    // If you wish to skip tests, set value as false. This is often very convinient because tests are so lengthy.
+    // Better way still would be to make this readable from a file.
+    testsToRun["robustnessBombing"] = true;
+    testsToRun["outOfProcessSession"] = true;
+    testsToRun["invalidSession"] = true;
+    testsToRun["repeatedOpenClose"] = true;
+    testsToRun["roamingErrorCodes"] = true;
+    testsToRun["sessionStop"] = true;
+    testsToRun["sessionProperties"] = true;
+    testsToRun["userChoiceSession"] = true;
+    testsToRun["sessionOpenCloseStop"] = true;
+	
 #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
     iapconf = new Maemo::IAPConf("007");
     iapconf->setValue("ipv4_type", "AUTO");
@@ -238,6 +252,10 @@ void tst_QNetworkSession::cleanupTestCase()
 // Robustness test for calling interfaces in nonsense order / with nonsense parameters
 void tst_QNetworkSession::robustnessBombing() 
 {
+    if (!testsToRun["robustnessBombing"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
+    
     QNetworkConfigurationManager mgr;
     QNetworkSession testSession(mgr.defaultConfiguration());
     // Should not reset even session is not opened
@@ -253,7 +271,10 @@ void tst_QNetworkSession::robustnessBombing()
 
 
 void tst_QNetworkSession::invalidSession()
-{
+{ 
+    if (!testsToRun["invalidSession"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
     // 1. Verify that session created with invalid configuration remains in invalid state
     QNetworkSession session(QNetworkConfiguration(), 0);
     QVERIFY(!session.isOpen());
@@ -270,11 +291,24 @@ void tst_QNetworkSession::invalidSession()
     QVERIFY(error == QNetworkSession::InvalidConfigurationError);
     QVERIFY(session.error() == QNetworkSession::InvalidConfigurationError);
     QVERIFY(session.state() == QNetworkSession::Invalid);
-
+    	
 #ifdef QNETWORKSESSION_MANUAL_TESTS
+
+    QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
+    if (invalidatedConfig.isValid()) {
+        // 3. Verify that invalidating a session after its successfully configured works
+        QNetworkSession invalidatedSession(invalidatedConfig);
+        qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name();
+        QTest::qWait(60000);
+        QVERIFY(!invalidatedConfig.isValid());
+        QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid);
+        qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name();
+        QTest::qWait(60000);
+    }
+    
     QNetworkConfiguration definedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
     if (definedConfig.isValid()) {
-        // 3. Verify that opening a session with defined configuration emits error and enters notavailable-state
+        // 4. Verify that opening a session with defined configuration emits error and enters notavailable-state
         // TODO these timer waits should be changed to waiting appropriate signals, now these wait excessively
         qDebug() << "Shutdown WLAN IAP (waiting 60 seconds): " << definedConfig.name();
         QTest::qWait(60000);
@@ -283,43 +317,27 @@ void tst_QNetworkSession::invalidSession()
         QNetworkSession definedSession(definedConfig);
         QSignalSpy errorSpy(&definedSession, SIGNAL(error(QNetworkSession::SessionError)));
         QNetworkSession::SessionError sessionError;
+        updateConfigurations();
 
         definedSession.open();
+#ifdef Q_OS_SYMBIAN
+        // On symbian, the connection opening is tried even with defined state.
+        qDebug("Waiting for 10 seconds to all signals to propagate.");
+        QTest::qWait(10000);
+#endif
+        updateConfigurations();
 
         QVERIFY(definedConfig.isValid()); // Session remains valid
         QVERIFY(definedSession.state() == QNetworkSession::NotAvailable); // State is not available because WLAN is not in coverage
         QVERIFY(!errorSpy.isEmpty()); // Session tells with error about invalidated configuration
         sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
-        qDebug() << "Error code is: " << sessionError;
         QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
-        
         qDebug() << "Turn the WLAN IAP back on (waiting 60 seconds): " << definedConfig.name();
         QTest::qWait(60000);
-        updateConfigurations();
-        
+        updateConfigurations();        
         QVERIFY(definedConfig.state() == QNetworkConfiguration::Discovered);
     }
-        
-    QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
-    if (invalidatedConfig.isValid()) {
-        // 4. Verify that invalidating a session after its successfully configured works
-        QNetworkSession invalidatedSession(invalidatedConfig);
-        QSignalSpy errorSpy(&invalidatedSession, SIGNAL(error(QNetworkSession::SessionError)));
-        QNetworkSession::SessionError sessionError;
-        
-        qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name();
-        QTest::qWait(60000);
-        
-        invalidatedSession.open();
-        QVERIFY(!invalidatedConfig.isValid());
-        QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid);
-        QVERIFY(!errorSpy.isEmpty());
-        
-        sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
-        QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
-        qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name();
-        QTest::qWait(60000);
-    }
+
 #endif
 }
 
@@ -337,12 +355,12 @@ void tst_QNetworkSession::sessionProperties_data()
 
 void tst_QNetworkSession::sessionProperties()
 {
+    if (!testsToRun["sessionProperties"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
     QFETCH(QNetworkConfiguration, configuration);
-
     QNetworkSession session(configuration);
-
     QVERIFY(session.configuration() == configuration);
-
     QStringList validBearerNames = QStringList() << QLatin1String("Unknown")
                                                  << QLatin1String("Ethernet")
                                                  << QLatin1String("WLAN")
@@ -356,9 +374,6 @@ void tst_QNetworkSession::sessionProperties()
     if (!configuration.isValid()) {
         QVERIFY(configuration.bearerName().isEmpty());
     } else {
-        qDebug() << "Type:" << configuration.type()
-                 << "Bearer:" << configuration.bearerName();
-
         switch (configuration.type())
         {
             case QNetworkConfiguration::ServiceNetwork:
@@ -374,9 +389,7 @@ void tst_QNetworkSession::sessionProperties()
 
     // QNetworkSession::interface() should return an invalid interface unless
     // session is in the connected state.
-    qDebug() << "Session state:" << session.state();
 #ifndef QT_NO_NETWORKINTERFACE
-    qDebug() << "Session iface:" << session.interface().isValid() << session.interface().name();
 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
     // On Symbian emulator, the support for data bearers is limited
     QCOMPARE(session.state() == QNetworkSession::Connected, session.interface().isValid());
@@ -420,7 +433,12 @@ void tst_QNetworkSession::repeatedOpenClose_data() {
 }
 
 // Tests repeated-open close.
-void tst_QNetworkSession::repeatedOpenClose() {
+void tst_QNetworkSession::repeatedOpenClose() 
+{	
+    if (!testsToRun["repeatedOpenClose"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
+	
     QFETCH(QString, bearerType);
     QFETCH(QNetworkConfiguration::Type, configurationType);
     QFETCH(int, repeatTimes);
@@ -436,13 +454,20 @@ void tst_QNetworkSession::repeatedOpenClose() {
         !closeSession(&permanentSession)) {
         QSKIP("Unable to open/close session, skipping this round of repeated open-close test.", SkipSingle); 
     }
-    for (int i = repeatTimes; i > 0; i--) { 
+    for (int i = 0; i < repeatTimes; i++) { 
+       qDebug() << "Opening, loop number " << i;
        QVERIFY(openSession(&permanentSession));
+       qDebug() << "Closing, loop number, then waiting 5 seconds: " << i;
        QVERIFY(closeSession(&permanentSession));
+       QTest::qWait(5000);
     }
 }
 
-void tst_QNetworkSession::roamingErrorCodes() {
+void tst_QNetworkSession::roamingErrorCodes() 
+{
+    if (!testsToRun["roamingErrorCodes"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }    
 #ifndef Q_OS_SYMBIAN
     QSKIP("Roaming supported on Symbian.", SkipAll);
 #else 
@@ -466,41 +491,11 @@ void tst_QNetworkSession::roamingErrorCodes() {
     adminIapSession.stop(); // requires NetworkControl capabilities
     QTRY_VERIFY(!errorSpy.isEmpty()); // wait for error signals
     QNetworkSession::SessionError error = qvariant_cast<QNetworkSession::SessionError>(errorSpy.first().at(0));
+    QTest::qWait(2000); // Wait for a moment to all platform signals to propagate
     QVERIFY(error == QNetworkSession::SessionAbortedError);
     QVERIFY(iapSession.state() == QNetworkSession::Disconnected);
     QVERIFY(adminIapSession.state() == QNetworkSession::Disconnected);
 #endif // Q_OS_SYMBIAN
-   
-#ifdef QNETWORKSESSION_MANUAL_TESTS
-     // Check for roaming error.
-     // Case requires that you have controllable WLAN in Internet SNAP (only).
-    QNetworkConfiguration snapConfig = suitableConfiguration("bearer_not_relevant_with_snaps", QNetworkConfiguration::ServiceNetwork);
-    if (!snapConfig.isValid()) {
-        QSKIP("No SNAP accessible, skipping test.", SkipAll);
-    }
-    QNetworkSession snapSession(snapConfig);
-    QVERIFY(openSession(&snapSession));
-    QSignalSpy errorSpySnap(&snapSession, SIGNAL(error(QNetworkSession::SessionError)));
-    qDebug("Disconnect the WLAN now");
-    QTRY_VERIFY(!errorSpySnap.isEmpty()); // wait for error signals
-    QVERIFY(errorSpySnap.count() == 1);
-    error = qvariant_cast<QNetworkSession::SessionError>(errorSpySnap.first().at(0));
-    qDebug() << "Error received when turning off wlan on SNAP: " << error;
-    QVERIFY(error == QNetworkSession::RoamingError);
-    
-    qDebug("Connect the WLAN now");
-    QTest::qWait(60000); // Wait for WLAN to get up
-    QNetworkConfiguration wlanIapConfig2 = suitableConfiguration("WLAN", QNetworkConfiguration::InternetAccessPoint);
-    QNetworkSession iapSession2(wlanIapConfig2);
-    QVERIFY(openSession(&iapSession2));
-    QSignalSpy errorSpy2(&iapSession2, SIGNAL(error(QNetworkSession::SessionError)));
-    qDebug("Disconnect the WLAN now");
-    QTRY_VERIFY(!errorSpy2.isEmpty()); // wait for error signals
-    QVERIFY(errorSpy2.count() == 1);
-    error = qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
-    QVERIFY(error == QNetworkSession::SessionAbortedError);
-    QVERIFY(iapSession2.state() == QNetworkSession::Disconnected);
-#endif
 }
 
 
@@ -515,6 +510,9 @@ void tst_QNetworkSession::sessionStop_data() {
 
 void tst_QNetworkSession::sessionStop() 
 {
+    if (!testsToRun["sessionStop"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
 #ifndef Q_OS_SYMBIAN
     QSKIP("Testcase contains mainly Symbian specific checks, because it is only platform to really support interface (IAP-level) Stop.", SkipAll);
 #endif 
@@ -522,6 +520,9 @@ void tst_QNetworkSession::sessionStop()
     QFETCH(QNetworkConfiguration::Type, configurationType);
     
     int configWaitdelayInMs = 2000;
+	
+    updateConfigurations();
+    printConfigurations();
     
     QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
     if (!config.isValid()) {
@@ -539,6 +540,9 @@ void tst_QNetworkSession::sessionStop()
     QSignalSpy closedSessionStateChangedSpy(&closedSession, SIGNAL(stateChanged(QNetworkSession::State)));
     QSignalSpy closedErrorSpy(&closedSession, SIGNAL(error(QNetworkSession::SessionError)));
     
+    QSignalSpy openedSessionClosedSpy(&openedSession, SIGNAL(closed()));
+    QSignalSpy openedSessionStateChangedSpy(&openedSession, SIGNAL(stateChanged(QNetworkSession::State)));
+    
     QSignalSpy innocentSessionClosedSpy(&innocentSession, SIGNAL(closed()));
     QSignalSpy innocentSessionStateChangedSpy(&innocentSession, SIGNAL(stateChanged(QNetworkSession::State)));
     QSignalSpy innocentErrorSpy(&innocentSession, SIGNAL(error(QNetworkSession::SessionError)));
@@ -554,10 +558,18 @@ void tst_QNetworkSession::sessionStop()
     closedSessionClosedSpy.clear();
     closedSessionStateChangedSpy.clear();
     closedErrorSpy.clear();
+    openedSessionStateChangedSpy.clear();
+    openedSessionClosedSpy.clear();
+    
     openedSession.stop();
 
-    QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
+    qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
     QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+    
+    // First to closing, then to disconnected
+    QVERIFY(openedSessionStateChangedSpy.count() == 2);
+    QVERIFY(!openedSessionClosedSpy.isEmpty());
+    QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
     QVERIFY(config.state() != QNetworkConfiguration::Active);
     
     // 2. Verify that stopping a session based on non-connected configuration does nothing
@@ -583,18 +595,20 @@ void tst_QNetworkSession::sessionStop()
     // 3. Check that stopping a opened session affects also other opened session based on the same configuration.
     if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
         qDebug("----------3. Check that stopping a opened session affects also other opened session based on the same configuration.");
+	
         QVERIFY(openSession(&openedSession));
         QVERIFY(openSession(&innocentSession));
-
+	    
         configChangeSpy.clear();
         innocentSessionClosedSpy.clear();
         innocentSessionStateChangedSpy.clear();
         innocentErrorSpy.clear();
-      
+        
         openedSession.stop();    
         qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
         QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
-
+	QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+	    
         QVERIFY(!innocentSessionClosedSpy.isEmpty());
         QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
         QVERIFY(!innocentErrorSpy.isEmpty());
@@ -614,14 +628,19 @@ void tst_QNetworkSession::sessionStop()
     if (config.type() == QNetworkConfiguration::ServiceNetwork) {
         qDebug("----------4. Skip for SNAP configuration.");
     } else if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
-        qDebug("----------4. Check that stopping a non-opened session stops the other session based on the same configuration");
-        QVERIFY(openSession(&innocentSession));
+        qDebug("----------4.   Check that stopping a non-opened session stops the other session based on the same configuration");
+	qDebug("----------4.1 Opening innocent session");
+        QVERIFY(openSession(&innocentSession));    
         qDebug("Waiting for %d ms after open to make sure all platform indications are propagated", configWaitdelayInMs);
         QTest::qWait(configWaitdelayInMs);
+    qDebug("----------4.2 Calling closedSession.stop()");
         closedSession.stop();
         qDebug("Waiting for %d ms to get all configurationChange signals from platform..", configWaitdelayInMs);
         QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
     
+	    QTest::qWait(configWaitdelayInMs);
+	    QTest::qWait(configWaitdelayInMs);
+	    
         QVERIFY(!innocentSessionClosedSpy.isEmpty());
         QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
         QVERIFY(!innocentErrorSpy.isEmpty());
@@ -653,6 +672,9 @@ void tst_QNetworkSession::userChoiceSession_data()
 
 void tst_QNetworkSession::userChoiceSession()
 {
+    if (!testsToRun["userChoiceSession"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
     QFETCH(QNetworkConfiguration, configuration);
 
     QVERIFY(configuration.type() == QNetworkConfiguration::UserChoice);
@@ -786,6 +808,9 @@ void tst_QNetworkSession::sessionOpenCloseStop_data()
 
 void tst_QNetworkSession::sessionOpenCloseStop()
 {
+    if (!testsToRun["sessionOpenCloseStop"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
     QFETCH(QNetworkConfiguration, configuration);
     QFETCH(bool, forceSessionStop);
 
@@ -894,26 +919,30 @@ void tst_QNetworkSession::sessionOpenCloseStop()
         QVERIFY(session.error() == QNetworkSession::UnknownSessionError);
 
         session2.open();
-
+	    
         QTRY_VERIFY(!sessionOpenedSpy2.isEmpty() || !errorSpy2.isEmpty());
 
+        if (errorSpy2.isEmpty()) {
+            QVERIFY(session2.isOpen());
+            QVERIFY(session2.state() == QNetworkSession::Connected);
+        }
         QVERIFY(session.isOpen());
-        QVERIFY(session2.isOpen());
         QVERIFY(session.state() == QNetworkSession::Connected);
-        QVERIFY(session2.state() == QNetworkSession::Connected);
 #ifndef QT_NO_NETWORKINTERFACE
 #if !(defined(Q_OS_SYMBIAN) && defined(__WINS__))
         // On Symbian emulator, the support for data bearers is limited
         QVERIFY(session.interface().isValid());
 #endif
-        QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
-        QCOMPARE(session.interface().index(), session2.interface().index());
+        if (errorSpy2.isEmpty()) {
+            QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress());
+            QCOMPARE(session.interface().index(), session2.interface().index());
+        }
 #endif
     }
 
     sessionOpenedSpy2.clear();
 
-    if (forceSessionStop) {
+    if (forceSessionStop && session2.isOpen()) {
         // Test forcing the second session to stop the interface.
         QNetworkSession::State previousState = session.state();
 #ifdef Q_CC_NOKIAX86
@@ -922,15 +951,17 @@ void tst_QNetworkSession::sessionOpenCloseStop()
 #else
         bool expectStateChange = previousState != QNetworkSession::Disconnected;
 #endif
-
         session2.stop();
 
+        // QNetworkSession::stop() must result either closed() signal
+        // or error() signal
         QTRY_VERIFY(!sessionClosedSpy2.isEmpty() || !errorSpy2.isEmpty());
-
         QVERIFY(!session2.isOpen());
 
         if (!errorSpy2.isEmpty()) {
-	    QVERIFY(!errorSpy.isEmpty());
+            // QNetworkSession::stop() resulted error() signal for session2
+            // => also session should emit error() signal
+            QTRY_VERIFY(!errorSpy.isEmpty());
 
             // check for SessionAbortedError
             QNetworkSession::SessionError error =
@@ -950,9 +981,12 @@ void tst_QNetworkSession::sessionOpenCloseStop()
 
         QVERIFY(errorSpy.isEmpty());
         QVERIFY(errorSpy2.isEmpty());
-
+        
+        // Wait for Disconnected state 
+        QTRY_NOOP(session2.state() == QNetworkSession::Disconnected);
+	
         if (expectStateChange)
-            QTRY_VERIFY(stateChangedSpy2.count() >= 2 || !errorSpy2.isEmpty());
+            QTRY_VERIFY(stateChangedSpy2.count() >= 1 || !errorSpy2.isEmpty());
 
         if (!errorSpy2.isEmpty()) {
             QVERIFY(session2.state() == previousState);
@@ -996,16 +1030,29 @@ void tst_QNetworkSession::sessionOpenCloseStop()
                     state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(3).at(0));
                     QVERIFY(state == QNetworkSession::Disconnected);
                     
+			
+                    QTRY_VERIFY(session.state() == QNetworkSession::Roaming ||
+                                session.state() == QNetworkSession::Connected ||
+                                session.state() == QNetworkSession::Disconnected);
+                    
                     QTRY_VERIFY(stateChangedSpy.count() > 0);
-                    state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(0).at(0));
+                    state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(stateChangedSpy.count() - 1).at(0));                    
+                    
                     if (state == QNetworkSession::Roaming) {
-                        QTRY_VERIFY(!errorSpy.isEmpty() || stateChangedSpy.count() > 1);
-                        if (stateChangedSpy.count() > 1 &&
-                            qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0)) ==
-                            QNetworkSession::Connected) {
-                            roamedSuccessfully = true;
+                        QTRY_VERIFY(session.state() == QNetworkSession::Connected);
+                        QTRY_VERIFY(session2.state() == QNetworkSession::Connected);
+                        roamedSuccessfully = true;
+                    } else if (state == QNetworkSession::Disconnected) {
+                        QTRY_VERIFY(!errorSpy.isEmpty());
+                        QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
+                  	} else if (state == QNetworkSession::Connected) {
+                        QTRY_VERIFY(errorSpy.isEmpty());
+                        if (stateChangedSpy.count() > 1) {
+                            state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(stateChangedSpy.count() - 2).at(0));                        
+                            QVERIFY(state == QNetworkSession::Roaming);
                         }
-                    }
+                        roamedSuccessfully = true;
+                  	}
 
                     if (roamedSuccessfully) {
                         QString configId = session.sessionProperty("ActiveConfiguration").toString();
@@ -1013,37 +1060,36 @@ void tst_QNetworkSession::sessionOpenCloseStop()
                         QNetworkSession session3(config);
                         QSignalSpy errorSpy3(&session3, SIGNAL(error(QNetworkSession::SessionError)));
                         QSignalSpy sessionOpenedSpy3(&session3, SIGNAL(opened()));
-                        
                         session3.open();
-                        session3.waitForOpened();
-                        
+                        session3.waitForOpened();      
                         if (session.isOpen())
                             QVERIFY(!sessionOpenedSpy3.isEmpty() || !errorSpy3.isEmpty());
-                        
                         session.stop();
-
                         QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
-                        QTRY_VERIFY(session3.state() == QNetworkSession::Disconnected);
                     }
 #ifndef Q_CC_NOKIAX86
                     if (!roamedSuccessfully)
                         QVERIFY(!errorSpy.isEmpty());
 #endif
                 } else {
-                    QCOMPARE(stateChangedSpy2.count(), 2);
-
-                    QNetworkSession::State state =
-                        qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
-                    QVERIFY(state == QNetworkSession::Closing);
-
-                    state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
-                    QVERIFY(state == QNetworkSession::Disconnected);
+                    QTest::qWait(2000); // Wait awhile to get all signals from platform
+        
+                    if (stateChangedSpy2.count() == 2)  {
+                        QNetworkSession::State state =
+                            qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
+                        QVERIFY(state == QNetworkSession::Closing);
+                        state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(1).at(0));
+                        QVERIFY(state == QNetworkSession::Disconnected);
+                    } else { // Assume .count() == 1
+                        QCOMPARE(stateChangedSpy2.count(), 1); 
+                        QNetworkSession::State state = qvariant_cast<QNetworkSession::State>(stateChangedSpy2.at(0).at(0));
+                         // Symbian version dependant.
+                        QVERIFY(state == QNetworkSession::Disconnected);	
+                    }
                 }
 
                 QTRY_VERIFY(!sessionClosedSpy.isEmpty());
-
                 QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
-                QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
             }
 
             QVERIFY(errorSpy2.isEmpty());
@@ -1062,7 +1108,7 @@ void tst_QNetworkSession::sessionOpenCloseStop()
         QVERIFY(!session.isOpen());
 #endif
         QVERIFY(!session2.isOpen());
-    } else {
+    } else if (session2.isOpen()) {
         // Test closing the second session.
         {
             int stateChangedCountBeforeClose = stateChangedSpy2.count();
@@ -1161,11 +1207,15 @@ QDebug operator<<(QDebug debug, const QList<QNetworkConfiguration> &list)
 // at Discovered -state.
 void tst_QNetworkSession::outOfProcessSession()
 {
-    qDebug() << "START";
-
+    if (!testsToRun["outOfProcessSession"]) {
+	QSKIP("Temporary skip due to value set false (or it is missing) in testsToRun map", SkipAll);    
+    }
 #if defined(Q_OS_SYMBIAN) && defined(__WINS__)
     QSKIP("Symbian emulator does not support two [QR]PRocesses linking a dll (QtBearer.dll) with global writeable static data.", SkipAll);
 #endif
+	updateConfigurations();	   
+	QTest::qWait(2000);
+	
     QNetworkConfigurationManager manager;
     // Create a QNetworkConfigurationManager to detect configuration changes made in Lackey. This
     // is actually the essence of this testcase - to check that platform mediates/reflects changes
@@ -1182,16 +1232,15 @@ void tst_QNetworkSession::outOfProcessSession()
     QLocalServer::removeServer("tst_qnetworksession");
     oopServer.listen("tst_qnetworksession");
 
-    qDebug() << "starting lackey";
     QProcess lackey;
     lackey.start("lackey/lackey");
     qDebug() << lackey.error() << lackey.errorString();
     QVERIFY(lackey.waitForStarted());
 
-    qDebug() << "waiting for connection";
+
     QVERIFY(oopServer.waitForNewConnection(-1));
     QLocalSocket *oopSocket = oopServer.nextPendingConnection();
-    qDebug() << "got connection";
+
     do {
         QByteArray output;
 
@@ -1258,7 +1307,6 @@ void tst_QNetworkSession::outOfProcessSession()
     default:
         QSKIP("Lackey failed", SkipAll);
     }
-    qDebug("STOP");
 }
 
 // A convinience / helper function for testcases. Return the first matching configuration.
@@ -1269,6 +1317,7 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur
     // Refresh configurations and derive configurations matching given parameters.
     QNetworkConfigurationManager mgr;
     QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
+    
     mgr.updateConfigurations();
     QTRY_NOOP(updateSpy.count() == 1);
     if (updateSpy.count() != 1) {
@@ -1277,8 +1326,7 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur
     }
     QList<QNetworkConfiguration> discoveredConfigs = mgr.allConfigurations(QNetworkConfiguration::Discovered);
     foreach(QNetworkConfiguration config, discoveredConfigs) {
-        if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
-            // qDebug() << "Dumping config because is active: " << config.name();
+        if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {        
             discoveredConfigs.removeOne(config);
         } else if (config.type() != configType) {
             // qDebug() << "Dumping config because type (IAP/SNAP) mismatches: " << config.name();
@@ -1315,9 +1363,23 @@ void updateConfigurations()
     QTRY_NOOP(updateSpy.count() == 1);
 }
 
+// A convinience-function: updates and prints all available confiurations and their states
+void printConfigurations()
+{
+    QNetworkConfigurationManager manager;
+    QList<QNetworkConfiguration> allConfigs =
+    manager.allConfigurations();
+    qDebug("tst_QNetworkSession::printConfigurations QNetworkConfigurationManager gives following configurations: ");
+    foreach(QNetworkConfiguration config, allConfigs) {
+        qDebug() << "Name of the configuration: " << config.name();
+        qDebug() << "State of the configuration: " << config.state();
+    }
+}
+
 // A convinience function for test-cases: opens the given configuration and return
 // true if it was done gracefully.
 bool openSession(QNetworkSession *session) {
+    bool result = true;
     QNetworkConfigurationManager mgr;
     QSignalSpy openedSpy(session, SIGNAL(opened()));
     QSignalSpy stateChangeSpy(session, SIGNAL(stateChanged(QNetworkSession::State)));
@@ -1327,43 +1389,57 @@ bool openSession(QNetworkSession *session) {
     // active by some other session
     QNetworkConfiguration::StateFlags configInitState = session->configuration().state();
     QNetworkSession::State sessionInitState = session->state();
+    qDebug() << "tst_QNetworkSession::openSession() name of the configuration to be opened:  " << session->configuration().name();
+    qDebug() << "tst_QNetworkSession::openSession() state of the configuration to be opened:  " << session->configuration().state();
+    qDebug() << "tst_QNetworkSession::openSession() state of the session to be opened:  " << session->state();
 
     if (session->isOpen() ||
         !session->sessionProperty("ActiveConfiguration").toString().isEmpty()) {
         qDebug("tst_QNetworkSession::openSession() failure: session was already open / active.");
-        return false;
+        result = false;
     } else {
         session->open();
         session->waitForOpened(120000); // Bringing interfaces up and down may take time at platform
     }
+    QTest::qWait(5000); // Wait a moment to ensure all signals are propagated
     // Check that connection opening went by the book. Add checks here if more strictness needed.
     if (!session->isOpen()) {
         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::open() failed.");
-        return false;
+        result =  false;
     }
     if (openedSpy.count() != 1) {
         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::opened() - signal not received.");
-        return false;
+        result =  false;
     }
     if (!errorSpy.isEmpty()) {
         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::error() - signal was detected.");
-        return false;
+        result = false;
     }
     if (sessionInitState != QNetworkSession::Connected && 
         stateChangeSpy.isEmpty()) {
         qDebug("tst_QNetworkSession::openSession() failure: QNetworkSession::stateChanged() - signals not detected.");
-        return false;
+        result =  false;
     }
     if (configInitState != QNetworkConfiguration::Active && 
         configChangeSpy.isEmpty()) {
         qDebug("tst_QNetworkSession::openSession() failure: QNetworkConfigurationManager::configurationChanged() - signals not detected.");
-        return false;
+        result =  false;
     }
     if (session->configuration().state() != QNetworkConfiguration::Active) {
         qDebug("tst_QNetworkSession::openSession() failure: session's configuration is not in 'Active' -state.");
-        return false;
+	qDebug() << "tst_QNetworkSession::openSession() state is:  " << session->configuration().state();
+        result =  false;
+    }
+    if (result == false) {
+	    qDebug() << "tst_QNetworkSession::openSession() opening session failed.";
+    } else {
+	    qDebug() << "tst_QNetworkSession::openSession() opening session succeeded.";
     }
-    return true;
+    qDebug() << "tst_QNetworkSession::openSession() name of the configuration is:  " << session->configuration().name();
+    qDebug() << "tst_QNetworkSession::openSession() configuration state is:  " << session->configuration().state();
+    qDebug() << "tst_QNetworkSession::openSession() session state is:  " << session->state();
+	    
+    return result;
 }
 
 // Helper function for closing opened session. Performs checks that 
@@ -1376,6 +1452,11 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
         qDebug("tst_QNetworkSession::closeSession() failure: NULL session given");
         return false;
     }
+    
+    qDebug() << "tst_QNetworkSession::closeSession() name of the configuration to be closed:  " << session->configuration().name();
+    qDebug() << "tst_QNetworkSession::closeSession() state of the configuration to be closed:  " << session->configuration().state();
+    qDebug() << "tst_QNetworkSession::closeSession() state of the session to be closed:  " << session->state();
+    
     if (session->state() != QNetworkSession::Connected || 
         !session->isOpen()) {
         qDebug("tst_QNetworkSession::closeSession() failure: session is not opened.");
@@ -1387,38 +1468,48 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
     QSignalSpy sessionErrorSpy(session, SIGNAL(error(QNetworkSession::SessionError)));
     QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
     
+    bool result = true;
     session->close();
+    QTest::qWait(5000); // Wait a moment so that all signals are propagated
     
     if (!sessionErrorSpy.isEmpty()) {
         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::error() received.");
-        return false;
+        result = false;
     }
     if (sessionClosedSpy.count() != 1) {
         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::closed() signal not received.");
-        return false;
+        result = false;
     }
     if (lastSessionOnConfiguration && 
         sessionStateChangedSpy.isEmpty()) {
         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession::stateChanged() signals not received.");
-        return false;
+        result = false;
     }
     if (lastSessionOnConfiguration &&
         session->state() != QNetworkSession::Disconnected) {
         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkSession is not in Disconnected -state");
-        return false;
+        result = false;
     }
     QTRY_NOOP(!configChangeSpy.isEmpty());
     if (lastSessionOnConfiguration &&
         configChangeSpy.isEmpty()) {
         qDebug("tst_QNetworkSession::closeSession() failure: QNetworkConfigurationManager::configurationChanged() - signal not detected.");
-        return false;
+        result = false;
     }
     if (lastSessionOnConfiguration &&
         session->configuration().state() == QNetworkConfiguration::Active) {
          qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is still in active state.");
-         return false;
+         result = false;
     }
-    return true;
+    if (result == false) {
+	    qDebug() << "tst_QNetworkSession::closeSession() closing session failed.";
+    } else {
+	    qDebug() << "tst_QNetworkSession::closeSession() closing session succeeded.";
+    } 
+    qDebug() << "tst_QNetworkSession::closeSession() name of the configuration is:  " << session->configuration().name();
+    qDebug() << "tst_QNetworkSession::closeSession() configuration state is:  " << session->configuration().state();
+    qDebug() << "tst_QNetworkSession::closeSession() session state is:  " << session->state();
+    return result;
 }
 
 void tst_QNetworkSession::sessionAutoClose_data()
-- 
cgit v0.12