connectionmonitoring/connmon/dataconnectionlogger/src/saeobserver.cpp
changeset 0 5a93021fdf25
child 2 086aae6fc07e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/connectionmonitoring/connmon/dataconnectionlogger/src/saeobserver.cpp	Thu Dec 17 08:55:21 2009 +0200
@@ -0,0 +1,815 @@
+/*
+* Copyright (c) 2007 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:  Updates P&S variables: KPSUidGprsStatus and KPSUidWcdmaStatus.
+*
+*/
+
+#include <NIFVAR.H>
+#include <e32svr.h>
+#include <PSVariables.h>
+
+#include "saeobserver.h"
+#include "dcl_log.h"
+
+// Used to internally initialize network status to unknwon -state.
+const TInt ENtwkStatusNotKnown( -1 );
+
+// ============================ MEMBER FUNCTIONS ===========================
+
+// -------------------------------------------------------------------------
+// CSaeObserver::CSaeObserver
+// -------------------------------------------------------------------------
+CSaeObserver::CSaeObserver( const RConnectionMonitor& aMonitor ) :
+    iMonitor( aMonitor ),
+    iNetworkIsUnAttached( ETrue ),
+    iNetworkIsSuspended ( EFalse ),
+    iCurrentBearerType ( ESAEUnknownConnectionType )
+    {
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::NewL
+// -------------------------------------------------------------------------
+CSaeObserver* CSaeObserver::NewL( const RConnectionMonitor& aMonitor )
+    {
+    CSaeObserver* self = new (ELeave) CSaeObserver( aMonitor );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop();
+    return self;
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::~CSaeObserver
+// -------------------------------------------------------------------------
+CSaeObserver::~CSaeObserver()
+    {
+    LOG( Log::Printf( _L("DCL: CSaeObserver::~CSaeObserver() start->" )));
+    iGPRSConnections.Close();
+    iWCDMAConnections.Close();
+    iSAProperty.Close();
+    LOG( Log::Printf( _L("DCL: CSaeObserver::~CSaeObserver() end." )));
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::ConstructL
+// -------------------------------------------------------------------------
+void CSaeObserver::ConstructL()
+    {
+    LOG( Log::Printf( _L("DCL: CSaeObserver::ConstructL() start  " )));
+
+    // Define PubSub values
+    _LIT_SECURITY_POLICY_PASS( KGeneralReadPolicy  );
+    _LIT_SECURITY_POLICY_PASS( KGeneralWritePolicy );
+
+    iSAProperty.Define( KUidSystemCategory,
+                        KPSUidGprsStatusValue,
+                        RProperty::EInt,
+                        KGeneralReadPolicy,
+                        KGeneralWritePolicy );
+
+    iSAProperty.Define( KUidSystemCategory,
+                        KPSUidWcdmaStatusValue,
+                        RProperty::EInt,
+                        KGeneralReadPolicy,
+                        KGeneralWritePolicy );
+
+    iGPRSConnections.Reset();
+    iWCDMAConnections.Reset();
+
+    // Initialize PubSub values
+    UpdateBearerNetworkStatusL( ESAEGPRSConnectionType );  // GPRS status
+    UpdateBearerNetworkStatusL( ESAEWCDMAConnectionType ); // WCDMA status
+
+    LOG( Log::Printf( _L("DCL: CSaeObserver::ConstructL() end." )));
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::EventL
+// Handles events sent by Connection Monitor
+// -------------------------------------------------------------------------
+void CSaeObserver::EventL( const CConnMonEventBase &aConnMonEvent )
+    {
+    LOG( Log::Printf( _L("DCL: CSaeObserver::EventL() start->" )));
+
+    switch( aConnMonEvent.EventType() )
+        {
+        case EConnMonDeleteConnection:
+            {
+            LOG( Log::Printf( _L("DCL: EConnMonDeleteConnection." )));
+            const CConnMonDeleteConnection* event =
+                          ( CConnMonDeleteConnection* ) &aConnMonEvent;
+            HandleEConnMonDeleteConnectionL( *event );
+            }
+            break;
+
+        case EConnMonNetworkStatusChange:
+            {
+            LOG( Log::Printf( _L("DCL: EConnMonNetworkStatusChange." )));
+            const CConnMonNetworkStatusChange* event =
+                        ( CConnMonNetworkStatusChange* ) &aConnMonEvent;
+            HandleEConnMonNetworkStatusChangeL( *event );
+            }
+            break;
+
+        case EConnMonConnectionStatusChange:
+            {
+            LOG( Log::Printf( _L("DCL: EConnMonConnectionStatusChange." )));
+            const CConnMonConnectionStatusChange* event =
+                      ( CConnMonConnectionStatusChange* ) &aConnMonEvent;
+            HandleEConnMonConnectionStatusChangeL( *event );
+            }
+            break;
+
+        case EConnMonBearerChange:
+            {
+            LOG( Log::Printf( _L("DCL: EConnMonBearerChange." )));
+            const CConnMonBearerChange* event =
+                                 ( CConnMonBearerChange* ) &aConnMonEvent;
+            HandleEConnMonBearerChangeL( *event );
+            }
+            break;
+
+        default:
+            // Unhandled event
+            LOG( Log::Printf( _L("DCL: Unhandled event type (%d)."),
+                 aConnMonEvent.EventType() ));
+            break;
+        }
+    LOG( Log::Printf( _L("DCL: CSaeObserver::EventL() end." )));
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::HandleEConnMonBearerChangeL
+// -------------------------------------------------------------------------
+void CSaeObserver::HandleEConnMonBearerChangeL( const CConnMonBearerChange& aEvent )
+    {
+    LOG( Log::Printf( _L("DCL: CSaeObserver::HandleEConnMonBearerChangeL()" )));
+    TInt newConnType( aEvent.ConnectionId() ); // Connection ID tells the new bearer type
+#ifdef _DEBUG
+    TInt oldConnType( ESAEUnknownConnectionType );
+#endif
+    TInt newSAEConnType(ESAEUnknownConnectionType);
+    TInt oldSAEConnType(ESAEUnknownConnectionType);
+
+
+    // Check what handover we are executing.
+    RArray<TUint>* fromArray;
+
+    if ( newConnType == EBearerIdGPRS )
+        {
+        // No way to check whether we actually allready are at EdgeGPRS...
+#ifdef _DEBUG
+        oldConnType = EBearerIdWCDMA;
+#endif
+        newSAEConnType = ESAEGPRSConnectionType;
+        oldSAEConnType = iCurrentBearerType;
+        fromArray = &iWCDMAConnections;
+        }
+    else if ( newConnType == EBearerIdWCDMA )
+        {
+#ifdef _DEBUG
+        oldConnType = EBearerIdGPRS;
+#endif
+        newSAEConnType = ESAEWCDMAConnectionType;
+        oldSAEConnType = iCurrentBearerType;
+        fromArray = &iGPRSConnections;
+        }
+    else
+        {
+        LOG( Log::Printf( _L("DCL: Connection type %d not supported."),
+             newConnType ));
+        }
+
+    LOG( Log::Printf( _L("DCL: NewConnType %d, OldConnType %d"),
+         newSAEConnType, oldSAEConnType ));
+
+    if ( newSAEConnType != ESAEUnknownConnectionType &&
+         newSAEConnType != iCurrentBearerType )
+        {
+
+        TInt fromArrayCount( fromArray->Count() );
+        LOG( Log::Printf( _L("DCL: Handover from %d to %d bearer, %d connections."),
+             oldConnType, newConnType, fromArrayCount ));
+
+        --fromArrayCount; // Indexing of array starts at 0...
+
+        // Move all connections from old bearer specific array to the new one...
+        while (fromArrayCount >= 0)
+            {
+            TUint connectionID(0);
+
+            connectionID = (*fromArray)[fromArrayCount];
+
+            LOG( Log::Printf( _L("DCL: Moving Connection ID %d from old array index %d to new array."),
+                 connectionID, fromArrayCount ));
+
+            RemoveFromConnArray( STATIC_CAST(TSAEConnectionType, oldSAEConnType), connectionID );
+            AddToConnArray( STATIC_CAST(TSAEConnectionType, newSAEConnType), connectionID );
+            --fromArrayCount;
+            }
+
+        iCurrentBearerType = newSAEConnType;
+
+        if (!iNetworkIsSuspended) // we are suspended, don't update the new network state.
+            {
+            UpdateBearerNetworkStatusL( STATIC_CAST(TSAEConnectionType, newSAEConnType) );
+            }
+
+        // Update all context activity
+        UpdateContextActivity( STATIC_CAST(TSAEConnectionType, oldSAEConnType) );
+        UpdateContextActivity( STATIC_CAST(TSAEConnectionType, newSAEConnType) );
+
+        }
+    else
+        {
+        LOG( Log::Printf( _L("DCL: Unknown connection type %d, or this connection type is allready active."),
+             newConnType ));
+        // No such connection ID...
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::UpdateBearerNetworkStatusL
+// -------------------------------------------------------------------------
+void CSaeObserver::UpdateBearerNetworkStatusL( const TSAEConnectionType& connType )
+    {
+    LOG( Log::Printf( _L("DCL: CSaeObserver::UpdateBearerNetworkStatusL(connType %d, bearer %d, suspended %d)"),
+         connType, iCurrentBearerType, iNetworkIsSuspended ));
+
+    // No connections active, so check network status and update if
+    // UnAttached. This prevents the state to hang to active in case
+    // of no network events...
+    TInt ntwStatus( ENtwkStatusNotKnown );
+    TRequestStatus status;
+    TInt subConId( 0 );
+
+    if ( connType == ESAEGPRSConnectionType )
+        {
+        iMonitor.GetIntAttribute( EBearerIdGPRS, subConId, KNetworkStatus, ntwStatus, status );
+        User::WaitForRequest( status );
+        LOG( Log::Printf( _L("+ DCL: Async call status==(%d)."), status.Int() ));
+
+        if ( (ntwStatus == EConnMonStatusNotAvailable) || (ntwStatus == EConnMonStatusUnattached) )
+            {
+            LOG( Log::Printf( _L("DCL: GPRS ntwk is UnAttached." )));
+            iNetworkIsUnAttached = ETrue;
+            NotifyPubSub( KPSUidGprsStatus, EPSGprsUnattached );
+            }
+        else if ( ntwStatus == ENtwkStatusNotKnown )
+            {
+            LOG( Log::Printf( _L("DCL: Async request for GPRS ntwk status failed %d!"),
+                 status.Int() ));
+            }
+        else
+            {
+            LOG( Log::Printf( _L("DCL: GPRS ntwk is Attached." )));
+            iNetworkIsUnAttached = EFalse;
+            NotifyPubSub( KPSUidGprsStatus, EPSGprsAttach );
+            }
+        }
+    else if ( connType == ESAEWCDMAConnectionType )
+        {
+        iMonitor.GetIntAttribute( EBearerIdWCDMA, subConId, KNetworkStatus, ntwStatus, status );
+        User::WaitForRequest( status );
+        LOG( Log::Printf( _L("+ DCL: Async call status==(%d)."), status.Int() ));
+
+        if ( (ntwStatus == EConnMonStatusNotAvailable) || (ntwStatus == EConnMonStatusUnattached) )
+            {
+            LOG( Log::Printf( _L("DCL: WCDMA ntwk is UnAttached." )));
+            iNetworkIsUnAttached = ETrue;
+            NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaUnattached );
+            }
+        else if ( ntwStatus == ENtwkStatusNotKnown )
+            {
+            LOG( Log::Printf( _L("DCL: Async request for WCDMA ntwk status failed %d!"),
+                 status.Int() ));
+            }
+        else
+            {
+            LOG( Log::Printf( _L("DCL: WCDMA ntwk is Attached." )));
+            iNetworkIsUnAttached = EFalse;
+            NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaAttach );
+            }
+        }
+    else
+        {
+        LOG( Log::Printf( _L("DCL: !ERROR! Unknown connection type %d !ERROR!"),
+             connType ));
+        User::Leave(KErrGeneral);
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::HandleEConnMonDeleteConnectionL
+// -------------------------------------------------------------------------
+void CSaeObserver::HandleEConnMonDeleteConnectionL( const CConnMonDeleteConnection& aEvent )
+    {
+    TUint connId( aEvent.ConnectionId() );
+    // Connection type cannot be read from the Delete -event, but is needed
+    // later...
+    TSAEConnectionType connType( ESAEUnknownConnectionType );
+    IdentifyTypeFromArrays( connId, connType );
+    RArray<TUint>* conns = MatchingConnArray( connType, connId );
+
+    if ( conns )
+        {
+        TInt connCount( conns->Count() );
+        if ( connCount > 0 )
+            {
+            // If the connection ID is found from the connection array,
+            // simply remove it.
+            if (RemoveFromConnArray( connType, connId ) == KErrNone)
+                {
+                LOG( Log::Printf( _L("DCL: Connection %d deleted (%d connections remaining)."),
+                     connId, conns->Count() ));
+
+                if( --connCount == 0 )
+                    {
+                    UpdateBearerNetworkStatusL( connType );
+                    }
+                else
+                    {
+                    // Some connection(s) still active, so update status.
+                    UpdateContextActivity( connType );
+                    }
+                }
+            }
+        else if ( iNetworkIsUnAttached && (connType == ESAEGPRSConnectionType) )
+            {
+            // No active connections and network is UnAttached, but this still is
+            // a GPRS event... this case can occur for instance when trying to
+            // establish a GPRS connection with a SIM that does not have the GPRS
+            // enabled by operator. If this would not be handled the state would
+            // hang to activating (no UnAttach event received since network's state
+            // does not change).
+            LOG( Log::Printf( _L("DCL: No connections have been active and ntwk is UnAttached." )));
+            NotifyPubSub( KPSUidGprsStatus, EPSGprsUnattached );
+            }
+        else if ( iNetworkIsUnAttached && (connType == ESAEWCDMAConnectionType) )
+            {
+            // Same case here as above but with WCDMA event...
+            LOG( Log::Printf( _L("DCL: No connections have been active and ntwk is UnAttached." )));
+            NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaUnattached );
+            }
+        else
+            {
+            LOG( Log::Printf( _L("DCL: No connections of type %d active."), connType ));
+            }
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::HandleEConnMonNetworkStatusChangeL
+// -------------------------------------------------------------------------
+void CSaeObserver::HandleEConnMonNetworkStatusChangeL( const CConnMonNetworkStatusChange& aEvent )
+    {
+    TSAEConnectionType connType( GetConnectionType( aEvent.ConnectionId() ) );
+    LOG( Log::Printf( _L("DCL: connection type: %d."), connType ));
+
+    if ( (connType == ESAEGPRSConnectionType) || (connType == ESAEWCDMAConnectionType) )
+        {
+        switch ( aEvent.NetworkStatus() )
+            {
+            case EConnMonStatusUnattached:
+                {
+                if ( connType == ESAEGPRSConnectionType )
+                    {
+                    LOG( Log::Printf( _L("DCL: EConnMonStatusUnattached, KUidGprsStatus, ESAGprsUnattached." )));
+                    iNetworkIsUnAttached = ETrue;
+                    iNetworkIsSuspended = EFalse;
+                    NotifyPubSub( KPSUidGprsStatus, EPSGprsUnattached );
+                    }
+                else // ESAEWCDMAConnectionType
+                    {
+                    LOG( Log::Printf( _L("DCL: EConnMonStatusUnattached, KUidWcdmaStatus, ESAWcdmaUnattached." )));
+                    iNetworkIsUnAttached = ETrue;
+                    iNetworkIsSuspended = EFalse;
+                    NotifyPubSub( KPSUidWcdmaStatus, EPSGprsUnattached );
+                    }
+                // Just in case; there shouldn't be any active connections by now anyway:
+                RemoveAllFromConnArray( connType );
+                }
+                break;
+
+            case EConnMonStatusAttached:
+                {
+                if ( connType == ESAEGPRSConnectionType )
+                    {
+                    LOG( Log::Printf( _L("DCL: EConnMonStatusAttached, KUidGprsStatus, ESAGprsAttach." )));
+                    iNetworkIsUnAttached = EFalse;
+                    iNetworkIsSuspended = EFalse;
+                    NotifyPubSub( KPSUidGprsStatus, EPSGprsAttach );
+                    }
+                else // ESAEWCDMAConnectionType
+                    {
+                    LOG( Log::Printf( _L("DCL: EConnMonStatusAttached, KUidWcdmaStatus, ESAWcdmaAttach." )));
+                    iNetworkIsUnAttached = EFalse;
+                    iNetworkIsSuspended = EFalse;
+                    NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaAttach );
+                    }
+                }
+                break;
+
+            case EConnMonStatusSuspended:
+                {
+                LOG( Log::Printf( _L("DCL: EConnMonStatusSuspended, -> ntwk to suspend." )));
+                iNetworkIsSuspended = ETrue;
+                NotifyPubSub( KPSUidGprsStatus, EPSGprsSuspend );
+                NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaSuspend );
+                }
+                break;
+
+            case EConnMonStatusActive:
+                {
+                if ( connType == ESAEGPRSConnectionType )
+                    {
+                    LOG( Log::Printf( _L("DCL: EConnMonStatusActive, KUidGprsStatus, current activity..." )));
+                    iNetworkIsUnAttached = EFalse;
+                    iNetworkIsSuspended = EFalse;
+                    }
+                else // ESAEWCDMAConnectionType
+                    {
+                    LOG( Log::Printf( _L("DCL: EConnMonStatusActive, KUidWcdmaStatus, current activity..." )));
+                    iNetworkIsUnAttached = EFalse;
+                    iNetworkIsSuspended = EFalse;
+                    }
+                UpdateContextActivity( connType );
+                }
+                break;
+
+            default:
+                LOG( Log::Printf( _L("DCL: Unhandled NtwStatusChange(%d)."), aEvent.NetworkStatus() ));
+                break;
+            }
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::HandleEConnMonConnectionStatusChangeL
+// -------------------------------------------------------------------------
+void CSaeObserver::HandleEConnMonConnectionStatusChangeL(const CConnMonConnectionStatusChange& aEvent )
+    {
+    TInt connStatus = aEvent.ConnectionStatus();
+    if ( connStatus == KPsdStartingActivation ||
+            connStatus == KPsdFinishedActivation ||
+            connStatus == KPsdFinishedDeactivation )
+        {
+        TUint connId( aEvent.ConnectionId() );
+        LOG( Log::Printf( _L("DCL: connection ID got: %d."), connId ));
+        TSAEConnectionType connType( GetConnectionType( connId ) );
+        LOG( Log::Printf( _L("DCL: connection type: %d."), connType ));
+
+        if ( (connType == ESAEGPRSConnectionType) || (connType == ESAEWCDMAConnectionType) )
+            {
+            LOG( Log::Printf( _L("DCL: trying to get connection status..."), connId));
+            switch ( connStatus )
+                {
+                case KPsdStartingActivation :
+                    {
+                    if ( connType == ESAEGPRSConnectionType )
+                        {
+                        LOG( Log::Printf( _L("DCL: KPsdStartingActivation : KUidGprsStatus, ESAGprsContextActivating." )));
+                        NotifyPubSub( KPSUidGprsStatus, EPSGprsContextActivating );
+                        iCurrentBearerType = ESAEGPRSConnectionType;
+                        }
+                    else // ESAEWCDMAConnectionType
+                        {
+                        LOG( Log::Printf( _L("DCL: KPsdStartingActivation : KUidWcdmaStatus, ESAWcdmaContextActivating." )));
+                        NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaContextActivating );
+                        iCurrentBearerType = ESAEWCDMAConnectionType;
+                        }
+                    AddToConnArray( connType, connId );
+                    }
+                    break;
+
+                case KPsdFinishedActivation :
+                    {
+                    LOG( Log::Printf( _L("DCL: KPsdFinishedActivation." )));
+                    // Connection opened, so add it to the array of open connections:
+                    AddToConnArray( connType, connId );
+                    UpdateContextActivity( connType );
+                    LOG( Log::Printf( _L("DCL: Connection %d of type %d finished activation."),
+                         connId, connType ));
+                    }
+                    break;
+
+                case KPsdFinishedDeactivation :
+                    {
+                    LOG( Log::Printf( _L("DCL: KPsdFinishedDeactivation." )));
+                    RemoveFromConnArray( connType, connId );
+                    LOG( Log::Printf( _L("DCL: Connection %d of type %d finished de-activation."),
+                         connId, connType ));
+
+                    if (iGPRSConnections.Count() == 0 && iWCDMAConnections.Count() == 0)
+                        {
+                        // No active contexts...
+                        UpdateBearerNetworkStatusL(connType);
+                        }
+                    else
+                        {
+                        // There is at least one active context
+                        UpdateContextActivity(connType);
+                        }
+                    }
+                    break;
+
+                default :
+                    LOG( Log::Printf( _L("DCL: Unhandled context connection status (%d)."),
+                         aEvent.ConnectionStatus() ));
+                    break;
+                }
+            }
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::NotifyPubSub
+// -------------------------------------------------------------------------
+void CSaeObserver::NotifyPubSub( const TUid aVariable, const TInt aState )
+    {
+    LOG( Log::Printf( _L("DCL: CSaeObserver::NotifyPubSub : aVariable == %d aState == %d"),
+         aVariable.iUid, aState ));
+
+    TInt returnValue = iSAProperty.Set(KUidSystemCategory, aVariable.iUid, aState);
+
+    LOG( Log::Printf( _L("DCL: CSaeObserver::NotifyPubSub : returnValue == %d"),
+         returnValue ));
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::GetConnectionType
+// -------------------------------------------------------------------------
+TSAEConnectionType CSaeObserver::GetConnectionType( const TUint &aConnectionId )
+    {
+    TRequestStatus status;
+    TInt connType( EBearerUnknown );
+    TInt subConId( 0 );
+    TSAEConnectionType ret( ESAEUnknownConnectionType );
+
+    // EBearerIdGPRS and -WCDMA means bearer specific Connection Id.
+    // This is a fix to get for instance network unattached state,
+    // since the actual connection Id is not necessarily available anymore.
+    switch ( aConnectionId )
+        {
+        case EBearerIdGPRS :
+            {
+            ret = ESAEGPRSConnectionType;
+            }
+            break;
+
+        case EBearerIdWCDMA :
+            {
+            ret = ESAEWCDMAConnectionType;
+            }
+            break;
+
+        default :
+            {
+            iMonitor.GetIntAttribute( aConnectionId, subConId, KBearer, connType, status );
+            User::WaitForRequest( status );
+            LOG( Log::Printf( _L("+ DCL: Async call status==(%d)."), status.Int() ));
+            if ( status == KErrNone )
+                {
+                // If bearer status can not be read the event is not handled, since
+                // connType == EBearerUnknown and ret == ESAEUnknownConnectionType.
+
+                if ( connType == EBearerGPRS ||
+                     connType == EBearerExternalGPRS ||
+                     connType == EBearerEdgeGPRS ||
+                     connType == EBearerExternalEdgeGPRS )
+                    {
+                    ret = ESAEGPRSConnectionType;
+                    }
+                else if ( connType == EBearerWCDMA ||
+                          connType == EBearerExternalWCDMA )
+                      {
+                    ret = ESAEWCDMAConnectionType;
+                    }
+                }
+            else
+                {
+                // Finally try to check if allready saved to some connection
+                // type specific connection array...
+                IdentifyTypeFromArrays( aConnectionId, ret );
+                }
+            }
+            break;
+        }
+
+#ifdef _DEBUG
+        switch ( ret )
+        {
+        case ESAEGPRSConnectionType :
+            {
+            LOG( Log::Printf( _L("DCL: This is a GPRS connection event." )));
+            }
+            break;
+        case ESAEWCDMAConnectionType :
+            {
+            LOG( Log::Printf( _L("DCL: This is a WCDMA connection event." )));
+            }
+            break;
+        default :
+            {
+            LOG( Log::Printf( _L("DCL: The event is not of any known type." )));
+            }
+            break;
+        }
+#endif //_DEBUG
+
+    return ret;
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::IdentifyTypeFromArrays
+// -------------------------------------------------------------------------
+void CSaeObserver::IdentifyTypeFromArrays( TUint aConnectionId,
+                                           TSAEConnectionType& aConnType )
+    {
+    // When, for instance, handling Delete Connection -event we can't get the
+    // connection type from the event, so we can search for the unique
+    // connection ID from the ones we allready have in the connection type
+    // specific member lists. We can then figure the connection type
+    // based on that.
+    if ( iGPRSConnections.Find(aConnectionId) != KErrNotFound )
+        {
+        LOG( Log::Printf( _L("DCL: IdentifyTypeFromArrays: Found from GPRS array" )));
+        aConnType = ESAEGPRSConnectionType;
+        }
+    else if ( iWCDMAConnections.Find(aConnectionId) != KErrNotFound )
+        {
+        LOG( Log::Printf( _L("DCL: IdentifyTypeFromArrays: Found from WCDMA array" )));
+        aConnType = ESAEWCDMAConnectionType;
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::MatchingConnArray
+// -------------------------------------------------------------------------
+RArray<TUint>* CSaeObserver::MatchingConnArray( const TSAEConnectionType& aConnType,
+                                                TUint aConnectionId )
+    {
+    LOG( Log::Printf( _L("DCL: MatchingConnArray: type:%d, id:%d"),
+         aConnType, aConnectionId ));
+    RArray<TUint>* ret = NULL;
+    switch ( aConnType )
+        {
+        case ESAEGPRSConnectionType :
+            {
+            LOG( Log::Printf( _L("DCL: MatchingConnArray: Returning GPRS array" )));
+            ret =  &iGPRSConnections;
+            }
+            break;
+        case ESAEWCDMAConnectionType :
+            {
+            LOG( Log::Printf( _L("DCL: MatchingConnArray: Returning WCDMA array" )));
+            ret = &iWCDMAConnections;
+            }
+            break;
+        case ESAEUnknownConnectionType :
+            {
+            // Check if connection ID allready in some type specific array
+            TSAEConnectionType type( ESAEUnknownConnectionType );
+            IdentifyTypeFromArrays( aConnectionId, type);
+            if ( type != ESAEUnknownConnectionType )
+                {
+                // Try to match again with the implicitly found out type...
+                ret = MatchingConnArray( type, aConnectionId );
+                }
+            }
+            break;
+        default :
+            LOG( Log::Printf( _L("DCL: MatchingConnArray: No array found, returning NULL" )));
+            break;
+        }
+    return ret;
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::UpdateContextActivity
+// -------------------------------------------------------------------------
+void CSaeObserver::UpdateContextActivity( const TSAEConnectionType& aConnType )
+{
+    // Check if network is UnAttached or unknown, do not update to active in
+    // this case since connection can not be active if ntwk is not attached.
+    // Also check if we are currently in suspend state. Only network events can
+    // trigger returning from suspend (the i*NetworkIsSuspended is unset only
+    // during handling of these events).
+    if ( aConnType == ESAEGPRSConnectionType )
+        {
+        TInt count( iGPRSConnections.Count() );
+        LOG( Log::Printf( _L("DCL: UpdateContextActivity (GPRS conns %d)"), count ));
+        if ( !iNetworkIsUnAttached && !iNetworkIsSuspended)
+            {
+            if ( count == 1 )
+                {
+                // One connection active
+                LOG( Log::Printf( _L("DCL: ESAGprsContextActive" )));
+                NotifyPubSub( KPSUidGprsStatus, EPSGprsContextActive );
+                iCurrentBearerType = ESAEGPRSConnectionType;
+                }
+            else if( count > 1 )
+                {
+                // Multiple connections active
+                LOG( Log::Printf( _L("DCL: ESAGprsMultibleContextActive" )));
+                NotifyPubSub( KPSUidGprsStatus, EPSGprsMultibleContextActive );
+                iCurrentBearerType = ESAEGPRSConnectionType;
+                }
+            }
+        }
+    else if ( aConnType == ESAEWCDMAConnectionType )
+        {
+        TInt count( iWCDMAConnections.Count() );
+        LOG( Log::Printf( _L("DCL: UpdateContextActivity (WCDMA conns %d)"), count ));
+        if ( !iNetworkIsUnAttached && !iNetworkIsSuspended)
+            {
+            if ( count == 1 )
+                {
+                // One connection active
+                LOG( Log::Printf( _L("DCL: ESAWcdmaContextActive" )));
+                NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaContextActive );
+                iCurrentBearerType = ESAEWCDMAConnectionType;
+                }
+            else if( count > 1 )
+                {
+                // Multiple connections active
+                LOG( Log::Printf( _L("DCL: ESAWcdmaMultipleContextActive" )));
+                NotifyPubSub( KPSUidWcdmaStatus, EPSWcdmaMultipleContextActive );
+                iCurrentBearerType = ESAEWCDMAConnectionType;
+                }
+            }
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::AddToConnArray
+// -------------------------------------------------------------------------
+void CSaeObserver::AddToConnArray( const TSAEConnectionType& aConnType,
+                                   const TUint aConnId )
+    {
+    RArray<TUint>* conns = MatchingConnArray( aConnType );
+
+    LOG( Log::Printf( _L("DCL: AddToConnArray(type %d)"), aConnType ));
+
+    // No duplicate connections. Also do not add bearer specific connection Id.
+    if ( conns && (conns->Find(aConnId) == KErrNotFound) &&
+        ((aConnId != EBearerIdGPRS) && (aConnId != EBearerIdWCDMA)) )
+        {
+        conns->Append( aConnId );
+        LOG( Log::Printf( _L("DCL: Contexts: GPRS %d, WCDMA %d"),
+             iGPRSConnections.Count(), iWCDMAConnections.Count() ));
+        }
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::RemoveFromConnArray
+// -------------------------------------------------------------------------
+TInt CSaeObserver::RemoveFromConnArray( const TSAEConnectionType& aConnType,
+                                        const TUint aConnId )
+    {
+    LOG( Log::Printf( _L("DCL: RemoveFromConnArray, type: %d, id: %d."),
+         aConnType, aConnId ));
+    TInt ret(KErrNotFound);
+    TInt index(0);
+    RArray<TUint>* conns = MatchingConnArray( aConnType );
+
+    if ( conns )
+        {
+        index = conns->Find( aConnId );
+        if ( index != KErrNotFound )
+            {
+            conns->Remove( index );
+            LOG( Log::Printf( _L("DCL: Context %d of type %d removed."),
+                 aConnId, aConnType ));
+            ret = KErrNone;
+            }
+        }
+    return ret;
+    }
+
+// -------------------------------------------------------------------------
+// CSaeObserver::RemoveAllFromConnArray
+// -------------------------------------------------------------------------
+void CSaeObserver::RemoveAllFromConnArray( const TSAEConnectionType& aConnType )
+    {
+    RArray<TUint>* conns = MatchingConnArray( aConnType );
+
+    if ( conns )
+        {
+        LOG( Log::Printf( _L("DCL: RemoveAllFromConnArray(), reseting ConnType %d array."),
+             aConnType ));
+        conns->Reset();
+        }
+    }