Revision: 201021 RCL_3
authorDremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 09 Jun 2010 10:36:00 +0300
branchRCL_3
changeset 5 4ea83c148e84
parent 4 d965ea371a4f
child 6 4203353e74ea
Revision: 201021 Kit: 2010123
qtmobility/data/qtmobility.sisx
qtmobility/src/bearer/qcorewlanengine_mac.mm
qtmobility/src/bearer/qcorewlanengine_mac_p.h
qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp
qtmobility/src/bearer/qnetworkconfigmanager_s60_p.h
qtmobility/src/bearer/qnetworkconfiguration_s60_p.h
qtmobility/src/bearer/qnetworksession_s60_p.cpp
qtmobility/src/bearer/qnetworksession_s60_p.h
qtmobility/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp
qtmobility/tests/auto/qnetworksession/lackey/main.cpp
qtmobility/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp
Binary file qtmobility/data/qtmobility.sisx has changed
--- a/qtmobility/src/bearer/qcorewlanengine_mac.mm	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qcorewlanengine_mac.mm	Wed Jun 09 10:36:00 2010 +0300
@@ -43,6 +43,7 @@
 #include "qnetworkconfiguration_p.h"
 
 #include <QtCore/qthread.h>
+#include <QThread>
 #include <QtCore/qmutex.h>
 #include <QtCore/qcoreapplication.h>
 #include <QtCore/qstringlist.h>
@@ -105,6 +106,8 @@
     QTM_NAMESPACE::QCoreWlanEngine::instance()->requestUpdate();
 }
 @end
+
+QNSListener *listener = 0;
 #endif
 
 QTM_BEGIN_NAMESPACE
@@ -143,11 +146,6 @@
     return result;
 }
 
-static QString qGetInterfaceType(const QString &interfaceString)
-{
-    return networkInterfaces.value(interfaceString, QLatin1String("Unknown"));
-}
-
 void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info)
 {
     for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) {
@@ -161,23 +159,314 @@
     return;
 }
 
+QScanThread::QScanThread(QObject *parent)
+    :QThread(parent), interfaceName(nil)
+{
+}
+
+QScanThread::~QScanThread()
+{
+}
+
+void QScanThread::quit()
+{
+    wait();
+}
+
+void QScanThread::run()
+{
+#if defined(MAC_SDK_10_6)
+    getUserProfiles();
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    QStringList found;
+    mutex.lock();
+    CWInterface *currentInterface;
+    if(interfaceName.isEmpty()) {
+        currentInterface = [CWInterface interfaceWithName:nil];
+        interfaceName = nsstringToQString([currentInterface name]);
+    } else {
+        currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)];
+    }
+    mutex.unlock();
+
+    if([currentInterface power]) {
+        NSError *err = nil;
+        NSDictionary *parametersDict =  [NSDictionary dictionaryWithObjectsAndKeys:
+                                         [NSNumber numberWithBool:YES], kCWScanKeyMerge,
+                                         [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil];
+
+        NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err];
+        CWNetwork *apNetwork;
+
+        if (!err) {
+            for(uint row=0; row < [apArray count]; row++ ) {
+                apNetwork = [apArray objectAtIndex:row];
+
+                const QString networkSsid = nsstringToQString([apNetwork ssid]);
+                found.append(networkSsid);
+
+                QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+
+                bool known = isKnownSsid(networkSsid);
+                if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
+                    if( networkSsid == nsstringToQString( [currentInterface ssid])) {
+                        state = QNetworkConfiguration::Active;
+                    }
+                }
+                if(state == QNetworkConfiguration::Undefined) {
+                    if(known) {
+                        state = QNetworkConfiguration::Discovered;
+                    } else {
+                        state = QNetworkConfiguration::Undefined;
+                    }
+                }
+
+                QNetworkConfiguration::Purpose purpose = QNetworkConfiguration::UnknownPurpose;
+                if([[apNetwork securityMode] intValue] == kCWSecurityModeOpen) {
+                    purpose = QNetworkConfiguration::PublicPurpose;
+                } else {
+                    purpose = QNetworkConfiguration::PrivatePurpose;
+                }
+
+                found.append(foundNetwork(networkSsid, networkSsid, state, interfaceName, purpose));
+
+            } //end row
+        }//end error
+    }// endwifi power
+
+// add known configurations that are not around.
+    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+    while (i.hasNext()) {
+        i.next();
+
+        QString networkName = i.key();
+        const QString id = networkName;
+
+        if(!found.contains(id)) {
+            QString networkSsid = getSsidFromNetworkName(networkName);
+            const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
+            QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+            QString interfaceName;
+            QMapIterator<QString, QString> ij(i.value());
+            while (ij.hasNext()) {
+                ij.next();
+                interfaceName = ij.value();
+            }
+
+            if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
+                if( networkSsid == nsstringToQString([currentInterface ssid])) {
+                    state = QNetworkConfiguration::Active;
+                }
+            }
+            if(state == QNetworkConfiguration::Undefined) {
+                if( userProfiles.contains(networkName)
+                    && found.contains(ssidId)) {
+                    state = QNetworkConfiguration::Discovered;
+                }
+            }
+
+            if(state == QNetworkConfiguration::Undefined) {
+                state = QNetworkConfiguration::Defined;
+            }
+
+            found.append(foundNetwork(id, networkName, state, interfaceName, QNetworkConfiguration::UnknownPurpose));
+        }
+    }
+    emit networksChanged();
+    [pool release];
+#endif
+}
+
+QStringList QScanThread::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName, const QNetworkConfiguration::Purpose purpose)
+{
+    QStringList found;
+    QMutexLocker locker(&mutex);
+    QNetworkConfigurationPrivate *ptr = new QNetworkConfigurationPrivate;
+
+    ptr->name = name;
+    ptr->isValid = true;
+    ptr->id = id;
+    ptr->state = state;
+    ptr->type = QNetworkConfiguration::InternetAccessPoint;
+    ptr->bearer = QLatin1String("WLAN");
+    ptr->purpose = purpose;
+    ptr->internet = true;
+    ptr->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName);
+
+    fetchedConfigurations.append( ptr);
+    configurationInterface[name] =  interfaceName;
+
+    locker.unlock();
+    locker.relock();
+    found.append(id);
+    return found;
+}
+
+QList<QNetworkConfigurationPrivate *> QScanThread::getConfigurations()
+{
+    QMutexLocker locker(&mutex);
+
+    QList<QNetworkConfigurationPrivate *> foundConfigurations;
+
+    for (int i = 0; i < fetchedConfigurations.count(); ++i) {
+        QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate;
+        config->name = fetchedConfigurations.at(i)->name;
+        config->isValid = fetchedConfigurations.at(i)->isValid;
+        config->id = fetchedConfigurations.at(i)->id;
+        config->state = fetchedConfigurations.at(i)->state;
+
+        config->type = fetchedConfigurations.at(i)->type;
+        config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported;
+        config->purpose = fetchedConfigurations.at(i)->purpose;
+        config->internet = fetchedConfigurations.at(i)->internet;
+        foundConfigurations.append(config);
+    }
+
+    return foundConfigurations;
+}
+
+void QScanThread::getUserProfiles()
+{
+#if defined(MAC_SDK_10_6)
+    QMutexLocker locker(&mutex);
+    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
+    userProfiles.clear();
+
+    NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
+    for(uint row=0; row < [wifiInterfaces count]; row++ ) {
+
+        CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]];
+        NSString *nsInterfaceName = [wifiInterface name];
+// add user configured system networks
+        SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
+        NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]);
+        CFRelease(dynRef);
+
+        NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
+
+        NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
+        NSEnumerator *ssidEnumerator = [thisSsidarray objectEnumerator];
+        NSString *ssidkey;
+        while ((ssidkey = [ssidEnumerator nextObject])) {
+            QString thisSsid = nsstringToQString(ssidkey);
+            if(!userProfiles.contains(thisSsid)) {
+                QMap <QString,QString> map;
+                map.insert(thisSsid, nsstringToQString(nsInterfaceName));
+                userProfiles.insert(thisSsid, map);
+            }
+        }
+        CFRelease(airportPlist);
+
+        // 802.1X user profiles
+        QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist";
+        NSDictionary* eapDict = [[[NSDictionary alloc] initWithContentsOfFile:qstringToNSString(userProfilePath)] autorelease];
+        NSString *profileStr= @"Profiles";
+        NSString *nameStr = @"UserDefinedName";
+        NSString *networkSsidStr = @"Wireless Network";
+
+        id profileKey;
+        NSEnumerator *dictEnumerator = [eapDict objectEnumerator];
+        while ((profileKey = [dictEnumerator nextObject])) {
+
+            if ([profileStr isEqualToString:profileKey]) {
+                NSDictionary *itemDict = [eapDict objectForKey:profileKey];
+                id itemKey;
+                NSEnumerator *dictEnumerator = [thisSsidarray objectEnumerator];
+                while ((itemKey = [dictEnumerator nextObject])) {
+
+                    NSInteger dictSize = [itemKey count];
+                    id objects[dictSize];
+                    id keys[dictSize];
+
+                    [itemKey getObjects:objects andKeys:keys];
+                    QString networkName;
+                    QString ssid;
+                    for(int i = 0; i < dictSize; i++) {
+                        if([nameStr isEqualToString:keys[i]]) {
+                            networkName = nsstringToQString(objects[i]);
+                        }
+                        if([networkSsidStr isEqualToString:keys[i]]) {
+                            ssid = nsstringToQString(objects[i]);
+                        }
+                        if(!userProfiles.contains(networkName)
+                            && !ssid.isEmpty()) {
+                            QMap<QString,QString> map;
+                            map.insert(ssid, nsstringToQString(nsInterfaceName));
+                            userProfiles.insert(networkName, map);
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    [pool release];
+#endif    
+}
+
+QString QScanThread::getSsidFromNetworkName(const QString &name)
+{
+    QMutexLocker locker(&mutex);
+    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+    while (i.hasNext()) {
+        i.next();
+        QMap<QString,QString> map = i.value();
+        QMapIterator<QString, QString> ij(i.value());
+         while (ij.hasNext()) {
+             ij.next();
+             const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key()));
+             if(name == i.key() || name == networkNameHash) {
+                 return ij.key();
+             }
+        }
+    }
+    return QString();
+}
+
+QString QScanThread::getNetworkNameFromSsid(const QString &ssid)
+{
+    QMutexLocker locker(&mutex);
+    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+    while (i.hasNext()) {
+        i.next();
+        QMap<QString,QString> map = i.value();
+        QMapIterator<QString, QString> ij(i.value());
+         while (ij.hasNext()) {
+             ij.next();
+             if(ij.key() == ssid) {
+                 return i.key();
+             }
+         }
+    }
+    return QString();
+}
+
+bool QScanThread::isKnownSsid(const QString &ssid)
+{
+    QMutexLocker locker(&mutex);
+
+    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+    while (i.hasNext()) {
+        i.next();
+        QMap<QString,QString> map = i.value();
+        if(map.keys().contains(ssid)) {
+            return true;
+        }
+    }
+    return false;
+}
+
+
 QCoreWlanEngine::QCoreWlanEngine(QObject *parent)
 :   QNetworkSessionEngine(parent)
 {
     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
     getAllScInterfaces();
-    startNetworkChangeLoop();
-#ifdef MAC_SDK_10_6
-    if([[CWInterface supportedInterfaces] count] > 0 ) {
-        QNSListener *listener;
-        listener = [[QNSListener alloc] init];
-        hasWifi = true;
-    } else {
-        hasWifi = false;
-    }
-#endif
-    getUserConfigurations();
-    requestUpdate();
+    scanThread = new QScanThread(this);
+    connect(scanThread, SIGNAL(networksChanged()),
+            this, SIGNAL(configurationsChanged()));
+
+    QTimer::singleShot(0,this,SLOT(init()));
     [pool release];
 }
 
@@ -191,82 +480,65 @@
     }
 }
 
