--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/connectionmonitoring/connmon/dataconnectionlogger/src/dcl.cpp Thu Dec 17 08:55:21 2009 +0200
@@ -0,0 +1,1851 @@
+/*
+* Copyright (c) 2003-2004 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: Data Connection Logger.
+*
+*/
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <logengdurations.h>
+#include <logwraplimits.h>
+#include <logengevents.h>
+#endif
+#include <cdbcols.h>
+#include <bldvariant.hrh> // Feature IDs
+#include <featmgr.h>
+#include <utf.h>
+
+#include <centralrepository.h>
+#include "DclPrivateCRKeys.h"
+
+#include "dcl.h"
+#include "dcl_log.h"
+
+// --------------------------------------------------------------------------
+// CEngine::CEngine
+// Constructor
+// --------------------------------------------------------------------------
+//
+CEngine::CEngine()
+ :
+ CActive( EPriorityStandard ),
+ iLogClient( NULL ),
+ iTimerInterval( KTimerInterval )
+ {
+ CActiveScheduler::Add( this );
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::NewLC
+// 1st phase constructor - for stack pointers to object
+// --------------------------------------------------------------------------
+//
+CEngine* CEngine::NewLC( )
+ {
+ CEngine* self = new( ELeave ) CEngine();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::NewL
+// 1st phase constructor - for heap pointers to object
+// --------------------------------------------------------------------------
+//
+CEngine* CEngine::NewL( )
+ {
+ CEngine* self = NewLC();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::ConstructL
+// 2nd phase constructor
+// --------------------------------------------------------------------------
+//
+void CEngine::ConstructL()
+ {
+ LOGENTRFN("CEngine::ConstructL()")
+ // Renaming the thread with the real process name helps debugging panics.
+ RThread::RenameMe( KDCLName );
+
+ FeatureManager::InitializeLibL();
+
+ iConnectionMonitor.ConnectL();
+
+ User::LeaveIfError( iFsEventLog.Connect() );
+
+ iLogWrap = CLogWrapper::NewL( iFsEventLog, CActive::EPriorityStandard );
+ iLogEventQueue = new( ELeave ) CArrayPtrFlat<CEvent>( KEventStateMaxCount );
+ iLogEventQueue->Reset();
+
+ iConnections = new( ELeave ) CArrayPtrFlat<CEvent>( KEventStateMaxCount );
+ iConnections->Reset();
+
+ iCurrentLogEvent = CLogEvent::NewL();
+
+ iLogClient = CLogClient::NewL( iFsEventLog );
+
+ // Connect to ETel server
+ // The RTelServer::Connect() might not always work with the first trial,
+ // because of a coding error related to using semaphores in the method.
+
+ TInt err( KErrNotReady );
+ TInt a = 0;
+ while( a < KPhoneRetryCount && err != KErrNone )
+ {
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ err = iTelServer.Connect();
+ LOGIT1("Connecting to ETel server <%d>", err)
+ a++;
+ }
+ User::LeaveIfError( err );
+
+ // Try to load phone.tsy
+ TBuf<KCommsDbSvrMaxColumnNameLength> tsyName;
+ tsyName.Copy( KMmTsyModuleName );
+ err = iTelServer.LoadPhoneModule( tsyName );
+
+ if ( err == KErrNone )
+ {
+ iTSYLoaded = 1;
+ // Phone info can be retrieved with value 0 if there is only 1 phone
+ RTelServer::TPhoneInfo info;
+ User::LeaveIfError( iTelServer.GetPhoneInfo( 0, info ) );
+ User::LeaveIfError( iMobilePhone.Open( iTelServer, info.iName ) );
+
+ // Open packet service
+ err = iPacketService.Open( iMobilePhone );
+ if ( err == KErrNone )
+ {
+ iPacketServLoaded = 1;
+ }
+ }
+ if ( FeatureManager::FeatureSupported( KFeatureIdLoggerGprs ) )
+ {
+ LOGIT0("LoggerGprs supported")
+
+ // Get the Attach Mode setting from CommDb and set ETel to use that
+ // value. Must not leave if an error occurs.
+ TRAPD( leaveCode, SetAttachModeL() );
+ LOGIT1("SetAttachModeL() result: <%d>", leaveCode)
+
+ // Get the default APN from CommDb and set ETel to use that APN.
+ // Must not leave if an error occurs.
+ TRAP( leaveCode, SetAPNL() );
+ LOGIT1("SetAPNL() result: <%d>", leaveCode)
+ }
+ // Adds the event type Wlan. Otherwise the LogClient
+ // will not understand this type of event.
+ AddEventTypeL();
+
+ // Read ini file settings
+ ReadIniFile();
+
+ // Create timer mode AO
+ iDclTimerAO = new( ELeave ) CDclTimerAO ( this, iTimerInterval );
+ iDclTimerAO->ConstructL();
+
+ // Create saeObserver for updating P&S variables
+ iSaeObserver = CSaeObserver::NewL( iConnectionMonitor );
+ LOGEXITFN("CEngine::ConstructL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::~CEngine
+// Destructor
+// Frees reserved resources.
+// --------------------------------------------------------------------------
+//
+CEngine::~CEngine()
+ {
+ LOGENTRFN("CEngine::~CEngine()")
+ FeatureManager::UnInitializeLib();
+
+ delete iSaeObserver;
+ iSaeObserver = NULL;
+
+ // Disconnect from CM server.
+ iConnectionMonitor.Close();
+
+ Cancel();
+ // The queue could be not empty if the active object
+ // is aborted and destructed.
+ if ( iLogEventQueue != 0 )
+ {
+ iLogEventQueue->ResetAndDestroy();
+ }
+
+ if ( iConnections != 0 )
+ {
+ iConnections->ResetAndDestroy();
+ }
+
+ delete iLogWrap;
+ iLogWrap = NULL;
+
+ delete iLogEventQueue;
+ iLogEventQueue = NULL;
+
+ delete iConnections;
+ iConnections = NULL;
+
+ delete iCurrentLogEvent;
+ iCurrentLogEvent = NULL;
+
+ delete iLogEventType;
+ iLogEventType = NULL;
+
+ delete iLogClient;
+ iLogClient = NULL;
+
+ iFsEventLog.Close();
+
+ // Close "global" ETEL objects
+ if ( iPacketServLoaded == 1 )
+ {
+ iPacketService.Close();
+ }
+
+ iMobilePhone.Close();
+ iTelServer.Close();
+
+ delete iDclTimerAO;
+ iDclTimerAO = NULL;
+ LOGEXITFN("CEngine::~CEngine()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::NotifyL
+// Request Connection Monitor server to send notifications of events.
+// --------------------------------------------------------------------------
+//
+void CEngine::NotifyL()
+ {
+ iConnectionMonitor.NotifyEventL( *this );
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::EventL
+// Receives notifications of events from Connection Monitor server.
+// --------------------------------------------------------------------------
+//
+void CEngine::EventL( const CConnMonEventBase& aConnMonEvent )
+ {
+ //LOGENTRFN("CEngine::EventL()")
+ LOGIT1("-> CEngine::EventL() entered, event type (%d)", aConnMonEvent.EventType())
+ TInt err( KErrNone );
+ TUint connectionId( 0 );
+
+ // Update P&S variables first
+ if ( iSaeObserver )
+ {
+ iSaeObserver->EventL( aConnMonEvent );
+ }
+
+ switch ( aConnMonEvent.EventType() )
+ {
+ case EConnMonCreateConnection:
+ {
+ TInt bearer( 0 );
+ TRequestStatus status( KErrNotReady );
+
+ const CConnMonCreateConnection* eventCreate;
+ eventCreate = static_cast<const CConnMonCreateConnection*>( &aConnMonEvent );
+ connectionId = eventCreate->ConnectionId();
+
+ LOGIT1("*** EConnMonCreateConnection event, id %d ***", connectionId)
+
+ // Get the bearer info from CM server.
+ err = KErrNotReady;
+ TInt a = 0;
+ while( a < KPhoneRetryCount && err != KErrNone )
+ {
+ // ConnMon might not be able to provide KBearer with the first trial.
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ iConnectionMonitor.GetIntAttribute(
+ connectionId,
+ KSubConnectionId,
+ KBearer,
+ bearer,
+ status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOGIT2("Got bearer %d from ConnMon <%d>", bearer, err)
+ a++;
+ }
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to get KBearer from ConnMon <%d>", err)
+ break;
+ }
+
+ // Check that it is GPRS or WCDMA.
+ if ( bearer == EBearerGPRS ||
+ bearer == EBearerEdgeGPRS ||
+ bearer == EBearerWCDMA )
+ {
+ LOGIT0("New internal connection")
+ // Set the uplink and downlink thresholds for this particular connection.
+ TUint threshold( iGPRSThreshold );
+ if ( bearer == EBearerWCDMA )
+ {
+ threshold = iWCDMAThreshold;
+ }
+
+ err = iConnectionMonitor.SetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KDownlinkDataThreshold,
+ threshold );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to set KDownlinkDataThreshold to ConnMon <%d>", err)
+ }
+
+ err = iConnectionMonitor.SetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KUplinkDataThreshold,
+ threshold );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to set KUplinkDataThreshold to ConnMon <%d>", err)
+ }
+
+ TName iapName;
+ iapName.FillZ();
+ iapName.Zero();
+
+ // Get String Attribute -> KIAPName.
+ // Get IAP name from CM server.
+ err = KErrNotReady;
+ a = 0;
+ while( a < KPhoneRetryCount && err != KErrNone )
+ {
+ // ConnMon might not be able to provide KIAPName with the first trial.
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ iConnectionMonitor.GetStringAttribute(
+ connectionId,
+ KSubConnectionId,
+ KIAPName,
+ iapName,
+ status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOG( TBuf<KMaxName+1> iapName2( iapName ); )
+ LOGIT2("Got KIAPName from ConnMon <%s>, <%d>", iapName2.PtrZ(), err)
+ a++;
+ }
+
+ if ( err == KErrNone )
+ {
+ LogDataAddEventL(
+ connectionId,
+ R_LOG_CON_CONNECTED,
+ iapName,
+ R_LOG_DIR_OUT,
+ KNullDesC,
+ KLogPacketDataEventTypeUid );
+ }
+ else
+ {
+ LOGIT1("FAILED to get KIAPName from ConnMon <%d>", err)
+ }
+ }
+ else if ( bearer == EBearerWLAN )
+ // Add EBearerExternalWLAN in order to enable DCL to log
+ // external WLAN connections, i.e. then the mobile phone
+ // functions as a WLAN modem
+ {
+ LOGIT0("New WLAN connection")
+
+ // Set the uplink and downlink thresholds for this particular connection.
+ err = iConnectionMonitor.SetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KDownlinkDataThreshold,
+ iWLANThreshold );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to set KDownlinkDataThreshold to ConnMon <%d>", err)
+ }
+
+ // Even if KDownlinkDataThreshold and KUplinkDataThreshold
+ // are used here ( 4096 bytes ), the Connection Monitor
+ // server actually sets the threshold to 20480 bytes =
+ // 20 kilobytes.
+ err = iConnectionMonitor.SetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KUplinkDataThreshold,
+ iWLANThreshold );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to set KUplinkDataThreshold to ConnMon <%d>", err)
+ }
+
+ TName iapName;
+ iapName.FillZ();
+ iapName.Zero();
+ // Get Uint Attribute -> KIAPId.
+ // Get IAP id from CM server.
+ err = KErrNotReady;
+ a = 0;
+ TUint iapId( 0 );
+ while( a < KPhoneRetryCount && err != KErrNone )
+ {
+ // ConnMon might not be able to provide KIAPId with the first trial.
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ iConnectionMonitor.GetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KIAPId,
+ iapId,
+ status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOGIT2("Got IAP ID %d from ConnMon <%d>", iapId, err)
+ a++;
+ }
+ // For each new WLAN connection, we need to check the used IAP.
+ // For a normal IAP, the IAP name is used for logging, but when
+ // customer is using the 'Search for WLAN' functionality and
+ // chooses a WLAN network that is not found in any current IAP,
+ // the Easy WLAN IAP is used instead. This IAP has some internal
+ // name, e.g. 'Easy WLAN', that should not be visible anywhere
+ // in the UI. So SSID of used network is used in logging instead.
+ //
+ if ( err == KErrNone )
+ {
+ // Create a session with the latest version CommsDat
+ CMDBSession* db = CMDBSession::NewLC( CMDBSession::LatestVersion() );
+ db->SetAttributeMask( ECDProtectedWrite );
+
+ // Load IAP record
+ CCDIAPRecord* iapRecord = static_cast<CCDIAPRecord*>(
+ CCDRecordBase::RecordFactoryL( KCDTIdIAPRecord ) );
+ CleanupStack::PushL( iapRecord );
+ iapRecord->SetRecordId( iapId );
+ iapRecord->LoadL( *db );
+ LOGIT0("Read IAP record from CommsDat")
+
+ // Load wlan service record
+ CCDWlanServiceRecord* wlanRecord = new( ELeave )CCDWlanServiceRecord(
+ CCDWlanServiceRecord::TableIdL( *db ) );
+ CleanupStack::PushL( wlanRecord );
+ wlanRecord->iWlanServiceId = iapRecord->iService;
+
+ if ( wlanRecord->FindL( *db ) )
+ {
+ wlanRecord->LoadL( *db );
+ LOGIT0("Read WLAN record from CommsDat")
+
+ if ( wlanRecord->iWLanSSID.IsNull() )
+ {
+ // Used IAP is the special 'Easy WLAN' IAP, so we need to
+ // log the used WLAN network SSID instead of 'Easy WLAN'.
+ // This can be read from the 'iWLanUsedSSID'-field.
+ if ( !( wlanRecord->iWLanUsedSSID.IsNull() ) )
+ {
+ iapName = wlanRecord->iWLanUsedSSID.GetL();
+ LOGIT1("Easy WLAN detected, got SSID <%s> from CommsDat", &iapName)
+ }
+ else
+ {
+ LOGIT0("Error, Easy WLAN detected but no SSID found from CommsDat")
+ }
+ }
+ else
+ {
+ // A noraml WLAN IAP, read IAP name and use it for logging
+ iapName = iapRecord->iRecordName.GetL();
+ LOGIT1("Got IAP name <%s> from CommsDat", &iapName)
+ }
+ }
+ else
+ {
+ LOGIT0("Error, WLAN record not found from CommsDat")
+ }
+ LogDataAddEventL(
+ connectionId,
+ R_LOG_CON_CONNECTED,
+ iapName,
+ R_LOG_DIR_OUT,
+ KNullDesC,
+ KLogWlanDataEventTypeUid );
+
+ CleanupStack::PopAndDestroy( wlanRecord );
+ CleanupStack::PopAndDestroy( iapRecord );
+ CleanupStack::PopAndDestroy( db );
+ }
+ else
+ {
+ LOGIT1("FAILED to get KIAPId from ConnMon", err)
+ }
+ }
+ // Check if it is EXTERNAL GPRS or WCDMA.
+ else if ( bearer == EBearerExternalGPRS ||
+ bearer == EBearerExternalEdgeGPRS ||
+ bearer == EBearerExternalWCDMA )
+ {
+ LOGIT0("New external connection")
+
+ TName apName;
+ apName.FillZ();
+ apName.Zero();
+
+ err = KErrNotReady;
+ a = 0;
+ // We loop until the retry count is reached or
+ // we get a name with length > 0
+ // This is because the connection monitor asks the PSD Fax
+ // for the name and PSD fax sometines returns an empty string
+ // without returning an error code (KErrNone is returned)
+ // However if no name for the APN has been defined this will
+ // loop for KPhoneRetryCount times for vain, but it's better than
+ // to use an empty name if one has been defined...
+ while( a < KPhoneRetryCount &&
+ ( ( err != KErrNone ) || ( apName.Length() == 0 ) ) )
+ {
+ // ConnMon might not be able to provide KAccessPointName with first trial.
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ // Get String Attribute -> KAccessPointName.
+ // Get APN from CM server.
+ iConnectionMonitor.GetStringAttribute(
+ connectionId,
+ KSubConnectionId,
+ KAccessPointName,
+ apName,
+ status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOG( TBuf<KMaxName+1> apName2( apName ); )
+ LOGIT2("Got KAccessPointName from ConnMon <%s>, <%d>", apName2.PtrZ(), err)
+ a++;
+ }
+ if ( err == KErrNone )
+ {
+ LogDataAddEventL(
+ connectionId,
+ R_LOG_CON_CONNECTED,
+ apName,
+ R_LOG_DIR_OUT,
+ KNullDesC,
+ KLogPacketDataEventTypeUid );
+ }
+ else
+ {
+ LOGIT1("FAILED to get KAccessPointName from ConnMon <%d>", err)
+ }
+ }
+ else
+ {
+ LOGIT0("Bearer neither GPRS nor WCDMA nor WLAN, ignored")
+ break;
+ }
+ break;
+ }
+
+ case EConnMonConnectionStatusChange:
+ {
+ TInt bearer( 0 );
+ TRequestStatus status( KErrNotReady );
+
+ const CConnMonConnectionStatusChange* eventStatus;
+ eventStatus = static_cast<const CConnMonConnectionStatusChange*>( &aConnMonEvent );
+ connectionId = eventStatus->ConnectionId();
+
+ LOGIT2("*** EConnMonConnectionStatusChange event, id %d, status %d ***",
+ connectionId, eventStatus->ConnectionStatus())
+
+ if ( eventStatus->ConnectionStatus() == KPsdFinishedActivation )
+ {
+ // Get the bearer info from CM server.
+ iConnectionMonitor.GetIntAttribute(
+ connectionId,
+ KSubConnectionId,
+ KBearer,
+ bearer,
+ status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to get bearer from ConnMon <%d>", err)
+ break;
+ }
+
+ // Check that it is external GPRS or WCDMA.
+ if ( bearer == EBearerExternalGPRS ||
+ bearer == EBearerExternalEdgeGPRS ||
+ bearer == EBearerExternalWCDMA )
+ // Add EBearerLAN in order to enable debugging in wins.
+ {
+ LOGIT1("Status: KPsdFinishedActivation, bearer: %d (valid external), updating AP name", bearer)
+ TName apName;
+ apName.FillZ();
+ apName.Zero();
+
+ err = KErrNotReady;
+ TInt a = 0;
+ // We loop until the retry count is reached or
+ // we get a name with length > 0
+ // This is because the connection monitor asks the PSD Fax
+ // for the name and PSD fax sometines returns an empty string
+ // without returning an error code (KErrNone is returned)
+ // However if no name for the APN has been defined this will
+ // loop for KPhoneRetryCount times for vain, but it's better than
+ // to use an empty name if one has been defined...
+ while( a < KPhoneRetryCount && (
+ ( err != KErrNone ) ||
+ ( apName.Length() == 0 )
+ ) )
+ {
+ // ConnMon might not be able to provide KAccessPointName with first trial.
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ // Get String Attribute -> KAccessPointName.
+ // Get APN from CM server.
+ iConnectionMonitor.GetStringAttribute(
+ connectionId,
+ KSubConnectionId,
+ KAccessPointName,
+ apName,
+ status );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOG( TBuf<KMaxName+1> apName2( apName ); )
+ LOGIT2("Got KAccessPointName from ConnMon <%s>, <%d>", apName2.PtrZ(), err)
+ a++;
+ }
+
+ if ( err == KErrNone )
+ {
+ // We want only to change the existing entry in the log,
+ // not add a new one, thus LogDataChangeEventL instead of
+ // LogDataAddEventL
+ LogDataChangeEventL( connectionId, apName );
+ }
+ else
+ {
+ LOGIT1("FAILED to get KAccessPointName from ConnMon <%d>", err)
+ }
+ }
+ else
+ {
+ LOGIT1("Status: KPsdFinishedActivation, bearer: %d (not valid external)", bearer)
+ }
+ }
+ }
+ break;
+
+ case EConnMonDeleteConnection:
+ {
+ const CConnMonDeleteConnection* eventDelete;
+ eventDelete = static_cast<const CConnMonDeleteConnection*>( &aConnMonEvent );
+ connectionId = eventDelete->ConnectionId();
+
+ LOGIT1("*** EConnMonDeleteConnection event, id %d ***", connectionId)
+ LOGIT1("sent: %d bytes", eventDelete->UplinkData())
+ LOGIT1("recv: %d bytes", eventDelete->DownlinkData())
+
+ // First update SharedData downlink and uplink data
+ UpdateSharedDataL(
+ connectionId,
+ eventDelete->UplinkData(),
+ eventDelete->DownlinkData() );
+
+ // Then update connection specific downlink and uplink data
+ err = LogDataUpdateEventL(
+ connectionId,
+ R_LOG_CON_DISCONNECTED,
+ TUid::Null(),
+ eventDelete->UplinkData(),
+ eventDelete->DownlinkData() );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to log connection deletion <%d>", err)
+ }
+
+ // Stop timer mode for this connection.
+ // It is ok to call this even if the connection was not in timer mode.
+ iDclTimerAO->Remove( connectionId );
+
+ }
+ break;
+
+ case EConnMonDownlinkDataThreshold:
+ {
+ TInt oldDuration( 0 );
+ TInt newDuration( 0 );
+
+ const CConnMonDownlinkDataThreshold* down;
+ down = static_cast<const CConnMonDownlinkDataThreshold*>( &aConnMonEvent );
+ connectionId = down->ConnectionId();
+
+ LOGIT1("*** EConnMonDownlinkDataThreshold event, id %d ***", connectionId)
+
+ if ( !GetDuration( connectionId, oldDuration ) )
+ {
+ return;
+ }
+
+ // First update SharedData downlink data
+ UpdateSharedDataL( connectionId, 0, down->DownlinkData() );
+
+ // Then update connection specific downlink data
+ // Also uplink data has to be updated at the same time,
+ // since CEventLog function SetDataL requires both values.
+ TRequestStatus status;
+ TUint uplinkData( 0 );
+ // Get the amount uplink data from CM server
+ iConnectionMonitor.GetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KUplinkData,
+ uplinkData,
+ status );
+ User::WaitForRequest( status );
+ if ( status.Int() != KErrNone )
+ {
+ LOGIT1("FAILED to get KUplinkData from ConnMon <%d>", err)
+ }
+
+ // The actual status of connection is R_LOG_CON_CONNECTED, but
+ // due to the performance reasons KConnectionStatusIdNotAvailable
+ // is used here. There is no need to read LOGWRAP.RSC every time.
+ err = LogDataUpdateEventL(
+ connectionId,
+ KConnectionStatusIdNotAvailable,
+ TUid::Null(),
+ uplinkData,
+ down->DownlinkData() );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to update log event <%d>", err)
+ }
+
+ // Switch to timer if we are updating log too often
+ if ( GetDuration( connectionId, newDuration ) )
+ {
+ if ( ( newDuration - oldDuration ) < iTimerInterval )
+ {
+ SwitchToTimerMode( connectionId );
+ }
+ }
+ }
+ break;
+
+ case EConnMonUplinkDataThreshold:
+ {
+ TInt oldDuration( 0 );
+ TInt newDuration( 0 );
+
+ const CConnMonUplinkDataThreshold* up;
+ up = static_cast<const CConnMonUplinkDataThreshold*>( &aConnMonEvent );
+ connectionId = up->ConnectionId();
+
+ LOGIT1("*** EConnMonUplinkDataThreshold event, id %d ***", connectionId)
+
+ if ( !GetDuration( connectionId, oldDuration ) )
+ {
+ return;
+ }
+
+ // First update SharedData uplink data
+ UpdateSharedDataL( connectionId, up->UplinkData(), 0 );
+
+ // Then update connection specific uplink data
+ // Also downlink data has to be updated at the same time,
+ // since CEventLog function SetDataL requires both values.
+ TRequestStatus status;
+ TUint downlinkData( 0 );
+
+ // Get the amount of downlink data from CM server
+ iConnectionMonitor.GetUintAttribute(
+ connectionId,
+ KSubConnectionId,
+ KDownlinkData,
+ downlinkData,
+ status );
+ User::WaitForRequest( status );
+ if ( status.Int() != KErrNone )
+ {
+ LOGIT1("FAILED to get KDownlinkData from ConnMon <%d>", err)
+ }
+
+ // The actual status of connection is R_LOG_CON_CONNECTED, but
+ // due to the performance reasons KConnectionStatusIdNotAvailable
+ // is used here. There is no need to read LOGWRAP.RSC every time.
+ err = LogDataUpdateEventL(
+ connectionId,
+ KConnectionStatusIdNotAvailable,
+ TUid::Null(),
+ up->UplinkData(),
+ downlinkData );
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to update log event <%d>", err)
+ }
+
+ // Switch to timer if we are updating log too often
+ if ( GetDuration( connectionId, newDuration ) )
+ {
+ if ( ( newDuration - oldDuration ) < iTimerInterval )
+ {
+ SwitchToTimerMode( connectionId );
+ }
+ }
+ }
+ break;
+
+ default:
+ /*
+ * By default Connection Monitor server sends all the events to
+ * all the clients, which have subscribed to reveive events. It
+ * is not possible to subscribe to only selected events.
+ *
+ * Therefore these events are not written to log.
+ */
+ break;
+ }
+ LOGEXITFN("CEngine::EventL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::LogDataAddEventL
+// Adds log events.
+//
+// Handles also multiple data connections.
+// --------------------------------------------------------------------------
+//
+void CEngine::LogDataAddEventL(
+ TLogId aConnectionId,
+ TInt aRConnectionStatusId,
+ const TDesC& aRemote,
+ TInt aLogDir,
+ const TDesC& aTelNum,
+ const TUid& aDataEventType )
+ {
+ LOGENTRFN("CEngine::LogDataAddEventL()")
+ // It is possible to add a new logevent with a new log id for the same
+ // connection (reconnect case) assuming that all the next updates will
+ // be for the new event and not the old one.
+ TTime time;
+ time.UniversalTime();
+ TBuf<KLogMaxStatusLength> logStatusBuf;
+ TBuf<KLogMaxDirectionLength> logDirBuf;
+
+ // Set the parameters for CEvent
+ CEvent* eventUpdate = CEvent::NewL();
+ CleanupStack::PushL( eventUpdate );
+ eventUpdate->iConnectionId = aConnectionId;
+ eventUpdate->iLogWrapEvent->SetId( KGenconnLogWaitingForLogId );
+ eventUpdate->iLogWrapEvent->SetTime( time );
+ // Ignore error - string blank on error which is ok.
+ iLogWrap->Log().GetString( logStatusBuf, aRConnectionStatusId );
+ eventUpdate->iLogWrapEvent->SetStatus( logStatusBuf );
+ eventUpdate->iLogWrapEvent->SetRemoteParty( aRemote );
+ // Ignore error - string blank on error which is ok.
+ iLogWrap->Log().GetString( logDirBuf, aLogDir );
+ eventUpdate->iLogWrapEvent->SetDirection( logDirBuf );
+ eventUpdate->iLogWrapEvent->SetNumber( aTelNum );
+ eventUpdate->iLogWrapEvent->SetEventType( *CONST_CAST( TUid*, &aDataEventType ) );
+ eventUpdate->iLogWrapEvent->SetDurationType( KLogDurationValid );
+
+ // If there are no requests in the queue, then write to log immediately.
+ if ( !IsActive() && ( iLogEventQueue->Count() == 0 ) )
+ {
+ iConnections->AppendL( eventUpdate );
+ iStatus = KRequestPending;
+ iLogWrap->Log().AddEvent( *eventUpdate->iLogWrapEvent, iStatus );
+ SetActive();
+ }
+ else
+ {
+ LOGIT0("Adding event to eventqueue")
+ // Add the request to the queue, it will be processed ASAP.
+ iLogEventQueue->AppendL( eventUpdate );
+ }
+ CleanupStack::Pop( eventUpdate );
+ LOGEXITFN("CEngine::LogDataAddEventL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::LogDataChangeEventL
+// Changes log events. Used to update the access point name of the
+// external GPRS ie. dial-up connections.
+//
+// Handles also multiple data connections.
+// --------------------------------------------------------------------------
+//
+void CEngine::LogDataChangeEventL( TLogId aConnectionId, const TDesC& aRemote )
+ {
+ LOGENTRFN("CEngine::LogDataChangeEventL()")
+
+ // Check event queue first, if a match is found, the connection hasn't been
+ // added to iConnections array yet. Update event in queue with correct
+ // access point name.
+ for ( TInt index = 0; index < iLogEventQueue->Count(); index++ )
+ {
+ LOGIT2("Checking event queue index %d, id %d", index, iLogEventQueue->At( index )->iConnectionId)
+ if ( iLogEventQueue->At( index )->iConnectionId == aConnectionId )
+ {
+ LOGIT0("Match found, merging updated apn to queued event")
+ iLogEventQueue->At( index )->iLogWrapEvent->SetRemoteParty( aRemote );
+ LOGEXITFN("CEngine::LogDataChangeEventL()")
+ return;
+ }
+ }
+
+ // Most likely event queue was empty, so next we need to find the relevant
+ // connection from iConnections array.
+ for ( TInt index = 0; index < iConnections->Count(); index++ )
+ {
+ LOGIT2("Checking connections index %d, id %d", index, iConnections->At( index )->iConnectionId)
+
+ if ( iConnections->At( index )->iConnectionId == aConnectionId )
+ {
+ // Can update now, or need add to queue
+ if ( !IsActive() && ( iLogEventQueue->Count() == 0 ) )
+ {
+ LOGIT0("Match found, updating apn immediately")
+
+ // Update apn and initiate LogWrapper update.
+ iConnections->At( index )->iLogWrapEvent->SetRemoteParty( aRemote );
+ iStatus = KRequestPending;
+ iLogWrap->Log().ChangeEvent( *iConnections->At( index )->iLogWrapEvent, iStatus );
+ SetActive();
+ }
+ else
+ {
+ LOGIT0("Match found, adding apn update event to queue")
+
+ // Make a copy of the CLogEvent, update apn and add the updated
+ // copy to event queue.
+ CEvent* eventUpdate = CEvent::NewL();
+ CleanupStack::PushL( eventUpdate );
+
+ eventUpdate->iConnectionId = aConnectionId;
+ eventUpdate->iLogWrapEvent->CopyL( *iConnections->At( index )->iLogWrapEvent );
+ eventUpdate->iLogWrapEvent->SetRemoteParty( aRemote );
+ iLogEventQueue->AppendL( eventUpdate );
+
+ CleanupStack::Pop( eventUpdate );
+ }
+ }
+ break; // for
+ }
+ LOGEXITFN("CEngine::LogDataChangeEventL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::LogDataUpdateEventL
+// Updates log events.
+//
+// Handles also multiple data connections.
+// --------------------------------------------------------------------------
+//
+TInt CEngine::LogDataUpdateEventL(
+ TLogId aConnectionId,
+ TInt aRConnectionStatusId,
+ const TUid& aDataEventType,
+ const TInt64& aBytesSent,
+ const TInt64& aBytesReceived )
+ {
+ LOGENTRFN("CEngine::LogDataUpdateEventL()")
+ TInt ret = KErrNone;
+ TLogId connectionId;
+
+ for ( TInt index = 0; index < iConnections->Count(); index++ )
+ {
+ connectionId = iConnections->At( index )->iConnectionId;
+
+ if ( connectionId == aConnectionId )
+ {
+ // Check if there is no request pending, then start it. Otherwise
+ // wait until the previous request is finished and keep going on.
+ if ( !IsActive() && ( iLogEventQueue->Count() == 0 ) )
+ {
+ // Request update straight on.
+ UpdateLogEventParamL(
+ aConnectionId,
+ *iConnections->At( index )->iLogWrapEvent,
+ aRConnectionStatusId,
+ aDataEventType,
+ aBytesSent,
+ aBytesReceived );
+
+ iConnections->At( index )->iPrevDuration =
+ iConnections->At( index )->iLogWrapEvent->Duration();
+
+ iLogWrap->Log().ChangeEvent( *iConnections->At( index )->iLogWrapEvent, iStatus );
+ SetActive();
+ }
+ else
+ {
+ LOGIT0("Adding event update to queue")
+ // Add the request to the queue, it will be processed ASAP.
+ CEvent* eventUpdate = CEvent::NewL();
+ CleanupStack::PushL( eventUpdate );
+ eventUpdate->iConnectionId = aConnectionId;
+ eventUpdate->iLogWrapEvent->CopyL( *iConnections->At( index )->iLogWrapEvent );
+ ret = UpdateLogEventParamL(
+ aConnectionId,
+ *eventUpdate->iLogWrapEvent,
+ aRConnectionStatusId,
+ aDataEventType,
+ aBytesSent,
+ aBytesReceived );
+
+ iConnections->At( index )->iPrevDuration =
+ eventUpdate->iLogWrapEvent->Duration();
+
+ // Add to the queue.
+ iLogEventQueue->AppendL( eventUpdate );
+ CleanupStack::Pop( eventUpdate );
+ }
+ }
+ }
+ LOGEXITFN1("CEngine::LogDataUpdateEventL()", ret)
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::UpdateLogEventParamL
+// Updates log event parameters.
+// --------------------------------------------------------------------------
+//
+TInt CEngine::UpdateLogEventParamL(
+ TLogId /*aConnectionId*/,
+ CLogEvent& aLogEvent,
+ TInt aRConnectionStatusId,
+ const TUid& aDataEventType,
+ const TInt64& aBytesSent,
+ const TInt64& aBytesReceived )
+ {
+ LOGENTRFN("CEngine::UpdateLogEventParamL()")
+ TInt ret( KErrNone );
+ TTime now;
+ TTimeIntervalSeconds seconds( 0 );
+ now.UniversalTime();
+
+ if ( now.SecondsFrom( aLogEvent.Time(), seconds ) != KErrNone )
+ {
+ seconds = 0; // No duration available -> error.
+ }
+ aLogEvent.SetDuration( seconds.Int() );
+
+ if ( KConnectionStatusIdNotAvailable != aRConnectionStatusId )
+ {
+ // Status needs to be updated.
+ TBuf<KLogMaxStatusLength> logStatusBuf;
+ // Ignore error - string blank on error which is ok.
+ iLogWrap->Log().GetString( logStatusBuf, aRConnectionStatusId );
+ aLogEvent.SetStatus( logStatusBuf );
+ }
+ if ( aDataEventType != TUid::Null() )
+ {
+ aLogEvent.SetEventType( *CONST_CAST( TUid*, &aDataEventType ) );
+ }
+ // Check if data metrics need to be updated.
+ TInt64 byteInfoNotAvailable( KBytesInfoNotAvailable );
+ if ( ( aBytesReceived != byteInfoNotAvailable ) &&
+ ( aBytesSent != byteInfoNotAvailable ) )
+ {
+ TBuf8<KDatabufferSize> dataBuffer;
+ dataBuffer.Num( aBytesSent );
+ dataBuffer.Append( TChar(',') );
+ dataBuffer.AppendNum( aBytesReceived );
+ TRAP( ret, aLogEvent.SetDataL( dataBuffer ) );
+ }
+ LOGEXITFN1("CEngine::UpdateLogEventParamL()", ret)
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::UpdateSharedDataL
+// Updates cumulative counters of SharedData.
+// --------------------------------------------------------------------------
+//
+void CEngine::UpdateSharedDataL(
+ TLogId aConnectionId,
+ const TInt64& aBytesSent,
+ const TInt64& aBytesReceived )
+ {
+ LOGENTRFN("CEngine::UpdateSharedDataL()")
+ TInt64 sent( 0 );
+ TInt64 received( 0 );
+ TInt64 increment( 0 );
+ TLogId connId;
+ TBuf<50> receivedBuf, sentBuf;
+ TBuf<50> receivedBuf2, sentBuf2;
+ TUid dataEventType = KLogPacketDataEventTypeUid;
+ TInt err, index;
+
+ // First find out the data event type (GPRS or WLAN)
+ for ( index = 0; index < iConnections->Count(); index++ )
+ {
+ connId = iConnections->At( index )->iConnectionId;
+ if ( connId == aConnectionId )
+ {
+ dataEventType = iConnections->At( index )->iLogWrapEvent->EventType();
+
+ if ( aBytesSent == 0 && aBytesReceived == 0 )
+ {
+ break;
+ }
+
+ CRepository* repository = NULL;
+ repository = CRepository::NewL( KCRUidDCLLogs );
+ if ( repository )
+ {
+ err = repository->StartTransaction( CRepository::EConcurrentReadWriteTransaction );
+ if ( err )
+ {
+ LOGIT1("UpdateSharedDataL: StartTransaction() returned error: %d", err)
+ delete repository;
+ break;
+ }
+
+ if ( aBytesReceived != 0 )
+ {
+ // Read current value.
+ if ( dataEventType == KLogPacketDataEventTypeUid )
+ {
+ err = repository->Get( KLogsGPRSReceivedCounter, receivedBuf );
+ }
+ else
+ {
+ err = repository->Get( KLogsWLANReceivedCounter, receivedBuf );
+ }
+ if ( err == KErrNone )
+ {
+ TLex lex( receivedBuf );
+ lex.Val( received );
+ }
+ else
+ {
+ LOGIT1("UpdateSharedDataL: aBytesReceived: Get() returned error: %d", err)
+ repository->CancelTransaction();
+ delete repository;
+ break;
+ }
+
+ // Calculate the increment
+ increment = aBytesReceived - iConnections->At( index )->iPrevDownValue;
+ // And add _only_ the increment
+ received += increment;
+ // Update the previous downlink value
+ iConnections->At( index )->iPrevDownValue = aBytesReceived;
+ receivedBuf2.Num( received );
+
+ // Store updated value.
+ if ( dataEventType == KLogPacketDataEventTypeUid )
+ {
+ err = repository->Set( KLogsGPRSReceivedCounter, receivedBuf2 );
+ }
+ else
+ {
+ err = repository->Set( KLogsWLANReceivedCounter, receivedBuf2 );
+ }
+ if ( err != KErrNone )
+ {
+ LOGIT1("UpdateSharedDataL: aBytesReceived: Set() returned error: %d", err)
+ repository->CancelTransaction();
+ delete repository;
+ break;
+ }
+ }
+ if ( aBytesSent != 0 )
+ {
+ // Read current value.
+ if ( dataEventType == KLogPacketDataEventTypeUid )
+ {
+ err = repository->Get( KLogsGPRSSentCounter, sentBuf );
+ }
+ else
+ {
+ err = repository->Get( KLogsWLANSentCounter, sentBuf );
+ }
+ if ( err == KErrNone )
+ {
+ TLex lex( sentBuf );
+ lex.Val( sent );
+ }
+ else
+ {
+ LOGIT1("UpdateSharedDataL: aBytesSent: Get() returned error: %d", err)
+ repository->CancelTransaction();
+ delete repository;
+ break;
+ }
+
+ // Calculate the increment
+ increment = aBytesSent - iConnections->At( index )->iPrevUpValue;
+ // And add _only_ the increment
+ sent += increment;
+ // Update the previous uplink value
+ iConnections->At( index )->iPrevUpValue = aBytesSent;
+ sentBuf2.Num( sent );
+
+ // Store updated value.
+ if ( dataEventType == KLogPacketDataEventTypeUid )
+ {
+ err = repository->Set( KLogsGPRSSentCounter, sentBuf2 );
+ }
+ else
+ {
+ err = repository->Set( KLogsWLANSentCounter, sentBuf2 );
+ }
+ if ( err != KErrNone )
+ {
+ LOGIT1("UpdateSharedDataL: aBytesSent: Set() returned error: %d", err)
+ repository->CancelTransaction();
+ delete repository;
+ break;
+ }
+ }
+ TUint32 keyInfo;
+ err = repository->CommitTransaction( keyInfo );
+ if ( err != KErrNone )
+ {
+ LOGIT2("UpdateSharedDataL: repository->CommitTransaction returned error: %d, %d", err, keyInfo)
+ repository->CancelTransaction();
+ delete repository;
+ break;
+ }
+ }
+ delete repository;
+ break;
+ }
+ } // for
+ LOGEXITFN("CEngine::UpdateSharedDataL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::RunL
+// Handles the completion of an asynchronous request.
+// This function is defined as pure virtual in CActive and any class derived
+// from CActive must define and implement it.
+// --------------------------------------------------------------------------
+//
+void CEngine::RunL()
+ {
+ LOGENTRFN("CEngine::RunL()")
+
+ // Request has completed.
+ // Delete the disconnected element of iConnections, if it has already been
+ // logged and the connection has been disconnected
+ if ( iConnections->Count() > 0 )
+ {
+ LOGIT1("RunL: iConnections->Count() = %d (>0), clearing old connections", iConnections->Count())
+
+ // Ignore error - string blank on error which is ok.
+ TBuf<KLogMaxStatusLength> logStatusBuf;
+ iLogWrap->Log().GetString( logStatusBuf, R_LOG_CON_DISCONNECTED );
+
+ for ( TInt i = iConnections->Count()-1; i >= 0; i-- )
+ {
+ CEvent* elemPtr = iConnections->At( i );
+
+ __ASSERT_DEBUG( ( elemPtr != NULL ), User::Panic( KDCLName, KErrNotReady ) );
+ LOGIT2("Checking index %d, connection id %d", i, elemPtr->iConnectionId)
+ if ( logStatusBuf == elemPtr->iLogWrapEvent->Status() )
+ {
+ LOGIT0("Status: disconnected, removing")
+
+ // Remove the pointer from the queue.
+ iConnections->Delete( i );
+ // Delete the completed CEvent
+ delete elemPtr;
+ }
+ }
+ }
+
+ // Delete completed event and check if there is a next event pending.
+ // If LogEng is not supported, a dummy logeng just returns error straight
+ // on, but we carry on doing all the requests.
+ if ( iLogEventQueue->Count() > 0 )
+ {
+ LOGIT1("RunL: iLogEventQueue->Count() = %d (>0), processing next event", iLogEventQueue->Count())
+
+ CEvent* nextEventPtr = iLogEventQueue->At( 0 );
+ __ASSERT_DEBUG( ( nextEventPtr != NULL ), User::Panic( KDCLName, KErrNotReady ) );
+ // In general, before the elements of this kind of array are deleted,
+ // the CBase derived objects to which those elements point should be
+ // destroyed. If they are not destroyed, then a separate copy of
+ // those elements (i.e. the pointers), must be taken to avoid
+ // orphaning the CBase derived objects on the heap.
+ iCurrentLogEvent->CopyL( *nextEventPtr->iLogWrapEvent );
+ iLogWrap->Log().ChangeEvent( *iCurrentLogEvent, iStatus );
+ SetActive();
+ // Remove the pointer from the queue.
+ iLogEventQueue->Delete( 0 );
+ // Delete the completed CEvent
+ delete nextEventPtr;
+ }
+ LOGEXITFN("CEngine::RunL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::DoCancel
+// Handles a cancel request to the service provider.
+// This function is defined as pure virtual in CActive and any class derived
+// from CActive must define and implement it.
+// --------------------------------------------------------------------------
+//
+void CEngine::DoCancel()
+ {
+ if ( iLogWrap )
+ {
+ iLogWrap->Log().Cancel();
+ }
+ // Usually you do not need to cancel an update on events, just let them
+ // go and be removed from the queue when update is done.
+ // If we cancel the logger, most likely the whole Logger Object will be
+ // destroyed.
+}
+
+// --------------------------------------------------------------------------
+// CEngine::SetAttachModeL
+// Gets the Attach Mode setting from CommDb and sets ETel to use that value.
+// --------------------------------------------------------------------------
+//
+void CEngine::SetAttachModeL() const
+ {
+ LOGENTRFN("CEngine::SetAttachModeL()")
+
+ TUint32 commdbAM = RPacketService::EAttachWhenNeeded;
+ TRequestStatus status;
+ RPacketService::TAttachMode etelAM;
+ CCommsDatabase* commDb = NULL;
+
+ if ( iPacketServLoaded != 1 )
+ {
+ LOGIT0("RPacketService not loaded")
+ return;
+ }
+
+ commDb = CCommsDatabase::NewL();
+
+ // Get the Attach Mode setting from CommDb
+ TRAPD( error, commDb->GetGlobalSettingL( TPtrC( GPRS_ATTACH_MODE ), commdbAM ) );
+ switch ( error )
+ {
+ case KErrNone:
+ // Attach Mode setting found in CommDb
+ break;
+ case KErrNotFound:
+ {
+ // Attach Mode setting not found in CommDb, it is set as EAttachWhenNeeded
+ TRAPD( leaveCode, commDb->SetGlobalSettingL( TPtrC( GPRS_ATTACH_MODE ), commdbAM ) );
+ if ( leaveCode )
+ {
+ LOGIT1("FAILED SetGlobalSettingL() <%d>", leaveCode)
+ }
+ }
+ break;
+ default:
+ {
+ LOGIT1("FAILED to get attach mode from CommDb <%d>", error)
+ }
+ break;
+ }
+
+ // And set ETel to use the Attach Mode value from CommDb
+ etelAM = STATIC_CAST( RPacketService::TAttachMode, commdbAM );
+
+ TInt err( KErrNotReady );
+ TInt a = 0;
+ while ( a < KPhoneRetryCount && err != KErrNone )
+ {
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ iPacketService.SetAttachMode( status, etelAM );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOGIT1("Set attach Mode to ETel <%d>", err)
+ a++;
+ }
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to set attach mode to ETel <%d>", err)
+ }
+ delete commDb;
+ LOGEXITFN("CEngine::SetAttachModeL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::SetAPNL
+// Gets the default Access Point Name from CommDb and
+// sets ETel to use that APN.
+// --------------------------------------------------------------------------
+//
+void CEngine::SetAPNL() const
+ {
+ LOGENTRFN("CEngine::SetAPNL()")
+
+ TBuf<KMaxAPName> apName;
+ TRequestStatus status( KErrNotReady );
+ CCommsDatabase* commDb = NULL;
+
+ if ( iPacketServLoaded != 1 )
+ {
+ LOGIT0("RPacketService not loaded")
+ return;
+ }
+
+ commDb = CCommsDatabase::NewL();
+ CleanupStack::PushL( commDb );
+
+ // Get the default Access Point Name from CommDb
+ CCommsDbTableView* table = commDb->OpenTableLC( TPtrC( DEFAULT_GPRS ) );
+
+ table->GotoFirstRecord();
+
+ //If APN is not initialized, ReadTextL will leave
+ apName.SetLength( 0 );
+
+ table->ReadTextL( TPtrC( DEFAULT_GPRS_APN ), apName );
+
+ CleanupStack::PopAndDestroy( table );
+
+ // Get DefaultContextParams from ETel
+ RPacketContext::TContextConfigGPRS* getParams = NULL;
+ getParams = new( ELeave ) RPacketContext::TContextConfigGPRS();
+
+ TPckg<RPacketContext::TContextConfigGPRS> getParamsPckg( *getParams );
+
+ TInt err( KErrNotReady );
+ TInt a = 0;
+ while ( a < KPhoneRetryCount && err != KErrNone )
+ {
+ // The RPacketService::GetDefaultContextParams() does not always work
+ // with the first trial, it might return KErrNotReady.
+ if ( a )
+ {
+ User::After( KPhoneRetryTimeout ); // Don't wait on first try
+ }
+ iPacketService.GetDefaultContextParams( status, getParamsPckg );
+ User::WaitForRequest( status );
+ err = status.Int();
+ LOGIT1("Got DefaultContextParams from ETel <%d>", err)
+ a++;
+ }
+
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to get DefaultContextParams from ETel <%d>", err)
+ }
+
+ // Replace ETel APN with CommDb APN
+ ReplaceAPN( getParams->iAccessPointName, apName );
+
+ // Set DefaultContextParams to ETel
+ iPacketService.SetDefaultContextParams( status, getParamsPckg );
+ User::WaitForRequest( status );
+
+ err = status.Int();
+ if ( err != KErrNone )
+ {
+ LOGIT1("FAILED to set DefaultContextParams to ETel <%d>", err)
+ }
+
+ delete getParams;
+ CleanupStack::PopAndDestroy( commDb );
+ LOGEXITFN("CEngine::SetAPNL()")
+ }
+
+// --------------------------------------------------------------------------
+// CEngine::AddEventTypeL
+// Adds the event type Wlan. Otherwise the LogClient
+// will not understand this type of event.
+// --------------------------------------------------------------------------
+//
+void CEngine::AddEventTypeL()
+ {
+ iLogEventType = CLogEventType::NewL();
+ iLogEventType->SetUid( KLogWlanDataEventTypeUid );
+ iLogEventType->SetDescription( _L("Wlan") );
+ iLogEventType->SetLoggingEnabled( ETrue );
+
+ iStatus = KRequestPending;
+ iLogClient->AddEventType( *iLogEventType, iStatus );
+
+ SetActive();
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::ReplaceAPN
+// This method will be used in platforms where ETel APN (aResult) is UNICODE.
+// -----------------------------------------------------------------------------
+//
+void CEngine::ReplaceAPN( TDes& aResult, const TDesC& aName ) const
+ {
+ aResult = aName;
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::ReplaceAPN
+// This method will be used in platforms where ETel APN (aResult) is UTF8.
+// -----------------------------------------------------------------------------
+//
+void CEngine::ReplaceAPN( TDes8& aResult, const TDesC& aName ) const
+ {
+ CnvUtfConverter::ConvertFromUnicodeToUtf8( aResult, aName );
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::LogDataInTimerModeL
+// -----------------------------------------------------------------------------
+//
+TInt CEngine::LogDataInTimerModeL( const TUint aConnectionId )
+ {
+ LOGENTRFN("CEngine::LogDataInTimerModeL()")
+ TInt index( 0 );
+ TInt64 prevDown( 0 );
+ TInt64 prevUp( 0 );
+
+ TInt count( iConnections->Count() );
+
+ LOGIT1("LogDataInTimerMode, id %d", aConnectionId)
+
+ // Does the connection still exist
+ for ( index = 0; index < count; index++ )
+ {
+ TUint connId( iConnections->At( index )->iConnectionId );
+
+ if ( connId == aConnectionId )
+ {
+ prevDown = iConnections->At(index)->iPrevDownValue;
+ prevUp = iConnections->At(index)->iPrevUpValue;
+ break;
+ }
+ }
+
+ if ( index == count )
+ {
+ return KErrNotFound;
+ }
+
+ // Read data volumes
+ TRequestStatus status;
+ TUint uplinkData( 0 );
+ TUint downlinkData( 0 );
+
+ // Get the amount uplink data from CM server
+ iConnectionMonitor.GetUintAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KUplinkData,
+ uplinkData,
+ status );
+ User::WaitForRequest( status );
+
+ if ( status.Int() != KErrNone )
+ {
+ LOGIT1("FAILED to get KUplinkData from ConnMon <%d>", status.Int())
+ }
+
+ // Get the amount of downlink data from CM server
+ iConnectionMonitor.GetUintAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KDownlinkData,
+ downlinkData,
+ status );
+ User::WaitForRequest( status );
+
+ if ( status.Int() != KErrNone )
+ {
+ LOGIT1("FAILED to get KDownlinkData from ConnMon <%d>", status.Int())
+ }
+
+ // Update SharedData downlink and uplink data
+ UpdateSharedDataL( aConnectionId, uplinkData, downlinkData );
+
+ TInt ret = KErrNone;
+ // The actual status of connection is R_LOG_CON_CONNECTED, but
+ // due to the performance reasons KConnectionStatusIdNotAvailable
+ // is used here. There is no need to read LOGWRAP.RSC every time.
+ ret = LogDataUpdateEventL(
+ aConnectionId,
+ KConnectionStatusIdNotAvailable,
+ TUid::Null(),
+ uplinkData,
+ downlinkData );
+ if ( ret != KErrNone )
+ {
+ LOGIT1("FAILED to update log data (timer mode) <%d>", ret)
+ }
+
+ // Check data volumes
+ TUint threshold( iGPRSThreshold );
+
+ ret = GetDefaultThreshold( aConnectionId, threshold );
+
+ if ( ret != KErrNotFound )
+ {
+ // If the increase both in uplink and downlink data volume is less than threshold/2
+ // switch the connection back to the threshold mode.
+ if ( ( ( iConnections->At(index)->iPrevDownValue - prevDown ) < threshold/2 )
+ &&
+ ( ( iConnections->At(index)->iPrevUpValue - prevUp ) < threshold/2 ))
+ {
+ SwitchToThresholdMode( aConnectionId, threshold );
+
+ // Return an error to stop the timer mode for this connection
+ ret = KErrCancel;
+ }
+ else
+ {
+ ret = KErrNone;
+ }
+ }
+ LOGEXITFN1("CEngine::LogDataInTimerModeL()", ret)
+ return ret;
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::SwitchToThresholdMode
+// -----------------------------------------------------------------------------
+//
+void CEngine::SwitchToThresholdMode( const TUint aConnectionId, const TUint aThreshold )
+ {
+ LOGENTRFN("CEngine::SwitchToThresholdMode()")
+ // Set thresholds to start the threshold mode
+ TUint threshold( aThreshold );
+
+ if ( threshold == 0 )
+ {
+ TInt ret = GetDefaultThreshold( aConnectionId, threshold );
+
+ if ( ret == KErrNotFound )
+ {
+ // Connection has closed
+ return;
+ }
+ }
+
+ iConnectionMonitor.SetUintAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KDownlinkDataThreshold,
+ threshold );
+
+ iConnectionMonitor.SetUintAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KUplinkDataThreshold,
+ threshold );
+
+ LOGIT1("Switched to threshold mode, id %d", aConnectionId)
+
+ LOGEXITFN("CEngine::SwitchToThresholdMode()")
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::SwitchToTimerMode
+// -----------------------------------------------------------------------------
+//
+void CEngine::SwitchToTimerMode( const TUint aConnectionId )
+ {
+ LOGENTRFN("CEngine::SwitchToTimerMode()")
+ if ( iDclTimerAO != 0 )
+ {
+ // Set thresholds to zero.
+ iConnectionMonitor.SetUintAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KDownlinkDataThreshold,
+ 0 );
+
+ iConnectionMonitor.SetUintAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KUplinkDataThreshold,
+ 0 );
+
+ iDclTimerAO->Add( aConnectionId );
+
+ LOGIT1("Switched to timer mode, id %d", aConnectionId)
+ }
+ LOGEXITFN("CEngine::SwitchToTimerMode()")
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::GetDuration
+// Retrieves iPrevDuration from connection in connection table with matching id.
+// -----------------------------------------------------------------------------
+//
+TBool CEngine::GetDuration( const TUint aConnectionId, TInt& aDuration )
+ {
+ TInt index( 0 );
+
+ for ( index = 0; index < iConnections->Count(); index++ )
+ {
+ TUint connId( iConnections->At( index )->iConnectionId );
+
+ if ( aConnectionId == connId )
+ {
+ aDuration = iConnections->At( index )->iPrevDuration;
+ return ETrue;
+ }
+ }
+
+ LOGIT1("FAILED to get duration for connection id %d", aConnectionId)
+ return EFalse;
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::GetDefaultThreshold
+// -----------------------------------------------------------------------------
+//
+TInt CEngine::GetDefaultThreshold( const TUint aConnectionId, TUint& aThreshold )
+ {
+ LOGENTRFN("CEngine::GetDefaultThreshold()")
+ TInt bearer( 0 );
+ TRequestStatus status( 0 );
+
+ // Initialize to the smallest value
+ aThreshold = iGPRSThreshold;
+
+ iConnectionMonitor.GetIntAttribute(
+ aConnectionId,
+ KSubConnectionId,
+ KBearer,
+ bearer,
+ status );
+ User::WaitForRequest( status );
+
+ if ( status.Int() != KErrNotFound )
+ {
+ if ( bearer == EBearerWCDMA || bearer == EBearerExternalWCDMA )
+ {
+ aThreshold = iWCDMAThreshold;
+ }
+ else if ( bearer == EBearerWLAN || bearer == EBearerExternalWLAN )
+ {
+ aThreshold = iWLANThreshold;
+ }
+ else
+ {
+ aThreshold = iGPRSThreshold;
+ }
+ }
+
+ LOGEXITFN1("CEngine::GetDefaultThreshold()", status.Int())
+ return status.Int();
+ }
+
+// -----------------------------------------------------------------------------
+// CEngine::ReadIniFile
+// -----------------------------------------------------------------------------
+//
+void CEngine::ReadIniFile()
+ {
+ LOGENTRFN("CEngine::ReadIniFile()")
+ TInt err( KErrNone );
+ TInt value( 0 );
+
+ // Initialize parameters to defaults because they might not be in SharedData.
+ iTimerInterval = KTimerInterval;
+ iGPRSThreshold = KGPRSDataThreshold;
+ iWCDMAThreshold = KWCDMADataThreshold;
+ iWLANThreshold = KWLANDataThreshold;
+
+ // Connecting and initialization:
+ CRepository* repository = NULL;
+
+ TRAPD( leaveCode, repository = CRepository::NewL( KCRUidDCL ) );
+
+ if ( leaveCode )
+ {
+ LOGIT1("CRepository::NewL() FAILED: %d", leaveCode)
+ // Go on using defaults
+ return;
+ }
+
+ err = repository->Get( KDCLGprsThreshold, value );
+
+ if ( err == KErrNone )
+ {
+ iGPRSThreshold = value;
+ }
+ else
+ {
+ LOGIT1("Reading KDCLGprsThreshold from CRepository FAILED: %d", err)
+ }
+
+ err = repository->Get( KDCLWcdmaThreshold, value );
+
+ if ( err == KErrNone )
+ {
+ iWCDMAThreshold = value;
+ }
+ else
+ {
+ LOGIT1("Reading KDCLWcdmaThreshold from CRepository FAILED: %d", err)
+ }
+
+ err = repository->Get( KDCLWlanThreshold, value );
+
+ if ( err == KErrNone )
+ {
+ iWLANThreshold = value;
+ }
+ else
+ {
+ LOGIT1("Reading KDCLWlanThreshold from CRepository FAILED: %d", err)
+ }
+
+ err = repository->Get( KDCLTimerInterval, value );
+
+ if ( err == KErrNone )
+ {
+ iTimerInterval = value;
+ }
+ else
+ {
+ LOGIT1("Reading KDCLTimerInterval from CRepository FAILED: %d", err)
+ }
+
+ // Closing connection:
+ delete repository;
+ LOGEXITFN("CEngine::ReadIniFile()")
+ }
+
+// End of file