blob: dc8c322151608db5480f1a2aae8e07dbea2f4813 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** GNU Lesser General Public License Usage
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this
** file. Please review the following information to ensure the GNU Lesser
** General Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file. Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "symbianengine.h"
#include "qnetworksession_impl.h"
#include <commdb.h>
#include <cdbcols.h>
#include <d32dbms.h>
#include <nifvar.h>
#include <QTimer>
#include <QTime> // For randgen seeding
#include <QtCore> // For randgen seeding
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
#include <QDebug>
#endif
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
#include <cmdestination.h>
#include <cmconnectionmethod.h>
#include <cmconnectionmethoddef.h>
#include <cmpluginwlandef.h>
#include <cmpluginpacketdatadef.h>
#include <cmplugindialcommondefs.h>
#else
#include <ApAccessPointItem.h>
#include <ApDataHandler.h>
#include <ApUtils.h>
#endif
#ifndef QT_NO_BEARERMANAGEMENT
QT_BEGIN_NAMESPACE
static const int KUserChoiceIAPId = 0;
SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
: numericId(0), connectionId(0)
{
}
SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate()
{
}
SymbianEngine::SymbianEngine(QObject *parent)
: QBearerEngine(parent), CActive(CActive::EPriorityHigh), iFirstUpdate(true), ipCommsDB(0),
iInitOk(true), iUpdatePending(false), ipAccessPointsAvailabilityScanner(0)
{
}
void SymbianEngine::initialize()
{
QMutexLocker locker(&mutex);
CActiveScheduler::Add(this);
// Seed the randomgenerator
qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
if (error != KErrNone) {
iInitOk = false;
return;
}
TRAP(error, StartConnectionMonitorNotifyL());
if (error != KErrNone) {
iInitOk = false;
return;
}
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
TRAP(error, iCmManager.OpenL());
if (error != KErrNone) {
iInitOk = false;
return;
}
#endif
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
cpPriv->name = "UserChoice";
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
cpPriv->state = QNetworkConfiguration::Discovered;
cpPriv->isValid = true;
cpPriv->id = QString::number(qHash(KUserChoiceIAPId));
cpPriv->numericId = KUserChoiceIAPId;
cpPriv->connectionId = 0;
cpPriv->type = QNetworkConfiguration::UserChoice;
cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
cpPriv->roamingSupported = false;
QNetworkConfigurationPrivatePointer ptr(cpPriv);
userChoiceConfigurations.insert(ptr->id, ptr);
updateConfigurations();
updateStatesToSnaps();
updateAvailableAccessPoints(); // On first time updates (without WLAN scans)
// Start monitoring IAP and/or SNAP changes in Symbian CommsDB
startCommsDatabaseNotifications();
}
void SymbianEngine::StartConnectionMonitorNotifyL()
{
iConnectionMonitor.ConnectL();
CleanupClosePushL(iConnectionMonitor);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
User::LeaveIfError(iConnectionMonitor.SetUintAttribute(EBearerIdAll, 0, KBearerGroupThreshold, 1));
#endif
iConnectionMonitor.NotifyEventL(*this);
CleanupStack::Pop();
}
SymbianEngine::~SymbianEngine()
{
Cancel();
//The scanner may be using the connection monitor so it needs to be
//deleted first while the handle is still valid.
delete ipAccessPointsAvailabilityScanner;
iConnectionMonitor.CancelNotifications();
iConnectionMonitor.Close();
// CCommsDatabase destructor and RCmManager.Close() use cleanup stack. Since QNetworkConfigurationManager
// is a global static, but the time we are here, E32Main() has been exited already and
// the thread's default cleanup stack has been deleted. Without this line, a
// 'E32USER-CBase 69' -panic will occur.
CTrapCleanup* cleanup = CTrapCleanup::New();
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
iCmManager.Close();
#endif
delete ipCommsDB;
delete cleanup;
}
void SymbianEngine::delayedConfigurationUpdate()
{
QMutexLocker locker(&mutex);
if (iUpdatePending) {
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug("QNCM delayed configuration update (ECommit or ERecover occurred).");
#endif
TRAPD(error, updateConfigurationsL());
if (error == KErrNone) {
updateStatesToSnaps();
}
iUpdatePending = false;
// Start monitoring again.
if (!IsActive()) {
SetActive();
// Start waiting for new notification
ipCommsDB->RequestNotification(iStatus);
}
}
}
bool SymbianEngine::hasIdentifier(const QString &id)
{
QMutexLocker locker(&mutex);
return accessPointConfigurations.contains(id) ||
snapConfigurations.contains(id) ||
userChoiceConfigurations.contains(id);
}
QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const
{
QNetworkConfigurationManager::Capabilities capFlags;
capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces |
QNetworkConfigurationManager::DirectConnectionRouting |
QNetworkConfigurationManager::SystemSessionSupport |
QNetworkConfigurationManager::DataStatistics |
QNetworkConfigurationManager::NetworkSessionRequired;
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming |
QNetworkConfigurationManager::ForcedRoaming;
#endif
return capFlags;
}
QNetworkSessionPrivate *SymbianEngine::createSessionBackend()
{
return new QNetworkSessionPrivateImpl(this);
}
void SymbianEngine::requestUpdate()
{
QMutexLocker locker(&mutex);
if (!iInitOk || iUpdateGoingOn) {
return;
}
iUpdateGoingOn = true;
stopCommsDatabaseNotifications();
updateConfigurations(); // Synchronous call
updateAvailableAccessPoints(); // Asynchronous call
}
void SymbianEngine::updateConfigurations()
{
if (!iInitOk)
return;
TRAP_IGNORE(updateConfigurationsL());
}
void SymbianEngine::updateConfigurationsL()
{
QList<QString> knownConfigs = accessPointConfigurations.keys();
QList<QString> knownSnapConfigs = snapConfigurations.keys();
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
// S60 version is >= Series60 3rd Edition Feature Pack 2
TInt error = KErrNone;
// Loop through all IAPs
RArray<TUint32> connectionMethods; // IAPs
CleanupClosePushL(connectionMethods);
iCmManager.ConnectionMethodL(connectionMethods);
for(int i = 0; i < connectionMethods.Count(); i++) {
RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]);
CleanupClosePushL(connectionMethod);
TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
if (accessPointConfigurations.contains(ident)) {
knownConfigs.removeOne(ident);
} else {
SymbianNetworkConfigurationPrivate* cpPriv = NULL;
TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
if (error == KErrNone) {
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
if (!iFirstUpdate) {
// Emit configuration added. Connected slots may throw execptions
// which propagate here --> must be converted to leaves (standard
// std::exception would cause any TRAP trapping this function to terminate
// program).
QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
updateStatesToSnaps();
mutex.unlock();
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
mutex.lock();
}
}
}
CleanupStack::PopAndDestroy(&connectionMethod);
}
CleanupStack::PopAndDestroy(&connectionMethods);
// Loop through all SNAPs
RArray<TUint32> destinations;
CleanupClosePushL(destinations);
iCmManager.AllDestinationsL(destinations);
for(int i = 0; i < destinations.Count(); i++) {
RCmDestination destination;
// Some destinatsions require ReadDeviceData -capability (MMS/WAP)
// The below function will leave in these cases. Don't. Proceed to
// next destination (if any).
TRAPD(error, destination = iCmManager.DestinationL(destinations[i]));
if (error == KErrPermissionDenied) {
continue;
} else {
User::LeaveIfError(error);
}
CleanupClosePushL(destination);
QString ident = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX +
QString::number(qHash(destination.Id()));
if (snapConfigurations.contains(ident)) {
knownSnapConfigs.removeOne(ident);
} else {
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
HBufC *pName = destination.NameLC();
QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
CleanupStack::PopAndDestroy(pName);
pName = NULL;
cpPriv->isValid = true;
cpPriv->id = ident;
cpPriv->numericId = destination.Id();
cpPriv->connectionId = 0;
cpPriv->state = QNetworkConfiguration::Defined;
cpPriv->type = QNetworkConfiguration::ServiceNetwork;
cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
cpPriv->roamingSupported = false;
QNetworkConfigurationPrivatePointer ptr(cpPriv);
snapConfigurations.insert(ident, ptr);
if (!iFirstUpdate) {
QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
updateStatesToSnaps();
mutex.unlock();
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
mutex.lock();
}
}
// Loop through all connection methods in this SNAP
QMap<unsigned int, QNetworkConfigurationPrivatePointer> connections;
for (int j=0; j < destination.ConnectionMethodCount(); j++) {
RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
CleanupClosePushL(connectionMethod);
TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
// Check that IAP can be found from accessPointConfigurations list
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
if (!ptr) {
SymbianNetworkConfigurationPrivate *cpPriv = NULL;
TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
if (error == KErrNone) {
ptr = QNetworkConfigurationPrivatePointer(cpPriv);
accessPointConfigurations.insert(ptr->id, ptr);
if (!iFirstUpdate) {
QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
updateStatesToSnaps();
mutex.unlock();
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
mutex.lock();
}
}
} else {
knownConfigs.removeOne(iface);
}
if (ptr) {
unsigned int priority;
TRAPD(error, priority = destination.PriorityL(connectionMethod));
if (!error)
connections.insert(priority, ptr);
}
CleanupStack::PopAndDestroy(&connectionMethod);
}
QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident);
QMutexLocker snapConfigLocker(&privSNAP->mutex);
if (privSNAP->serviceNetworkMembers != connections) {
privSNAP->serviceNetworkMembers = connections;
// Roaming is supported only if SNAP contains more than one IAP
privSNAP->roamingSupported = privSNAP->serviceNetworkMembers.count() > 1;
snapConfigLocker.unlock();
updateStatesToSnaps();
mutex.unlock();
QT_TRYCATCH_LEAVING(emit configurationChanged(privSNAP));
mutex.lock();
}
CleanupStack::PopAndDestroy(&destination);
}
CleanupStack::PopAndDestroy(&destinations);
#else
// S60 version is < Series60 3rd Edition Feature Pack 2
CCommsDbTableView* pDbTView = ipCommsDB->OpenTableLC(TPtrC(IAP));
// Loop through all IAPs
TUint32 apId = 0;
TInt retVal = pDbTView->GotoFirstRecord();
while (retVal == KErrNone) {
pDbTView->ReadUintL(TPtrC(COMMDB_ID), apId);
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
if (accessPointConfigurations.contains(ident)) {
knownConfigs.removeOne(ident);
} else {
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) {
QNetworkConfigurationPrivatePointer ptr(cpPriv);
accessPointConfigurations.insert(ident, ptr);
if (!iFirstUpdate) {
QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
updateStatesToSnaps();
mutex.unlock();
QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
mutex.lock();
}
} else {
delete cpPriv;
}
}
retVal = pDbTView->GotoNextRecord();
}
CleanupStack::PopAndDestroy(pDbTView);
#endif
QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
foreach (const QString &oldIface, knownConfigs) {
//remove non existing IAP
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface);
mutex.unlock();
emit configurationRemoved(ptr);
QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr));
mutex.lock();
// Remove non existing IAP from SNAPs
foreach (const QString &iface, snapConfigurations.keys()) {
QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface);
// => Check if one of the IAPs of the SNAP is active
QMutexLocker snapConfigLocker(&ptr2->mutex);
QMutableMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr2->serviceNetworkMembers);
while (i.hasNext()) {
i.next();
if (toSymbianConfig(i.value())->numericIdentifier() ==
toSymbianConfig(ptr)->numericIdentifier()) {
i.remove();
break;
}
}
}
}
foreach (const QString &oldIface, knownSnapConfigs) {
//remove non existing SNAPs
QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface);
mutex.unlock();
emit configurationRemoved(ptr);
QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr));
mutex.lock();
}
// find default configuration.
stopCommsDatabaseNotifications();
TRAP_IGNORE(defaultConfig = defaultConfigurationL());
startCommsDatabaseNotifications();
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
updateStatesToSnaps();
#endif
}
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL(
RCmConnectionMethod& connectionMethod)
{
SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
CleanupStack::PushL(pName);
QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
CleanupStack::PopAndDestroy(pName);
pName = NULL;
TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
switch (bearerId) {
case KCommDbBearerCSD:
cpPriv->bearerType = QNetworkConfiguration::Bearer2G;
break;
case KCommDbBearerWcdma:
cpPriv->bearerType = QNetworkConfiguration::BearerWCDMA;
break;
case KCommDbBearerLAN:
cpPriv->bearerType = QNetworkConfiguration::BearerEthernet;
break;
case KCommDbBearerVirtual:
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
break;
case KCommDbBearerPAN:
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
break;
case KCommDbBearerWLAN:
cpPriv->bearerType = QNetworkConfiguration::BearerWLAN;
break;
default:
cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
break;
}
TInt error = KErrNone;
TUint32 bearerType = connectionMethod.GetIntAttributeL(CMManager::ECmBearerType);
switch (bearerType) {
case KUidPacketDataBearerType:
// "Packet data" Bearer => Mapping is done using "Access point name"
TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EPacketDataAPName));
break;
case KUidWlanBearerType:
// "Wireless LAN" Bearer => Mapping is done using "WLAN network name" = SSID
TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EWlanSSID));
break;
}
if (!pName) {
// "Data call" Bearer or "High Speed (GSM)" Bearer => Mapping is done using "Dial-up number"
TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
}
if (error == KErrNone && pName) {
CleanupStack::PushL(pName);
QT_TRYCATCH_LEAVING(cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length()));
CleanupStack::PopAndDestroy(pName);
pName = NULL;
}
cpPriv->state = QNetworkConfiguration::Defined;
TBool isConnected = connectionMethod.GetBoolAttributeL(CMManager::ECmConnected);
if (isConnected) {
cpPriv->state = QNetworkConfiguration::Active;
}
cpPriv->isValid = true;
cpPriv->id = ident;
cpPriv->numericId = iapId;
cpPriv->connectionId = 0;
cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
cpPriv->roamingSupported = false;
return cpPriv;
}
#else
bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb(
TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
{
TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration));
if (error != KErrNone) {
return false;
}
return true;
}
void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL(
TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
{
CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB);
CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC();
TBuf<KCommsDbSvrMaxColumnNameLength> name;
CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB);
TUint32 apId = pApUtils->WapIdFromIapIdL(aApId);
pDataHandler->AccessPointDataL(apId,*pAPItem);
pAPItem->ReadTextL(EApIapName, name);
if (name.Compare(_L("Easy WLAN")) == 0) {
// "Easy WLAN" won't be accepted to the Configurations list
User::Leave(KErrNotFound);
}
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(aApId));
QT_TRYCATCH_LEAVING(apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length()));
apNetworkConfiguration->isValid = true;
apNetworkConfiguration->id = ident;
apNetworkConfiguration->numericId = aApId;
apNetworkConfiguration->connectionId = 0;
apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
apNetworkConfiguration->type = QNetworkConfiguration::InternetAccessPoint;
apNetworkConfiguration->purpose = QNetworkConfiguration::UnknownPurpose;
apNetworkConfiguration->roamingSupported = false;
switch (pAPItem->BearerTypeL()) {
case EApBearerTypeCSD:
apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G;
break;
case EApBearerTypeGPRS:
apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G;
break;
case EApBearerTypeHSCSD:
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerHSPA;
break;
case EApBearerTypeCDMA:
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerCDMA2000;
break;
case EApBearerTypeWLAN:
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerWLAN;
break;
case EApBearerTypeLAN:
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet;
break;
case EApBearerTypeLANModem:
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet;
break;
default:
apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerUnknown;
break;
}
CleanupStack::PopAndDestroy(pApUtils);
CleanupStack::PopAndDestroy(pAPItem);
CleanupStack::PopAndDestroy(pDataHandler);
}
#endif
QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration()
{
QMutexLocker locker(&mutex);
return defaultConfig;
}
QStringList SymbianEngine::accessPointConfigurationIdentifiers()
{
QMutexLocker locker(&mutex);
return accessPointConfigurations.keys();
}
QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL()
{
QNetworkConfigurationPrivatePointer ptr;
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
// Check Default Connection (SNAP or IAP)
TCmDefConnValue defaultConnectionValue;
iCmManager.ReadDefConnL(defaultConnectionValue);
if (defaultConnectionValue.iType == ECmDefConnDestination) {
QString iface = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX +
QString::number(qHash(defaultConnectionValue.iId));
ptr = snapConfigurations.value(iface);
} else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) {
QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
QString::number(qHash(defaultConnectionValue.iId));
ptr = accessPointConfigurations.value(iface);
}
#endif
if (ptr) {
QMutexLocker configLocker(&ptr->mutex);
if (ptr->isValid)
return ptr;
}
QString iface = QString::number(qHash(KUserChoiceIAPId));
return userChoiceConfigurations.value(iface);
}
void SymbianEngine::updateActiveAccessPoints()
{
bool online = false;
QList<QString> inactiveConfigs = accessPointConfigurations.keys();
TRequestStatus status;
TUint connectionCount;
iConnectionMonitor.GetConnectionCount(connectionCount, status);
User::WaitForRequest(status);
// Go through all connections and set state of related IAPs to Active.
// Status needs to be checked carefully, because ConnMon lists also e.g.
// WLAN connections that are being currently tried --> we don't want to
// state these as active.
TUint connectionId;
TUint subConnectionCount;
TUint apId;
TInt connectionStatus;
if (status.Int() == KErrNone) {
for (TUint i = 1; i <= connectionCount; i++) {
iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
User::WaitForRequest(status);
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (!ptr) {
// If IAP was not found, check if the update was about EasyWLAN
ptr = configurationFromEasyWlan(apId, connectionId);
// Change the ident correspondingly
if (ptr) {
ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
QString::number(qHash(toSymbianConfig(ptr)->numericIdentifier()));
}
}
#endif
if (ptr) {
iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
User::WaitForRequest(status);
if (connectionStatus == KLinkLayerOpen) {
online = true;
inactiveConfigs.removeOne(ident);
ptr->mutex.lock();
toSymbianConfig(ptr)->connectionId = connectionId;
ptr->mutex.unlock();
// Configuration is Active
changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
}
}
}
}
// Make sure that state of rest of the IAPs won't be Active
foreach (const QString &iface, inactiveConfigs) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
if (ptr) {
// Configuration is either Defined or Discovered
changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
}
}
if (iOnline != online) {
iOnline = online;
mutex.unlock();
emit this->onlineStateChanged(online);
mutex.lock();
}
}
void SymbianEngine::updateAvailableAccessPoints()
{
if (!ipAccessPointsAvailabilityScanner) {
ipAccessPointsAvailabilityScanner = new AccessPointsAvailabilityScanner(*this, iConnectionMonitor);
}
if (ipAccessPointsAvailabilityScanner) {
// Scanning may take a while because WLAN scanning will be done (if device supports WLAN).
ipAccessPointsAvailabilityScanner->StartScanning();
}
}
void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo)
{
iUpdateGoingOn = false;
if (scanSuccessful) {
QList<QString> unavailableConfigs = accessPointConfigurations.keys();
// Set state of returned IAPs to Discovered
// if state is not already Active
for(TUint i=0; i<iapInfo.iCount; i++) {
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
QString::number(qHash(iapInfo.iIap[i].iIapId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
if (ptr) {
unavailableConfigs.removeOne(ident);
QMutexLocker configLocker(&ptr->mutex);
if (ptr->state < QNetworkConfiguration::Active) {
// Configuration is either Discovered or Active
changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
}
}
}
// Make sure that state of rest of the IAPs won't be Active
foreach (const QString &iface, unavailableConfigs) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
if (ptr) {
// Configuration is Defined
changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
}
}
}
updateStatesToSnaps();
if (!iFirstUpdate) {
startCommsDatabaseNotifications();
mutex.unlock();
emit updateCompleted();
mutex.lock();
} else {
iFirstUpdate = false;
if (iScanInQueue) {
iScanInQueue = EFalse;
updateAvailableAccessPoints();
}
}
}
void SymbianEngine::updateStatesToSnaps()
{
// Go through SNAPs and set correct state to SNAPs
foreach (const QString &iface, snapConfigurations.keys()) {
bool discovered = false;
bool active = false;
QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
QMutexLocker snapConfigLocker(&ptr->mutex);
// => Check if one of the IAPs of the SNAP is discovered or active
// => If one of IAPs is active, also SNAP is active
// => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered
QMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr->serviceNetworkMembers);
while (i.hasNext()) {
i.next();
const QNetworkConfigurationPrivatePointer child = i.value();
QMutexLocker configLocker(&child->mutex);
if ((child->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
active = true;
break;
} else if ((child->state & QNetworkConfiguration::Discovered) ==
QNetworkConfiguration::Discovered) {
discovered = true;
}
}
snapConfigLocker.unlock();
if (active) {
changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
} else if (discovered) {
changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
} else {
changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
}
}
}
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
void SymbianEngine::updateMobileBearerToConfigs(TConnMonBearerInfo bearerInfo)
{
QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
accessPointConfigurations.constBegin();
while (i != accessPointConfigurations.constEnd()) {
QNetworkConfigurationPrivatePointer ptr = i.value();
QMutexLocker locker(&ptr->mutex);
SymbianNetworkConfigurationPrivate *p = toSymbianConfig(ptr);
if (p->bearerType >= QNetworkConfiguration::Bearer2G &&
p->bearerType <= QNetworkConfiguration::BearerHSPA) {
switch (bearerInfo) {
case EBearerInfoCSD:
p->bearerType = QNetworkConfiguration::Bearer2G;
break;
case EBearerInfoWCDMA:
p->bearerType = QNetworkConfiguration::BearerWCDMA;
break;
case EBearerInfoCDMA2000:
p->bearerType = QNetworkConfiguration::BearerCDMA2000;
break;
case EBearerInfoGPRS:
p->bearerType = QNetworkConfiguration::Bearer2G;
break;
case EBearerInfoHSCSD:
p->bearerType = QNetworkConfiguration::Bearer2G;
break;
case EBearerInfoEdgeGPRS:
p->bearerType = QNetworkConfiguration::Bearer2G;
break;
case EBearerInfoWcdmaCSD:
p->bearerType = QNetworkConfiguration::BearerWCDMA;
break;
case EBearerInfoHSDPA:
p->bearerType = QNetworkConfiguration::BearerHSPA;
break;
case EBearerInfoHSUPA:
p->bearerType = QNetworkConfiguration::BearerHSPA;
break;
case EBearerInfoHSxPA:
p->bearerType = QNetworkConfiguration::BearerHSPA;
break;
}
}
++i;
}
}
#endif
bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
QNetworkConfiguration::StateFlags newState)
{
ptr->mutex.lock();
if (newState != ptr->state) {
ptr->state = newState;
ptr->mutex.unlock();
mutex.unlock();
emit configurationChanged(ptr);
mutex.lock();
return true;
} else {
ptr->mutex.unlock();
}
return false;
}
/* changeConfigurationStateAtMinTo function does not overwrite possible better
* state (e.g. Discovered state does not overwrite Active state) but
* makes sure that state is at minimum given state.
*/
bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
QNetworkConfiguration::StateFlags newState)
{
ptr->mutex.lock();
if ((newState | ptr->state) != ptr->state) {
ptr->state = (ptr->state | newState);
ptr->mutex.unlock();
mutex.unlock();
emit configurationChanged(ptr);
mutex.lock();
return true;
} else {
ptr->mutex.unlock();
}
return false;
}
/* changeConfigurationStateAtMaxTo function overwrites possible better
* state (e.g. Discovered state overwrites Active state) and
* makes sure that state is at maximum given state (e.g. Discovered state
* does not overwrite Defined state).
*/
bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
QNetworkConfiguration::StateFlags newState)
{
ptr->mutex.lock();
if ((newState & ptr->state) != ptr->state) {
ptr->state = (newState & ptr->state);
ptr->mutex.unlock();
mutex.unlock();
emit configurationChanged(ptr);
mutex.lock();
return true;
} else {
ptr->mutex.unlock();
}
return false;
}
void SymbianEngine::startCommsDatabaseNotifications()
{
if (!iWaitingCommsDatabaseNotifications) {
iWaitingCommsDatabaseNotifications = ETrue;
if (!IsActive()) {
SetActive();
// Start waiting for new notification
ipCommsDB->RequestNotification(iStatus);
}
}
}
void SymbianEngine::stopCommsDatabaseNotifications()
{
if (iWaitingCommsDatabaseNotifications) {
iWaitingCommsDatabaseNotifications = EFalse;
Cancel();
}
}
void SymbianEngine::RunL()
{
QMutexLocker locker(&mutex);
if (iStatus != KErrCancel) {
// By default, start relistening notifications. Stop only if interesting event occurred.
iWaitingCommsDatabaseNotifications = true;
RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
switch (event) {
case RDbNotifier::ECommit: /** A transaction has been committed. */
case RDbNotifier::ERecover: /** The database has been recovered */
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
#endif
// Mark that there is update pending. No need to ask more events,
// as we know we will be updating anyway when the timer expires.
if (!iUpdatePending) {
iUpdatePending = true;
iWaitingCommsDatabaseNotifications = false;
// Update after random time, so that many processes won't
// start updating simultaneously
updateConfigurationsAfterRandomTime();
}
break;
default:
// Do nothing
break;
}
}
if (iWaitingCommsDatabaseNotifications) {
if (!IsActive()) {
SetActive();
// Start waiting for new notification
ipCommsDB->RequestNotification(iStatus);
}
}
}
void SymbianEngine::DoCancel()
{
QMutexLocker locker(&mutex);
ipCommsDB->CancelRequestNotification();
}
void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
{
QMutexLocker locker(&mutex);
switch (aEvent.EventType()) {
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
case EConnMonBearerInfoChange:
{
CConnMonBearerInfoChange* realEvent;
realEvent = (CConnMonBearerInfoChange*) &aEvent;
TUint connectionId = realEvent->ConnectionId();
if (connectionId == EBearerIdAll) {
//Network level event
TConnMonBearerInfo bearerInfo = (TConnMonBearerInfo)realEvent->BearerInfo();
updateMobileBearerToConfigs(bearerInfo);
}
break;
}
#endif
case EConnMonConnectionStatusChange:
{
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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (!ptr) {
// Check if status was regarding EasyWLAN
ptr = configurationFromEasyWlan(apId, connectionId);
}
#endif
if (ptr) {
ptr->mutex.lock();
toSymbianConfig(ptr)->connectionId = connectionId;
ptr->mutex.unlock();
QT_TRYCATCH_LEAVING(
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
connectionId, QNetworkSession::Connecting)
);
}
} 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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (!ptr) {
// Check for EasyWLAN
ptr = configurationFromEasyWlan(apId, connectionId);
}
#endif
if (ptr) {
ptr->mutex.lock();
toSymbianConfig(ptr)->connectionId = connectionId;
ptr->mutex.unlock();
// Configuration is Active
QT_TRYCATCH_LEAVING(
if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) {
updateStatesToSnaps();
}
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
connectionId, QNetworkSession::Connected);
if (!iOnline) {
iOnline = true;
emit this->onlineStateChanged(iOnline);
}
);
}
} else if (connectionStatus == KConfigDaemonStartingDeregistration) {
TUint connectionId = realEvent->ConnectionId();
QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
if (ptr) {
QT_TRYCATCH_LEAVING(
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
connectionId, QNetworkSession::Closing)
);
}
} else if (connectionStatus == KLinkLayerClosed ||
connectionStatus == KConnectionClosed) {
// Connection has been closed. Which of the above events is reported, depends on the Symbian
// platform.
TUint connectionId = realEvent->ConnectionId();
QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
if (ptr) {
// Configuration is either Defined or Discovered
QT_TRYCATCH_LEAVING(
if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
updateStatesToSnaps();
}
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
connectionId, QNetworkSession::Disconnected);
);
}
bool online = false;
foreach (const QString &iface, accessPointConfigurations.keys()) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
QMutexLocker configLocker(&ptr->mutex);
if (ptr->state == QNetworkConfiguration::Active) {
online = true;
break;
}
}
if (iOnline != online) {
iOnline = online;
QT_TRYCATCH_LEAVING(emit this->onlineStateChanged(iOnline));
}
}
}
break;
case EConnMonIapAvailabilityChange:
{
CConnMonIapAvailabilityChange* realEvent;
realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
TConnMonIapInfo iaps = realEvent->IapAvailability();
QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys();
for ( TUint i = 0; i < iaps.Count(); i++ ) {
QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
QString::number(qHash(iaps.iIap[i].iIapId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
if (ptr) {
// Configuration is either Discovered or Active
QT_TRYCATCH_LEAVING(changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered));
unDiscoveredConfigs.removeOne(ident);
}
}
foreach (const QString &iface, unDiscoveredConfigs) {
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
if (ptr) {
// Configuration is Defined
QT_TRYCATCH_LEAVING(changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined));
}
}
// Something has in IAPs, update states to SNAPs
updateStatesToSnaps();
}
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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
if (!ptr) {
// If IAP was not found, check if the update was about EasyWLAN
ptr = configurationFromEasyWlan(apId, connectionId);
}
#endif
if (ptr) {
QMutexLocker configLocker(&ptr->mutex);
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name;
#endif
toSymbianConfig(ptr)->connectionId = connectionId;
}
}
break;
default:
// For unrecognized events
break;
}
}
/*
Returns the network configuration that matches the given SSID.
*/
QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromSsid(const QString &ssid)
{
QMutexLocker locker(&mutex);
// Browser through all items and check their name for match
QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i =
accessPointConfigurations.constBegin();
while (i != accessPointConfigurations.constEnd()) {
QNetworkConfigurationPrivatePointer ptr = i.value();
QMutexLocker configLocker(&ptr->mutex);
if (ptr->name == ssid) {
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNCM EasyWlan uses real SSID: " << ssid;
#endif
return ptr;
}
++i;
}
return QNetworkConfigurationPrivatePointer();
}
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
// Tries to derive configuration from EasyWLAN.
// First checks if the interface brought up was EasyWLAN, then derives the real SSID,
// and looks up configuration based on that one.
QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUint32 apId,
TUint connectionId)
{
if (apId == iCmManager.EasyWlanIdL()) {
TRequestStatus status;
TBuf<50> easyWlanNetworkName;
iConnectionMonitor.GetStringAttribute( connectionId, 0, KNetworkName,
easyWlanNetworkName, status );
User::WaitForRequest(status);
if (status.Int() == KErrNone) {
const QString realSSID = QString::fromUtf16(easyWlanNetworkName.Ptr(),
easyWlanNetworkName.Length());
// Browser through all items and check their name for match
QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i =
accessPointConfigurations.constBegin();
while (i != accessPointConfigurations.constEnd()) {
QNetworkConfigurationPrivatePointer ptr = i.value();
QMutexLocker configLocker(&ptr->mutex);
if (ptr->name == realSSID) {
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug() << "QNCM EasyWlan uses real SSID: " << realSSID;
#endif
return ptr;
}
++i;
}
}
}
return QNetworkConfigurationPrivatePointer();
}
#endif
// Sessions may use this function to report configuration state changes,
// because on some Symbian platforms (especially Symbian^3) all state changes are not
// reported by the RConnectionMonitor, in particular in relation to stop() call,
// whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
// this data here so that other sessions may benefit from it too (not all sessions necessarily have
// RConnection progress notifiers available but they relay on having e.g. disconnected information from
// manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
{
QMutexLocker locker(&mutex);
#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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
QString::number(qHash(accessPointId));
QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
if (ptr) {
// Configuration is either Defined or Discovered
if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
updateStatesToSnaps();
}
locker.unlock();
emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
toSymbianConfig(ptr)->connectionIdentifier(),
QNetworkSession::Disconnected);
locker.relock();
}
}
break;
default:
break;
}
}
// Waits for 2..6 seconds.
void SymbianEngine::updateConfigurationsAfterRandomTime()
{
int iTimeToWait = qMax(1000, (qAbs(qrand()) % 68) * 100);
#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
qDebug("QNCM waiting random time: %d ms", iTimeToWait);
#endif
QTimer::singleShot(iTimeToWait, this, SLOT(delayedConfigurationUpdate()));
}
QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
{
QNetworkConfiguration item;
QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
accessPointConfigurations.constBegin();
while (i != accessPointConfigurations.constEnd()) {
QNetworkConfigurationPrivatePointer ptr = i.value();
if (toSymbianConfig(ptr)->connectionIdentifier() == aConnectionId)
return ptr;
++i;
}
return QNetworkConfigurationPrivatePointer();
}
AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner,
RConnectionMonitor& connectionMonitor)
: CActive(CActive::EPriorityHigh), iOwner(owner), iConnectionMonitor(connectionMonitor)
{
CActiveScheduler::Add(this);
}
AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
{
Cancel();
}
void AccessPointsAvailabilityScanner::DoCancel()
{
iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute);
iScanActive = EFalse;
iOwner.iScanInQueue = EFalse;
}
void AccessPointsAvailabilityScanner::StartScanning()
{
if (!iScanActive) {
iScanActive = ETrue;
if (iOwner.iFirstUpdate) {
// On first update (the mgr is being instantiated) update only those bearers who
// don't need time-consuming scans (WLAN).
// Note: EBearerIdWCDMA covers also GPRS bearer
iConnectionMonitor.GetPckgAttribute(EBearerIdWCDMA, 0, KIapAvailability, iIapBuf, iStatus);
} else {
iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus);
}
if (!IsActive()) {
SetActive();
}
} else {
// Queue scan for getting WLAN info after first request returns
if (iOwner.iFirstUpdate) {
iOwner.iScanInQueue = ETrue;
}
}
}
void AccessPointsAvailabilityScanner::RunL()
{
QMutexLocker locker(&iOwner.mutex);
iScanActive = EFalse;
if (iStatus.Int() != KErrNone) {
iIapBuf().iCount = 0;
QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(false,iIapBuf()));
} else {
QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(true,iIapBuf()));
}
}
QT_END_NAMESPACE
#endif // QT_NO_BEARERMANAGEMENT