+void QCoreWlanEngine::init()
+{
+#ifdef MAC_SDK_10_6
+    if([[CWInterface supportedInterfaces] count] > 0 && !listener) {
+        listener = [[QNSListener alloc] init];
+        hasWifi = true;
+    } else {
+        hasWifi = false;
+    }
+#endif
+    storeSession = NULL;
+    scanThread->start();
+
+    startNetworkChangeLoop();
+}
+
+
 QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::getConfigurations(bool *ok)
 {
     if (ok)
         *ok = true;
     foundConfigurations.clear();
 
-    uint identifier;
-    QMapIterator<QString, QString> i(networkInterfaces);
     QNetworkConfigurationPrivate* cpPriv = 0;
-    while (i.hasNext()) {
-        i.next();
-        if (i.value() == "WLAN") {
-            QList<QNetworkConfigurationPrivate *> fetchedConfigurations = scanForSsids(i.key());
-            for (int i = 0; i < fetchedConfigurations.count(); ++i) {
-
-                QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate();
-                cpPriv = fetchedConfigurations.at(i);
-                config->name = cpPriv->name;
-                config->isValid = cpPriv->isValid;
-                config->id = cpPriv->id;
+    QMutexLocker locker(&mutex);
+     QList<QNetworkConfigurationPrivate *> fetchedConfigurations = scanThread->getConfigurations();
+locker.unlock();
 
-                config->state = cpPriv->state;
-                config->type = cpPriv->type;
-                config->roamingSupported = cpPriv->roamingSupported;
-                config->purpose = cpPriv->purpose;
-                config->internet = cpPriv->internet;
-                config->serviceInterface = cpPriv->serviceInterface;
-                config->bearer = cpPriv->bearer;
-
-                identifier = config->name.toUInt();
-                configurationInterface[identifier] =  config->serviceInterface.name();
-                foundConfigurations.append(config);
-                delete cpPriv;
-            }
-        }
+     for (int i = 0; i < fetchedConfigurations.count(); ++i) {
 
-        QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key());
-        QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate();
-        const QString humanReadableName = interface.humanReadableName();
-        cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName;
-        cpPriv->isValid = true;
-
-        if (interface.index())
-            identifier = interface.index();
-        else
-            identifier = qHash(interface.hardwareAddress());
-
-        cpPriv->id = QString::number(identifier);
-        cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
-        cpPriv->state = QNetworkConfiguration::Undefined;
+         QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate();
+         cpPriv = fetchedConfigurations.at(i);
+         config->name = cpPriv->name;
+         config->isValid = cpPriv->isValid;
+         config->id = cpPriv->id;
+         config->state = cpPriv->state;
+         config->type = cpPriv->type;
+         config->roamingSupported = cpPriv->roamingSupported;
+         config->purpose = cpPriv->purpose;
+         config->internet = cpPriv->internet;
+         config->serviceInterface = cpPriv->serviceInterface;
+         config->bearer = cpPriv->bearer;
 
-        if (interface.flags() & QNetworkInterface::IsRunning) {
-            cpPriv->state = QNetworkConfiguration::Defined;
-            cpPriv->internet = true;
-        }
-        if ( !interface.addressEntries().isEmpty())  {
-            cpPriv->state |= QNetworkConfiguration::Active;
-            cpPriv->internet = true;
-        }
-        configurationInterface[identifier] = interface.name();
-        cpPriv->bearer = interface.name().isEmpty()? QLatin1String("Unknown") : qGetInterfaceType(interface.name());
-        foundConfigurations.append(cpPriv);
-    }
+         foundConfigurations.append(config);
+         delete cpPriv;
+     }
 
-    pollTimer.start();
-    return foundConfigurations;
+
+     return foundConfigurations;
 }
 
 QString QCoreWlanEngine::getInterfaceFromId(const QString &id)
 {
-    return configurationInterface.value(id.toUInt());
+    return scanThread->configurationInterface.value(id);
 }
 
 bool QCoreWlanEngine::hasIdentifier(const QString &id)
 {
-    return configurationInterface.contains(id.toUInt());
+    return scanThread->configurationInterface.contains(id);
 }
 
 void QCoreWlanEngine::connectToId(const QString &id)
@@ -285,13 +557,13 @@
             QString wantedSsid = 0;
             bool using8021X = false;
 
