--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectionmonitoring/connmon/connectionmonitor/src/connmoncommsdatcache.cpp Thu Dec 17 08:55:21 2009 +0200
@@ -0,0 +1,2046 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: Provides cached information on IAPs and SNAPs in CommsDat.
+*
+*/
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <commsdat_partner.h>
+#endif
+#include <datamobilitycommsdattypes.h>
+
+#include "ConnMonServ.h"
+#include "CEventQueue.h"
+#include "ConnMonIAP.h"
+#include "ConnMonBearer.h"
+#include "connmoncommsdatcache.h"
+#include "log.h"
+
+using namespace CommsDat;
+
+TConnMonSnapEntry::TConnMonSnapEntry()
+ {
+ iId = 0;
+ iNextLayerIapId = 0;
+ iNextLayerSnapId = 0;
+ iAvailability = 0;
+ iNextLayerIndex = KErrNotFound;
+ }
+
+TConnMonSnapEntry::TConnMonSnapEntry(
+ TUint aId,
+ TUint aNextLayerIapId,
+ TUint aNextLayerSnapId )
+ :
+ iId( aId ),
+ iNextLayerIapId( aNextLayerIapId ),
+ iNextLayerSnapId( aNextLayerSnapId )
+ {
+ iAvailability = 0;
+ iNextLayerIndex = KErrNotFound;
+ }
+
+TInt TConnMonSnapEntry::Compare(
+ const TConnMonSnapEntry& aFirst,
+ const TConnMonSnapEntry& aSecond )
+ {
+ // Availability info is ignored
+ if ( aFirst.iId < aSecond.iId ) return -1;
+ if ( aFirst.iId > aSecond.iId ) return 1;
+ if ( aFirst.iNextLayerSnapId < aSecond.iNextLayerSnapId ) return -1;
+ if ( aFirst.iNextLayerSnapId > aSecond.iNextLayerSnapId ) return 1;
+ if ( aFirst.iNextLayerIapId < aSecond.iNextLayerIapId ) return -1;
+ if ( aFirst.iNextLayerIapId > aSecond.iNextLayerIapId ) return 1;
+ return 0;
+ }
+
+TInt TConnMonSnapEntry::FindCompare(
+ const TInt* aKey,
+ const TConnMonSnapEntry& aEntry )
+ {
+ // Zero if match, negative if first is smaller, positive otherwise
+ return ( *aKey ) - aEntry.iId;
+ }
+
+TBool TConnMonSnapEntry::Match(
+ const TConnMonSnapEntry& aFirst,
+ const TConnMonSnapEntry& aSecond )
+ {
+ // Availability info is ignored
+ if ( ( aFirst.iId == aSecond.iId ) &&
+ ( aFirst.iNextLayerIapId == aSecond.iNextLayerIapId ) &&
+ ( aFirst.iNextLayerSnapId == aSecond.iNextLayerSnapId ) )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+
+TConnMonIapEntry::TConnMonIapEntry()
+ {
+ iId = 0;
+ iBearerType = 0;
+ iServiceType = 0;
+ iAvailability = 0;
+ iNextLayerIapId = 0;
+ iNextLayerSnapId = 0;
+ iNextLayerIndex = KErrNotFound;
+ }
+
+TConnMonIapEntry::TConnMonIapEntry(
+ TUint aId,
+ TUint aBearerType,
+ TUint aServiceType )
+ :
+ iId( aId ),
+ iBearerType( aBearerType ),
+ iServiceType( aServiceType )
+ {
+ iAvailability = 0;
+ iNextLayerIndex = KErrNotFound;
+ iNextLayerIapId = 0;
+ iNextLayerSnapId = 0;
+ }
+
+TInt TConnMonIapEntry::Compare(
+ const TConnMonIapEntry& aFirst,
+ const TConnMonIapEntry& aSecond )
+ {
+ // Zero if match, negative if first is smaller, positive otherwise
+ // Availability info is ignored
+ return aFirst.iId - aSecond.iId;
+ }
+
+TInt TConnMonIapEntry::FindCompare(
+ const TInt* aKey,
+ const TConnMonIapEntry& aEntry )
+ {
+ // Zero if match, negative if first is smaller, positive otherwise
+ return ( *aKey ) - aEntry.iId;
+ }
+
+TBool TConnMonIapEntry::Match(
+ const TConnMonIapEntry& aFirst,
+ const TConnMonIapEntry& aSecond )
+ {
+ // Availability info is ignored
+ if ( ( aFirst.iId == aSecond.iId ) &&
+ ( aFirst.iBearerType == aSecond.iBearerType ) &&
+ ( aFirst.iServiceType == aSecond.iServiceType ) )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+
+TConnMonVirtualIapEntry::TConnMonVirtualIapEntry()
+ {
+ iId = 0;
+ iNextLayerIapId = 0;
+ iNextLayerSnapId = 0;
+ }
+
+TConnMonVirtualIapEntry::TConnMonVirtualIapEntry(
+ TUint aId,
+ TUint aNextLayerIapId,
+ TUint aNextLayerSnapId )
+ :
+ iId( aId ),
+ iNextLayerIapId( aNextLayerIapId ),
+ iNextLayerSnapId( aNextLayerSnapId )
+ {
+ }
+
+TInt TConnMonVirtualIapEntry::Compare(
+ const TConnMonVirtualIapEntry& aFirst,
+ const TConnMonVirtualIapEntry& aSecond )
+ {
+ // Zero if match, negative if first is smaller, positive otherwise
+ return aFirst.iId - aSecond.iId;
+ }
+
+TInt TConnMonVirtualIapEntry::FindCompare(
+ const TInt* aKey,
+ const TConnMonVirtualIapEntry& aEntry )
+ {
+ // Zero if match, negative if first is smaller, positive otherwise
+ return ( *aKey ) - aEntry.iId;
+ }
+
+TBool TConnMonVirtualIapEntry::Match(
+ const TConnMonVirtualIapEntry& aFirst,
+ const TConnMonVirtualIapEntry& aSecond )
+ {
+ if ( ( aFirst.iId == aSecond.iId ) &&
+ ( aFirst.iNextLayerIapId == aSecond.iNextLayerIapId ) &&
+ ( aFirst.iNextLayerSnapId == aSecond.iNextLayerSnapId ) )
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+
+// ---------------------------------------------------------------------------
+// Two phased constructor.
+// ---------------------------------------------------------------------------
+//
+CConnMonCommsDatCache* CConnMonCommsDatCache::NewL()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::NewL()")
+
+ CConnMonCommsDatCache* self = CConnMonCommsDatCache::NewLC();
+ CleanupStack::Pop( self );
+
+ //LOGEXITFN("CConnMonCommsDatCache::NewL()")
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two phased constructor.
+// ---------------------------------------------------------------------------
+//
+CConnMonCommsDatCache* CConnMonCommsDatCache::NewLC()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::NewLC()")
+
+ CConnMonCommsDatCache* self = new( ELeave ) CConnMonCommsDatCache;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+
+ //LOGEXITFN("CConnMonCommsDatCache::NewLC()")
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor.
+// ---------------------------------------------------------------------------
+//
+CConnMonCommsDatCache::~CConnMonCommsDatCache()
+ {
+ LOGENTRFN("CConnMonCommsDatCache::~CConnMonCommsDatCache()")
+
+ if ( iSnapCache )
+ {
+ iSnapCache->Close();
+ delete iSnapCache;
+ iSnapCache = NULL;
+ }
+ if ( iIapCache )
+ {
+ iIapCache->Close();
+ delete iIapCache;
+ iIapCache = NULL;
+ }
+ if ( iVirtualIapCache )
+ {
+ iVirtualIapCache->Close();
+ delete iVirtualIapCache;
+ iVirtualIapCache = NULL;
+ }
+
+ iWlanIapIdCache.Close();
+ iIapIdCache.Close();
+ iSnapIdCache.Close();
+
+ LOGEXITFN("CConnMonCommsDatCache::~CConnMonCommsDatCache()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all IAP and SNAP information from CommsDat and initializes the cache
+// with it.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::Init(
+ CConnMonServer* aServer,
+ CConnMonIAP* aConnMonIap,
+ RPointerArray<TConnMonBearer>* aBearers )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::Init()")
+
+ iServer = aServer;
+ iIap = aConnMonIap;
+ iBearers = aBearers;
+
+ if ( iInitStatus != EConnMonCacheInitNotStarted )
+ {
+ LOGIT("Init: ERROR, ConnMon CommsDat cache init called too many times")
+ return;
+ }
+ iInitStatus = EConnMonCacheInitInProgress;
+
+ // Check if WLAN bearer is available
+ for ( TInt i = 0; i < iBearers->Count(); i++ )
+ {
+ if ( (*iBearers)[i]->BearerId() == EBearerIdWLAN )
+ {
+ iWlanSupportEnabled = ETrue;
+ break;
+ }
+ }
+
+ TRAPD( leaveCode, InitCommsDatCacheL() );
+ if ( leaveCode )
+ {
+ LOGIT1("Init: ERROR (Ok if empty), LEAVE in ConnMon CommsDat cache init <%d>", leaveCode)
+ }
+
+ RefreshAvailabilityInfo( EFalse ); // Never send events in Init phase
+ iInitStatus = EConnMonCacheInitCompleted;
+
+ LOGEXITFN("CConnMonCommsDatCache::Init()")
+ }
+
+// ---------------------------------------------------------------------------
+// Calls the correct method to read the CommsDat table, refered to with
+// parameter aTableId, to cache. This should be called when a change is
+// detected in CommsDat through central repository events.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::RefreshCommsDatCacheL( const TUint32 aTableId )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::RefreshCommsDatCacheL()")
+
+ CMDBSession* db = CMDBSession::NewLC( CMDBSession::LatestVersion() );
+ db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+ if ( aTableId == iIapRecordTableId )
+ {
+ LOGIT("RefreshCommsDatCacheL: IAP table change event")
+ RefreshCommsDatIapCacheL( *db );
+ }
+ else if ( aTableId == iSnapRecordTableId )
+ {
+ LOGIT("RefreshCommsDatCacheL: SNAP table change event")
+ RefreshCommsDatSnapCacheL( *db );
+ }
+ else if ( aTableId == iVirtualRecordTableId )
+ {
+ LOGIT("RefreshCommsDatCacheL: Virtual record table change event")
+ RefreshCommsDatVirtualIapCacheL( *db );
+ }
+ else if ( aTableId == 0 )
+ {
+ // This option is not currently used, but provided to support the
+ // possibility to read CommsDat information again when client is
+ // asking for IAP/SNAP availability information as a request.
+ // This would be needed in the case that CenRep change events
+ // become unreliable for some reason, and thus the CommsDat cache
+ // would not be reliably up to date.
+ LOGIT("RefreshCommsDatCacheL: Reading all commsdat tables")
+ RefreshCommsDatIapCacheL( *db );
+ RefreshCommsDatSnapCacheL( *db );
+ RefreshCommsDatVirtualIapCacheL( *db );
+ }
+
+ CleanupStack::PopAndDestroy( db );
+
+ //LOGEXITFN("CConnMonCommsDatCache::RefreshCommsDatCacheL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Solves IAP and SNAP availability. The availability information in the cache
+// tables will be up to date after a call to this method.
+// If parameter aCanSendEvents is true, availability changed events will be
+// sent to clients if any changes from previous availability state is detected.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::RefreshAvailabilityInfo( const TBool aCanSendEvents )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::RefreshAvailabilityInfo()")
+
+ // If any relevant commsdat table changed.
+ //
+ // These flags are set to true only when CommsDat change event is received,
+ // CommsDat information is read into ConnMon cache, and that information
+ // has changed.
+ if ( iIapsChanged || iSnapsChanged || iVirtualIapsChanged )
+ {
+ UpdateSnapAndVirtualIapLinks();
+ iIapsChanged = EFalse;
+ iSnapsChanged = EFalse;
+ iVirtualIapsChanged = EFalse;
+ }
+
+ ResetAllAvailabilityInfo();
+ for ( TInt i = 0; i < iBearers->Count(); i++ )
+ {
+ (*iBearers)[i]->FlagAvailableIaps();
+ }
+ SolveSnapAndVirtualIapAvailability();
+
+ LOGIT(".")
+ TBool availableIapsChanged = UpdateAvailableIaps();
+
+ #ifdef _DEBUG
+ // Print available IAP IDs to log
+ for ( TInt j = 0; j < iIapCache->Count(); j++ )
+ {
+ if ( (*iIapCache)[j].iAvailability == EConnMonAvailabilityAvailable )
+ {
+ TUint currentId = (*iIapCache)[j].iId;
+ if ( (*iIapCache)[j].iBearerType == EConnMonCacheBearerTypeVirtual )
+ {
+ switch ( (*iIapCache)[j].iServiceType )
+ {
+ case EConnMonCacheServiceTypeCsd:
+ LOGIT1(" %3d: CSD, virtual", currentId) break;
+ case EConnMonCacheServiceTypeGprs:
+ LOGIT1(" %3d: GPRS, virtual", currentId) break;
+ case EConnMonCacheServiceTypeLan:
+ LOGIT1(" %3d: LAN, virtual", currentId) break;
+ case EConnMonCacheServiceTypeWlan:
+ LOGIT1(" %3d: WLAN, virtual", currentId) break;
+ default:
+ LOGIT1(" %3d: Unknown, virtual", currentId) break;
+ }
+ }
+ else
+ {
+ switch ( (*iIapCache)[j].iServiceType )
+ {
+ case EConnMonCacheServiceTypeCsd:
+ LOGIT1(" %3d: CSD", currentId) break;
+ case EConnMonCacheServiceTypeGprs:
+ LOGIT1(" %3d: GPRS", currentId) break;
+ case EConnMonCacheServiceTypeLan:
+ LOGIT1(" %3d: LAN", currentId) break;
+ case EConnMonCacheServiceTypeWlan:
+ LOGIT1(" %3d: WLAN", currentId) break;
+ default:
+ LOGIT1(" %3d: Unknown", currentId) break;
+ }
+ }
+ }
+ }
+ #endif // _DEBUG
+
+ TBool availableSnapsChanged = UpdateAvailableSnaps();
+
+ // Print available SNAP IDs to log
+ #ifdef _DEBUG
+ TUint lastSnapId( 0 );
+ for ( TInt k = 0; k < iSnapCache->Count(); k++ )
+ {
+ TUint currentId = (*iSnapCache)[k].iId;
+ if ( currentId != lastSnapId )
+ {
+ lastSnapId = currentId;
+ if ( (*iSnapCache)[k].iAvailability == EConnMonAvailabilityAvailable )
+ {
+ LOGIT1(" %4d", currentId)
+ }
+ }
+ }
+ LOGIT(".")
+ #endif // _DEBUG
+
+ if ( aCanSendEvents )
+ {
+ if ( availableIapsChanged )
+ {
+ LOGIT("RefreshAvailabilityInfo: sending IAP availability event")
+ SendIapAvailabilityEvent();
+ }
+ if ( availableSnapsChanged )
+ {
+ LOGIT("RefreshAvailabilityInfo: sending SNAP availability event")
+ SendSnapAvailabilityEvent();
+ }
+ }
+
+ LOGEXITFN("CConnMonCommsDatCache::RefreshAvailabilityInfo()")
+ }
+
+// ---------------------------------------------------------------------------
+// Set as available all IAPs which correspond to the given bearer ID
+// (converted to service type).
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::SetAvailableIapsWithBearerId( const TUint aBearerId )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::SetAvailableIapsWithBearerId()")
+ TInt err( KErrNone );
+
+ TUint serviceType;
+ err = ConvertBearerIdToServiceType( aBearerId, serviceType );
+
+ if ( !err )
+ {
+ const TInt iapCount = iIapCache->Count();
+ for ( TInt i = 0; i < iapCount; i++ )
+ {
+ if ( (*iIapCache)[i].iServiceType == serviceType )
+ {
+ (*iIapCache)[i].iAvailability = EConnMonAvailabilityAvailable;
+ }
+ }
+ }
+
+ //LOGEXITFN("CConnMonCommsDatCache::SetAvailableIapsWithBearerId()")
+ }
+
+// ---------------------------------------------------------------------------
+// Set as available the IAP with matching ID.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::SetAvailableIapWithId( const TUint aId )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::SetAvailableIapWithId()")
+
+ TInt index = iIapCache->FindInOrder<TInt>( aId, TConnMonIapEntry::FindCompare );
+ if ( index >= 0)
+ {
+ (*iIapCache)[index].iAvailability = EConnMonAvailabilityAvailable;
+ }
+
+ //LOGEXITFN("CConnMonCommsDatCache::SetAvailableIapWithId()")
+ }
+
+// ---------------------------------------------------------------------------
+// Get available IAP IDs for the requested bearer ID. IAP availability is
+// re-solved first.
+// Maximum number of IAP IDs is limited by KConnMonMaxIAPCount.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::GetAvailableIaps(
+ const TUint aBearerId,
+ TConnMonIapInfo& aIapInfo )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::GetAvailableIaps()")
+ TInt err( KErrNone );
+
+ TBool availabilityEventsEnabled( EFalse );
+ if ( ( aBearerId == EBearerIdAll ) || ( aBearerId == EBearerIdVirtualVPN ) )
+ {
+ // If WLAN background scanning is on, and client is asking IAP
+ // availability for all- or virtual IAPs, send IAP availability changed
+ // events if any changes detected.
+ TRAPD( traperr, availabilityEventsEnabled = IsWlanBackgroundScanningEnabledL() );
+ if ( traperr )
+ {
+ // If error here, continue as WLAN background scanning is disabled.
+ availabilityEventsEnabled = EFalse;
+ LOGIT1("ERROR, WLAN background scan discovery failed with <%d>", traperr)
+ }
+ }
+
+ RefreshAvailabilityInfo( availabilityEventsEnabled );
+
+ TInt iapCount( 0 );
+ TUint bearerType( 0 );
+ TUint serviceType( 0 );
+ TBool done( EFalse );
+
+ switch ( aBearerId )
+ {
+ case EBearerIdAll:
+ {
+ iapCount = iIapIdCache.Count();
+ if ( iapCount > KConnMonMaxIAPCount )
+ {
+ iapCount = KConnMonMaxIAPCount;
+ }
+ aIapInfo.iCount = iapCount;
+ for ( TInt i = 0; i < iapCount; i++ )
+ {
+ aIapInfo.iIap[i].iIapId = iIapIdCache[i];
+ }
+ done = ETrue;
+ }
+ break;
+ case EBearerIdGPRS:
+ case EBearerIdWCDMA:
+ serviceType = EConnMonCacheServiceTypeGprs;
+ break;
+ case EBearerIdWLAN:
+ serviceType = EConnMonCacheServiceTypeWlan;
+ break;
+ case EBearerIdCSD:
+ case EBearerIdWcdmaCSD:
+ serviceType = EConnMonCacheServiceTypeCsd;
+ break;
+ case EBearerIdVirtualVPN:
+ bearerType = EConnMonCacheBearerTypeVirtual;
+ break;
+ case EBearerIdLAN:
+ serviceType = EConnMonCacheServiceTypeLan;
+ break;
+ default:
+ err = KErrArgument;
+ done = ETrue;
+ break;
+ }
+
+ if ( !done )
+ {
+ TInt totalCount = iIapCache->Count();
+ for ( TInt i = 0; i < totalCount && iapCount < KConnMonMaxIAPCount; i++ )
+ {
+ if ( serviceType )
+ {
+ if ( (*iIapCache)[i].iAvailability == EConnMonAvailabilityAvailable &&
+ (*iIapCache)[i].iServiceType == serviceType )
+ {
+ aIapInfo.iIap[iapCount].iIapId = (*iIapCache)[i].iId;
+ iapCount++;
+ }
+ }
+ else if ( bearerType )
+ {
+ if ( (*iIapCache)[i].iAvailability == EConnMonAvailabilityAvailable &&
+ (*iIapCache)[i].iBearerType == bearerType )
+ {
+ aIapInfo.iIap[iapCount].iIapId = (*iIapCache)[i].iId;
+ iapCount++;
+ }
+ }
+ }
+ aIapInfo.iCount = iapCount;
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::GetAvailableIaps()", err)
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Get available SNAP IDs. SNAP availability is re-solved first.
+// Maximum number of SNAP IDs is limited by KConnMonMaxSNAPsCount.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::GetAvailableSnaps( TConnMonSNAPInfo& aSnapInfo )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::GetAvailableSnaps()")
+
+ TBool availabilityEventsEnabled( EFalse );
+ // If WLAN background scanning is on, and client is asking SNAP
+ // availability, send SNAP availability changed events if any changes
+ // detected.
+ TRAPD( traperr, availabilityEventsEnabled = IsWlanBackgroundScanningEnabledL() );
+ if ( traperr )
+ {
+ // If error here, continue as WLAN background scanning is disabled.
+ availabilityEventsEnabled = EFalse;
+ LOGIT1("ERROR, WLAN background scan discovery failed: <%d>", traperr)
+ }
+
+ RefreshAvailabilityInfo( availabilityEventsEnabled );
+
+ TInt snapCount = iSnapIdCache.Count();
+ if ( snapCount > KConnMonMaxSNAPsCount )
+ {
+ snapCount = KConnMonMaxSNAPsCount;
+ }
+ aSnapInfo.iCount = snapCount;
+ for ( TInt i = 0; i < snapCount; i++ )
+ {
+ aSnapInfo.iSNAP[i].iSNAPId = iSnapIdCache[i];
+ }
+
+ LOGEXITFN("CConnMonCommsDatCache::GetAvailableSnaps()")
+ }
+
+// ---------------------------------------------------------------------------
+// Get available SNAP IDs. SNAP availability is re-solved first.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::GetAvailableSnaps( RArray<TConnMonId>& aSnapIds )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::GetAvailableSnaps()")
+
+ TBool availabilityEventsEnabled( EFalse );
+ // If WLAN background scanning is on, and client is asking SNAP
+ // availability, send SNAP availability changed events if any changes
+ // detected.
+ TRAPD( traperr, availabilityEventsEnabled = IsWlanBackgroundScanningEnabledL() );
+ if ( traperr )
+ {
+ // If error here, continue as WLAN background scanning is disabled.
+ availabilityEventsEnabled = EFalse;
+ LOGIT1("ERROR, WLAN background scan discovery failed: <%d>", traperr)
+ }
+
+ RefreshAvailabilityInfo( availabilityEventsEnabled );
+
+ // Return KErrNoMemory only if RArray fails to allocate memory, KErrNone otherwise
+ TInt err( KErrNone );
+ err = aSnapIds.Reserve( iSnapIdCache.Count() );
+ if ( !err )
+ {
+ for ( TInt i = 0; i < iSnapIdCache.Count(); i++ )
+ {
+ aSnapIds.Append( TConnMonId( iSnapIdCache[i] ) );
+ }
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::GetAvailableSnaps()", err)
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CConnMonCommsDatCache::CConnMonCommsDatCache()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::CConnMonCommsDatCache()")
+ //LOGEXITFN("CConnMonCommsDatCache::CConnMonCommsDatCache()")
+ }
+
+// ---------------------------------------------------------------------------
+// 2nd phase constructor
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ConstructL()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::ConstructL()")
+
+ iIap = NULL;
+ iInitStatus = EConnMonCacheInitNotStarted;
+ iVirtualIapCount = 0;
+ iWlanSupportEnabled = EFalse; // Set in Init()-method
+
+ iIapsChanged = EFalse;
+ iSnapsChanged = EFalse;
+ iVirtualIapsChanged = EFalse;
+
+ iIapRecordTableId = KCDTIdIAPRecord;
+ iSnapRecordTableId = 0; // Read from CommsDat when needed for first time
+ iVirtualRecordTableId = 0; // Read from CommsDat when needed for first time
+
+ iIapCache = new( ELeave ) RArray<TConnMonIapEntry>();
+ iSnapCache = new( ELeave ) RArray<TConnMonSnapEntry>();
+ iVirtualIapCache = new( ELeave ) RArray<TConnMonVirtualIapEntry>();
+
+ //LOGEXITFN("CConnMonCommsDatCache::ConstructL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all relevant CommsDat information to cache and initializes the SNAP
+// and virtual IAP table IDs.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::InitCommsDatCacheL()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::InitCommsDatCacheL()")
+
+ CMDBSession* db = CMDBSession::NewLC( CMDBSession::LatestVersion() );
+ db->SetAttributeMask( ECDHidden | ECDProtectedWrite );
+
+ // Find out the table IDs for CCDDataMobilitySelectionPolicyRecord and
+ // CCDVirtualIAPNextLayerRecord, only need to do this once.
+ iVirtualRecordTableId = CCDVirtualIAPNextLayerRecord::TableIdL( *db );
+ iSnapRecordTableId = CCDDataMobilitySelectionPolicyRecord::TableIdL( *db );
+
+ LOGIT("InitCommsDatCacheL: reading commsdat tables")
+ RefreshCommsDatIapCacheL( *db );
+ RefreshCommsDatSnapCacheL( *db );
+ RefreshCommsDatVirtualIapCacheL( *db );
+
+ CleanupStack::PopAndDestroy( db );
+
+ //LOGEXITFN("CConnMonCommsDatCache::InitCommsDatCacheL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all IAP information from CommsDat and updates the cache if necessary.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::RefreshCommsDatIapCacheL( CMDBSession& aDb )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::RefreshCommsDatIapCacheL()")
+
+ // Will only leave if device runs out of memory or LoadL fails on IAP
+ // record set. This will result in an empty IAP cache and thus no IAP
+ // will be reported available through ConnMon API.
+
+ RArray<TUint> currentWlanIapIds;
+ CleanupClosePushL( currentWlanIapIds );
+
+ RArray<TConnMonIapEntry>* currentIapData;
+ if ( iInitStatus == EConnMonCacheInitCompleted )
+ {
+ // Array to read current CommsDat info into.
+ currentIapData = new( ELeave ) RArray<TConnMonIapEntry>; // Heap used by design
+ CleanupClosePushL( *currentIapData );
+ }
+ else
+ {
+ // Init-phase, read current CommsDat info directly into cache array,
+ // since it is still empty. Then stop (don't send any events).
+ iWlanIapIdCache.Reset();
+ currentIapData = iIapCache;
+ }
+ currentIapData->Reset();
+
+ ReadCommsDatIapTableL( aDb, *currentIapData, currentWlanIapIds );
+
+ if ( iInitStatus != EConnMonCacheInitCompleted )
+ {
+ // This is Init pass. CommsDat has been read and stored in cache. return now.
+ // Note, currentIapData not in cleanup stack
+
+ // If no WLAN, this will just be an empty array
+ DeepCopy( currentWlanIapIds, iWlanIapIdCache );
+ CleanupStack::Pop( ¤tWlanIapIds );
+ currentWlanIapIds.Close();
+
+ iIapsChanged = ETrue;
+ LOGEXITFN1("CConnMonCommsDatCache::RefreshCommsDatIapCache()", iIapsChanged)
+ return iIapsChanged;
+ }
+
+ CleanupStack::Pop( currentIapData );
+ iIapsChanged = EFalse;
+
+ // WLAN IAPs are most likely to change. Check those first for changes.
+ if ( iWlanSupportEnabled )
+ {
+ iIapsChanged = CompareSortedArrays( currentWlanIapIds, iWlanIapIdCache );
+ if ( iIapsChanged )
+ {
+ if ( iIap )
+ {
+ iIap->EnableWlanScan(); // Important
+ }
+ DeepCopy( currentWlanIapIds, iWlanIapIdCache );
+ }
+ }
+ CleanupStack::Pop( ¤tWlanIapIds );
+ currentWlanIapIds.Close();
+
+ // If WLAN IAPs didn't change, check the rest of the IAPs for changes.
+ if ( !iIapsChanged )
+ {
+ iIapsChanged = CompareSortedArrays( *currentIapData, *iIapCache );
+ }
+
+ // Delete the obsolete IAP cache table. Either the new table that was just
+ // read, or the old table if the new one is different.
+ if ( iIapsChanged )
+ {
+ iIapCache->Close();
+ delete iIapCache;
+ iIapCache = currentIapData;
+ LOGIT("RefreshCommsDatIapCacheL: updated IAP cache")
+ }
+ else
+ {
+ currentIapData->Close();
+ delete currentIapData;
+ currentIapData = NULL;
+ LOGIT("RefreshCommsDatIapCacheL: IAP cache did not change")
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::RefreshCommsDatIapCacheL()", iIapsChanged)
+ return iIapsChanged;
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all IAP table information from CommsDat into an array.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ReadCommsDatIapTableL(
+ CMDBSession& aDb,
+ RArray<TConnMonIapEntry>& aCurrentIapData,
+ RArray<TUint>& aCurrentWlanIapIds )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::ReadCommsDatIapTableL()")
+
+ // Explicitly build a TLinearOrder<class>. Used as parameter to RArray::InsertInOrder().
+ TLinearOrder<TConnMonIapEntry> iapEntryOrderingLogic( TConnMonIapEntry::Compare );
+
+ CMDBRecordSet<CCDIAPRecord>* ptrIapRecordSet = new( ELeave )
+ CMDBRecordSet<CCDIAPRecord>( iIapRecordTableId );
+ CleanupStack::PushL( ptrIapRecordSet );
+ ptrIapRecordSet->LoadL( aDb );
+
+ // Check LAN bearer table for WLAN bearer entries and store results in array.
+ // This information is used to separate LAN and WLAN IAPs from each other.
+ RArray<TLanBearerEntry> lanBearerTableCache;
+ CleanupClosePushL( lanBearerTableCache );
+ TRAPD( leaveCode, ReadCommsDatLanBearerTableL( aDb, lanBearerTableCache ) );
+ if ( leaveCode )
+ {
+ LOGIT1("ERROR reading LAN bearer table, LEAVE with <%d>", leaveCode)
+ lanBearerTableCache.Reset();
+ }
+
+ iVirtualIapCount = 0;
+ TInt iapRecordCount( ptrIapRecordSet->iRecords.Count() );
+ LOGIT1("ReadCommsDatIapTableL: IAP record count %d (commsdat)", iapRecordCount)
+
+ TUint iapId( 0 );
+ TUint bearerType( 0 );
+ TUint serviceType( 0 );
+
+ for ( TInt i = 0; i < iapRecordCount; i++ )
+ {
+ TRAP( leaveCode, ReadCommsDatIapEntryL(
+ (CCDIAPRecord*)ptrIapRecordSet->iRecords[i],
+ lanBearerTableCache,
+ bearerType,
+ serviceType ) );
+
+ if ( leaveCode )
+ {
+ // Skip this IAP and continue with next one
+ LOGIT1("ERROR reading IAP entry, LEAVE with <%d>", leaveCode)
+ break;
+ }
+
+ iapId = ptrIapRecordSet->iRecords[i]->RecordId();
+
+ if ( serviceType == EConnMonCacheServiceTypeWlan && iWlanSupportEnabled )
+ {
+ // Add WLAN IAP ID to WLAN IAP cache
+ TInt err = aCurrentWlanIapIds.InsertInOrder( iapId );
+ if ( err )
+ {
+ LOGIT1("ERROR inserting WLAN IAP ID to WLAN cache <%d>", err)
+ serviceType = 0;
+ }
+ }
+
+ // Unknown IAP or error while reading it
+ if ( !serviceType && !bearerType )
+ {
+ LOGIT1("WARNING, unknown IAP in CommsDat IAP table with id %d", iapId)
+ iapId = 0; // ID to zero so this IAP will be ignored
+ }
+
+ if ( iapId )
+ {
+ // Adding IAP to cache
+ TConnMonIapEntry iapEntry( iapId, bearerType, serviceType );
+
+ TInt err = aCurrentIapData.InsertInOrder( iapEntry , iapEntryOrderingLogic );
+ if ( err )
+ {
+ LOGIT1("ERROR inserting IAP to current IAP data <%d>", err)
+ }
+ }
+ }
+
+ CleanupStack::Pop( &lanBearerTableCache );
+ lanBearerTableCache.Close();
+ CleanupStack::PopAndDestroy( ptrIapRecordSet );
+ LOGIT1("ReadCommsDatIapTableL: IAP record count %d (cache)", aCurrentIapData.Count())
+
+ LOGEXITFN("CConnMonCommsDatCache::ReadCommsDatIapTableL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads one record from IAP table and finds out the service and bearer types.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ReadCommsDatIapEntryL(
+ CCDIAPRecord* aIapEntry,
+ RArray<TLanBearerEntry>& aLanBearerTableCache,
+ TUint& aBearerType,
+ TUint& aServiceType )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::ReadCommsDatIapEntryL()")
+
+ aBearerType = 0;
+ aServiceType = 0;
+ TBuf<KMaxTextLength> bearerTypeName( aIapEntry->iBearerType.GetL() );
+ TBuf<KMaxTextLength> serviceTypeName( aIapEntry->iServiceType.GetL() );
+
+ if ( serviceTypeName == TPtrC( KCDTypeNameOutgoingWCDMA ) ||
+ serviceTypeName == TPtrC( KCDTypeNameIncomingWCDMA ) )
+ {
+ aServiceType = EConnMonCacheServiceTypeGprs; // GPRS IAP
+ }
+ else if ( serviceTypeName == TPtrC( KCDTypeNameLANService ) )
+ {
+ // LAN or WLAN IAP
+ TUint32 bearerId( aIapEntry->iBearer );
+ if ( bearerTypeName == TPtrC( KCDTypeNameLANBearer ) &&
+ HasWlanBearer( bearerId, aLanBearerTableCache ) )
+ {
+ aServiceType = EConnMonCacheServiceTypeWlan; // WLAN IAP
+ }
+ else
+ {
+ aServiceType = EConnMonCacheServiceTypeLan; // LAN IAP
+ }
+ }
+ else if ( ( serviceTypeName == TPtrC( KCDTypeNameDialOutISP ) ) ||
+ ( serviceTypeName == TPtrC( KCDTypeNameDialInISP ) ) )
+ {
+ aServiceType = EConnMonCacheServiceTypeCsd; // CSD IAP
+ }
+
+ if ( bearerTypeName == TPtrC( KCDTypeNameVirtualBearer ) )
+ {
+ iVirtualIapCount++;
+ aBearerType = EConnMonCacheBearerTypeVirtual; // Virtual IAP
+ }
+
+ //LOGEXITFN("CConnMonCommsDatCache::ReadCommsDatIapEntryL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all records from the LAN bearer table and checks if they are WLAN
+// bearer type. Results are stored in an array.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ReadCommsDatLanBearerTableL(
+ CMDBSession& aDb,
+ RArray<TLanBearerEntry>& aLanBearerTableCache )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::ReadCommsDatLanBearerTableL()")
+
+ CMDBRecordSet<CCDLANBearerRecord>* ptrLanBearerRecordSet = new( ELeave )
+ CMDBRecordSet<CCDLANBearerRecord>( KCDTIdLANBearerRecord );
+ CleanupStack::PushL( ptrLanBearerRecordSet );
+ ptrLanBearerRecordSet->LoadL( aDb );
+
+ TInt lanBearerRecordCount( ptrLanBearerRecordSet->iRecords.Count() );
+ for ( TInt i = 0; i < lanBearerRecordCount; i++ )
+ {
+ TLanBearerEntry lanBearerEntry;
+ lanBearerEntry.iId = ptrLanBearerRecordSet->iRecords[i]->RecordId();
+
+ TBuf<KMaxTextLength> bearerRecordName(
+ ( (CCDLANBearerRecord*)ptrLanBearerRecordSet->iRecords[i] )->iRecordName.GetL() );
+
+ if ( bearerRecordName == TPtrC( KWlanBearerRecordName ) )
+ {
+ lanBearerEntry.iWlanBearer = ETrue;
+ }
+ else
+ {
+ lanBearerEntry.iWlanBearer = EFalse;
+ }
+ aLanBearerTableCache.Append( lanBearerEntry );
+ }
+ CleanupStack::PopAndDestroy( ptrLanBearerRecordSet );
+ LOGIT2("LAN bearer record count %d/%d", aLanBearerTableCache.Count(), lanBearerRecordCount)
+
+ LOGEXITFN("CConnMonCommsDatCache::ReadCommsDatLanBearerTableL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all SNAP information from CommsDat and updates the cache if necessary.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::RefreshCommsDatSnapCacheL( CMDBSession& aDb )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::RefreshCommsDatSnapCacheL()")
+
+ RArray<TConnMonSnapEntry>* currentSnapData;
+ if ( iInitStatus == EConnMonCacheInitCompleted )
+ {
+ // Array to read current CommsDat info into.
+ currentSnapData = new( ELeave ) RArray<TConnMonSnapEntry>; // Heap used by design
+ CleanupClosePushL( *currentSnapData );
+ }
+ else
+ {
+ // Init phase. Read CommsDat and store to cache. Then stop. (no events)
+ currentSnapData = iSnapCache; // Cache is still empty at init-phase.
+ }
+ currentSnapData->Reset();
+
+ ReadCommsDatSnapTableL( aDb, *currentSnapData );
+
+ if ( iInitStatus != EConnMonCacheInitCompleted )
+ {
+ // This is Init pass. CommsDat SNAPs have been read and stored in cache. return now.
+ // Note, currentSnapData not in cleanup stack
+ iSnapsChanged = ETrue;
+ LOGEXITFN1("CConnMonCommsDatCache::RefreshCommsDatSnapCache()", iSnapsChanged)
+ return iSnapsChanged;
+ }
+
+ CleanupStack::Pop( currentSnapData );
+ iSnapsChanged = CompareSortedArrays( *currentSnapData, *iSnapCache );
+
+ // Delete the obsolete SNAP cache table. Either the new table that was just
+ // read, or the old table if the new one is different.
+ if ( iSnapsChanged )
+ {
+ iSnapCache->Close();
+ delete iSnapCache;
+ iSnapCache = currentSnapData;
+ LOGIT("RefreshCommsDatSnapCacheL: updated SNAP cache")
+ }
+ else
+ {
+ currentSnapData->Close();
+ delete currentSnapData;
+ currentSnapData = NULL;
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::RefreshCommsDatSnapCacheL()", iSnapsChanged)
+ return iSnapsChanged;
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all SNAP information from CommsDat to an array.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ReadCommsDatSnapTableL(
+ CommsDat::CMDBSession& aDb,
+ RArray<TConnMonSnapEntry>& aCurrentSnapData )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::ReadCommsDatSnapTableL()")
+ // Explicitly build a TLinearOrder<class>. Used as parameter to RArray::InsertInOrder().
+ TLinearOrder<TConnMonSnapEntry> snapEntryOrderingLogic( TConnMonSnapEntry::Compare );
+
+ CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>* ptrSnapRecordSet = new( ELeave )
+ CMDBRecordSet<CCDDataMobilitySelectionPolicyRecord>( iSnapRecordTableId );
+ CleanupStack::PushL( ptrSnapRecordSet );
+
+ CCDDataMobilitySelectionPolicyRecord* ptrSnapRecord = new( ELeave )
+ CCDDataMobilitySelectionPolicyRecord( iSnapRecordTableId );
+ CleanupStack::PushL( ptrSnapRecord );
+
+ ptrSnapRecordSet->LoadL( aDb );
+ TInt snapRecordCount( ptrSnapRecordSet->iRecords.Count() );
+ LOGIT1("ReadCommsDatSnapTableL: SNAP record count %d (commsdat)", snapRecordCount)
+
+ TUint snapId( 0 );
+ TUint includedIapId( 0 );
+ TUint embeddedSnapId( 0 );
+ TInt tempSnapId( 0 );
+ TInt tempEmbeddedSnapId( 0 );
+
+ for ( TInt i = 0; i < snapRecordCount; i++ )
+ {
+ ptrSnapRecord->SetElementId( ptrSnapRecordSet->iRecords[i]->ElementId() );
+ ptrSnapRecord->LoadL( aDb );
+
+ // SNAP ID records in CCDDataMobilitySelectionPolicyRecord-table were changed
+ // from record links to TInt type, as part of new CommsInfra changes.
+ tempSnapId = ptrSnapRecord->iSNAP;
+ if ( tempSnapId < 0 )
+ {
+ tempSnapId = 0;
+ }
+ snapId = (TUint) tempSnapId;
+
+ includedIapId = ( ptrSnapRecord->iIAP & KCDMaskShowRecordId ) >> KBitsInByte;
+
+ tempEmbeddedSnapId = ptrSnapRecord->iEmbeddedSNAP;
+ if ( tempEmbeddedSnapId < 0 )
+ {
+ tempEmbeddedSnapId = 0;
+ }
+ embeddedSnapId = (TUint) tempEmbeddedSnapId;
+
+ // Empty SNAPs are not included in cache
+ if ( includedIapId || embeddedSnapId )
+ {
+ TConnMonSnapEntry snapEntry( snapId, includedIapId, embeddedSnapId );
+ TInt err = aCurrentSnapData.InsertInOrder( snapEntry , snapEntryOrderingLogic );
+ if ( err )
+ {
+ LOGIT1("ERROR inserting SNAP record to current SNAP data <%d>", err)
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy( ptrSnapRecord );
+ CleanupStack::PopAndDestroy( ptrSnapRecordSet );
+ LOGIT1("ReadCommsDatSnapTableL: SNAP record count %d (cache)", aCurrentSnapData.Count())
+ LOGEXITFN("CConnMonCommsDatCache::ReadCommsDatSnapTableL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all virtual IAP link information from CommsDat and updates the cache
+// if necessary. CommsDat is not read if IAP table did not contain any virtual
+// IAPs. Returns ETrue if cache information was changed, EFalse otherwise.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::RefreshCommsDatVirtualIapCacheL( CMDBSession& aDb )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::RefreshCommsDatVirtualIapCacheL()")
+
+ RArray<TConnMonVirtualIapEntry>* currentVirtualIapData;
+ if ( iInitStatus == EConnMonCacheInitCompleted )
+ {
+ // Array to read current CommsDat info into.
+ currentVirtualIapData = new( ELeave ) RArray<TConnMonVirtualIapEntry>; // Heap used by design
+ CleanupClosePushL( *currentVirtualIapData );
+ }
+ else
+ {
+ // Init-phase, read current CommsDat info directly into cache array,
+ // since it is still empty. Then stop (don't send any events.)
+ currentVirtualIapData = iVirtualIapCache;
+ }
+ currentVirtualIapData->Reset();
+
+ // If there is no virtual IAPs, there is no need to read virtual IAP link
+ // information, and virtual IAP cache will be left empty.
+ if ( iVirtualIapCount )
+ {
+ TRAPD( leaveCode, ReadCommsDatVirtualIapTableL( aDb, *currentVirtualIapData ) );
+ if ( leaveCode )
+ {
+ LOGIT1("ERROR reading virtual IAP table, LEAVE with <%d>", leaveCode)
+ }
+ }
+ else
+ {
+ LOGIT("RefreshCommsDatVirtualIapCacheL: no virtual IAPs, skipping")
+ }
+
+ if ( iInitStatus != EConnMonCacheInitCompleted )
+ {
+ // This is Init pass. CommsDat has been read and stored in cache. return now.
+ // Note, currentVirtualIapData not in cleanup stack
+ iVirtualIapsChanged = ETrue;
+ LOGEXITFN1("CConnMonCommsDatCache::RefreshCommsDatVirtualIapCacheL()", iVirtualIapsChanged)
+ return iVirtualIapsChanged;
+ }
+
+ CleanupStack::Pop( currentVirtualIapData );
+ iVirtualIapsChanged = CompareSortedArrays( *currentVirtualIapData, *iVirtualIapCache );
+
+ // Delete the obsolete virtual IAP cache table. Either the new table that
+ // was just read, or the old table if the new one is different.
+ if ( iVirtualIapsChanged )
+ {
+ iVirtualIapCache->Close();
+ delete iVirtualIapCache;
+ iVirtualIapCache = currentVirtualIapData;
+ LOGIT("RefreshCommsDatVirtualIapCacheL: updated virtual IAP cache")
+ }
+ else
+ {
+ currentVirtualIapData->Close();
+ delete currentVirtualIapData;
+ currentVirtualIapData = NULL;
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::RefreshCommsDatVirtualIapCacheL()", iVirtualIapsChanged)
+ return iVirtualIapsChanged;
+ }
+
+// ---------------------------------------------------------------------------
+// Reads all virtual IAP link information from CommsDat to an array.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ReadCommsDatVirtualIapTableL(
+ CommsDat::CMDBSession& aDb,
+ RArray<TConnMonVirtualIapEntry>& aCurrentVirtualIapData )
+ {
+ LOGENTRFN("CConnMonCommsDatCache::ReadCommsDatVirtualIapTableL()")
+
+ // Explicitly build a TLinearOrder<class>. Used as parameter to RArray::InsertInOrder().
+ TLinearOrder<TConnMonVirtualIapEntry> virtualEntryOrderingLogic(
+ TConnMonVirtualIapEntry::Compare );
+
+ CMDBRecordSet<CCDVirtualIAPNextLayerRecord>* ptrVirtualRecordSet = new( ELeave )
+ CMDBRecordSet<CCDVirtualIAPNextLayerRecord>( iVirtualRecordTableId );
+ CleanupStack::PushL( ptrVirtualRecordSet );
+
+ CCDVirtualIAPNextLayerRecord* ptrVirtualRecord = new( ELeave )
+ CCDVirtualIAPNextLayerRecord( iVirtualRecordTableId );
+ CleanupStack::PushL( ptrVirtualRecord );
+
+ // Load and loop through the records.
+ ptrVirtualRecordSet->LoadL( aDb );
+ TInt virtualRecordCount( ptrVirtualRecordSet->iRecords.Count() );
+ LOGIT1("ReadCommsDatVirtualIapTableL: virtual record count %d (commsdat)", virtualRecordCount)
+
+ TUint iapId( 0 );
+ TUint nextLayerSnap( 0 );
+ TUint nextLayerIap( 0 );
+
+ for ( TInt i = 0; i < virtualRecordCount; i++ )
+ {
+ ptrVirtualRecord->SetElementId( ptrVirtualRecordSet->iRecords[i]->ElementId() );
+ ptrVirtualRecord->LoadL( aDb );
+
+ iapId = ptrVirtualRecord->iIAP;
+ nextLayerSnap = ptrVirtualRecord->iNextLayerSNAP;
+ nextLayerIap = ptrVirtualRecord->iNextLayerIAP;
+
+ // Either iNextLayerSNAP or iNextLayerIAP must be NULL. Only 1 link.
+ if ( iapId && ( ( nextLayerSnap && !nextLayerIap ) ||
+ ( nextLayerIap && !nextLayerSnap ) ) )
+ {
+ TConnMonVirtualIapEntry virtualEntry( iapId, nextLayerIap, nextLayerSnap );
+ TInt err = aCurrentVirtualIapData.InsertInOrder(
+ virtualEntry,
+ virtualEntryOrderingLogic );
+ if ( err )
+ {
+ LOGIT1("ERROR inserting virtual IAP link record to cache <%d>", err)
+ }
+ }
+ else
+ {
+ LOGIT2("WARNING, invalid virtual record, iap: %d, snap: %d", nextLayerIap, nextLayerSnap )
+ }
+ }
+ CleanupStack::PopAndDestroy( ptrVirtualRecord );
+ CleanupStack::PopAndDestroy( ptrVirtualRecordSet );
+
+ LOGIT1("ReadCommsDatVirtualIapTableL: virtual record count %d (cache)", aCurrentVirtualIapData.Count())
+ LOGEXITFN("CConnMonCommsDatCache::ReadCommsDatVirtualIapTableL()")
+ }
+
+// ---------------------------------------------------------------------------
+// Compares two sorted RArray<TUint> arrays. Returns ETrue if the arrays are
+// not identical.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::CompareSortedArrays(
+ const RArray<TUint>& aFirstArray,
+ const RArray<TUint>& aSecondArray )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::CompareSortedArrays()")
+ TBool arraysDiffer( EFalse );
+
+ const TInt firstCount = aFirstArray.Count();
+ if ( firstCount != aSecondArray.Count() )
+ {
+ arraysDiffer = ETrue;
+ }
+ else
+ {
+ for ( TInt i = 0; i < firstCount; i++ )
+ {
+ if ( aFirstArray[i] != aSecondArray[i] )
+ {
+ arraysDiffer = ETrue;
+ break; // No need to continue
+ }
+ }
+ }
+
+ //LOGEXITFN1("CConnMonCommsDatCache::CompareSortedArrays()", arraysDiffer)
+ return arraysDiffer;
+ }
+
+// ---------------------------------------------------------------------------
+// Compares two sorted RArray<TConnMonIapEntry> arrays. Returns ETrue if the
+// arrays are not identical.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::CompareSortedArrays(
+ const RArray<TConnMonIapEntry>& aFirstArray,
+ const RArray<TConnMonIapEntry>& aSecondArray )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::CompareSortedArrays()")
+ TBool arraysDiffer( EFalse );
+
+ const TInt firstCount = aFirstArray.Count();
+ if ( firstCount != aSecondArray.Count() )
+ {
+ arraysDiffer = ETrue;
+ }
+ else
+ {
+ for ( TInt i = 0; i < firstCount; i++ )
+ {
+ if ( !TConnMonIapEntry::Match( aFirstArray[i], aSecondArray[i] ) )
+ {
+ arraysDiffer = ETrue;
+ break; // No need to continue
+ }
+ }
+ }
+
+ //LOGEXITFN1("CConnMonCommsDatCache::CompareSortedArrays()", arraysDiffer)
+ return arraysDiffer;
+ }
+
+// ---------------------------------------------------------------------------
+// Compares two sorted RArray<TConnMonSnapEntry> arrays. Returns ETrue if the
+// arrays are not identical.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::CompareSortedArrays(
+ const RArray<TConnMonSnapEntry>& aFirstArray,
+ const RArray<TConnMonSnapEntry>& aSecondArray )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::CompareSortedArrays()")
+ TBool arraysDiffer( EFalse );
+
+ const TInt firstCount = aFirstArray.Count();
+ if ( firstCount != aSecondArray.Count() )
+ {
+ arraysDiffer = ETrue;
+ }
+ else
+ {
+ for ( TInt i = 0; i < firstCount; i++ )
+ {
+ if ( !TConnMonSnapEntry::Match( aFirstArray[i], aSecondArray[i] ) )
+ {
+ arraysDiffer = ETrue;
+ break; // No need to continue
+ }
+ }
+ }
+
+ //LOGEXITFN1("CConnMonCommsDatCache::CompareSortedArrays()", arraysDiffer)
+ return arraysDiffer;
+ }
+
+// ---------------------------------------------------------------------------
+// Compares two sorted RArray<TConnMonVirtualIapEntry> arrays. Returns ETrue
+// if the arrays are not identical.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::CompareSortedArrays(
+ const RArray<TConnMonVirtualIapEntry>& aFirstArray,
+ const RArray<TConnMonVirtualIapEntry>& aSecondArray )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::CompareSortedArrays()")
+ TBool arraysDiffer( EFalse );
+
+ const TInt firstCount = aFirstArray.Count();
+ if ( firstCount != aSecondArray.Count() )
+ {
+ arraysDiffer = ETrue;
+ }
+ else
+ {
+ for ( TInt i = 0; i < firstCount; i++ )
+ {
+ if ( !TConnMonVirtualIapEntry::Match( aFirstArray[i], aSecondArray[i] ) )
+ {
+ arraysDiffer = ETrue;
+ break; // No need to continue
+ }
+ }
+ }
+
+ //LOGEXITFN1("CConnMonCommsDatCache::CompareSortedArrays()", arraysDiffer)
+ return arraysDiffer;
+ }
+
+// ---------------------------------------------------------------------------
+// Copy new data into a RArray<TUint> array.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::DeepCopy(
+ const RArray<TUint>& aSourceArray,
+ RArray<TUint>& aTargetArray )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::DeepCopy()")
+
+ const TInt count = aSourceArray.Count();
+ aTargetArray.Reset();
+ TInt err = aTargetArray.Reserve( count );
+ if ( KErrNone == err )
+ {
+ for ( TInt i = 0; i < count; i++ )
+ {
+ aTargetArray.Append( aSourceArray[i] );
+ }
+ }
+
+ //LOGEXITFN("CConnMonCommsDatCache::DeepCopy()")
+ }
+
+// ---------------------------------------------------------------------------
+// Updates the index links for SNAPs and virtual IAPs.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::UpdateSnapAndVirtualIapLinks()
+ {
+ LOGENTRFN("CConnMonCommsDatCache::UpdateSnapAndVirtualIapLinks()")
+
+ TInt count = iSnapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ TConnMonSnapEntry* pSnap = &(*iSnapCache)[i];
+ if ( pSnap->iNextLayerIapId )
+ {
+ pSnap->iNextLayerIndex = FindIapIndex( pSnap->iNextLayerIapId );
+ }
+ else if ( pSnap->iNextLayerSnapId )
+ {
+ pSnap->iNextLayerIndex = FindSnapIndex( pSnap->iNextLayerSnapId );
+ }
+ }
+
+ count = iIapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ TConnMonIapEntry* pIap = &(*iIapCache)[i];
+ // Only virtual IAPs can have links
+ if ( pIap->iBearerType == EConnMonCacheBearerTypeVirtual )
+ {
+ TInt index = iVirtualIapCache->FindInOrder<TInt>(
+ pIap->iId,
+ TConnMonVirtualIapEntry::FindCompare );
+
+ if ( index < 0)
+ {
+ pIap->iNextLayerIapId = 0;
+ pIap->iNextLayerSnapId = 0;
+ pIap->iNextLayerIndex = KErrNotFound;
+ }
+ else
+ {
+ pIap->iNextLayerIapId = (*iVirtualIapCache)[index].iNextLayerIapId;
+ pIap->iNextLayerSnapId = (*iVirtualIapCache)[index].iNextLayerSnapId;
+
+ // Either iNextLayerIapId or iNextLayerSnapId is 0. (already checked)
+ // Link to SNAP is more likely than link to IAP
+ if ( pIap->iNextLayerSnapId )
+ {
+ // Returns KErrNotFound if not found
+ pIap->iNextLayerIndex = FindSnapIndex( pIap->iNextLayerSnapId );
+ }
+ else if ( pIap->iNextLayerIapId )
+ {
+ // Returns KErrNotFound if not found
+ pIap->iNextLayerIndex = FindIapIndex( pIap->iNextLayerIapId );
+ }
+ }
+ }
+ }
+
+ LOGEXITFN("CConnMonCommsDatCache::UpdateSnapAndVirtualIapLinks()")
+ }
+
+// ---------------------------------------------------------------------------
+// Resets the availability status for all SNAPs and IAPs. SNAPs and virtual
+// IAPs are set to unknown, because their availability depends on real IAPs
+// and needs to be solved using recursive algorithms. Real IAPs are set to
+// unavailable. The next step should be to find the real IAPs that are
+// available.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::ResetAllAvailabilityInfo()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::ResetAllAvailabilityInfo()")
+
+ TInt count = iIapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ if ( (*iIapCache)[i].iBearerType == EConnMonCacheBearerTypeVirtual )
+ {
+ (*iIapCache)[i].iAvailability = EConnMonAvailabilityUnknown;
+ }
+ else
+ {
+ (*iIapCache)[i].iAvailability = EConnMonAvailabilityUnavailable;
+ }
+ }
+
+ count = iSnapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ (*iSnapCache)[i].iAvailability = EConnMonAvailabilityUnknown;
+ }
+
+ //LOGEXITFN("CConnMonCommsDatCache::ResetAllAvailabilityInfo()")
+ }
+
+// ---------------------------------------------------------------------------
+// Solve SNAP and virtual IAP availability. The results depend on real IAP
+// availability, so those need to be set when this method is called.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::SolveSnapAndVirtualIapAvailability()
+ {
+ LOGENTRFN("CConnMonCommsDatCache::SolveSnapAndVirtualIapAvailability()")
+
+ TInt count = iSnapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ // Check SNAP availability recursively at index i
+ CheckSnapAvailability( i );
+ }
+
+ count = iIapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ if ( (*iIapCache)[i].iBearerType == EConnMonCacheBearerTypeVirtual )
+ {
+ // Check IAP availability recursively at index i
+ CheckIapAvailability( i );
+ }
+ }
+
+ LOGEXITFN("CConnMonCommsDatCache::SolveSnapAndVirtualIapAvailability()")
+ }
+
+// ---------------------------------------------------------------------------
+// Create a EConnMonIapAvailabilityChange event and add it to the event
+// queue to be sent to clients.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::SendIapAvailabilityEvent()
+ {
+ LOGENTRFN("CConnMonCommsDatCache::SendIapAvailabilityEvent()")
+ TInt err( KErrNone );
+
+ TInt iapCount = iIapIdCache.Count();
+ if ( iapCount > KConnMonMaxIAPCount )
+ {
+ // If too many IAPs available, clip the extras away from event.
+ LOGIT1("WARNING, too many IAPs (%d), all did not fit into event", iapCount)
+ iapCount = KConnMonMaxIAPCount;
+ }
+
+ TEventInfo info;
+ info.Reset();
+ info.iEventType = EConnMonIapAvailabilityChange;
+ info.iConnectionId = EBearerIdAll;
+ info.iData = iapCount;
+
+ // Create event data area. Leave left out intentionally, check for NULL instead
+ TConnMonIapInfo* eventIaps = new TConnMonIapInfo; // No (ELeave)
+ if ( !eventIaps )
+ {
+ err = KErrNoMemory;
+ }
+ else
+ {
+ eventIaps->iCount = iapCount;
+ TInt i = 0;
+ for ( ; i < iapCount; i++ )
+ {
+ eventIaps->iIap[i].iIapId = iIapIdCache[i];
+ }
+ for ( ; i < KConnMonMaxIAPCount; i++ )
+ {
+ eventIaps->iIap[i].iIapId = 0;
+ }
+
+ // EventQueue will finally destroy the memory area pointed by eventIaps.
+ // However, if all the clients can't receive the event right away the
+ // event queue will keep it until the last client has received it.
+ iServer->EventQueue()->Add(
+ info,
+ reinterpret_cast<const TUint8*>( eventIaps ),
+ sizeof( TConnMonIapInfo ) );
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::SendIapAvailabilityEvent()", err)
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Create a EConnMonSNAPsAvailabilityChange event and add it to the event
+// queue to be sent to clients.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::SendSnapAvailabilityEvent()
+ {
+ LOGENTRFN("CConnMonCommsDatCache::SendSnapAvailabilityEvent()")
+ TInt err( KErrNone );
+
+ TInt snapCount = iSnapIdCache.Count();
+
+ TEventInfo info;
+ info.Reset();
+ info.iEventType = EConnMonSNAPsAvailabilityChange;
+ info.iConnectionId = EBearerIdAll;
+ info.iData = snapCount; // Total amount of available SNAPs
+
+ if ( snapCount > KConnMonMaxSNAPsCount )
+ {
+ // If too many SNAPs available, clip the extras away from event.
+ LOGIT1("WARNING, too many SNAPs (%d), all did not fit into event", snapCount)
+ snapCount = KConnMonMaxSNAPsCount;
+ }
+
+ // Create event data area. Leave left out intentionally, check for NULL instead
+ TConnMonSNAPInfo* eventSnaps = new TConnMonSNAPInfo; // No (ELeave)
+ if ( !eventSnaps )
+ {
+ err = KErrNoMemory;
+ }
+ else
+ {
+ eventSnaps->iCount = snapCount;
+ TInt i = 0;
+ for ( ; i < snapCount; i++ )
+ {
+ eventSnaps->iSNAP[i].iSNAPId = iSnapIdCache[i];
+ }
+ for ( ; i < KConnMonMaxSNAPsCount; i++ )
+ {
+ eventSnaps->iSNAP[i].iSNAPId = 0;
+ }
+
+ // EventQueue will finally destroy the memory area pointed by eventSnaps.
+ // However, if all the clients can't receive the event right away the
+ // event queue will keep it until the last client has received it.
+ iServer->EventQueue()->Add(
+ info,
+ reinterpret_cast<const TUint8*>( eventSnaps ),
+ sizeof( TConnMonSNAPInfo ) );
+ }
+
+ LOGEXITFN1("CConnMonCommsDatCache::SendSnapAvailabilityEvent()", err)
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Finds the index in cache for IAP with id aId. Returns KErrNotFound (-1) if
+// no match is found.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::FindIapIndex( const TUint aId )
+ {
+ TInt index = iIapCache->FindInOrder<TInt>( aId, TConnMonIapEntry::FindCompare );
+ return index;
+ }
+
+// ---------------------------------------------------------------------------
+// Finds the first index in cache for SNAP with ID aId. Returns KErrNotFound
+// (-1) if no match is found.
+// The SNAP cache is sorted by ID, so the first index is found by traversing
+// decrementally from the initial index returned by RArray's FindInOrder.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::FindSnapIndex( const TUint aId )
+ {
+ TInt index = iSnapCache->FindInOrder<TInt>( aId, TConnMonSnapEntry::FindCompare );
+ for ( ; index > 0; index-- )
+ {
+ if ( (*iSnapCache)[index-1].iId != aId )
+ {
+ return index;
+ }
+ }
+ return index;
+ }
+
+// ---------------------------------------------------------------------------
+// Takes a SNAP cache index and reads the ID from that entry. Then adjusts the
+// availability for each cache entry related to that ID.
+// ---------------------------------------------------------------------------
+//
+void CConnMonCommsDatCache::SetSnapAvailabilityAtIndex( TUint aIndex, TInt aAvailability )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::SetSnapAvailabilityAtIndex()")
+
+ TUint id = (*iSnapCache)[aIndex].iId;
+ (*iSnapCache)[aIndex].iAvailability = aAvailability;
+
+ TInt count = iSnapCache->Count();
+ for ( TInt i = aIndex+1; i < count; i++ )
+ {
+ if ( (*iSnapCache)[i].iId != id )
+ {
+ return;
+ }
+ (*iSnapCache)[i].iAvailability = aAvailability;
+ }
+
+ //LOGEXITFN("CConnMonCommsDatCache::SetSnapAvailabilityAtIndex()")
+ }
+
+// ---------------------------------------------------------------------------
+// Check IAP availability by index. In case of virtual IAP, keeps checking
+// recursively until something is found available or all link chains are
+// checked.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::CheckIapAvailability( TUint aIndex )
+ {
+ TConnMonIapEntry* pIap = &(*iIapCache)[aIndex];
+ TInt currentAvailability = pIap->iAvailability;
+ switch ( currentAvailability )
+ {
+ // Real IAPs should have availability status of either available or unavailable at this
+ // point. Unprocessed virtual IAPs and SNAPs should have availability status unknown.
+ //
+ case EConnMonAvailabilityProcessing: // Loop. Fallthrough intended
+ case EConnMonAvailabilityUnavailable:
+ return EConnMonAvailabilityUnavailable;
+ case EConnMonAvailabilityAvailable:
+ return EConnMonAvailabilityAvailable;
+ case EConnMonAvailabilityUnknown:
+ {
+ if ( pIap->iNextLayerIndex >= 0 )
+ {
+ // Set availability status to processing (to detect/prevent loops)
+ pIap->iAvailability = EConnMonAvailabilityProcessing;
+ if ( pIap->iNextLayerSnapId )
+ {
+ pIap->iAvailability = CheckSnapAvailability( pIap->iNextLayerIndex );
+ }
+ else
+ {
+ pIap->iAvailability = CheckIapAvailability( pIap->iNextLayerIndex );
+ }
+ }
+ else
+ {
+ // Virtual IAP that does not point anywhere
+ pIap->iAvailability = EConnMonAvailabilityUnavailable;
+ }
+ }
+ break;
+ default:
+ LOGIT1("ERROR, IAP entry contained invalid availability value: %d", currentAvailability)
+ return EConnMonAvailabilityUnavailable;
+ }
+ return pIap->iAvailability;
+ }
+
+// ---------------------------------------------------------------------------
+// Check SNAP availability by index. Keeps checking recursively until something
+// is found available inside or all contents of this SNAP have are checked.
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::CheckSnapAvailability( TUint aIndex )
+ {
+ TInt currentAvailability = (*iSnapCache)[aIndex].iAvailability;
+ switch ( currentAvailability )
+ {
+ case EConnMonAvailabilityProcessing: // Loop. Fallthrough intended
+ case EConnMonAvailabilityUnavailable:
+ return EConnMonAvailabilityUnavailable;
+ case EConnMonAvailabilityAvailable:
+ return EConnMonAvailabilityAvailable;
+ case EConnMonAvailabilityUnknown:
+ {
+ // Set availability status to processing (to detect/prevent loops)
+ SetSnapAvailabilityAtIndex( aIndex, EConnMonAvailabilityProcessing );
+
+ const TUint id = (*iSnapCache)[aIndex].iId;
+ const TInt count = iSnapCache->Count();
+
+ currentAvailability = EConnMonAvailabilityUnavailable;
+ for ( TInt i = aIndex; i < count; i++ )
+ {
+ if ( (*iSnapCache)[i].iId != id )
+ {
+ // This line belongs to next SNAP, finish here
+ break;
+ }
+ TInt link = (*iSnapCache)[i].iNextLayerIndex;
+ if ( link >= 0 )
+ {
+ if ( (*iSnapCache)[i].iNextLayerIapId )
+ {
+ currentAvailability = CheckIapAvailability( link );
+ }
+ else
+ {
+ currentAvailability = CheckSnapAvailability( link );
+ }
+ }
+ if ( currentAvailability == EConnMonAvailabilityAvailable )
+ {
+ // Something inside this SNAP is available, no need to continue
+ break;
+ }
+ }
+ // Set this SNAP as available (all lines in cache that belong to this SNAP)
+ SetSnapAvailabilityAtIndex( aIndex, currentAvailability );
+ }
+ break;
+ default:
+ LOGIT("ERROR, SNAP entry contained invalid availability value")
+ return EConnMonAvailabilityUnavailable;
+ }
+ return currentAvailability;
+ }
+
+// ---------------------------------------------------------------------------
+// Updates the internal list of available IAP IDs and returns ETrue if it has
+// changed.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::UpdateAvailableIaps()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::UpdateAvailableIaps()")
+
+ RArray<TUint> currentIapIds;
+
+ // Read available IAP IDs from IAP cache
+ const TInt count = iIapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ if ( (*iIapCache)[i].iAvailability == EConnMonAvailabilityAvailable )
+ {
+ TInt err = currentIapIds.InsertInOrder( (*iIapCache)[i].iId );
+ if ( KErrNone != err )
+ {
+ LOGIT1("ERROR inserting IAP ID to available IAPs cache <%d>", err)
+ break;
+ }
+ }
+ }
+
+ // Check for changes
+ TBool arrayChanged = CompareSortedArrays( currentIapIds, iIapIdCache );
+ if ( arrayChanged )
+ {
+ LOGIT1("Available IAP count: %d (changed)", currentIapIds.Count())
+ DeepCopy( currentIapIds, iIapIdCache );
+ }
+ else
+ {
+ LOGIT1("Available IAP count: %d", currentIapIds.Count())
+ }
+ currentIapIds.Close();
+
+ //LOGEXITFN1("CConnMonCommsDatCache::UpdateAvailableIaps()", arrayChanged)
+ return arrayChanged;
+ }
+
+// ---------------------------------------------------------------------------
+// Updates the internal list of available SNAP IDs and returns ETrue if it has
+// changed.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::UpdateAvailableSnaps()
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::UpdateAvailableSnaps()")
+
+ TUint lastSnapId( 0 );
+ RArray<TUint> currentSnapIds;
+
+ // Read available SNAP IDs from SNAP cache.
+ // If there is n items inside a SNAP, then SNAP cache will contain n entries for that SNAP
+ const TInt count = iSnapCache->Count();
+ for ( TInt i = 0; i < count; i++ )
+ {
+ TUint currentId = (*iSnapCache)[i].iId;
+ if ( currentId != lastSnapId )
+ {
+ lastSnapId = currentId;
+ if ( (*iSnapCache)[i].iAvailability == EConnMonAvailabilityAvailable )
+ {
+ TInt err = currentSnapIds.InsertInOrder( currentId );
+ if ( KErrNone != err )
+ {
+ LOGIT1("ERROR inserting SNAP ID to available SNAPs cache <%d>", err)
+ break;
+ }
+ }
+ }
+ }
+
+ // Check for changes
+ TBool arrayChanged = CompareSortedArrays( currentSnapIds, iSnapIdCache );
+ if ( arrayChanged )
+ {
+ LOGIT1("Available SNAP count: %d (changed)", currentSnapIds.Count())
+ DeepCopy( currentSnapIds, iSnapIdCache );
+ }
+ else
+ {
+ LOGIT1("Available SNAP count: %d", currentSnapIds.Count())
+ }
+ currentSnapIds.Close();
+
+ //LOGEXITFN1("CConnMonCommsDatCache::UpdateAvailableSnaps()", arrayChanged)
+ return arrayChanged;
+ }
+
+// ---------------------------------------------------------------------------
+// Checks from 'LAN bearer table' array if given ID has a WLAN bearer
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::HasWlanBearer(
+ TUint32 aId,
+ RArray<TLanBearerEntry>& aLanBearerTableCache )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::HasWlanBearer()")
+ TBool wlanBearer( EFalse );
+
+ for ( TInt i = 0; i < aLanBearerTableCache.Count(); i++ )
+ {
+ if ( aLanBearerTableCache[i].iId == aId )
+ {
+ wlanBearer = aLanBearerTableCache[i].iWlanBearer;
+ break;
+ }
+ }
+
+ //LOGEXITFN1("CConnMonCommsDatCache::HasWlanBearer()", wlanBearer)
+ return wlanBearer;
+ }
+
+// ---------------------------------------------------------------------------
+// Convert a bearer ID to (cache internal) service type
+// ---------------------------------------------------------------------------
+//
+TInt CConnMonCommsDatCache::ConvertBearerIdToServiceType(
+ const TUint aBearerId,
+ TUint& aServiceType )
+ {
+ //LOGENTRFN("CConnMonCommsDatCache::ConvertBearerIdToServiceType()")
+ TInt err( KErrNone );
+
+ switch ( aBearerId )
+ {
+ case EBearerIdGPRS:
+ case EBearerIdWCDMA:
+ aServiceType = EConnMonCacheServiceTypeGprs;
+ break;
+ case EBearerIdCSD:
+ aServiceType = EConnMonCacheServiceTypeCsd;
+ break;
+ case EBearerIdWLAN:
+ aServiceType = EConnMonCacheServiceTypeWlan;
+ break;
+ case EBearerIdLAN:
+ aServiceType = EConnMonCacheServiceTypeLan;
+ break;
+ default:
+ LOGIT1("WARNING, ConvertBearerIdToServiceType() called with bad bearerId: %d", aBearerId)
+ aServiceType = EConnMonCacheServiceTypeUnknown;
+ err = KErrNotFound;
+ }
+
+ //LOGEXITFN1("CConnMonCommsDatCache::ConvertBearerIdToServiceType()", err)
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// Checks from CommsDat if WLAN background scans are enabled.
+// ---------------------------------------------------------------------------
+//
+TBool CConnMonCommsDatCache::IsWlanBackgroundScanningEnabledL()
+ {
+ LOGENTRFN("CConnMonCommsDatCache::IsWlanBackgroundScanningEnabledL()")
+
+ TBool bgScanEnabled( EFalse );
+ CMDBSession* db = CMDBSession::NewLC( CMDBSession::LatestVersion() );
+
+ CCDWlanDeviceSettingsRecord* ptrWlanDevSettingsRecord = new( ELeave )
+ CCDWlanDeviceSettingsRecord( CCDWlanDeviceSettingsRecord::TableIdL( *db ) );
+ CleanupStack::PushL( ptrWlanDevSettingsRecord );
+
+ ptrWlanDevSettingsRecord->iWlanDeviceSettingsType = KWlanUserSettings;
+ if( ptrWlanDevSettingsRecord->FindL( *db ) )
+ {
+ ptrWlanDevSettingsRecord->LoadL( *db );
+ if ( ptrWlanDevSettingsRecord->iBgScanInterval > 0 )
+ {
+ bgScanEnabled = ETrue;
+ LOGIT1("WLAN background scans are enabled, interval: %d", (TUint)ptrWlanDevSettingsRecord->iBgScanInterval)
+ }
+ }
+ CleanupStack::PopAndDestroy( ptrWlanDevSettingsRecord );
+ CleanupStack::PopAndDestroy( db );
+
+ LOGEXITFN1("CConnMonCommsDatCache::IsWlanBackgroundScanningEnabledL()", bgScanEnabled)
+ return bgScanEnabled;
+ }
+
+// End-of-file