qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp
changeset 11 06b8e2af4411
parent 4 90517678cc4f
child 14 6fbed849b4f4
--- a/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp	Thu May 27 13:42:11 2010 +0300
+++ b/qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp	Fri Jun 11 14:26:25 2010 +0300
@@ -44,14 +44,14 @@
 #include <commdb.h>
 #include <cdbcols.h>
 #include <d32dbms.h>
+#include <nifvar.h>
 #include <QEventLoop>
 #include <QTimer>
 #include <QTime>  // For randgen seeding
 #include <QtCore> // For randgen seeding
 
-// #define QT_BEARERMGMT_CONFIGMGR_DEBUG
 
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
 #include <QDebug>
 #endif
 
@@ -70,7 +70,9 @@
 
 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()
@@ -607,10 +609,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 +625,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 +684,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);
             }
         }
     }
@@ -808,20 +818,21 @@
 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).");
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+        qDebug("QNCM CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
 #endif
         return;
     }
     if (iStatus != KErrCancel) {
         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
+
         switch (event) {
         case RDbNotifier::EUnlock:   /** All read locks have been removed.  */
         case RDbNotifier::ECommit:   /** A transaction has been committed.  */ 
         case RDbNotifier::ERollback: /** A transaction has been rolled back */
         case RDbNotifier::ERecover:  /** The database has been recovered    */
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
-            qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+            qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
 #endif
             iIgnoringUpdates = true;
             // Other events than ECommit get lower priority. In practice with those events,
@@ -867,64 +878,87 @@
     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;
+                emit this->configurationStateChanged(priv.data()->numericId, connectionId, QNetworkSession::Connecting);
             }
-            if (!iOnline) {
-                iOnline = true;
+        } 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
+                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()) {
+                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
+                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;
                 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:
         {
@@ -951,21 +985,74 @@
         }
         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.
+// 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)
+{
+#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::waitRandomTime()
 {
-    iTimeToWait = (qAbs(qrand()) % 5) * 1000;
-    if (iTimeToWait < 1000) {
-        iTimeToWait = 1000;
+    iTimeToWait = (qAbs(qrand()) % 7) * 1000;
+    if (iTimeToWait < 2000) {
+        iTimeToWait = 2000;
     }
-#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
-    qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+    qDebug("QNCM waiting random time: %d ms", iTimeToWait);
 #endif
     QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
     iIgnoreEventLoop->exec();
@@ -974,7 +1061,6 @@
 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
 {
     QNetworkConfiguration item;
-    
     QHash<QString, QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> >::const_iterator i =
             accessPointConfigurations.constBegin();
     while (i != accessPointConfigurations.constEnd()) {