-            if(getNetworkNameFromSsid(id) != id) {
+            if(scanThread->getNetworkNameFromSsid(id) != id) {
                 NSArray *array = [CW8021XProfile allUser8021XProfiles];
                 for (NSUInteger i=0; i<[array count]; ++i) {
 
                     if(id == nsstringToQString([[array objectAtIndex:i] userDefinedName])
                         || id == nsstringToQString([[array objectAtIndex:i] ssid]) ) {
-                        QString thisName = getSsidFromNetworkName(id);
+                        QString thisName = scanThread->getSsidFromNetworkName(id);
                         if(thisName.isEmpty()) {
                             wantedSsid = id;
                         } else {
@@ -306,12 +578,12 @@
 
             if(!using8021X) {
                 QString wantedNetwork;
-                QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
+                QMapIterator<QString, QMap<QString,QString> > i(scanThread->userProfiles);
                 while (i.hasNext()) {
                     i.next();
                     wantedNetwork = i.key();
                     if(id == wantedNetwork) {
-                        wantedSsid = getSsidFromNetworkName(wantedNetwork);
+                        wantedSsid = scanThread->getSsidFromNetworkName(wantedNetwork);
                         break;
                     }
                 }
@@ -319,12 +591,12 @@
 
             NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys:
                                        [NSNumber numberWithBool:YES], kCWScanKeyMerge,
+                                       [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType,
                                        [NSNumber numberWithInteger:100], kCWScanKeyRestTime,
                                        qstringToNSString(wantedSsid), kCWScanKeySSID,
                                        nil];
 
-
-            NSArray *scanArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]];
+            NSArray *scanArray = [wifiInterface scanForNetworksWithParameters:parametersDict error:&err];
             if(!err) {
                 for(uint row=0; row < [scanArray count]; row++ ) {
                     CWNetwork *apNetwork = [scanArray objectAtIndex:row];
@@ -353,11 +625,13 @@
 
                             SecKeychainSearchRef searchRef;
                             OSErr result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef);
-
+Q_UNUSED(result);
                             NSString *password = @"";
                             SecKeychainItemRef searchItem;
+                            OSStatus resultStatus;
+                            resultStatus = SecKeychainSearchCopyNext(searchRef, &searchItem);
 
-                            if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) {
+                            if (resultStatus == errSecSuccess) {
                                 UInt32 realPasswordLength;
                                 SecKeychainAttribute attributesW[8];
                                 attributesW[0].tag = kSecAccountItemAttr;
@@ -380,7 +654,7 @@
                                 CFRelease(searchItem);
                                 SecKeychainItemFreeContent(&listW, realPassword);
                             } else {
-                                qDebug() << "SecKeychainSearchCopyNext error";
+                                qDebug() << "SecKeychainSearchCopyNext error" << cfstringRefToQstring(SecCopyErrorMessageString(resultStatus, NULL));
                             }
                             [params setValue: password forKey: kCWAssocKeyPassphrase];
                         } // end using8021X
@@ -403,6 +677,7 @@
             [autoreleasepool release];
 
         } else {
+            qDebug() << "wifi power off";
             // not wifi
         }
 #endif
@@ -433,8 +708,8 @@
 void QCoreWlanEngine::requestUpdate()
 {
     getAllScInterfaces();
-    getUserConfigurations();
-    emit configurationsChanged();
+    scanThread->getUserProfiles();
+    scanThread->start();
 }
 
 QCoreWlanEngine *QCoreWlanEngine::instance()
@@ -442,148 +717,6 @@
     return coreWlanEngine();
 }
 
-QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name)
-{
-    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
-    while (i.hasNext()) {
-        i.next();
-        QMap<QString,QString> map = i.value();
-        QMapIterator<QString, QString> ij(i.value());
-         while (ij.hasNext()) {
-             ij.next();
-             if(name == i.key()) {
-                 return ij.key();
-             }
-        }
-    }
-    return QString();
-}
-
-QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid)
-{
-    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
-    while (i.hasNext()) {
-        i.next();
-        QMap<QString,QString> map = i.value();
-        QMapIterator<QString, QString> ij(i.value());
-         while (ij.hasNext()) {
-             ij.next();
-             if(ij.key() == ssid) {
-                 return i.key();
-             }
-         }
-    }
-    return QString();
-}
-
-QList<QNetworkConfigurationPrivate *> QCoreWlanEngine::scanForSsids(const QString &interfaceName)
-{
-    QList<QNetworkConfigurationPrivate *> foundConfigs;
-    if(!hasWifi) {
-        return foundConfigs;
-    }
-#if defined(MAC_SDK_10_6)
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
-    CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)];
-    QStringList addedConfigs;
-
-    if([currentInterface power]) {
-        NSError *err = nil;
-        NSDictionary *parametersDict =  [NSDictionary dictionaryWithObjectsAndKeys:
-                                   [NSNumber numberWithBool:YES], kCWScanKeyMerge,
-                                   [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, // get the networks in the scan cache
-                                   [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil];
-        NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err];
-        CWNetwork *apNetwork;
-        if(!err) {
-            for(uint row=0; row < [apArray count]; row++ ) {
-                apNetwork = [apArray objectAtIndex:row];
-
-                QString networkSsid = nsstringToQString([apNetwork ssid]);
-
-                QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
-                cpPriv->name = networkSsid;
-                cpPriv->isValid = true;
-                cpPriv->id = networkSsid;
-                cpPriv->internet = true;
-                cpPriv->bearer = QLatin1String("WLAN");
-                cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
-                cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName);
-                bool known = isKnownSsid(networkSsid);
-                if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
-                    if( cpPriv->name == nsstringToQString( [currentInterface ssid])) {
-                        cpPriv->state |=  QNetworkConfiguration::Active;
-                    }
-                }
-
-                if(!cpPriv->state) {
-                    if(known) {
-                        cpPriv->state =  QNetworkConfiguration::Discovered;
-                    } else {
-                        cpPriv->state = QNetworkConfiguration::Undefined;
-                    }
-                }
-                if([[apNetwork securityMode ] intValue]== kCWSecurityModeOpen)
-                    cpPriv->purpose = QNetworkConfiguration::PublicPurpose;
-                else
-                    cpPriv->purpose = QNetworkConfiguration::PrivatePurpose;
-
-                foundConfigs.append(cpPriv);
-                addedConfigs << networkSsid;
-
-            } //end scanned row
-        }
-    } //end power
-
-
-    // add known configurations that are not around.
-    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
-    while (i.hasNext()) {
-        i.next();
-        QString networkName = i.key();
-
-        if(!addedConfigs.contains(networkName)) {
-            QString interfaceName;
-            QMapIterator<QString, QString> ij(i.value());
-             while (ij.hasNext()) {
-                 ij.next();
-                 interfaceName = ij.value();
-             }
-
-            QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
-            cpPriv->name = networkName;
-            cpPriv->isValid = true;
-            cpPriv->id = networkName;
-            cpPriv->internet = true;
-            cpPriv->bearer = QLatin1String("WLAN");
-            cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
-            cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(interfaceName);
-            QString ssid = getSsidFromNetworkName(networkName);
-            if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
-                if( ssid == nsstringToQString( [currentInterface ssid])) {
-                    cpPriv->state |=  QNetworkConfiguration::Active;
-                }
-            }
-
-            if( addedConfigs.contains(ssid)) {
-                cpPriv->state |=  QNetworkConfiguration::Discovered;
-            }
-
-            if(!cpPriv->state) {
-                cpPriv->state =  QNetworkConfiguration::Defined;
-            }
-
-            foundConfigs.append(cpPriv);
-        }
-    }
-
-    [autoreleasepool drain];
-#else
-    Q_UNUSED(interfaceName);
-#endif
-    return foundConfigs;
-}
-
 bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
 {
 #if defined(MAC_SDK_10_6)
@@ -598,23 +731,6 @@
     return false;
 }
 
-bool QCoreWlanEngine::isKnownSsid( const QString &ssid)
-{
-#if defined(MAC_SDK_10_6)
-    QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
-    while (i.hasNext()) {
-        i.next();
-        QMap<QString,QString> map = i.value();
-        if(map.keys().contains(ssid)) {
-            return true;
-        }
-    }
-#else
-    Q_UNUSED(ssid);
-#endif
-    return false;
-}
-
 bool QCoreWlanEngine::getAllScInterfaces()
 {
     networkInterfaces.clear();
@@ -665,7 +781,7 @@
                                  networkChangeCallback,
                                  &dynStoreContext);
     if (!storeSession ) {
-        qWarning() << "could not open dynamic store: error:" << SCErrorString(SCError());
+        qDebug() << "could not open dynamic store: error:" << SCErrorString(SCError());
         return;
     }
 
@@ -689,7 +805,7 @@
     CFRelease(storeKey);
 
     if (!SCDynamicStoreSetNotificationKeys(storeSession , notificationKeys, patternsArray)) {
-        qWarning() << "register notification error:"<< SCErrorString(SCError());
+        qDebug() << "register notification error:"<< SCErrorString(SCError());
         CFRelease(storeSession );
         CFRelease(notificationKeys);
         CFRelease(patternsArray);
@@ -700,7 +816,7 @@
 
     runloopSource = SCDynamicStoreCreateRunLoopSource(NULL, storeSession , 0);
     if (!runloopSource) {
-        qWarning() << "runloop source error:"<< SCErrorString(SCError());
+        qDebug() << "runloop source error:"<< SCErrorString(SCError());
         CFRelease(storeSession );
         return;
     }
@@ -708,79 +824,6 @@
     CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode);
     return;
 }
