qtmobility/src/bearer/qnetworkconfigmanager_s60_p.cpp
branchRCL_3
changeset 1 5822d84012fb
parent 0 cfcbf08528c4
child 5 4ea83c148e84
equal deleted inserted replaced
0:cfcbf08528c4 1:5822d84012fb
     1 /****************************************************************************
     1 /****************************************************************************
     2 **
     2 **
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
     4 ** All rights reserved.
     4 ** All rights reserved.
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
     6 **
     6 **
     7 ** This file is part of the Qt Mobility Components.
     7 ** This file is part of the Qt Mobility Components.
     8 **
     8 **
    42 #include "qnetworkconfigmanager_s60_p.h"
    42 #include "qnetworkconfigmanager_s60_p.h"
    43 
    43 
    44 #include <commdb.h>
    44 #include <commdb.h>
    45 #include <cdbcols.h>
    45 #include <cdbcols.h>
    46 #include <d32dbms.h>
    46 #include <d32dbms.h>
       
    47 #include <QEventLoop>
       
    48 #include <QTimer>
       
    49 #include <QTime>  // For randgen seeding
       
    50 #include <QtCore> // For randgen seeding
       
    51 
       
    52 // #define QT_BEARERMGMT_CONFIGMGR_DEBUG
       
    53 
       
    54 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
       
    55 #include <QDebug>
       
    56 #endif
    47 
    57 
    48 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
    58 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
    49     #include <cmdestination.h>
    59     #include <cmdestination.h>
    50     #include <cmconnectionmethod.h>
    60     #include <cmconnectionmethod.h>
    51     #include <cmconnectionmethoddef.h>
    61     #include <cmconnectionmethoddef.h>
    62 
    72 
    63 static const int KValueThatWillBeAddedToSNAPId = 1000;
    73 static const int KValueThatWillBeAddedToSNAPId = 1000;
    64 static const int KUserChoiceIAPId = 0;
    74 static const int KUserChoiceIAPId = 0;
    65 
    75 
    66 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
    76 QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
    67     : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0), iFirstUpdate(true), iInitOk(true)
    77     : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0),
       
    78     iFirstUpdate(true), iInitOk(true), iIgnoringUpdates(false),
       
    79     iTimeToWait(0), iIgnoreEventLoop(0)
    68 {
    80 {
    69     CActiveScheduler::Add(this);
    81     CActiveScheduler::Add(this);
       
    82 
       
    83     // Seed the randomgenerator
       
    84     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
       
    85     iIgnoreEventLoop = new QEventLoop(this);
    70 
    86 
    71     registerPlatformCapabilities();
    87     registerPlatformCapabilities();
    72     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
    88     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
    73     if (error != KErrNone) {
    89     if (error != KErrNone) {
    74         iInitOk = false;
    90         iInitOk = false;
    98     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
   114     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
    99     cpPriv->roamingSupported = false;
   115     cpPriv->roamingSupported = false;
   100     cpPriv->manager = this;
   116     cpPriv->manager = this;
   101     QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   117     QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
   102     userChoiceConfigurations.insert(cpPriv->id, ptr);
   118     userChoiceConfigurations.insert(cpPriv->id, ptr);
   103 
       
   104     updateConfigurations();
   119     updateConfigurations();
   105     updateStatesToSnaps();
   120     updateStatesToSnaps();
   106 
       
   107     updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans)
   121     updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans)
   108     
       
   109     // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
   122     // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
   110     startCommsDatabaseNotifications();
   123     startCommsDatabaseNotifications();
   111     iFirstUpdate = false;
   124     iFirstUpdate = false;
   112 }
   125 }
   113 
   126 
   114 QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() 
   127 QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() 
   115 {
   128 {
   116     Cancel();
   129     Cancel();
   117 
   130 
   118     QList<QString> configIdents = snapConfigurations.keys();
   131     foreach (const QString &oldIface, snapConfigurations.keys()) {
   119     foreach(QString oldIface, configIdents) {
       
   120         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
   132         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
   121         priv->isValid = false;
   133         priv->isValid = false;
   122         priv->id.clear();
   134         priv->id.clear();
   123     }
   135     }
   124 
   136 
   125     configIdents = accessPointConfigurations.keys();
   137     foreach (const QString &oldIface, accessPointConfigurations.keys()) {
   126     foreach(QString oldIface, configIdents) {
       
   127         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
   138         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
   128         priv->isValid = false;
   139         priv->isValid = false;
   129         priv->id.clear();
   140         priv->id.clear();
   130     }
   141     }
   131 
   142 
   132     configIdents = userChoiceConfigurations.keys();
   143     foreach (const QString &oldIface, userChoiceConfigurations.keys()) {
   133     foreach(QString oldIface, configIdents) {
       
   134         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = userChoiceConfigurations.take(oldIface);
   144         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = userChoiceConfigurations.take(oldIface);
   135         priv->isValid = false;
   145         priv->isValid = false;
   136         priv->id.clear();
   146         priv->id.clear();
   137         priv->manager = 0;
   147         priv->manager = 0;
   138     }
   148     }
   164 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
   174 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
   165     capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming;
   175     capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming;
   166     capFlags |= QNetworkConfigurationManager::ForcedRoaming;
   176     capFlags |= QNetworkConfigurationManager::ForcedRoaming;
   167 #endif
   177 #endif
   168     capFlags |= QNetworkConfigurationManager::DataStatistics;
   178     capFlags |= QNetworkConfigurationManager::DataStatistics;
       
   179     capFlags |= QNetworkConfigurationManager::NetworkSessionRequired;
   169 }
   180 }
   170 
   181 
   171 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
   182 void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
   172 {
   183 {
   173     if (!iInitOk || iUpdateGoingOn) {
   184     if (!iInitOk || iUpdateGoingOn) {
   191 
   202 
   192 void QNetworkConfigurationManagerPrivate::updateConfigurationsL()
   203 void QNetworkConfigurationManagerPrivate::updateConfigurationsL()
   193 {
   204 {
   194     QList<QString> knownConfigs = accessPointConfigurations.keys();
   205     QList<QString> knownConfigs = accessPointConfigurations.keys();
   195     QList<QString> knownSnapConfigs = snapConfigurations.keys();
   206     QList<QString> knownSnapConfigs = snapConfigurations.keys();
   196     
   207 
   197 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
   208 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
   198     // S60 version is >= Series60 3rd Edition Feature Pack 2
   209     // S60 version is >= Series60 3rd Edition Feature Pack 2
   199     TInt error = KErrNone;
   210     TInt error = KErrNone;
   200     
   211     
   201     // Loop through all IAPs
   212     // Loop through all IAPs
   348     }
   359     }
   349     CleanupStack::PopAndDestroy(pDbTView);
   360     CleanupStack::PopAndDestroy(pDbTView);
   350 #endif
   361 #endif
   351     updateActiveAccessPoints();
   362     updateActiveAccessPoints();
   352     
   363     
   353     foreach (QString oldIface, knownConfigs) {
   364     foreach (const QString &oldIface, knownConfigs) {
   354         //remove non existing IAP
   365         //remove non existing IAP
   355         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
   366         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.take(oldIface);
   356         priv->isValid = false;
   367         priv->isValid = false;
   357         if (!iFirstUpdate) {
   368         if (!iFirstUpdate) {
   358             QNetworkConfiguration item;
   369             QNetworkConfiguration item;
   359             item.d = priv;
   370             item.d = priv;
   360             emit configurationRemoved(item);
   371             emit configurationRemoved(item);
   361         }
   372         }
   362         // Remove non existing IAP from SNAPs
   373         // Remove non existing IAP from SNAPs
   363         QList<QString> snapConfigIdents = snapConfigurations.keys();
   374         foreach (const QString &iface, snapConfigurations.keys()) {
   364         foreach (QString iface, snapConfigIdents) {
       
   365             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface);
   375             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv2 = snapConfigurations.value(iface);
   366             // => Check if one of the IAPs of the SNAP is active
   376             // => Check if one of the IAPs of the SNAP is active
   367             for (int i=0; i<priv2->serviceNetworkMembers.count(); i++) {
   377             for (int i=0; i<priv2->serviceNetworkMembers.count(); i++) {
   368                 if (priv2->serviceNetworkMembers[i]->numericId == priv->numericId) {
   378                 if (priv2->serviceNetworkMembers[i]->numericId == priv->numericId) {
   369                     priv2->serviceNetworkMembers.removeAt(i);
   379                     priv2->serviceNetworkMembers.removeAt(i);
   370                     break;
   380                     break;
   371                 }
   381                 }
   372             }
   382             }
   373         }    
   383         }    
   374     }
   384     }
   375     foreach (QString oldIface, knownSnapConfigs) {
   385     foreach (const QString &oldIface, knownSnapConfigs) {
   376         //remove non existing SNAPs
   386         //remove non existing SNAPs
   377         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
   387         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.take(oldIface);
   378         priv->isValid = false;
   388         priv->isValid = false;
   379         if (!iFirstUpdate) {
   389         if (!iFirstUpdate) {
   380             QNetworkConfiguration item;
   390             QNetworkConfiguration item;
   617             }
   627             }
   618         }
   628         }
   619     }
   629     }
   620 
   630 
   621     // Make sure that state of rest of the IAPs won't be Active
   631     // Make sure that state of rest of the IAPs won't be Active
   622     foreach (QString iface, inactiveConfigs) {
   632     foreach (const QString &iface, inactiveConfigs) {
   623         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   633         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   624         if (priv.data()) {
   634         if (priv.data()) {
   625             // Configuration is either Defined or Discovered
   635             // Configuration is either Defined or Discovered
   626             changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered);
   636             changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered);
   627         }
   637         }
   663                 }
   673                 }
   664             }
   674             }
   665         }
   675         }
   666         
   676         
   667         // Make sure that state of rest of the IAPs won't be Discovered or Active
   677         // Make sure that state of rest of the IAPs won't be Discovered or Active
   668         foreach (QString iface, unavailableConfigs) {
   678         foreach (const QString &iface, unavailableConfigs) {
   669             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   679             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   670             if (priv.data()) {
   680             if (priv.data()) {
   671                 // Configuration is Defined
   681                 // Configuration is Defined
   672                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
   682                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
   673             }
   683             }
   683 }
   693 }
   684 
   694 
   685 void QNetworkConfigurationManagerPrivate::updateStatesToSnaps()
   695 void QNetworkConfigurationManagerPrivate::updateStatesToSnaps()
   686 {
   696 {
   687     // Go through SNAPs and set correct state to SNAPs
   697     // Go through SNAPs and set correct state to SNAPs
   688     QList<QString> snapConfigIdents = snapConfigurations.keys();
   698     foreach (const QString &iface, snapConfigurations.keys()) {
   689     foreach (QString iface, snapConfigIdents) {
       
   690         bool discovered = false;
   699         bool discovered = false;
   691         bool active = false;
   700         bool active = false;
   692         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.value(iface);
   701         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = snapConfigurations.value(iface);
   693         // => Check if one of the IAPs of the SNAP is discovered or active
   702         // => Check if one of the IAPs of the SNAP is discovered or active
   694         //    => If one of IAPs is active, also SNAP is active
   703         //    => If one of IAPs is active, also SNAP is active
   796     }
   805     }
   797 }
   806 }
   798 
   807 
   799 void QNetworkConfigurationManagerPrivate::RunL()
   808 void QNetworkConfigurationManagerPrivate::RunL()
   800 {
   809 {
       
   810     if (iIgnoringUpdates) {
       
   811 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
       
   812         qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
       
   813 #endif
       
   814         return;
       
   815     }
   801     if (iStatus != KErrCancel) {
   816     if (iStatus != KErrCancel) {
   802         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
   817         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
   803         switch (event) {
   818         switch (event) {
   804 //        case RDbNotifier::EUnlock:   /** All read locks have been removed.  */
   819         case RDbNotifier::EUnlock:   /** All read locks have been removed.  */
   805         case RDbNotifier::ECommit:   /** A transaction has been committed.  */ 
   820         case RDbNotifier::ECommit:   /** A transaction has been committed.  */ 
   806         case RDbNotifier::ERollback: /** A transaction has been rolled back */
   821         case RDbNotifier::ERollback: /** A transaction has been rolled back */
   807         case RDbNotifier::ERecover:  /** The database has been recovered    */
   822         case RDbNotifier::ERecover:  /** The database has been recovered    */
   808             // Note that if further database events occur while a client is handling
   823 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
   809             // a request completion, the notifier records the most significant database
   824             qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
   810             // event and this is signalled as soon as the client issues the next
   825 #endif
   811             // RequestNotification() request.
   826             iIgnoringUpdates = true;
   812             // => Stop recording notifications
   827             // Other events than ECommit get lower priority. In practice with those events,
   813             stopCommsDatabaseNotifications();
   828             // we delay_before_updating methods, whereas
   814             TRAPD(error, updateConfigurationsL());
   829             // with ECommit we _update_before_delaying the reaction to next event.
   815             if (error == KErrNone) {
   830             // Few important notes: 1) listening to only ECommit does not seem to be adequate,
   816                 updateStatesToSnaps();
   831             // but updates will be missed. Hence other events are reacted upon too.
   817             }
   832             // 2) RDbNotifier records the most significant event, and that will be returned once
       
   833             // we issue new RequestNotification, and hence updates will not be missed even
       
   834             // when we are 'not reacting to them' for few seconds.
       
   835             if (event == RDbNotifier::ECommit) {
       
   836                 TRAPD(error, updateConfigurationsL());
       
   837                 if (error == KErrNone) {
       
   838                     updateStatesToSnaps();
       
   839                 }
       
   840                 waitRandomTime();
       
   841             } else {
       
   842                 waitRandomTime();
       
   843                 TRAPD(error, updateConfigurationsL());
       
   844                 if (error == KErrNone) {
       
   845                     updateStatesToSnaps();
       
   846                 }   
       
   847             }
       
   848             iIgnoringUpdates = false; // Wait time done, allow updating again
   818             iWaitingCommsDatabaseNotifications = true;
   849             iWaitingCommsDatabaseNotifications = true;
   819             break;
   850             break;
   820         default:
   851         default:
   821             // Do nothing
   852             // Do nothing
   822             break;
   853             break;
   823         }
   854         }
   824     }
   855     }
   825 
       
   826     if (iWaitingCommsDatabaseNotifications) {
   856     if (iWaitingCommsDatabaseNotifications) {
   827         if (!IsActive()) {
   857         if (!IsActive()) {
   828             SetActive();
   858             SetActive();
   829             // Start waiting for new notification
   859             // Start waiting for new notification
   830             ipCommsDB->RequestNotification(iStatus);
   860             ipCommsDB->RequestNotification(iStatus);
   880                 updateStatesToSnaps();
   910                 updateStatesToSnaps();
   881             }
   911             }
   882         }
   912         }
   883         
   913         
   884         bool online = false;
   914         bool online = false;
   885         QList<QString> iapConfigs = accessPointConfigurations.keys();
   915         foreach (const QString &iface, accessPointConfigurations.keys()) {
   886         foreach (QString iface, iapConfigs) {
       
   887             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   916             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   888             if (priv.data()->state == QNetworkConfiguration::Active) {
   917             if (priv.data()->state == QNetworkConfiguration::Active) {
   889                 online = true;
   918                 online = true;
   890                 break;
   919                 break;
   891             }
   920             }
   910                 // Configuration is either Discovered or Active 
   939                 // Configuration is either Discovered or Active 
   911                 changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered);
   940                 changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered);
   912                 unDiscoveredConfigs.removeOne(ident);
   941                 unDiscoveredConfigs.removeOne(ident);
   913             }
   942             }
   914         }
   943         }
   915         foreach (QString iface, unDiscoveredConfigs) {
   944         foreach (const QString &iface, unDiscoveredConfigs) {
   916             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   945             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = accessPointConfigurations.value(iface);
   917             if (priv.data()) {
   946             if (priv.data()) {
   918                 // Configuration is Defined
   947                 // Configuration is Defined
   919                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
   948                 changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined);
   920             }
   949             }
   924 
   953 
   925     default:
   954     default:
   926         // For unrecognized events
   955         // For unrecognized events
   927         break;
   956         break;
   928     }
   957     }
       
   958 }
       
   959 
       
   960 // Waits for 1..4 seconds.
       
   961 void QNetworkConfigurationManagerPrivate::waitRandomTime()
       
   962 {
       
   963     iTimeToWait = (qAbs(qrand()) % 5) * 1000;
       
   964     if (iTimeToWait < 1000) {
       
   965         iTimeToWait = 1000;
       
   966     }
       
   967 #ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
       
   968     qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
       
   969 #endif
       
   970     QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
       
   971     iIgnoreEventLoop->exec();
   929 }
   972 }
   930 
   973 
   931 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
   974 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId)
   932 {
   975 {
   933     QNetworkConfiguration item;
   976     QNetworkConfiguration item;