src/plugins/bearer/symbian/symbianengine.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the plugins of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "symbianengine.h"
       
    43 #include "qnetworksession_impl.h"
       
    44 
       
    45 #include <commdb.h>
       
    46 #include <cdbcols.h>
       
    47 #include <d32dbms.h>
       
    48 #include <nifvar.h>
       
    49 #include <QEventLoop>
       
    50 #include <QTimer>
       
    51 #include <QTime>  // For randgen seeding
       
    52 #include <QtCore> // For randgen seeding
       
    53 
       
    54 
       
    55 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
    56 #include <QDebug>
       
    57 #endif
       
    58 
       
    59 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
    60     #include <cmdestination.h>
       
    61     #include <cmconnectionmethod.h>
       
    62     #include <cmconnectionmethoddef.h>
       
    63     #include <cmpluginwlandef.h>
       
    64     #include <cmpluginpacketdatadef.h>
       
    65     #include <cmplugindialcommondefs.h>
       
    66 #else
       
    67     #include <apaccesspointitem.h>
       
    68     #include <apdatahandler.h>
       
    69     #include <aputils.h> 
       
    70 #endif
       
    71 
       
    72 #ifndef QT_NO_BEARERMANAGEMENT
       
    73 
       
    74 QT_BEGIN_NAMESPACE
       
    75 
       
    76 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
    77     static const int KValueThatWillBeAddedToSNAPId = 1000;
       
    78 #endif
       
    79 static const int KUserChoiceIAPId = 0;
       
    80 
       
    81 SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
       
    82 :   bearer(BearerUnknown), numericId(0), connectionId(0)
       
    83 {
       
    84 }
       
    85 
       
    86 SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate()
       
    87 {
       
    88 }
       
    89 
       
    90 QString SymbianNetworkConfigurationPrivate::bearerName() const
       
    91 {
       
    92     QMutexLocker locker(&mutex);
       
    93 
       
    94     switch (bearer) {
       
    95     case BearerEthernet:
       
    96         return QLatin1String("Ethernet");
       
    97     case BearerWLAN:
       
    98         return QLatin1String("WLAN");
       
    99     case Bearer2G:
       
   100         return QLatin1String("2G");
       
   101     case BearerCDMA2000:
       
   102         return QLatin1String("CDMA2000");
       
   103     case BearerWCDMA:
       
   104         return QLatin1String("WCDMA");
       
   105     case BearerHSPA:
       
   106         return QLatin1String("HSPA");
       
   107     case BearerBluetooth:
       
   108         return QLatin1String("Bluetooth");
       
   109     case BearerWiMAX:
       
   110         return QLatin1String("WiMAX");
       
   111     default:
       
   112         return QString();
       
   113     }
       
   114 }
       
   115 
       
   116 SymbianEngine::SymbianEngine(QObject *parent)
       
   117 :   QBearerEngine(parent), CActive(CActive::EPriorityIdle), iFirstUpdate(true), iInitOk(true),
       
   118     iIgnoringUpdates(false), iTimeToWait(0), iIgnoreEventLoop(0)
       
   119 {
       
   120     CActiveScheduler::Add(this);
       
   121 
       
   122     // Seed the randomgenerator
       
   123     qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
       
   124     iIgnoreEventLoop = new QEventLoop(this);
       
   125 
       
   126     TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
       
   127     if (error != KErrNone) {
       
   128         iInitOk = false;
       
   129         return;
       
   130     }
       
   131 
       
   132     TRAP_IGNORE(iConnectionMonitor.ConnectL());
       
   133     TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
       
   134 
       
   135 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
       
   136     TRAP(error, iCmManager.OpenL());
       
   137     if (error != KErrNone) {
       
   138         iInitOk = false;
       
   139         return;
       
   140     }
       
   141 #endif
       
   142 }
       
   143 
       
   144 void SymbianEngine::initialize()
       
   145 {
       
   146     QMutexLocker locker(&mutex);
       
   147 
       
   148     SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
       
   149     cpPriv->name = "UserChoice";
       
   150     cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
       
   151     cpPriv->state = QNetworkConfiguration::Discovered;
       
   152     cpPriv->isValid = true;
       
   153     cpPriv->id = QString::number(qHash(KUserChoiceIAPId));
       
   154     cpPriv->numericId = KUserChoiceIAPId;
       
   155     cpPriv->connectionId = 0;
       
   156     cpPriv->type = QNetworkConfiguration::UserChoice;
       
   157     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
       
   158     cpPriv->roamingSupported = false;
       
   159 
       
   160     QNetworkConfigurationPrivatePointer ptr(cpPriv);
       
   161     userChoiceConfigurations.insert(ptr->id, ptr);
       
   162 
       
   163     updateConfigurations();
       
   164     updateStatesToSnaps();
       
   165     updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans)
       
   166     // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
       
   167     startCommsDatabaseNotifications();
       
   168     iFirstUpdate = false;
       
   169 }
       
   170 
       
   171 SymbianEngine::~SymbianEngine()
       
   172 {
       
   173     Cancel();
       
   174 
       
   175     iConnectionMonitor.CancelNotifications();
       
   176     iConnectionMonitor.Close();
       
   177     
       
   178 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
       
   179     iCmManager.Close();
       
   180 #endif
       
   181     
       
   182     delete ipAccessPointsAvailabilityScanner;
       
   183 
       
   184     // CCommsDatabase destructor uses cleanup stack. Since QNetworkConfigurationManager
       
   185     // is a global static, but the time we are here, E32Main() has been exited already and
       
   186     // the thread's default cleanup stack has been deleted. Without this line, a
       
   187     // 'E32USER-CBase 69' -panic will occur.
       
   188     CTrapCleanup* cleanup = CTrapCleanup::New();
       
   189     delete ipCommsDB;
       
   190     delete cleanup;
       
   191 }
       
   192 
       
   193 bool SymbianEngine::hasIdentifier(const QString &id)
       
   194 {
       
   195     QMutexLocker locker(&mutex);
       
   196 
       
   197     return accessPointConfigurations.contains(id) ||
       
   198            snapConfigurations.contains(id) ||
       
   199            userChoiceConfigurations.contains(id);
       
   200 }
       
   201 
       
   202 QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const
       
   203 {
       
   204     QNetworkConfigurationManager::Capabilities capFlags;
       
   205 
       
   206     capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces |
       
   207                QNetworkConfigurationManager::DirectConnectionRouting |
       
   208                QNetworkConfigurationManager::SystemSessionSupport |
       
   209                QNetworkConfigurationManager::DataStatistics |
       
   210                QNetworkConfigurationManager::NetworkSessionRequired;
       
   211 
       
   212 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   213     capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming |
       
   214                 QNetworkConfigurationManager::ForcedRoaming;
       
   215 #endif
       
   216 
       
   217     return capFlags;
       
   218 }
       
   219 
       
   220 QNetworkSessionPrivate *SymbianEngine::createSessionBackend()
       
   221 {
       
   222     return new QNetworkSessionPrivateImpl(this);
       
   223 }
       
   224 
       
   225 void SymbianEngine::requestUpdate()
       
   226 {
       
   227     QMutexLocker locker(&mutex);
       
   228 
       
   229     if (!iInitOk || iUpdateGoingOn) {
       
   230         return;
       
   231     }
       
   232     iUpdateGoingOn = true;
       
   233 
       
   234     stopCommsDatabaseNotifications();
       
   235     updateConfigurations(); // Synchronous call
       
   236     updateAvailableAccessPoints(); // Asynchronous call
       
   237 }
       
   238 
       
   239 void SymbianEngine::updateConfigurations()
       
   240 {
       
   241     QMutexLocker locker(&mutex);
       
   242 
       
   243     if (!iInitOk) {
       
   244         return;
       
   245     }
       
   246 
       
   247     TRAP_IGNORE(updateConfigurationsL());
       
   248 }
       
   249 
       
   250 void SymbianEngine::updateConfigurationsL()
       
   251 {
       
   252     QMutexLocker locker(&mutex);
       
   253 
       
   254     QList<QString> knownConfigs = accessPointConfigurations.keys();
       
   255     QList<QString> knownSnapConfigs = snapConfigurations.keys();
       
   256 
       
   257 #ifdef SNAP_FUNCTIONALITY_AVAILABLE    
       
   258     // S60 version is >= Series60 3rd Edition Feature Pack 2
       
   259     TInt error = KErrNone;
       
   260     
       
   261     // Loop through all IAPs
       
   262     RArray<TUint32> connectionMethods; // IAPs
       
   263     CleanupClosePushL(connectionMethods);
       
   264     iCmManager.ConnectionMethodL(connectionMethods);
       
   265     for(int i = 0; i < connectionMethods.Count(); i++) {
       
   266         RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]);
       
   267         CleanupClosePushL(connectionMethod);
       
   268         TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
       
   269         QString ident = QString::number(qHash(iapId));
       
   270         if (accessPointConfigurations.contains(ident)) {
       
   271             knownConfigs.removeOne(ident);
       
   272         } else {
       
   273             SymbianNetworkConfigurationPrivate* cpPriv = NULL;
       
   274             TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
       
   275             if (error == KErrNone) {
       
   276                 QNetworkConfigurationPrivatePointer ptr(cpPriv);
       
   277                 accessPointConfigurations.insert(ptr->id, ptr);
       
   278 
       
   279                 locker.unlock();
       
   280                 emit configurationAdded(ptr);
       
   281                 locker.relock();
       
   282             }
       
   283         }
       
   284         CleanupStack::PopAndDestroy(&connectionMethod);
       
   285     }
       
   286     CleanupStack::PopAndDestroy(&connectionMethods);
       
   287     
       
   288     // Loop through all SNAPs
       
   289     RArray<TUint32> destinations;
       
   290     CleanupClosePushL(destinations);
       
   291     iCmManager.AllDestinationsL(destinations);
       
   292     for(int i = 0; i < destinations.Count(); i++) {
       
   293         RCmDestination destination;
       
   294         destination = iCmManager.DestinationL(destinations[i]);
       
   295         CleanupClosePushL(destination);
       
   296         QString ident = QString::number(qHash(destination.Id()+KValueThatWillBeAddedToSNAPId)); //TODO: Check if it's ok to add 1000 SNAP Id to prevent SNAP ids overlapping IAP ids
       
   297         if (snapConfigurations.contains(ident)) {
       
   298             knownSnapConfigs.removeOne(ident);
       
   299         } else {
       
   300             SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
       
   301             CleanupStack::PushL(cpPriv);
       
   302     
       
   303             HBufC *pName = destination.NameLC();
       
   304             cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
       
   305             CleanupStack::PopAndDestroy(pName);
       
   306             pName = NULL;
       
   307     
       
   308             cpPriv->isValid = true;
       
   309             cpPriv->id = ident;
       
   310             cpPriv->numericId = destination.Id();
       
   311             cpPriv->connectionId = 0;
       
   312             cpPriv->state = QNetworkConfiguration::Defined;
       
   313             cpPriv->type = QNetworkConfiguration::ServiceNetwork;
       
   314             cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
       
   315             cpPriv->roamingSupported = false;
       
   316 
       
   317             QNetworkConfigurationPrivatePointer ptr(cpPriv);
       
   318             snapConfigurations.insert(ident, ptr);
       
   319 
       
   320             locker.unlock();
       
   321             emit configurationAdded(ptr);
       
   322             locker.relock();
       
   323             
       
   324             CleanupStack::Pop(cpPriv);
       
   325         }
       
   326         QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident);
       
   327             
       
   328         for (int j=0; j < destination.ConnectionMethodCount(); j++) {
       
   329             RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
       
   330             CleanupClosePushL(connectionMethod);
       
   331             
       
   332             TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
       
   333             QString iface = QString::number(qHash(iapId));
       
   334             // Check that IAP can be found from accessPointConfigurations list
       
   335             QNetworkConfigurationPrivatePointer priv = accessPointConfigurations.value(iface);
       
   336             if (!priv) {
       
   337                 SymbianNetworkConfigurationPrivate *cpPriv = NULL;
       
   338                 TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
       
   339                 if (error == KErrNone) {
       
   340                     QNetworkConfigurationPrivatePointer ptr(cpPriv);
       
   341                     toSymbianConfig(ptr)->serviceNetworkPtr = privSNAP;
       
   342                     accessPointConfigurations.insert(ptr->id, ptr);
       
   343 
       
   344                     locker.unlock();
       
   345                     emit configurationAdded(ptr);
       
   346                     locker.relock();
       
   347 
       
   348                     privSNAP->serviceNetworkMembers.append(ptr);
       
   349                 }
       
   350             } else {
       
   351                 knownConfigs.removeOne(iface);
       
   352                 // Check that IAP can be found from related SNAP's configuration list
       
   353                 bool iapFound = false;
       
   354                 for (int i = 0; i < privSNAP->serviceNetworkMembers.count(); i++) {
       
   355                     if (toSymbianConfig(privSNAP->serviceNetworkMembers[i])->numericId == iapId) {
       
   356                         iapFound = true;
       
   357                         break;
       
   358                     }
       
   359                 }
       
   360                 if (!iapFound) {
       
   361                     toSymbianConfig(priv)->serviceNetworkPtr = privSNAP;
       
   362                     privSNAP->serviceNetworkMembers.append(priv);
       
   363                 }
       
   364             }
       
   365             
       
   366             CleanupStack::PopAndDestroy(&connectionMethod);
       
   367         }
       
   368         
       
   369         if (privSNAP->serviceNetworkMembers.count() > 1) {
       
   370             // Roaming is supported only if SNAP contains more than one IAP
       
   371             privSNAP->roamingSupported = true;
       
   372         }
       
   373         
       
   374         CleanupStack::PopAndDestroy(&destination);
       
   375     }
       
   376     CleanupStack::PopAndDestroy(&destinations);
       
   377     
       
   378 #else
       
   379     // S60 version is < Series60 3rd Edition Feature Pack 2
       
   380     CCommsDbTableView* pDbTView = ipCommsDB->OpenTableLC(TPtrC(IAP));
       
   381 
       
   382     // Loop through all IAPs
       
   383     TUint32 apId = 0;
       
   384     TInt retVal = pDbTView->GotoFirstRecord();
       
   385     while (retVal == KErrNone) {
       
   386         pDbTView->ReadUintL(TPtrC(COMMDB_ID), apId);
       
   387         QString ident = QString::number(qHash(apId));
       
   388         if (accessPointConfigurations.contains(ident)) {
       
   389             knownConfigs.removeOne(ident);
       
   390         } else {
       
   391             SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
       
   392             if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) {
       
   393                 QNetworkConfigurationPrivatePointer ptr(cpPriv);
       
   394                 accessPointConfigurations.insert(ident, ptr);
       
   395 
       
   396                 locker.unlock();
       
   397                 emit configurationAdded(ptr);
       
   398                 locker.relock();
       
   399             } else {
       
   400                 delete cpPriv;
       
   401             }
       
   402         }
       
   403         retVal = pDbTView->GotoNextRecord();
       
   404     }
       
   405     CleanupStack::PopAndDestroy(pDbTView);
       
   406 #endif
       
   407     updateActiveAccessPoints();
       
   408     
       
   409     foreach (const QString &oldIface, knownConfigs) {
       
   410         //remove non existing IAP
       
   411         QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface);
       
   412 
       
   413         locker.unlock();
       
   414         emit configurationRemoved(ptr);
       
   415         locker.relock();
       
   416 
       
   417         // Remove non existing IAP from SNAPs
       
   418         foreach (const QString &iface, snapConfigurations.keys()) {
       
   419             QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface);
       
   420             // => Check if one of the IAPs of the SNAP is active
       
   421             for (int i = 0; i < ptr2->serviceNetworkMembers.count(); ++i) {
       
   422                 if (toSymbianConfig(ptr2->serviceNetworkMembers[i])->numericId ==
       
   423                     toSymbianConfig(ptr)->numericId) {
       
   424                     ptr2->serviceNetworkMembers.removeAt(i);
       
   425                     break;
       
   426                 }
       
   427             }
       
   428         }    
       
   429     }
       
   430 
       
   431     foreach (const QString &oldIface, knownSnapConfigs) {
       
   432         //remove non existing SNAPs
       
   433         QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface);
       
   434 
       
   435         locker.unlock();
       
   436         emit configurationRemoved(ptr);
       
   437         locker.relock();
       
   438     }
       
   439 }
       
   440 
       
   441 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   442 SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL(
       
   443         RCmConnectionMethod& connectionMethod)
       
   444 {
       
   445     QMutexLocker locker(&mutex);
       
   446 
       
   447     SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
       
   448     CleanupStack::PushL(cpPriv);
       
   449     
       
   450     TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
       
   451     QString ident = QString::number(qHash(iapId));
       
   452     
       
   453     HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
       
   454     CleanupStack::PushL(pName);
       
   455     cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
       
   456     CleanupStack::PopAndDestroy(pName);
       
   457     pName = NULL;
       
   458     
       
   459     TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
       
   460     switch (bearerId) {
       
   461     case KCommDbBearerCSD:
       
   462         cpPriv->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
       
   463         break;
       
   464     case KCommDbBearerWcdma:
       
   465         cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerWCDMA;
       
   466         break;
       
   467     case KCommDbBearerLAN:
       
   468         cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
       
   469         break;
       
   470     case KCommDbBearerVirtual:
       
   471         cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
       
   472         break;
       
   473     case KCommDbBearerPAN:
       
   474         cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
       
   475         break;
       
   476     case KCommDbBearerWLAN:
       
   477         cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerWLAN;
       
   478         break;
       
   479     default:
       
   480         cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
       
   481         break;
       
   482     }
       
   483     
       
   484     TInt error = KErrNone;
       
   485     TUint32 bearerType = connectionMethod.GetIntAttributeL(CMManager::ECmBearerType);
       
   486     switch (bearerType) {
       
   487     case KUidPacketDataBearerType:
       
   488         // "Packet data" Bearer => Mapping is done using "Access point name"
       
   489         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EPacketDataAPName));
       
   490         break;
       
   491     case KUidWlanBearerType:
       
   492         // "Wireless LAN" Bearer => Mapping is done using "WLAN network name" = SSID
       
   493         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EWlanSSID));
       
   494         break;
       
   495     }
       
   496     if (!pName) {
       
   497         // "Data call" Bearer or "High Speed (GSM)" Bearer => Mapping is done using "Dial-up number"
       
   498         TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
       
   499     }
       
   500 
       
   501     if (error == KErrNone && pName) {
       
   502         CleanupStack::PushL(pName);
       
   503         cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length());
       
   504         CleanupStack::PopAndDestroy(pName);
       
   505         pName = NULL;
       
   506     }
       
   507  
       
   508     cpPriv->state = QNetworkConfiguration::Defined;
       
   509     TBool isConnected = connectionMethod.GetBoolAttributeL(CMManager::ECmConnected);
       
   510     if (isConnected) {
       
   511         cpPriv->state = QNetworkConfiguration::Active;
       
   512     }
       
   513     
       
   514     cpPriv->isValid = true;
       
   515     cpPriv->id = ident;
       
   516     cpPriv->numericId = iapId;
       
   517     cpPriv->connectionId = 0;
       
   518     cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
       
   519     cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
       
   520     cpPriv->roamingSupported = false;
       
   521     
       
   522     CleanupStack::Pop(cpPriv);
       
   523     return cpPriv;
       
   524 }
       
   525 #else
       
   526 bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb(
       
   527         TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
       
   528 {
       
   529     QMutexLocker locker(&mutex);
       
   530 
       
   531     TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration));
       
   532     if (error != KErrNone) {
       
   533         return false;        
       
   534     }
       
   535     return true;
       
   536 }
       
   537 
       
   538 void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL(
       
   539         TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
       
   540 {
       
   541     QMutexLocker locker(&mutex);
       
   542 
       
   543     CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB); 
       
   544     CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC(); 
       
   545     TBuf<KCommsDbSvrMaxColumnNameLength> name;
       
   546     
       
   547     CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB);
       
   548     TUint32 apId = pApUtils->WapIdFromIapIdL(aApId);
       
   549     
       
   550     pDataHandler->AccessPointDataL(apId,*pAPItem);
       
   551     pAPItem->ReadTextL(EApIapName, name);
       
   552     if (name.Compare(_L("Easy WLAN")) == 0) {
       
   553         // "Easy WLAN" won't be accepted to the Configurations list
       
   554         User::Leave(KErrNotFound);
       
   555     }
       
   556     
       
   557     QString ident = QString::number(qHash(aApId));
       
   558     
       
   559     apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length());
       
   560     apNetworkConfiguration->isValid = true;
       
   561     apNetworkConfiguration->id = ident;
       
   562     apNetworkConfiguration->numericId = aApId;
       
   563     apNetworkConfiguration->connectionId = 0;
       
   564     apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
       
   565     apNetworkConfiguration->type = QNetworkConfiguration::InternetAccessPoint;
       
   566     apNetworkConfiguration->purpose = QNetworkConfiguration::UnknownPurpose;
       
   567     apNetworkConfiguration->roamingSupported = false;
       
   568     switch (pAPItem->BearerTypeL()) {
       
   569     case EApBearerTypeCSD:      
       
   570         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
       
   571         break;
       
   572     case EApBearerTypeGPRS:
       
   573         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
       
   574         break;
       
   575     case EApBearerTypeHSCSD:
       
   576         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerHSPA;
       
   577         break;
       
   578     case EApBearerTypeCDMA:
       
   579         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerCDMA2000;
       
   580         break;
       
   581     case EApBearerTypeWLAN:
       
   582         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerWLAN;
       
   583         break;
       
   584     case EApBearerTypeLAN:
       
   585         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
       
   586         break;
       
   587     case EApBearerTypeLANModem:
       
   588         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
       
   589         break;
       
   590     default:
       
   591         apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
       
   592         break;
       
   593     }
       
   594     
       
   595     CleanupStack::PopAndDestroy(pApUtils);
       
   596     CleanupStack::PopAndDestroy(pAPItem);
       
   597     CleanupStack::PopAndDestroy(pDataHandler);
       
   598 }
       
   599 #endif
       
   600 
       
   601 QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration()
       
   602 {
       
   603     QMutexLocker locker(&mutex);
       
   604 
       
   605     QNetworkConfigurationPrivatePointer ptr;
       
   606 
       
   607     if (iInitOk) {
       
   608         stopCommsDatabaseNotifications();
       
   609         TRAP_IGNORE(ptr = defaultConfigurationL());
       
   610         startCommsDatabaseNotifications();
       
   611     }
       
   612 
       
   613     return ptr;
       
   614 }
       
   615 
       
   616 QStringList SymbianEngine::accessPointConfigurationIdentifiers()
       
   617 {
       
   618     QMutexLocker locker(&mutex);
       
   619 
       
   620     return accessPointConfigurations.keys();
       
   621 }
       
   622 
       
   623 QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL()
       
   624 {
       
   625     QMutexLocker locker(&mutex);
       
   626 
       
   627     QNetworkConfigurationPrivatePointer ptr;
       
   628 
       
   629 #ifdef SNAP_FUNCTIONALITY_AVAILABLE
       
   630     // Check Default Connection (SNAP or IAP)
       
   631     TCmDefConnValue defaultConnectionValue;
       
   632     iCmManager.ReadDefConnL(defaultConnectionValue);
       
   633     if (defaultConnectionValue.iType == ECmDefConnDestination) {
       
   634         QString iface = QString::number(qHash(defaultConnectionValue.iId+KValueThatWillBeAddedToSNAPId));
       
   635         ptr = snapConfigurations.value(iface);
       
   636     } else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) {
       
   637         QString iface = QString::number(qHash(defaultConnectionValue.iId));
       
   638         ptr = accessPointConfigurations.value(iface);
       
   639     }
       
   640 #endif
       
   641     
       
   642     if (!ptr || !ptr->isValid) {
       
   643         QString iface = QString::number(qHash(KUserChoiceIAPId));
       
   644         ptr = userChoiceConfigurations.value(iface);
       
   645     }
       
   646     
       
   647     return ptr;
       
   648 }
       
   649 
       
   650 void SymbianEngine::updateActiveAccessPoints()
       
   651 {
       
   652     QMutexLocker locker(&mutex);
       
   653 
       
   654     bool online = false;
       
   655     QList<QString> inactiveConfigs = accessPointConfigurations.keys();
       
   656 
       
   657     TRequestStatus status;
       
   658     TUint connectionCount;
       
   659     iConnectionMonitor.GetConnectionCount(connectionCount, status);
       
   660     User::WaitForRequest(status);
       
   661     
       
   662     // Go through all connections and set state of related IAPs to Active.
       
   663     // Status needs to be checked carefully, because ConnMon lists also e.g.
       
   664     // WLAN connections that are being currently tried --> we don't want to
       
   665     // state these as active.
       
   666     TUint connectionId;
       
   667     TUint subConnectionCount;
       
   668     TUint apId;
       
   669     TInt connectionStatus;
       
   670     if (status.Int() == KErrNone) {
       
   671         for (TUint i = 1; i <= connectionCount; i++) {
       
   672             iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
       
   673             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
       
   674             User::WaitForRequest(status);
       
   675             QString ident = QString::number(qHash(apId));
       
   676             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
   677             if (ptr) {
       
   678                 iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
       
   679                 User::WaitForRequest(status);          
       
   680                 if (connectionStatus == KLinkLayerOpen) {
       
   681                     online = true;
       
   682                     inactiveConfigs.removeOne(ident);
       
   683 
       
   684                     QMutexLocker configLocker(&ptr->mutex);
       
   685                     toSymbianConfig(ptr)->connectionId = connectionId;
       
   686 
       
   687                     // Configuration is Active
       
   688                     changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
       
   689                 }
       
   690             }
       
   691         }
       
   692     }
       
   693 
       
   694     // Make sure that state of rest of the IAPs won't be Active
       
   695     foreach (const QString &iface, inactiveConfigs) {
       
   696         QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
       
   697         if (ptr) {
       
   698             // Configuration is either Defined or Discovered
       
   699             changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
       
   700         }
       
   701     }
       
   702 
       
   703     if (iOnline != online) {
       
   704         iOnline = online;
       
   705         locker.unlock();
       
   706         emit this->onlineStateChanged(iOnline);
       
   707         locker.relock();
       
   708     }
       
   709 }
       
   710 
       
   711 void SymbianEngine::updateAvailableAccessPoints()
       
   712 {
       
   713     QMutexLocker locker(&mutex);
       
   714 
       
   715     if (!ipAccessPointsAvailabilityScanner) {
       
   716         ipAccessPointsAvailabilityScanner = new AccessPointsAvailabilityScanner(*this, iConnectionMonitor);
       
   717     }
       
   718     if (ipAccessPointsAvailabilityScanner) {
       
   719         // Scanning may take a while because WLAN scanning will be done (if device supports WLAN).
       
   720         ipAccessPointsAvailabilityScanner->StartScanning();
       
   721     }
       
   722 }
       
   723 
       
   724 void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo)
       
   725 {
       
   726     QMutexLocker locker(&mutex);
       
   727 
       
   728     iUpdateGoingOn = false;
       
   729     if (scanSuccessful) {
       
   730         QList<QString> unavailableConfigs = accessPointConfigurations.keys();
       
   731         
       
   732         // Set state of returned IAPs to Discovered
       
   733         // if state is not already Active
       
   734         for(TUint i=0; i<iapInfo.iCount; i++) {
       
   735             QString ident = QString::number(qHash(iapInfo.iIap[i].iIapId));
       
   736             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
   737             if (ptr) {
       
   738                 unavailableConfigs.removeOne(ident);
       
   739                 if (ptr->state < QNetworkConfiguration::Active) {
       
   740                     // Configuration is either Discovered or Active
       
   741                     changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
       
   742                 }
       
   743             }
       
   744         }
       
   745         
       
   746         // Make sure that state of rest of the IAPs won't be Active
       
   747         foreach (const QString &iface, unavailableConfigs) {
       
   748             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
       
   749             if (ptr) {
       
   750                 // Configuration is Defined
       
   751                 changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
       
   752             }
       
   753         }
       
   754     }
       
   755 
       
   756     updateStatesToSnaps();
       
   757     
       
   758     if (!iFirstUpdate) {
       
   759         startCommsDatabaseNotifications();
       
   760         locker.unlock();
       
   761         emit updateCompleted();
       
   762         locker.relock();
       
   763     }
       
   764 }
       
   765 
       
   766 void SymbianEngine::updateStatesToSnaps()
       
   767 {
       
   768     QMutexLocker locker(&mutex);
       
   769 
       
   770     // Go through SNAPs and set correct state to SNAPs
       
   771     foreach (const QString &iface, snapConfigurations.keys()) {
       
   772         bool discovered = false;
       
   773         bool active = false;
       
   774         QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
       
   775         // => Check if one of the IAPs of the SNAP is discovered or active
       
   776         //    => If one of IAPs is active, also SNAP is active
       
   777         //    => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered
       
   778         for (int i=0; i<ptr->serviceNetworkMembers.count(); i++) {
       
   779             if ((ptr->serviceNetworkMembers[i]->state & QNetworkConfiguration::Active)
       
   780                     == QNetworkConfiguration::Active) {
       
   781                 active = true;
       
   782                 break;
       
   783             } else if ((ptr->serviceNetworkMembers[i]->state & QNetworkConfiguration::Discovered)
       
   784                         == QNetworkConfiguration::Discovered) {
       
   785                 discovered = true;
       
   786             }
       
   787         }
       
   788         if (active) {
       
   789             changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
       
   790         } else if (discovered) {
       
   791             changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
       
   792         } else {
       
   793             changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
       
   794         }
       
   795     }    
       
   796 }
       
   797 
       
   798 bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
       
   799                                                QNetworkConfiguration::StateFlags newState)
       
   800 {
       
   801     QMutexLocker locker(&mutex);
       
   802 
       
   803     ptr->mutex.lock();
       
   804     if (newState != ptr->state) {
       
   805         ptr->state = newState;
       
   806         ptr->mutex.unlock();
       
   807 
       
   808         locker.unlock();
       
   809         emit configurationChanged(ptr);
       
   810         locker.relock();
       
   811 
       
   812         return true;
       
   813     } else {
       
   814         ptr->mutex.unlock();
       
   815     }
       
   816     return false;
       
   817 }
       
   818 
       
   819 /* changeConfigurationStateAtMinTo function does not overwrite possible better
       
   820  * state (e.g. Discovered state does not overwrite Active state) but
       
   821  * makes sure that state is at minimum given state.
       
   822 */
       
   823 bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
       
   824                                                     QNetworkConfiguration::StateFlags newState)
       
   825 {
       
   826     QMutexLocker locker(&mutex);
       
   827 
       
   828     ptr->mutex.lock();
       
   829     if ((newState | ptr->state) != ptr->state) {
       
   830         ptr->state = (ptr->state | newState);
       
   831         ptr->mutex.unlock();
       
   832 
       
   833         locker.unlock();
       
   834         emit configurationChanged(ptr);
       
   835         locker.relock();
       
   836 
       
   837         return true;
       
   838     } else {
       
   839         ptr->mutex.unlock();
       
   840     }
       
   841     return false;
       
   842 }
       
   843 
       
   844 /* changeConfigurationStateAtMaxTo function overwrites possible better
       
   845  * state (e.g. Discovered state overwrites Active state) and
       
   846  * makes sure that state is at maximum given state (e.g. Discovered state
       
   847  * does not overwrite Defined state).
       
   848 */
       
   849 bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
       
   850                                                     QNetworkConfiguration::StateFlags newState)
       
   851 {
       
   852     QMutexLocker locker(&mutex);
       
   853 
       
   854     ptr->mutex.lock();
       
   855     if ((newState & ptr->state) != ptr->state) {
       
   856         ptr->state = (newState & ptr->state);
       
   857         ptr->mutex.unlock();
       
   858 
       
   859         locker.unlock();
       
   860         emit configurationChanged(ptr);
       
   861         locker.relock();
       
   862 
       
   863         return true;
       
   864     } else {
       
   865         ptr->mutex.unlock();
       
   866     }
       
   867     return false;
       
   868 }
       
   869 
       
   870 void SymbianEngine::startCommsDatabaseNotifications()
       
   871 {
       
   872     QMutexLocker locker(&mutex);
       
   873 
       
   874     if (!iWaitingCommsDatabaseNotifications) {
       
   875         iWaitingCommsDatabaseNotifications = ETrue;
       
   876         if (!IsActive()) {
       
   877             SetActive();
       
   878             // Start waiting for new notification
       
   879             ipCommsDB->RequestNotification(iStatus);
       
   880         }
       
   881     }
       
   882 }
       
   883 
       
   884 void SymbianEngine::stopCommsDatabaseNotifications()
       
   885 {
       
   886     QMutexLocker locker(&mutex);
       
   887 
       
   888     if (iWaitingCommsDatabaseNotifications) {
       
   889         iWaitingCommsDatabaseNotifications = EFalse;
       
   890         if (!IsActive()) {
       
   891             SetActive();
       
   892             // Make sure that notifier recorded events will not be returned
       
   893             // as soon as the client issues the next RequestNotification() request.
       
   894             ipCommsDB->RequestNotification(iStatus);
       
   895             ipCommsDB->CancelRequestNotification();
       
   896         } else {
       
   897             ipCommsDB->CancelRequestNotification();
       
   898         }
       
   899     }
       
   900 }
       
   901 
       
   902 void SymbianEngine::RunL()
       
   903 {
       
   904     QMutexLocker locker(&mutex);
       
   905 
       
   906     if (iIgnoringUpdates) {
       
   907 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   908         qDebug("QNCM CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
       
   909 #endif
       
   910         return;
       
   911     }
       
   912 
       
   913     if (iStatus != KErrCancel) {
       
   914         RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
       
   915 
       
   916         switch (event) {
       
   917         case RDbNotifier::EUnlock:   /** All read locks have been removed.  */
       
   918         case RDbNotifier::ECommit:   /** A transaction has been committed.  */ 
       
   919         case RDbNotifier::ERollback: /** A transaction has been rolled back */
       
   920         case RDbNotifier::ERecover:  /** The database has been recovered    */
       
   921 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   922             qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
       
   923 #endif
       
   924             iIgnoringUpdates = true;
       
   925             // Other events than ECommit get lower priority. In practice with those events,
       
   926             // we delay_before_updating methods, whereas
       
   927             // with ECommit we _update_before_delaying the reaction to next event.
       
   928             // Few important notes: 1) listening to only ECommit does not seem to be adequate,
       
   929             // but updates will be missed. Hence other events are reacted upon too.
       
   930             // 2) RDbNotifier records the most significant event, and that will be returned once
       
   931             // we issue new RequestNotification, and hence updates will not be missed even
       
   932             // when we are 'not reacting to them' for few seconds.
       
   933             if (event == RDbNotifier::ECommit) {
       
   934                 TRAPD(error, updateConfigurationsL());
       
   935                 if (error == KErrNone) {
       
   936                     updateStatesToSnaps();
       
   937                 }
       
   938                 waitRandomTime();
       
   939             } else {
       
   940                 waitRandomTime();
       
   941                 TRAPD(error, updateConfigurationsL());
       
   942                 if (error == KErrNone) {
       
   943                     updateStatesToSnaps();
       
   944                 }   
       
   945             }
       
   946             iIgnoringUpdates = false; // Wait time done, allow updating again
       
   947             iWaitingCommsDatabaseNotifications = true;
       
   948             break;
       
   949         default:
       
   950             // Do nothing
       
   951             break;
       
   952         }
       
   953     }
       
   954 
       
   955     if (iWaitingCommsDatabaseNotifications) {
       
   956         if (!IsActive()) {
       
   957             SetActive();
       
   958             // Start waiting for new notification
       
   959             ipCommsDB->RequestNotification(iStatus);
       
   960         }
       
   961     }
       
   962 }
       
   963 
       
   964 void SymbianEngine::DoCancel()
       
   965 {
       
   966     QMutexLocker locker(&mutex);
       
   967 
       
   968     ipCommsDB->CancelRequestNotification();
       
   969 }
       
   970 
       
   971 void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
       
   972 {
       
   973     QMutexLocker locker(&mutex);
       
   974 
       
   975     switch (aEvent.EventType()) {
       
   976     case EConnMonConnectionStatusChange:
       
   977         {
       
   978         CConnMonConnectionStatusChange* realEvent;
       
   979         realEvent = (CConnMonConnectionStatusChange*) &aEvent;
       
   980         TInt connectionStatus = realEvent->ConnectionStatus();
       
   981 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
   982         qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId();
       
   983 #endif
       
   984         if (connectionStatus == KConfigDaemonStartingRegistration) {
       
   985             TUint connectionId = realEvent->ConnectionId();
       
   986             TUint subConnectionCount = 0;
       
   987             TUint apId;            
       
   988             TRequestStatus status;
       
   989             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
       
   990             User::WaitForRequest(status);
       
   991             QString ident = QString::number(qHash(apId));
       
   992             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
   993             if (ptr) {
       
   994                 QMutexLocker configLocker(&ptr->mutex);
       
   995                 toSymbianConfig(ptr)->connectionId = connectionId;
       
   996                 emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connecting);
       
   997             }
       
   998         } else if (connectionStatus == KLinkLayerOpen) {
       
   999             // Connection has been successfully opened
       
  1000             TUint connectionId = realEvent->ConnectionId();
       
  1001             TUint subConnectionCount = 0;
       
  1002             TUint apId;            
       
  1003             TRequestStatus status;
       
  1004             iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
       
  1005             User::WaitForRequest(status);
       
  1006             QString ident = QString::number(qHash(apId));
       
  1007             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
  1008             if (ptr) {
       
  1009                 QMutexLocker configLocker(&ptr->mutex);
       
  1010                 toSymbianConfig(ptr)->connectionId = connectionId;
       
  1011                 // Configuration is Active
       
  1012                 if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) {
       
  1013                     updateStatesToSnaps();
       
  1014                 }
       
  1015                 emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Connected);
       
  1016                 if (!iOnline) {
       
  1017                     iOnline = true;
       
  1018                     emit this->onlineStateChanged(iOnline);
       
  1019                 }
       
  1020             }
       
  1021         } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
       
  1022             TUint connectionId = realEvent->ConnectionId();
       
  1023             QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
       
  1024             if (ptr) {
       
  1025                 QMutexLocker configLocker(&ptr->mutex);
       
  1026                 emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Closing);
       
  1027             }
       
  1028         } else if (connectionStatus == KLinkLayerClosed ||
       
  1029                    connectionStatus == KConnectionClosed) {
       
  1030             // Connection has been closed. Which of the above events is reported, depends on the Symbian
       
  1031             // platform.
       
  1032             TUint connectionId = realEvent->ConnectionId();
       
  1033             QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
       
  1034             if (ptr) {
       
  1035                 // Configuration is either Defined or Discovered
       
  1036                 if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
       
  1037                     updateStatesToSnaps();
       
  1038                 }
       
  1039 
       
  1040                 QMutexLocker configLocker(&ptr->mutex);
       
  1041                 emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId, connectionId, QNetworkSession::Disconnected);
       
  1042             }
       
  1043             
       
  1044             bool online = false;
       
  1045             foreach (const QString &iface, accessPointConfigurations.keys()) {
       
  1046                 QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
       
  1047                 QMutexLocker configLocker(&ptr->mutex);
       
  1048                 if (ptr->state == QNetworkConfiguration::Active) {
       
  1049                     online = true;
       
  1050                     break;
       
  1051                 }
       
  1052             }
       
  1053             if (iOnline != online) {
       
  1054                 iOnline = online;
       
  1055                 emit this->onlineStateChanged(iOnline);
       
  1056             }
       
  1057         }
       
  1058         }
       
  1059         break;    
       
  1060 
       
  1061     case EConnMonIapAvailabilityChange:
       
  1062         {
       
  1063         CConnMonIapAvailabilityChange* realEvent;
       
  1064         realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
       
  1065         TConnMonIapInfo iaps = realEvent->IapAvailability();
       
  1066         QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys();
       
  1067         for ( TUint i = 0; i < iaps.Count(); i++ ) {
       
  1068             QString ident = QString::number(qHash(iaps.iIap[i].iIapId));
       
  1069 
       
  1070             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
  1071             if (ptr) {
       
  1072                 // Configuration is either Discovered or Active 
       
  1073                 changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
       
  1074                 unDiscoveredConfigs.removeOne(ident);
       
  1075             }
       
  1076         }
       
  1077         foreach (const QString &iface, unDiscoveredConfigs) {
       
  1078             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
       
  1079             if (ptr) {
       
  1080                 // Configuration is Defined
       
  1081                 changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
       
  1082             }
       
  1083         }
       
  1084         }
       
  1085         break;
       
  1086 
       
  1087     case EConnMonCreateConnection:
       
  1088         {
       
  1089         // This event is caught to keep connection monitor IDs up-to-date.
       
  1090         CConnMonCreateConnection* realEvent;
       
  1091         realEvent = (CConnMonCreateConnection*) &aEvent;
       
  1092         TUint subConnectionCount = 0;
       
  1093         TUint apId;
       
  1094         TUint connectionId = realEvent->ConnectionId();
       
  1095         TRequestStatus status;
       
  1096         iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
       
  1097         User::WaitForRequest(status);
       
  1098         QString ident = QString::number(qHash(apId));
       
  1099         QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
  1100         if (ptr) {
       
  1101             QMutexLocker configLocker(&ptr->mutex);
       
  1102 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1103             qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name;
       
  1104 #endif
       
  1105             toSymbianConfig(ptr)->connectionId = connectionId;
       
  1106         }
       
  1107         }
       
  1108         break;
       
  1109     default:
       
  1110         // For unrecognized events
       
  1111         break;
       
  1112     }
       
  1113 }
       
  1114 
       
  1115 // Sessions may use this function to report configuration state changes,
       
  1116 // because on some Symbian platforms (especially Symbian^3) all state changes are not
       
  1117 // reported by the RConnectionMonitor, in particular in relation to stop() call,
       
  1118 // whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
       
  1119 // this data here so that other sessions may benefit from it too (not all sessions necessarily have
       
  1120 // RConnection progress notifiers available but they relay on having e.g. disconnected information from
       
  1121 // manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
       
  1122 void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
       
  1123 {
       
  1124 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1125     qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState;
       
  1126 #endif
       
  1127     switch (newState) {
       
  1128     case QNetworkSession::Disconnected:
       
  1129         {
       
  1130             QString ident = QString::number(qHash(accessPointId));
       
  1131             QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
       
  1132             if (ptr) {
       
  1133                 // Configuration is either Defined or Discovered
       
  1134                 if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
       
  1135                     updateStatesToSnaps();
       
  1136                 }
       
  1137 
       
  1138                 QMutexLocker configLocker(&ptr->mutex);
       
  1139                 emit this->configurationStateChanged(toSymbianConfig(ptr)->numericId,
       
  1140                                                      toSymbianConfig(ptr)->connectionId,
       
  1141                                                      QNetworkSession::Disconnected);
       
  1142             }
       
  1143         }
       
  1144         break;
       
  1145     default:
       
  1146         break;
       
  1147     }
       
  1148 }
       
  1149 
       
  1150 // Waits for 2..6 seconds.
       
  1151 void SymbianEngine::waitRandomTime()
       
  1152 {
       
  1153     iTimeToWait = (qAbs(qrand()) % 7) * 1000;
       
  1154     if (iTimeToWait < 2000) {
       
  1155         iTimeToWait = 2000;
       
  1156     }
       
  1157 #ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
       
  1158     qDebug("QNCM waiting random time: %d ms", iTimeToWait);
       
  1159 #endif
       
  1160     QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
       
  1161     iIgnoreEventLoop->exec();
       
  1162 }
       
  1163 
       
  1164 QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
       
  1165 {
       
  1166     QMutexLocker locker(&mutex);
       
  1167 
       
  1168     QNetworkConfiguration item;
       
  1169     QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
       
  1170             accessPointConfigurations.constBegin();
       
  1171     while (i != accessPointConfigurations.constEnd()) {
       
  1172         QNetworkConfigurationPrivatePointer ptr = i.value();
       
  1173         QMutexLocker configLocker(&ptr->mutex);
       
  1174         if (toSymbianConfig(ptr)->connectionId == aConnectionId)
       
  1175             return ptr;
       
  1176 
       
  1177         ++i;
       
  1178     }
       
  1179 
       
  1180     return QNetworkConfigurationPrivatePointer();
       
  1181 }
       
  1182 
       
  1183 AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner,
       
  1184                                                                RConnectionMonitor& connectionMonitor)
       
  1185     : CActive(CActive::EPriorityStandard), iOwner(owner), iConnectionMonitor(connectionMonitor)
       
  1186 {
       
  1187     CActiveScheduler::Add(this);  
       
  1188 }
       
  1189 
       
  1190 AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
       
  1191 {
       
  1192     Cancel();
       
  1193 }
       
  1194 
       
  1195 void AccessPointsAvailabilityScanner::DoCancel()
       
  1196 {
       
  1197     iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute);
       
  1198 }
       
  1199 
       
  1200 void AccessPointsAvailabilityScanner::StartScanning()
       
  1201 {
       
  1202     if (iOwner.iFirstUpdate) {
       
  1203         // On first update (the mgr is being instantiated) update only those bearers who
       
  1204         // don't need time-consuming scans (WLAN).
       
  1205         // Note: EBearerIdWCDMA covers also GPRS bearer
       
  1206         iConnectionMonitor.GetPckgAttribute(EBearerIdWCDMA, 0, KIapAvailability, iIapBuf, iStatus);
       
  1207         User::WaitForRequest(iStatus);
       
  1208         if (iStatus.Int() == KErrNone) {
       
  1209             iOwner.accessPointScanningReady(true,iIapBuf());
       
  1210         }
       
  1211     } else {
       
  1212         iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus);
       
  1213         if (!IsActive()) {
       
  1214             SetActive();
       
  1215         }
       
  1216     }
       
  1217 }
       
  1218 
       
  1219 void AccessPointsAvailabilityScanner::RunL()
       
  1220 {
       
  1221     if (iStatus.Int() != KErrNone) {
       
  1222         iIapBuf().iCount = 0;
       
  1223         iOwner.accessPointScanningReady(false,iIapBuf());
       
  1224     } else {
       
  1225         iOwner.accessPointScanningReady(true,iIapBuf());
       
  1226     }
       
  1227 }
       
  1228 
       
  1229 QT_END_NAMESPACE
       
  1230 
       
  1231 #endif // QT_NO_BEARERMANAGEMENT