-
-void QCoreWlanEngine::getUserConfigurations()
-{
-#ifdef MAC_SDK_10_6
-    NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
-    userProfiles.clear();
-
-    NSArray *wifiInterfaces = [CWInterface supportedInterfaces];
-    for(uint row=0; row < [wifiInterfaces count]; row++ ) {
-
-        CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]];
-        NSString *nsInterfaceName = [wifiInterface name];
-// add user configured system networks
-        SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
-        NSDictionary *airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName] autorelease]);
-        CFRelease(dynRef);
-
-        NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
-
-        NSArray *thisSsidarray = [prefNetDict valueForKey:@"SSID_STR"];
-        for(NSString *ssidkey in thisSsidarray) {
-            QString thisSsid = nsstringToQString(ssidkey);
-            if(!userProfiles.contains(thisSsid)) {
-                QMap <QString,QString> map;
-                map.insert(thisSsid, nsstringToQString(nsInterfaceName));
-                userProfiles.insert(thisSsid, map);
-            }
-        }
-        CFRelease(airportPlist);
-
-        // 802.1X user profiles
-        QString userProfilePath = QDir::homePath() + "/Library/Preferences/com.apple.eap.profiles.plist";
-        NSDictionary* eapDict = [[NSDictionary alloc] initWithContentsOfFile:qstringToNSString(userProfilePath)];
-        NSString *profileStr= @"Profiles";
-        NSString *nameStr = @"UserDefinedName";
-        NSString *networkSsidStr = @"Wireless Network";
-        for (id profileKey in eapDict) {
-            if ([profileStr isEqualToString:profileKey]) {
-                NSDictionary *itemDict = [eapDict objectForKey:profileKey];
-                for (id itemKey in itemDict) {
-
-                    NSInteger dictSize = [itemKey count];
-                    id objects[dictSize];
-                    id keys[dictSize];
-
-                    [itemKey getObjects:objects andKeys:keys];
-                    QString networkName;
-                    QString ssid;
-                    for(int i = 0; i < dictSize; i++) {
-                        if([nameStr isEqualToString:keys[i]]) {
-                            networkName = nsstringToQString(objects[i]);
-                        }
-                        if([networkSsidStr isEqualToString:keys[i]]) {
-                            ssid = nsstringToQString(objects[i]);
-                        }
-                        if(!userProfiles.contains(networkName)
-                            && !ssid.isEmpty()) {
-                            QMap<QString,QString> map;
-                            map.insert(ssid, nsstringToQString(nsInterfaceName));
-                            userProfiles.insert(networkName, map);
-                        }
-                    }
-                }
-                [itemDict release];
-            }
-        }
-        [eapDict release];
-    }
-    [autoreleasepool release];
-#endif
-
-}
-
 #include "moc_qcorewlanengine_mac_p.cpp"
 
 QTM_END_NAMESPACE
--- a/qtmobility/src/bearer/qcorewlanengine_mac_p.h	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qcorewlanengine_mac_p.h	Wed Jun 09 10:36:00 2010 +0300
@@ -54,17 +54,23 @@
 //
 
 #include "qnetworksessionengine_p.h"
+#include "qnetworkconfiguration.h"
+
 #include <QMap>
 #include <QTimer>
 #include <SystemConfiguration/SystemConfiguration.h>
+#include <QThread>
+#include <QMutex>
 
 QTM_BEGIN_NAMESPACE
 
 class QNetworkConfigurationPrivate;
+class QScanThread;
 
 class QCoreWlanEngine : public QNetworkSessionEngine
 {
     Q_OBJECT
+    friend class QScanThread;
 
 public:
     QCoreWlanEngine(QObject *parent = 0);
@@ -82,30 +88,62 @@
     void requestUpdate();
 
     static QCoreWlanEngine *instance();
-    static bool getAllScInterfaces();
+    QString interfaceName;
 
 private:
     bool isWifiReady(const QString &dev);
-    QMap<uint, QString> configurationInterface;
     QTimer pollTimer;
-    QList<QNetworkConfigurationPrivate *> scanForSsids(const QString &interfaceName);
-
-    bool isKnownSsid(const QString &ssid);
     QList<QNetworkConfigurationPrivate *> foundConfigurations;
 
     SCDynamicStoreRef storeSession;
     CFRunLoopSourceRef runloopSource;
     bool hasWifi;
+    QScanThread *scanThread;
+    QMutex mutex;
+    static bool getAllScInterfaces();
+
+private Q_SLOTS:
+    void init();
 
 protected:
-   QMap<QString, QMap<QString,QString> > userProfiles;
+    void startNetworkChangeLoop();
+};
+
+class QScanThread : public QThread
+{
+    Q_OBJECT
 
-    void startNetworkChangeLoop();
-    void getUserConfigurations();
+public:
+    QScanThread(QObject *parent = 0);
+    ~QScanThread();
+
+    void quit();
+    QList<QNetworkConfigurationPrivate *> getConfigurations();
+    QString interfaceName;
+    QMap<QString, QString> configurationInterface;
+    void getUserProfiles();
     QString getNetworkNameFromSsid(const QString &ssid);
     QString getSsidFromNetworkName(const QString &name);
+    bool isKnownSsid(const QString &ssid);
+    QMap<QString, QMap<QString,QString> > userProfiles;
+
+signals:
+    void networksChanged();
+
+protected:
+    void run();
+
+private:
+    QList<QNetworkConfigurationPrivate *> fetchedConfigurations;
+    QMutex mutex;
+    QStringList foundNetwork(const QString &id, const QString &ssid,
+                             const QNetworkConfiguration::StateFlags state,
+                             const QString &interfaceName,
+                             const QNetworkConfiguration::Purpose purpose);
+
 };
 
+
 QTM_END_NAMESPACE
 
 #endif
--- a/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp	Wed Jun 09 10:36:00 2010 +0300
@@ -44,14 +44,13 @@
 #include <commdb.h>
 #include <cdbcols.h>
 #include <d32dbms.h>
-#include <QEventLoop>
+#include <nifvar.h>
 #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
 
@@ -70,19 +69,20 @@
 
 QTM_BEGIN_NAMESPACE
 
-static const int KValueThatWillBeAddedToSNAPId = 1000;
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+    static const int KValueThatWillBeAddedToSNAPId = 1000;
+#endif
 static const int KUserChoiceIAPId = 0;
 
 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
     : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0),
-    iFirstUpdate(true), iInitOk(true), iIgnoringUpdates(false),
-    iTimeToWait(0), iIgnoreEventLoop(0)
+    iFirstUpdate(true), iInitOk(true), iUpdatePending(false),
+    iTimeToWait(0)
 {
     CActiveScheduler::Add(this);
 
     // Seed the randomgenerator
     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
-    iIgnoreEventLoop = new QEventLoop(this);
 
     registerPlatformCapabilities();
     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
@@ -165,6 +165,25 @@
     delete cleanup;
 }
 
+void QNetworkConfigurationManagerPrivate::delayedConfigurationUpdate()
+{
+    if (iUpdatePending) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug("QNCM delayed configuration update (ECommit or ERecover occurred).");
+#endif
+        TRAPD(error, updateConfigurationsL());
+        if (error == KErrNone) {
+            updateStatesToSnaps();
+        }
+        iUpdatePending = false;
+        // Start monitoring again.
+        if (!IsActive()) {
+            SetActive();
+            // Start waiting for new notification
+            ipCommsDB->RequestNotification(iStatus);
+        }
+    }
+}
 
 void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities()
 {
@@ -229,7 +248,11 @@
                 if (!iFirstUpdate) {
                     QNetworkConfiguration item;
                     item.d = ptr;
-                    emit configurationAdded(item);
+                    // Emit configuration added. Connected slots may throw execptions
+                    // which propagate here --> must be converted to leaves (standard
+                    // std::exception would cause any TRAP trapping this function to terminate
+                    // program).
+                    QT_TRYCATCH_LEAVING(emit configurationAdded(item));
                 }
             }
         }
@@ -250,10 +273,9 @@
             knownSnapConfigs.removeOne(ident);
         } else {
             QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
-            CleanupStack::PushL(cpPriv);
     
             HBufC *pName = destination.NameLC();
-            cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
+            QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
             CleanupStack::PopAndDestroy(pName);
             pName = NULL;
     
@@ -272,10 +294,8 @@
             if (!iFirstUpdate) {
                 QNetworkConfiguration item;
                 item.d = ptr;
-                emit configurationAdded(item);
+                QT_TRYCATCH_LEAVING(emit configurationAdded(item));
             }
-            
-            CleanupStack::Pop(cpPriv);
         }
         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> privSNAP = snapConfigurations.value(ident);
             
@@ -297,7 +317,7 @@
                     if (!iFirstUpdate) {
                         QNetworkConfiguration item;
                         item.d = ptr;
-                        emit configurationAdded(item);
+                        QT_TRYCATCH_LEAVING(emit configurationAdded(item));
                     }
                     privSNAP->serviceNetworkMembers.append(ptr);
                 }
@@ -349,7 +369,7 @@
                 if (!iFirstUpdate) {
                     QNetworkConfiguration item;
                     item.d = ptr;
-                    emit configurationAdded(item);
+                    QT_TRYCATCH_LEAVING(emit configurationAdded(item));
                 }
             } else {
                 delete cpPriv;
@@ -359,7 +379,7 @@
     }
     CleanupStack::PopAndDestroy(pDbTView);
 #endif
-    updateActiveAccessPoints();
+    QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
     
     foreach (const QString &oldIface, knownConfigs) {
         //remove non existing IAP
@@ -368,7 +388,7 @@
         if (!iFirstUpdate) {
             QNetworkConfiguration item;
             item.d = priv;
-            emit configurationRemoved(item);
+            QT_TRYCATCH_LEAVING(emit configurationRemoved(item));
         }
         // Remove non existing IAP from SNAPs
         foreach (const QString &iface, snapConfigurations.keys()) {
@@ -389,7 +409,7 @@
         if (!iFirstUpdate) {
             QNetworkConfiguration item;
             item.d = priv;
-            emit configurationRemoved(item);
+            QT_TRYCATCH_LEAVING(emit configurationRemoved(item));
         }
     }
 }
@@ -399,14 +419,12 @@
         RCmConnectionMethod& connectionMethod)
 {
     QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
-    CleanupStack::PushL(cpPriv);
-    
     TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
     QString ident = QString::number(qHash(iapId));
     
     HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
     CleanupStack::PushL(pName);
-    cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
+    QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
     CleanupStack::PopAndDestroy(pName);
     pName = NULL;
     
@@ -454,7 +472,7 @@
 
     if (error == KErrNone && pName) {
         CleanupStack::PushL(pName);
-        cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length());
+        QT_TRYCATCH_LEAVING(cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length()));
         CleanupStack::PopAndDestroy(pName);
         pName = NULL;
     }
@@ -473,8 +491,6 @@
     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
     cpPriv->roamingSupported = false;
     cpPriv->manager = this;
-    
-    CleanupStack::Pop(cpPriv);
     return cpPriv;
 }
 #else
@@ -507,7 +523,7 @@
     
     QString ident = QString::number(qHash(aApId));
     
-    apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length());
+    QT_TRYCATCH_LEAVING(apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length()));
     apNetworkConfiguration->isValid = true;
     apNetworkConfiguration->id = ident;
     apNetworkConfiguration->numericId = aApId;
@@ -607,10 +623,14 @@
     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);
@@ -619,11 +639,15 @@
             QString ident = QString::number(qHash(apId));
             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
             if (priv.data()) {
-                online = true;
-                inactiveConfigs.removeOne(ident);
-                priv.data()->connectionId = connectionId;
-                // Configuration is Active
-                changeConfigurationStateTo(priv, QNetworkConfiguration::Active);
+                iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
+                User::WaitForRequest(status);          
+                if (connectionStatus == KLinkLayerOpen) {
+                    online = true;
+                    inactiveConfigs.removeOne(ident);
+                    priv.data()->connectionId = connectionId;
+                    // Configuration is Active
+                    changeConfigurationStateTo(priv, QNetworkConfiguration::Active);
+                }
             }
         }
     }
@@ -674,12 +698,12 @@
             }
         }
         
-        // 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) {
             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
             if (priv.data()) {
                 // Configuration is Defined
-                changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
+                changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered);
             }
         }
     }
@@ -807,47 +831,26 @@
 
 void QNetworkConfigurationManagerPrivate::RunL()
 {
-    if (iIgnoringUpdates) {
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
-        qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
+    if (iStatus != KErrCancel) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
 #endif
-        return;
-    }
-    if (iStatus != KErrCancel) {
+        // By default, start relistening notifications. Stop only if interesting event occured.
+        iWaitingCommsDatabaseNotifications = true;
         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());
-#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();
-                }   
+            // Mark that there is update pending. No need to ask more events,
+            // as we know we will be updating anyway when the timer expires.
+            if (!iUpdatePending) {
+                iUpdatePending = true;
+                iWaitingCommsDatabaseNotifications = false;
+                // Update after random time, so that many processes won't
+                // start updating simultaneously
+                updateConfigurationsAfterRandomTime();
             }
-            iIgnoringUpdates = false; // Wait time done, allow updating again
-            iWaitingCommsDatabaseNotifications = true;
-            break;
+            break;           
         default:
             // Do nothing
             break;
@@ -867,64 +870,91 @@
     ipCommsDB->CancelRequestNotification();
 }
 
-
 void QNetworkConfigurationManagerPrivate::EventL(const CConnMonEventBase& aEvent)
 {
     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));
-        QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
-        if (priv.data()) {
-            priv.data()->connectionId = connectionId;
-            // Configuration is Active
-            if (changeConfigurationStateTo(priv, QNetworkConfiguration::Active)) {
-                updateStatesToSnaps();
+        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));
+            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
+            if (priv.data()) {
+                priv.data()->connectionId = connectionId;
+                QT_TRYCATCH_LEAVING(emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Connecting));
             }
-            if (!iOnline) {
-                iOnline = true;
-                emit this->onlineStateChanged(iOnline);
+        } 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));
+            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
+            if (priv.data()) {
+                priv.data()->connectionId = connectionId;
+                // Configuration is Active
+                QT_TRYCATCH_LEAVING(
+                    if (changeConfigurationStateTo(priv, QNetworkConfiguration::Active)) {
+                        updateStatesToSnaps();
+                    }
+                    emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Connected);
+                    if (!iOnline) {
+                        iOnline = true;
+                        emit this->onlineStateChanged(iOnline);
+                    }
+                );
+            }
+        } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
+            TUint connectionId = realEvent->ConnectionId();
+            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = dataByConnectionId(connectionId);
+            if (priv.data()) {
+                QT_TRYCATCH_LEAVING(emit this->configurationStateChanged(priv.data()->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();
+            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = dataByConnectionId(connectionId);
+            if (priv.data()) {
+                // Configuration is either Defined or Discovered
+                QT_TRYCATCH_LEAVING(
+                    if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) {
+                        updateStatesToSnaps();
+                    }
+                    emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Disconnected);
+                );
+            }
+            
+            bool online = false;
+            foreach (const QString &iface, accessPointConfigurations.keys()) {
+                QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
+                if (priv.data()->state == QNetworkConfiguration::Active) {
+                    online = true;
+                    break;
+                }
+            }
+            if (iOnline != online) {
+                iOnline = online;
+                QT_TRYCATCH_LEAVING(emit this->onlineStateChanged(iOnline));
             }
         }
         }
-        break;
-
-    case EConnMonDeleteConnection:
-        {
-        CConnMonDeleteConnection* realEvent;
-        realEvent = (CConnMonDeleteConnection*) &aEvent;
-        TUint connectionId = realEvent->ConnectionId();
-        QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = dataByConnectionId(connectionId);
-        if (priv.data()) {
-            priv.data()->connectionId = 0;
-            // Configuration is either Defined or Discovered
-            if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) {
-                updateStatesToSnaps();
-            }
-        }
-        
-        bool online = false;
-        foreach (const QString &iface, accessPointConfigurations.keys()) {
-            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
-            if (priv.data()->state == QNetworkConfiguration::Active) {
-                online = true;
-                break;
-            }
-        }
-        if (iOnline != online) {
-            iOnline = online;
-            emit this->onlineStateChanged(iOnline);
-        }
-        }
-        break;
+        break;    
 
     case EConnMonIapAvailabilityChange:
         {
@@ -937,7 +967,7 @@
             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
             if (priv.data()) {
                 // Configuration is either Discovered or Active 
-                changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered);
+                QT_TRYCATCH_LEAVING(changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered));
                 unDiscoveredConfigs.removeOne(ident);
             }
         }
@@ -945,36 +975,87 @@
             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
             if (priv.data()) {
                 // Configuration is Defined
-                changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
+                QT_TRYCATCH_LEAVING(changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined));
             }
         }
         }
         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));
+        QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
+        if (priv.data()) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+            qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << priv.data()->connectionId << connectionId << priv->name;
+#endif
+            priv.data()->connectionId = connectionId;
+        }
+        }
+        break;
     default:
         // For unrecognized events
         break;
     }
 }
 
-// Waits for 1..4 seconds.
-void QNetworkConfigurationManagerPrivate::waitRandomTime()
+// 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 QNetworkConfigurationManagerPrivate::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
 {
-    iTimeToWait = (qAbs(qrand()) % 5) * 1000;
+#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));
+            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(ident);
+            if (priv.data()) {
+                // Configuration is either Defined or Discovered
+                if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) {
+                    updateStatesToSnaps();
+                }
+                emit this->configurationStateChanged(
+                        priv.data()->numericId, priv.data()->connectionId, QNetworkSession::Disconnected);
+            }
+        }
+        break;
+    default:
+        break;
+    }
+}
+
+// Waits for 2..6 seconds.
+void QNetworkConfigurationManagerPrivate::updateConfigurationsAfterRandomTime()
+{
+    iTimeToWait = (qAbs(qrand()) % 68) * 100;
     if (iTimeToWait < 1000) {
         iTimeToWait = 1000;
     }
-#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();
+    QTimer::singleShot(iTimeToWait, this, SLOT(delayedConfigurationUpdate()));
 }
 
 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
 {
     QNetworkConfiguration item;
-    
     QHash<QString, QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> >::const_iterator i =
             accessPointConfigurations.constBegin();
     while (i != accessPointConfigurations.constEnd()) {
@@ -990,7 +1071,7 @@
 
 AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(QNetworkConfigurationManagerPrivate& owner,
                                                                RConnectionMonitor& connectionMonitor)
-    : CActive(CActive::EPriorityStandard), iOwner(owner), iConnectionMonitor(connectionMonitor)
+    : CActive(CActive::EPriorityHigh), iOwner(owner), iConnectionMonitor(connectionMonitor)
 {
     CActiveScheduler::Add(this);  
 }
@@ -1028,9 +1109,9 @@
 {
     if (iStatus.Int() != KErrNone) {
         iIapBuf().iCount = 0;
-        iOwner.accessPointScanningReady(false,iIapBuf());
+        QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(false,iIapBuf()));
     } else {
-        iOwner.accessPointScanningReady(true,iIapBuf());
+        QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(true,iIapBuf()));
     }
 }
 #include "moc_qnetworkconfigmanager_s60_p.cpp"
--- a/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.h	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.h	Wed Jun 09 10:36:00 2010 +0300
@@ -55,6 +55,7 @@
 
 #include <qnetworkconfigmanager.h>
 #include <qnetworkconfiguration_s60_p.h>
+#include <qnetworksession.h>
 
 #include <QHash>
 #include <rconnmon.h>
@@ -62,6 +63,9 @@
     #include <cmmanager.h>
 #endif
 
+// Uncomment and compile QtBearer to gain detailed state tracing
+// #define QT_BEARERMGMT_SYMBIAN_DEBUG
+
 class CCommsDatabase;
 class QEventLoop;
 
@@ -92,8 +96,12 @@
     void configurationChanged(const QNetworkConfiguration& config);
     void onlineStateChanged(bool isOnline);
     
+    void configurationStateChanged(TUint32 accessPointId, TUint32 connMonId,
+                                   QNetworkSession::State newState);
+    
 public Q_SLOTS:
     void updateConfigurations();
+    void delayedConfigurationUpdate();
 
 private:
     void registerPlatformCapabilities();
@@ -119,19 +127,24 @@
     void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo);
     void startCommsDatabaseNotifications();
     void stopCommsDatabaseNotifications();
-    void waitRandomTime();
+    void updateConfigurationsAfterRandomTime();
 
     QNetworkConfiguration defaultConfigurationL();
     TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const;
     void startMonitoringIAPData(TUint32 aIapId);
     QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> 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);
 
 public: // Data
     //this table contains an up to date list of all configs at any time.
@@ -151,9 +164,8 @@
     TBool              iOnline;
     TBool              iInitOk;
     TBool              iUpdateGoingOn;
-    TBool              iIgnoringUpdates;
+    TBool              iUpdatePending;
     TUint              iTimeToWait;
-    QEventLoop*        iIgnoreEventLoop;
 
     AccessPointsAvailabilityScanner* ipAccessPointsAvailabilityScanner;
     
--- a/qtmobility/src/bearer/qnetworkconfiguration_s60_p.h	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qnetworkconfiguration_s60_p.h	Wed Jun 09 10:36:00 2010 +0300
@@ -88,7 +88,18 @@
 
     QNetworkConfigurationPrivate::Bearer bearer;
     QString bearerName() const;
+    // 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;
     
     TAny* manager;
--- a/qtmobility/src/bearer/qnetworksession_s60_p.cpp	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qnetworksession_s60_p.cpp	Wed Jun 09 10:36:00 2010 +0300
@@ -52,15 +52,17 @@
 QTM_BEGIN_NAMESPACE
 
 QNetworkSessionPrivate::QNetworkSessionPrivate()
-    : CActive(CActive::EPriorityStandard), state(QNetworkSession::Invalid),
-      isOpen(false), ipConnectionNotifier(0), iError(QNetworkSession::UnknownSessionError),
-      iALREnabled(0), iConnectInBackground(false)
+    : CActive(CActive::EPriorityUserInput), state(QNetworkSession::Invalid),
+      isOpen(false), 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());
 }
 
@@ -89,9 +91,43 @@
     
     // Close global 'Open C' RConnection
     setdefaultif(0);
+    
+    iConnectionMonitor.Close();
+}
 
-    iConnectionMonitor.CancelNotifications();
-    iConnectionMonitor.Close();
+void QNetworkSessionPrivate::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 QNetworkSessionPrivate::configurationRemoved(const QNetworkConfiguration& config)
+{
+    if (!publicConfig.d.data()) {
+        return;
+    }
+    if (config.d.data()->numericId == publicConfig.d.data()->numericId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+                 << "configurationRemoved IAP: " << QString::number(publicConfig.d.data()->numericId) << " : going to State: Invalid";
+#endif
+        this->newState(QNetworkSession::Invalid, publicConfig.d.data()->numericId);
+    }
 }
 
 void QNetworkSessionPrivate::syncStateWithInterface()
@@ -100,8 +136,17 @@
         return;
     }
 
-    // Start monitoring changes in IAP states
-    TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+    if (iFirstSync && publicConfig.d.data()) {
+        QObject::connect(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager), 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(((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager),
+                         SIGNAL(configurationRemoved(QNetworkConfiguration)),
+                         this, SLOT(configurationRemoved(QNetworkConfiguration)));
+    }
+    // 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 +182,7 @@
     }
 
     if (state != QNetworkSession::Connected) {
-        // There were no open connections to used IAP or SNAP
-        if (iError == QNetworkSession::InvalidConfigurationError) {
-            newState(QNetworkSession::Invalid);
-        }
-        else if ((publicConfig.d.data()->state & QNetworkConfiguration::Discovered) ==
+        if ((publicConfig.d.data()->state & QNetworkConfiguration::Discovered) ==
             QNetworkConfiguration::Discovered) {
             newState(QNetworkSession::Disconnected);
         } else {
@@ -242,13 +283,18 @@
 
 void QNetworkSessionPrivate::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).
@@ -256,19 +302,25 @@
         newState(QNetworkSession::Invalid);
         iError = QNetworkSession::InvalidConfigurationError;
         emit q->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 q->error(iError);
         return;
     }
-    
+    // Clear possible previous states
+    iStoppedByUser = false;
+    iClosedByUser = false;
+    iDeprecatedConnectionId = 0;
+
     TInt error = iSocketServ.Connect();
     if (error != KErrNone) {
         // Could not open RSocketServ
@@ -420,11 +472,19 @@
 
 void QNetworkSessionPrivate::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;
 
-    TUint activeIap = activeConfig.d.data()->numericId;
     isOpen = false;
     activeConfig = QNetworkConfiguration();
     serviceConfig = QNetworkConfiguration();
@@ -437,8 +497,10 @@
     }
 #endif
 
-    if (ipConnectionNotifier) {
+    if (ipConnectionNotifier && !iHandleStateNotificationsFromManager) {
         ipConnectionNotifier->StopNotifications();
+        // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+        iHandleStateNotificationsFromManager = true;
     }
     
     iConnection.Close();
@@ -447,29 +509,31 @@
     // Close global 'Open C' RConnection
     setdefaultif(0);
 
-#ifdef Q_CC_NOKIAX86
-    if ((allowSignals && iapClientCount(activeIap) <= 0) ||
-#else
-    if ((allowSignals && iapClientCount(activeIap) <= 1) ||
-#endif
-        (publicConfig.type() == QNetworkConfiguration::UserChoice)) {
+    if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
         newState(QNetworkSession::Closing);
+        newState(QNetworkSession::Disconnected);
     }
     
-    syncStateWithInterface();
     if (allowSignals) {
-        if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
-            newState(QNetworkSession::Disconnected);
-        }
         emit q->closed();
     }
 }
 
 void QNetworkSessionPrivate::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,
@@ -483,7 +547,7 @@
         }
         TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f
         TUint connectionId;
-        for (TInt i = 1; i <= count; ++i) {
+        for (TUint i = 1; i <= count; ++i) {
             // Get (connection monitor's assigned) connection ID
             TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);            
             if (ret == KErrNone) {
@@ -495,11 +559,25 @@
                                                               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);
@@ -592,7 +670,15 @@
         QList<QNetworkConfiguration> configs = publicConfig.children();
         for (int i=0; i < configs.count(); i++) {
             if (configs[i].d.data()->numericId == aNewAPInfo.AccessPoint()) {
-                emit q->preferredConfigurationChanged(configs[i],aIsSeamless);
+                // Any slot connected to the signal might throw an std::exception,
+                // which must not propagate into Symbian code (this function is a callback
+                // from platform). We could convert exception to a symbian Leave, but since the
+                // prototype of this function bans this (no trailing 'L'), we just catch
+                // and drop.
+                QT_TRY {
+                    emit q->preferredConfigurationChanged(configs[i],aIsSeamless);
+                }
+                QT_CATCH (std::exception&) {}
             }
         }
     } else {
@@ -603,7 +689,10 @@
 void QNetworkSessionPrivate::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*/, TBool /*aIsSeamless*/)
 {
     if (iALREnabled > 0) {
-        emit q->newConfigurationActivated();
+        QT_TRY {
+            emit q->newConfigurationActivated();
+        }
+        QT_CATCH (std::exception&) {}
     } else {
         accept();
     }
@@ -611,6 +700,10 @@
 
 void QNetworkSessionPrivate::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();
@@ -621,13 +714,24 @@
         if (ipConnectionNotifier) {
             ipConnectionNotifier->StopNotifications();
         }
-        syncStateWithInterface();
-        // In some cases IAP is still in Connected state when
-        // syncStateWithInterface(); is called
-        // => Following call makes sure that Session state
-        //    changes immediately to Disconnected.
-        newState(QNetworkSession::Disconnected);
-        emit q->closed();
+        QT_TRY {
+            syncStateWithInterface();
+            // In some cases IAP is still in Connected state when
+            // syncStateWithInterface(); is called
+            // => Following call makes sure that Session state
+            //    changes immediately to Disconnected.
+            newState(QNetworkSession::Disconnected);
+            emit q->closed();
+        }
+        QT_CATCH (std::exception&) {}
+    } 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.
+        QT_TRY {
+            newState(QNetworkSession::Disconnected);
+        }
+        QT_CATCH (std::exception&) {}
     }
 }
 #endif
@@ -854,12 +958,12 @@
             if (error != KErrNone) {
                 isOpen = false;
                 iError = QNetworkSession::UnknownSessionError;
-                emit q->error(iError);
+                QT_TRYCATCH_LEAVING(emit q->error(iError));
                 Cancel();
                 if (ipConnectionNotifier) {
                     ipConnectionNotifier->StopNotifications();
                 }
-                syncStateWithInterface();
+                QT_TRYCATCH_LEAVING(syncStateWithInterface());
                 return;
             }
  
@@ -880,8 +984,10 @@
             
             startTime = QDateTime::currentDateTime();
 
-            newState(QNetworkSession::Connected);
-            emit quitPendingWaitsForOpened();
+            QT_TRYCATCH_LEAVING({
+                    newState(QNetworkSession::Connected);
+                    emit quitPendingWaitsForOpened();
+                });
             }
             break;
         case KErrNotFound: // Connection failed
@@ -889,12 +995,12 @@
             activeConfig = QNetworkConfiguration();
             serviceConfig = QNetworkConfiguration();
             iError = QNetworkSession::InvalidConfigurationError;
-            emit q->error(iError);
+            QT_TRYCATCH_LEAVING(emit q->error(iError));
             Cancel();
             if (ipConnectionNotifier) {
                 ipConnectionNotifier->StopNotifications();
             }
-            syncStateWithInterface();
+            QT_TRYCATCH_LEAVING(syncStateWithInterface());
             break;
         case KErrCancel: // Connection attempt cancelled
         case KErrAlreadyExists: // Connection already exists
@@ -902,13 +1008,18 @@
             isOpen = false;
             activeConfig = QNetworkConfiguration();
             serviceConfig = QNetworkConfiguration();
-            iError = QNetworkSession::UnknownSessionError;
-            emit q->error(iError);
+            if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+                publicConfig.state() == QNetworkConfiguration::Defined) {
+                iError = QNetworkSession::InvalidConfigurationError;
+            } else {
+                iError = QNetworkSession::UnknownSessionError;
+            }
+            QT_TRYCATCH_LEAVING(emit q->error(iError));
             Cancel();
             if (ipConnectionNotifier) {
                 ipConnectionNotifier->StopNotifications();
             }
-            syncStateWithInterface();
+            QT_TRYCATCH_LEAVING(syncStateWithInterface());
             break;
     }
 }
@@ -918,8 +1029,16 @@
     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 QNetworkSessionPrivate::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 &&
@@ -937,9 +1056,29 @@
     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
@@ -953,26 +1092,35 @@
         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 q->stateChanged(state);
         retVal = true;
     } else {
         if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
             if (publicConfig.d.data()->numericId == accessPointId) {
                 state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed B to: " << state;
+#endif
                 emit q->stateChanged(state);
                 retVal = true;
             }
         } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isOpen) {
             if (activeConfig.d.data()->numericId == accessPointId) {
                 state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed C to: " << state;
+#endif
                 emit q->stateChanged(state);
                 retVal = true;
             }
@@ -980,26 +1128,33 @@
             QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
             for (int i = 0; i < subConfigurations.count(); i++) {
                 if (subConfigurations[i].d.data()->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.
-                        subConfigurations[i].d.data()->state = QNetworkConfiguration::Active;
-    
+                    if (newState != QNetworkSession::Disconnected) {
                         state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                        qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D  to: " << state;
+#endif
                         emit q->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.
-                            subConfigurations[i].d.data()->state = QNetworkConfiguration::Defined;
-                        }
                         QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
                         if ((config.state() == QNetworkConfiguration::Defined) ||
                             (config.state() == QNetworkConfiguration::Discovered)) {
                             state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                            qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E  to: " << state;
+#endif
                             emit q->stateChanged(state);
                             retVal = true;
+                        } else if (config.state() == QNetworkConfiguration::Active) {
+                            // Connection to used IAP was closed, but there is another
+                            // IAP that's active in used SNAP
+                            // => Change state back to Connected
+                            state =  QNetworkSession::Connected;
+                            emit q->stateChanged(state);
+                            retVal = true;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+                            qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed F  to: " << state;
+#endif
                         }
                     }
                 }
@@ -1010,6 +1165,13 @@
     if (emitSessionClosed) {
         emit q->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.
+        iDeprecatedConnectionId = publicConfig.d.data()->connectionId;
+    }
 
     return retVal;
 }
@@ -1018,6 +1180,9 @@
                                                                  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
@@ -1056,6 +1221,7 @@
         case KCsdGotLoginInfo:
             break;
 
+        case KConfigDaemonStartingRegistration:
         // Creating connection (e.g. GPRS activation)
         case KCsdStartingConnect:
         case KCsdFinishedConnect:
@@ -1082,6 +1248,7 @@
         case KDataTransferTemporarilyBlocked:
             break;
 
+        case KConfigDaemonStartingDeregistration:
         // Hangup or GRPS deactivation
         case KConnectionStartingClose:
             newState(QNetworkSession::Closing,accessPointId);
@@ -1089,110 +1256,27 @@
 
         // 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.d.data()) {
+                ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->configurationStateChangeReport(publicConfig.d.data()->numericId, QNetworkSession::Disconnected);
+            }
             break;
-
         // Unhandled state
         default:
             break;
         }
 }
 
-void QNetworkSessionPrivate::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++ ) {
-                    if (subConfigurations[i].d.data()->connectionId == connectionId) {
-                        apId = subConfigurations[i].d.data()->numericId;
-                        break;
-                    }
-                }
-            } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-                if (publicConfig.d.data()->connectionId == connectionId) {
-                    apId = publicConfig.d.data()->numericId;
-                }
-            }
-
-            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++ ) {
-                        if (subConfigurations[i].d.data()->numericId == apId) {
-                            subConfigurations[i].d.data()->connectionId = connectionId;
-                            break;
-                        }
-                    }
-                } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-                    if (publicConfig.d.data()->numericId == apId) {
-                        publicConfig.d.data()->connectionId = connectionId;
-                    }
-                }
-            }
-            }
-            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++ ) {
-                    if (subConfigurations[i].d.data()->connectionId == connectionId) {
-                        subConfigurations[i].d.data()->connectionId = 0;
-                        break;
-                    }
-                }
-            } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
-                if (publicConfig.d.data()->connectionId == connectionId) {
-                    publicConfig.d.data()->connectionId = 0;
-                }
-            }
-            }
-            break;
-
-        default:
-            // For unrecognized events
-            break;
-    }
-}
-
 ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivate& owner, RConnection& connection)
-    : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection)
+    : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection)
 {
     CActiveScheduler::Add(this);
 }
@@ -1223,7 +1307,7 @@
 void ConnectionProgressNotifier::RunL()
 {
     if (iStatus == KErrNone) {
-        iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError);
+        QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError));
     
         SetActive();
         iConnection.ProgressNotification(iProgress, iStatus);
--- a/qtmobility/src/bearer/qnetworksession_s60_p.h	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/src/bearer/qnetworksession_s60_p.h	Wed Jun 09 10:36:00 2010 +0300
@@ -72,11 +72,10 @@
 
 class ConnectionProgressNotifier;
 
-class QNetworkSessionPrivate : public QObject, public CActive,
+class QNetworkSessionPrivate : public QObject, public CActive
 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
-                               public MMobilityProtocolResp,
+                               , public MMobilityProtocolResp
 #endif
-                               public MConnectionMonitorObserver
 {
     Q_OBJECT
 public:
@@ -129,8 +128,9 @@
     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(const QNetworkConfiguration& config);
     
 private:
     TUint iapClientCount(TUint aIAPId) const;
@@ -166,6 +166,13 @@
     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    
--- a/qtmobility/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp	Wed Jun 09 10:36:00 2010 +0300
@@ -44,6 +44,13 @@
 #include "../../../src/bearer/qnetworkconfiguration.h"
 #include "../../../src/bearer/qnetworkconfigmanager.h"
 
+/*
+  Although this unit test doesn't use QNetworkAccessManager
+  this include is used to ensure that bearer continues to compile against
+  Qt 4.7+ which has a QNetworkConfiguration enabled QNetworkAccessManager
+*/
+#include <QNetworkAccessManager>
+
 #if defined(Q_WS_MAEMO_6) || defined(Q_WS_MAEMO_5)
 #include <stdio.h>
 #include <iapconf.h>
--- a/qtmobility/tests/auto/qnetworksession/lackey/main.cpp	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/tests/auto/qnetworksession/lackey/main.cpp	Wed Jun 09 10:36:00 2010 +0300
@@ -46,6 +46,8 @@
 #include "../../../../src/bearer/qnetworkconfiguration.h"
 #include "../../../../src/bearer/qnetworksession.h"
 
+#include <QEventLoop>
+#include <QTimer>
 #include <QDebug>
 
 QTM_USE_NAMESPACE
@@ -59,7 +61,14 @@
 {
     QCoreApplication app(argc, argv);
 
+    // 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);
 
@@ -75,7 +84,6 @@
 
     // Cannot read/write to processes on WinCE or Symbian.
     // Easiest alternative is to use sockets for IPC.
-
     QLocalSocket oopSocket;
 
     oopSocket.connectToServer("tst_qnetworksession");
--- a/qtmobility/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp	Tue May 25 13:34:51 2010 +0300
+++ b/qtmobility/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp	Wed Jun 09 10:36:00 2010 +0300
@@ -1,5 +1,5 @@
 /****************************************************************************
-**
+** 
 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
@@ -96,6 +96,7 @@
 
 private:
     QNetworkConfigurationManager manager;
+    QMap<QString, bool> testsToRun;
 
     uint inProcessSessionManagementCount;
 
@@ -113,6 +114,7 @@
 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()
@@ -121,7 +123,19 @@
     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");
@@ -234,6 +248,10 @@
 // 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
@@ -241,15 +259,14 @@
     testSession.accept();
     testSession.ignore();
     testSession.reject();
-    quint64 temp;
-    temp = testSession.bytesWritten();
-    temp = testSession.bytesReceived();
-    temp = testSession.activeTime();
 }
 
 
 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());
@@ -264,11 +281,24 @@
            qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
     QVERIFY(error == QNetworkSession::InvalidConfigurationError);
     QVERIFY(session.state() == QNetworkSession::Invalid);
+    	
+#ifdef QNETWORKSESSION_MANUAL_TESTS
 
-#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);
@@ -277,43 +307,27 @@
         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
 }
 
@@ -331,12 +345,12 @@
 
 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")
@@ -407,7 +421,12 @@
 }
 
 // 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);
@@ -423,13 +442,20 @@
         !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 
@@ -453,41 +479,11 @@
     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
 }
 
 
@@ -502,6 +498,9 @@
 
 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 
@@ -509,6 +508,9 @@
     QFETCH(QNetworkConfiguration::Type, configurationType);
     
     int configWaitdelayInMs = 2000;
+	
+    updateConfigurations();
+    printConfigurations();
     
     QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
     if (!config.isValid()) {
@@ -526,6 +528,9 @@
     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)));
@@ -541,10 +546,18 @@
     closedSessionClosedSpy.clear();
     closedSessionStateChangedSpy.clear();
     closedErrorSpy.clear();
+    openedSessionStateChangedSpy.clear();
+    openedSessionClosedSpy.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
+    
+    // First to closing, then to disconnected
+    QVERIFY(openedSessionStateChangedSpy.count() == 2);
+    QVERIFY(!openedSessionClosedSpy.isEmpty());
     QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
-    QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
     QVERIFY(config.state() != QNetworkConfiguration::Active);
     
     // 2. Verify that stopping a session based on non-connected configuration does nothing
@@ -570,18 +583,20 @@
     // 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());
@@ -601,14 +616,19 @@
     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());
@@ -640,6 +660,9 @@
 
 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);
@@ -669,7 +692,20 @@
 
         session.open();
 
+#if defined(Q_OS_SYMBIAN)
+        // Opening & closing multiple connections in a row sometimes
+        // results hanging of connection opening on Symbian devices
+        // => If first open fails, wait a moment and try again.
+        if (!session.waitForOpened()) {
+            qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****");        
+            session.close();
+            QTest::qWait(5000); // Wait a while before trying to open session again
+            session.open();
+            session.waitForOpened();
+        }
+#else        
         session.waitForOpened();
+#endif        
 
         if (session.isOpen())
             QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
@@ -769,6 +805,9 @@
 
 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);
 
@@ -801,7 +840,20 @@
 
         session.open();
 
+#if defined(Q_OS_SYMBIAN)
+        // Opening & closing multiple connections in a row sometimes
+        // results hanging of connection opening on Symbian devices
+        // => If first open fails, wait a moment and try again.
+        if (!session.waitForOpened()) {
+            qDebug("**** Session open Timeout - Wait 5 seconds and try once again ****");        
+            session.close();
+            QTest::qWait(5000); // Wait a while before trying to open session again
+            session.open();
+            session.waitForOpened();
+        }
+#else        
         session.waitForOpened();
+#endif        
 
         if (session.isOpen())
             QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty());
@@ -875,24 +927,28 @@
         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);
 #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());
+        }
     }
 
     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
@@ -901,15 +957,17 @@
 #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 =
@@ -929,9 +987,12 @@
 
         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);
@@ -975,54 +1036,66 @@
                     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);
+                        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(1).at(0));
-                            if (state == QNetworkSession::Connected) {
-                                roamedSuccessfully = true;
-                                QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
-                            }
+                            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();
                         QNetworkConfiguration config = manager.configurationFromIdentifier(configId); 
                         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());
-                QVERIFY(session.state() == QNetworkSession::Disconnected);
-                QVERIFY(session2.state() == QNetworkSession::Disconnected);
+                QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
             }
 
             QVERIFY(errorSpy2.isEmpty());
@@ -1041,7 +1114,7 @@
         QVERIFY(!session.isOpen());
 #endif
         QVERIFY(!session2.isOpen());
-    } else {
+    } else if (session2.isOpen()) {
         // Test closing the second session.
         {
             int stateChangedCountBeforeClose = stateChangedSpy2.count();
@@ -1138,9 +1211,15 @@
 // at Discovered -state.
 void tst_QNetworkSession::outOfProcessSession()
 {
+    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
@@ -1161,6 +1240,7 @@
     lackey.start("qnetworksessionlackey");
     QVERIFY(lackey.waitForStarted());
 
+
     QVERIFY(oopServer.waitForNewConnection(-1));
     QLocalSocket *oopSocket = oopServer.nextPendingConnection();
 
@@ -1241,6 +1321,7 @@
     // 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) {
@@ -1249,8 +1330,7 @@
     }
     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();
@@ -1287,9 +1367,23 @@
     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)));
@@ -1299,43 +1393,57 @@
     // 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;
     }
-    return true;
+    if (result == false) {
+	    qDebug() << "tst_QNetworkSession::openSession() opening session failed.";
+    } else {
+	    qDebug() << "tst_QNetworkSession::openSession() opening session succeeded.";
+    }
+    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 
@@ -1348,6 +1456,11 @@
         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.");
@@ -1359,38 +1472,48 @@
     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;
 }
 
 QTEST_MAIN(tst_QNetworkSession)