convergedconnectionhandler/cchserver/src/cchservicehandler.cpp
changeset 0 a4daefaec16c
child 9 bddb6d4447db
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/convergedconnectionhandler/cchserver/src/cchservicehandler.cpp	Mon Jan 18 20:12:36 2010 +0200
@@ -0,0 +1,1748 @@
+/*
+* Copyright (c) 2007-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:  CCCHServiceHandler implementation
+*
+*/
+
+
+// INCLUDE FILES
+#include <cchclientserver.h>
+#include <spnotifychange.h>
+
+#include "cchservicehandler.h"
+#include "cchserverbase.h"
+#include "cchspshandler.h"
+#include "cchlogger.h"
+#include "cchpluginhandler.h"
+#include "cchuihandler.h"
+#include "cchconnmonhandler.h"
+#include "cchwlanextension.h"
+#include "cchcommdbwatcher.h"
+#include "cchcommdbwatcherobserver.h"
+
+// EXTERNAL DATA STRUCTURES
+// None
+
+// EXTERNAL FUNCTION PROTOTYPES
+// None
+
+// CONSTANTS
+
+const TInt KConnectionRecoveryMaxTries = 5;
+
+const TInt KCCHFirstRecovery    = 15000000;
+const TInt KCCHSecondRecovery   = 15000000;
+const TInt KCCHThirdRecovery    = 30000000;
+const TInt KCCHFourthRecovery   = 60000000;
+const TInt KCCHFifthRecovery    = 60000000;
+
+const TInt KCCHPluginUnloadTimeout = 5000000;
+// MACROS
+// None
+
+// LOCAL CONSTANTS AND MACROS
+// None
+
+// MODULE DATA STRUCTURES
+// None
+
+// LOCAL FUNCTION PROTOTYPES
+// None
+
+// FORWARD DECLARATIONS
+// None.
+
+// ============================= LOCAL FUNCTIONS =============================
+
+// ============================ MEMBER FUNCTIONS =============================
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::CCCHServiceHandler
+// C++ default constructor can NOT contain any code, that might leave.
+// ---------------------------------------------------------------------------
+//
+CCCHServiceHandler::CCCHServiceHandler( CCCHServerBase& aServer ) :
+    iServer( aServer ),
+    iConnectionRecoveryTry( 0 ),
+    iCancelNotify( ETrue ) 
+    {
+    // No implementation required
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::ConstructL()
+    {
+    iNotifier = CSPNotifyChange::NewL( *this );
+    iCchUIHandler = CCchUIHandler::NewL( iServer, *this );
+    iPhoneStartupMonitor = CCchPhoneStartupMonitor::NewL( *iCchUIHandler );
+    iConnectionRecoveryTimer = CPeriodic::NewL( CPeriodic::EPriorityStandard );
+    iCommDbWatcher = CCCHCommDbWatcher::NewL( *this );
+    iPluginUnloadTimer = CPeriodic::NewL( CPeriodic::EPriorityStandard );
+    iRecoveryInterval.Append( KCCHFirstRecovery );
+    iRecoveryInterval.Append( KCCHSecondRecovery );
+    iRecoveryInterval.Append( KCCHThirdRecovery );
+    iRecoveryInterval.Append( KCCHFourthRecovery );
+    iRecoveryInterval.Append( KCCHFifthRecovery );
+    iWlanExtension = CCchWlanExtension::NewL( );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::NewL
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CCCHServiceHandler* CCCHServiceHandler::NewL( CCCHServerBase& aServer )
+    {
+    CCCHServiceHandler* self = CCCHServiceHandler::NewLC( aServer );
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::NewLC
+// Two-phased constructor.
+// ---------------------------------------------------------------------------
+//
+CCCHServiceHandler* CCCHServiceHandler::NewLC( CCCHServerBase& aServer )
+    {
+    CCCHServiceHandler* self = new (ELeave) CCCHServiceHandler( aServer );
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    return self;
+    }
+
+// Destructor
+CCCHServiceHandler::~CCCHServiceHandler()
+    {
+    if ( iCchUIHandler )
+        {
+        iCchUIHandler->Destroy();
+        }
+
+    delete iPhoneStartupMonitor;
+    delete iWlanExtension;
+    delete iConnectionRecoveryTimer;
+    delete iPluginUnloadTimer;
+    delete iCommDbWatcher;
+
+    if( iNotifier )
+        {
+        iNotifier->Cancel();
+        delete iNotifier;
+        iNotifier = NULL;    
+        }
+
+    iServiceIds.Close();
+    iServer.PluginHandler().RemoveServiceNotifier( this );
+    iServices.ResetAndDestroy();
+    iServicesInRecovery.Close();
+    iRecoveryInterval.Close();
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::InitServiceHandlerL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::InitServiceHandlerL()
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler::InitServiceHandlerL [0x%x]: IN",this );
+    
+    RArray<TUint> serviceIds;
+    CleanupClosePushL( serviceIds );
+    iServer.SPSHandler().GetServiceIdsL( serviceIds );
+    for ( TInt i( 0 ); i < serviceIds.Count(); i++ )
+        {        
+        if ( KErrNotFound == FindService( serviceIds[ i ] ) )
+            {
+            TCCHService service;
+            TRAPD( error, iServer.SPSHandler().GetServiceInfoL( 
+                serviceIds[ i ], service ) );
+            if ( KErrNone == error )
+                {
+                AddServiceL( service );    
+                }                    
+            }
+        }
+    CleanupStack::PopAndDestroy( &serviceIds );
+    // Subscribe to service change notifies    
+    EnableNotifyChange();
+    
+    CCHLOGSTRING( "CCCHServiceHandler::InitServiceHandlerL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::AddServiceL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::AddServiceL( TCCHService& aService )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::AddServiceL: IN" );
+    
+    CCCHServiceInfo* cchServiceInfo = CCCHServiceInfo::NewLC( iServer );
+    cchServiceInfo->SetServiceId( aService.iServiceId );
+    cchServiceInfo->SetName( aService.iServiceName );
+    CCHLOGSTRING2( "CCCHServiceHandler::AddServiceL: adding service with %d subservices",aService.iSubservices.Count() );
+    for ( TInt i( 0 ); i < aService.iSubservices.Count(); i++ )
+        {
+        cchServiceInfo->AddSubserviceL( aService.iSubservices[ i ] );
+        }
+        
+    CleanupStack::Pop( cchServiceInfo );
+    iServices.Append( cchServiceInfo );
+    
+    CCHLOGSTRING( "CCCHServiceHandler::AddServiceL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::UpdateL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::UpdateL( TBool aReadSettingTable )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::UpdateL: IN" );
+    
+    // Read settings from service table
+    if ( aReadSettingTable )
+        {
+        RArray<TUint> serviceIds;
+        CleanupClosePushL( serviceIds );
+        
+        TInt index( KErrNotFound );
+        iServer.SPSHandler().GetServiceIdsL( serviceIds );
+        
+        for ( TInt i( 0 ); i < serviceIds.Count(); i++ )
+            {        
+            index = FindService( serviceIds[ i ] );
+            if ( KErrNotFound != index )
+                {
+                iServices[ index ]->UpdateL( ETrue );
+                }
+            else
+                {
+                CCHLOGSTRING2
+                    ( "CCCHSeviceHandler::UpdateL: \
+                        New service found: ServiceId %d", serviceIds[ i ] );
+                TCCHService service;
+                TRAPD( error, iServer.SPSHandler().GetServiceInfoL( 
+                    serviceIds[ i ], service ) );
+                if ( KErrNone == error )
+                    {
+                    AddServiceL( service );
+                    }                
+                }
+            }
+        if ( serviceIds.Count() < iServices.Count() )
+            {
+            // Remove service's which does not exist anymore            
+            for ( TInt i( 0 ); i < iServices.Count(); i++ )
+                {            
+                if ( KErrNotFound == serviceIds.Find( 
+                    iServices[ i ]->GetServiceId( ) ) )
+                    {
+                    CCHLOGSTRING2
+                        ( "CCCHSeviceHandler::UpdateL: \
+                        service removed: ServiceId %d", 
+                        iServices[ i ]->GetServiceId() );
+                    delete iServices[ i ];
+                    iServices.Remove( i );
+                    i--;
+                    StartPluginUnloadTimer( );
+                    }
+                }
+            }
+        CleanupStack::PopAndDestroy( &serviceIds );
+        }
+    else
+        {
+        for ( TInt i( 0 ); i < iServices.Count(); i++ )
+            {
+            iServices[ i ]->UpdateL();
+            }    
+        }
+    
+    CCHLOGSTRING( "CCCHServiceHandler::UpdateL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::IsStartupFlagSet
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::IsStartupFlagSet() const
+    {
+    TBool ret( EFalse );
+
+    for ( TInt i( 0 ); i < iServices.Count() && !ret; i++ )
+        {
+        ret = iServices[ i ]->StartupFlagSet();
+        }
+        
+    CCHLOGSTRING2( "CCCHServiceHandler::IsStartupFlagSet: %d", ret );
+    return ret;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::IsRecoveryNeeded
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::IsRecoveryNeeded( 
+                               const TCCHSubserviceState aState, 
+                               TInt aError )
+    {
+    TBool recover( EFalse );
+    CCHLOGSTRING( "CCCHServiceHandler::IsRecoveryNeeded: IN" );
+    if( !iServer.FeatureManager().OfflineMode() &&
+        ECCHConnecting == aState && ( 
+        KCCHErrorNetworkLost == aError || 
+        KCCHErrorServiceNotResponding == aError ) &&
+        !iConnectionRecoveryTimer->IsActive() )
+        {
+        recover = ETrue;            
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::IsRecoveryNeeded: OUT, value=%d", recover );
+    return recover;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::StateChangedL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::StateChangedL( const TUint aServiceId,
+                                        const TCCHSubserviceType aType,
+                                        const TCCHSubserviceState aState,
+                                        const TInt aError )
+    {
+    
+    CCHLOGSTRING( "CCCHServiceHandler::StateChanged: IN" );
+    CCHLOGSTRING2( "CCCHServiceHandler::StateChanged: service id;        %d",aServiceId );
+    CCHLOGSTRING2( "CCCHServiceHandler::StateChanged: service type;      %d",aType );
+    CCHLOGSTRING2( "CCCHServiceHandler::StateChanged: service new state; %d",aState );
+    CCHLOGSTRING2( "CCCHServiceHandler::StateChanged: service error;     %d",aError );
+    TInt index( FindService( aServiceId ) );
+    if ( KErrNotFound != index )
+        {
+        iServices[ index ]->SetErrorL( aType, aError );
+        iServices[ index ]->SetStateL( aType, aState );
+        //toggle voip indicator & emergency note if needed
+        if( ECCHVoIPSub == aType )
+            {
+            iCchUIHandler->UpdateUI( );
+            }
+        
+        // Check for possible first usage of GPRS (roaming cost warning)
+        TServiceConnectionInfo serviceConnInfo( aServiceId, aType, 0, 0 );
+        GetConnectionInfo( serviceConnInfo );
+        
+        if ( serviceConnInfo.iIapId && ECCHEnabled == aState )
+            {
+            if( !iCommDbWatcher->IsWlanApL( serviceConnInfo.iIapId ) )
+                {                
+                iCchUIHandler->CheckGprsFirstUsageL();
+                }
+            }
+        
+        //unload useless plugins    
+        if( ECCHDisabled == aState )
+            {
+            StartPluginUnloadTimer( );
+            }
+        //start fast recovery if not started
+        else if( IsRecoveryNeeded( aState, aError ) )
+            {
+            CCHLOGSTRING( "CCCHServiceHandler::StateChangedL network lost, starting recovery" );
+            iServicesInRecovery.Append( TServiceSelection( aServiceId, aType ) );
+            StartConnectionRecoveryTimer( CCCHServiceHandler::ConnectionRecoveryEvent );                
+            }
+        //stop fast recovery
+        if( ECCHConnecting != aState && 
+                KErrNone == aError &&
+                0 < iServicesInRecovery.Count() )
+            {
+            CCHLOGSTRING( "CCCHServiceHandler::StateChangedL checking if recovery is still needed" );
+            TInt idx = iServicesInRecovery.Find( TServiceSelection( aServiceId, aType ) );
+            if( KErrNotFound != idx )
+                {
+                CCHLOGSTRING( "CCCHServiceHandler::StateChangedL this service has recovered, recovery still on..." );
+                iServicesInRecovery.Remove( idx );
+                }
+            if( 0 == iServicesInRecovery.Count() )
+                {
+                CCHLOGSTRING( "CCCHServiceHandler::StateChangedL all services recovered, stopping recovery" );
+                CancelConnectionRecoveryTimer();
+                }
+            }
+        
+        if ( ECCHConnecting != aState || 
+            ECCHConnecting == aState && KErrNone != aError )
+            {
+            // reset startup counter
+            TBool startupFlag( EFalse );
+            iServer.SPSHandler().LoadAtStartUpL( aServiceId, aType, startupFlag );
+            if ( startupFlag )
+                {
+                iServer.ResetStartupCounterL();
+                }
+            }
+        }
+    else
+        {
+        User::Leave( index );
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::StateChanged: OUT" );
+        
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::StartConnectionRecoveryTimer
+// -----------------------------------------------------------------------------
+//
+void CCCHServiceHandler::StartConnectionRecoveryTimer( TInt (*aFunction)(TAny* aPtr) )
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler[0x%x]::StartConnectionRecoveryTimer; IN", this );
+    CancelConnectionRecoveryTimer();
+    if( !iConnectionRecoveryTimer->IsActive() )
+        {
+        iConnectionRecoveryTry = 0;
+        iConnectionRecoveryTimer->Start( iRecoveryInterval[ iConnectionRecoveryTry ] , 
+                              0, 
+                              TCallBack( aFunction, this ) );
+        CCHLOGSTRING( "CCCHServiceHandler::StartConnectionRecoveryTimer; recovery timer started");
+        
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::StartConnectionRecoveryTimer; OUT");
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::CancelConnectionRecoveryTimer
+// -----------------------------------------------------------------------------
+//
+void CCCHServiceHandler::CancelConnectionRecoveryTimer()
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler[0x%x]::CancelConnectionRecoveryTimer; IN", this );
+
+    if( iConnectionRecoveryTimer->IsActive() )
+        {
+        iConnectionRecoveryTimer->Cancel();
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::CancelConnectionRecoveryTimer; OUT" );        
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::ConnectionRecoveryEvent
+// -----------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::ConnectionRecoveryEvent( TAny* aSelf )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::ConnectionRecoveryEvent; IN" );
+    CCCHServiceHandler* self = static_cast<CCCHServiceHandler*>( aSelf );
+    self->HandleConnectionRecovery();
+    CCHLOGSTRING( "CCCHServiceHandler::ConnectionRecoveryEvent; OUT" );
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::HandleConnectionRecovery
+// -----------------------------------------------------------------------------
+//
+void CCCHServiceHandler::HandleConnectionRecovery()
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler[0x%x]::HandleConnectionRecovery IN",
+                   this );
+    iConnectionRecoveryTry++;
+    CCHLOGSTRING2( "CCCHServiceHandler::HandleConnectionRecovery; recovery try:%d",iConnectionRecoveryTry );
+    iServer.ConnMonHandler().ScanNetworks( ETrue );    
+    CancelConnectionRecoveryTimer();
+    
+    if( KConnectionRecoveryMaxTries > iConnectionRecoveryTry )
+        {
+        CCHLOGSTRING( "CCCHServiceHandler::HandleConnectionRecovery; recovery continues" );
+        iConnectionRecoveryTimer->Start( iRecoveryInterval[ iConnectionRecoveryTry ], 
+                              0,
+                              TCallBack( CCCHServiceHandler::ConnectionRecoveryEvent, this ) );
+        }
+    else
+        {
+        CCHLOGSTRING( "CCCHServiceHandler::HandleConnectionRecovery; max tries reached, recovery canceled" );
+        }                   
+    CCHLOGSTRING( "CCCHServiceHandler::HandleConnectionRecovery OUT" );
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::StartPluginUnloadTimer
+// -----------------------------------------------------------------------------
+//
+void CCCHServiceHandler::StartPluginUnloadTimer( )
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler[0x%x]::StartPluginUnloadTimer; IN", this );
+    CancelPluginUnloadTimer();
+    if( !iPluginUnloadTimer->IsActive() )
+        {
+        iPluginUnloadTimer->Start( KCCHPluginUnloadTimeout , 
+                              0, 
+                              TCallBack( CCCHServiceHandler::PluginUnloadEvent, this ) );
+        CCHLOGSTRING( "CCCHServiceHandler::StartPluginUnloadTimer; plugin unload timer started");
+        
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::StartPluginUnloadTimer; OUT");
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::CancelPluginUnloadTimer
+// -----------------------------------------------------------------------------
+//
+void CCCHServiceHandler::CancelPluginUnloadTimer()
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler[0x%x]::CancelPluginUnloadTimer; IN", this );
+
+    if( iPluginUnloadTimer->IsActive() )
+        {
+        iPluginUnloadTimer->Cancel();
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::CancelPluginUnloadTimer; OUT" );        
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::PluginUnloadEvent
+// -----------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::PluginUnloadEvent( TAny* aSelf )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::PluginUnloadEvent; IN" );
+    CCCHServiceHandler* self = static_cast<CCCHServiceHandler*>( aSelf );
+    self->HandlePluginUnload();
+    CCHLOGSTRING( "CCCHServiceHandler::PluginUnloadEvent; OUT" );
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CCCHServiceHandler::HandlePluginUnload
+// -----------------------------------------------------------------------------
+//
+void CCCHServiceHandler::HandlePluginUnload()
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler[0x%x]::HandlePluginUnload IN",
+                   this );
+    CancelPluginUnloadTimer();
+    TRAP_IGNORE( UnloadDisabledPluginsL( ) );
+    
+    CCHLOGSTRING( "CCCHServiceHandler::HandlePluginUnload OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::Exists
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::Exists( TCCHSubserviceType aType, 
+                                  TCCHSubserviceState aState,
+                                  TInt aError ) const
+    {
+    CCHLOGSTRING3( "CCCHServiceHandler::Exists(%d,%d)",aType,aState );
+    TBool bReturn( EFalse );
+    for( TInt i( 0 ); i < iServices.Count(); i++ )
+        {
+        for ( TInt j( 0 ); j < iServices[ i ]->SubserviceCount(); j++ )
+            {
+            TCCHSubserviceState state = ECCHUninitialized;
+            TInt err = iServices[ i ]->GetStatus(iServices[ i ]->GetSubserviceType( j ), state );
+            if( err == KErrNone )
+                {
+                if( aType == iServices[ i ]->GetSubserviceType( j ) && 
+                    aState == state &&
+                    aError == iServices[ i ]->GetError(iServices[ i ]->GetSubserviceType( j ) ) )
+                    {
+                    bReturn = ETrue;
+                    break;
+                    }
+                }
+            }
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::Exists returns: %d",bReturn );        
+    return bReturn;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::LoadPluginsL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::LoadPluginsL()
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::LoadPluginsL: IN" );
+    
+    // Get plugin uids to array;
+    RArray<TUid> uids;
+    CleanupClosePushL( uids );
+    
+    TUid pluginUid( KNullUid );
+        
+    for( TInt i( 0 ); i < iServices.Count(); i++ )
+        {     
+        for ( TInt j( 0 ); j < iServices[ i ]->SubserviceCount(); j++ )
+            {
+            if ( iServices[ i ]->StartupFlagSet( j ) )
+                {
+                pluginUid = iServices[ i ]->GetUidL( j );
+    
+                if ( KErrNotFound == uids.Find( pluginUid ) && 
+                    KNullUid != pluginUid )
+                    {
+                    uids.Append( pluginUid );
+
+                    TRAP_IGNORE( 
+                        iServer.PluginHandler().LoadPluginsL( pluginUid ) );
+                    
+                    // Set notifier to loaded Plug-ins                        
+                    iServer.PluginHandler().SetServiceNotifier( this );                        
+                    }
+                // Enable subservice
+                TServiceSelection selection;
+                selection.iServiceId = iServices[ i ]->GetServiceId();
+                selection.iType = iServices[ i ]->GetSubserviceType( j );
+                EnableService( selection, EFalse );
+                }           
+            }
+        }        
+    CleanupStack::PopAndDestroy( &uids );    
+    
+    CCHLOGSTRING( "CCCHServiceHandler::LoadPluginsL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::UnloadPlugin
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::UnloadDisabledPluginsL( )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::UnloadDisabledPluginsL: IN" );
+    
+    // Get plugin uids to array;
+    RArray<TUid> uidsToBeUnloaded;
+    RArray<TUid> uidsNotToBeUnloaded;
+    CleanupClosePushL( uidsToBeUnloaded );
+    CleanupClosePushL( uidsNotToBeUnloaded );
+    
+    
+    // ...let's go through services & sub services
+    for ( TInt ixSer=0; ixSer < iServices.Count(); ixSer++ )
+        {
+        for ( TInt ixSub=0; ixSub < iServices[ ixSer ]->SubserviceCount(); ixSub++ )
+            {
+            TUid pluginUid( KNullUid );
+            TInt error( KErrNone );
+            TRAP( error, pluginUid = iServices[ ixSer ]->GetUidL( ixSub ));
+            // if subservice was found
+            if( KErrNone == error )
+                {
+                
+                TCCHSubserviceState state = ECCHUninitialized;
+                
+                // subservice was found, so don't need to check return value
+                iServices[ ixSer ]->GetStatus(
+                     iServices[ ixSer ]->GetSubserviceType( ixSub ), state );
+                     
+                // if non disabled subservice found, add it to non-unload arry                     
+                if( ECCHDisabled != state )
+                    {
+                    uidsNotToBeUnloaded.Append( pluginUid );
+                    }
+                    
+                else
+                    {
+                    if( KErrNotFound == uidsToBeUnloaded.Find( pluginUid ) )
+                        {
+                        // the others go to unload array
+                        uidsToBeUnloaded.Append( pluginUid );        
+                        }
+                    }
+                }
+            }
+        }
+    iServer.PluginHandler().RemoveServiceNotifier( this );
+    for( TInt i=0; i<uidsToBeUnloaded.Count(); i++ )
+        {
+        //unload plugin & set state if not found from non-unloadable array
+        if( KErrNotFound == uidsNotToBeUnloaded.Find( uidsToBeUnloaded[i] ) )
+            {
+            CCHLOGSTRING2(
+                "CCCHServiceHandler::UnloadDisabledPluginsL; unloading plugin UID:0x%x",
+                    uidsToBeUnloaded[i] );
+            iServer.PluginHandler().UnloadPlugin( uidsToBeUnloaded[i] );
+            }
+        }
+    iServer.PluginHandler().SetServiceNotifier( this );
+    CleanupStack::PopAndDestroy( &uidsNotToBeUnloaded );   
+    CleanupStack::PopAndDestroy( &uidsToBeUnloaded );    
+    CCHLOGSTRING( "CCCHServiceHandler::UnloadDisabledPluginsL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::EnableService
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::EnableService( 
+    const TServiceSelection aServiceSelection, 
+    const TBool aConnectivityCheck )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::EnableService: IN" );
+    TInt error( ServiceExist( aServiceSelection ) );
+    TBool connectionOk( EFalse );
+    if ( KErrNotFound != error )
+        {
+        TInt index = error;
+        TRAP( error, connectionOk = IsServiceConnectivityDefinedL( aServiceSelection ) );
+        if( KErrNone == error )
+            {
+            if( connectionOk )
+                {
+                if( iCancelNotify )
+                    {
+                    DisableNotifyChange();
+                    }
+         
+                CCHLOGSTRING3( "CCCHServiceHandler::EnableService: service:%d, type:%d",
+                        aServiceSelection.iServiceId, aServiceSelection.iType );
+    
+                // If client wants to enable VoIP subservice and VoIP are not supported
+                // send KErrNotSupported notify to the client
+                if ( ( ECCHUnknown == aServiceSelection.iType ||
+                       ECCHVoIPSub == aServiceSelection.iType ) &&
+                       iServices[ index ]->SubserviceExist( ECCHVoIPSub ) &&
+                       !iServer.FeatureManager().VoIPSupported() )
+                    {
+                    CCHLOGSTRING( "CCCHServiceHandler::EnableService: No support for VoIP" );
+                    TRAP_IGNORE( iServices[ index ]->SetErrorL( ECCHVoIPSub, KErrNotSupported ) );
+                    TRAP_IGNORE( iServices[ index ]->SetStateL( ECCHVoIPSub, ECCHDisabled ) );
+                    // Enable one by one all subservices except VoIP
+                    if ( ECCHUnknown == aServiceSelection.iType )
+                        {
+                        for ( TInt i( 0 ); i < iServices[ index ]->SubserviceCount(); i++ )
+                            {
+                            if ( ECCHVoIPSub != iServices[ index ]->GetSubserviceType( i ) )
+                                {
+                                TRAP( error, iServices[ index ]->EnableL(
+                                    iServices[ index ]->GetSubserviceType( i ),
+                                        aConnectivityCheck, this ) );
+                                }
+                            }
+                        }
+                    }
+                else
+                    {
+                    TRAP( error, iServices[ index ]->EnableL( 
+                        aServiceSelection.iType, aConnectivityCheck, this ) );
+                    }
+                if( iCancelNotify )
+                    {
+                    EnableNotifyChange();
+                    }
+                if( HasWlanIap( aServiceSelection ) && KErrNone == error )
+                    {
+                    CCHLOGSTRING( "CCCHServiceHandler::EnableService: Launching WLAN scan..." );
+                    TRAP_IGNORE( iWlanExtension->EnableWlanScanL() );
+                    }
+                // There could be new Plug-ins after EnableL, so we must set
+                // notifier to loaded Plug-ins
+                iServer.PluginHandler().SetServiceNotifier( this );
+                }
+            else
+                {
+                error = KCCHErrorAccessPointNotDefined;
+                }
+            CCHLOGSTRING2
+                    ( "CCCHServiceHandler::EnableService: error: %d", error );
+            }
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::EnableService: OUT" );
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::DisableService
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::DisableService( 
+    const TServiceSelection aServiceSelection )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::DisableService: IN" );
+    TInt error( ServiceExist( aServiceSelection ) );
+    
+    if ( KErrNotFound != error )
+        {
+        TInt index( error );
+        if( iCancelNotify )
+            {
+            DisableNotifyChange();
+            }
+
+        TRAP( error, iServices[ index ]->DisableL(
+            aServiceSelection.iType ) );
+        
+        DisableWlanScan();
+        if( iCancelNotify )
+            {
+            EnableNotifyChange();            
+            }
+            CCHLOGSTRING2
+                ( "CCCHServiceHandler::DisableService: error: %d", error );
+        }
+    CCHLOGSTRING2(
+        "CCCHServiceHandler::DisableService: return %d OUT", error );
+    return error;
+    }
+    
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::DisableWlanScan
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::DisableWlanScan( )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::DisableWlanScan: IN" );
+    
+    TBool disableWlanScan( ETrue );
+    TCCHSubserviceState serviceState( ECCHUninitialized );
+    TCCHSubserviceType serviceType( ECCHUnknown );
+    TInt serviceId( 0 );
+    
+     // ...let's go through services & sub services
+    for ( TInt ixSer = 0; ixSer < iServices.Count(); ixSer++ )
+        {
+        for ( TInt ixSub = 0; ixSub < iServices[ ixSer ]->SubserviceCount(); ixSub++ )
+            {
+            serviceType = iServices[ ixSer ]->GetSubserviceType( ixSub );
+            TInt err = iServices[ ixSer ]->GetStatus( serviceType, serviceState );
+            if( err == KErrNone )
+                {
+                // if found even one enabled/connecting service, do not deactivate scan
+                if( ECCHEnabled == serviceState || ECCHConnecting == serviceState )
+                    {
+                    serviceId =  iServices[ ixSer ]->GetServiceId();
+                    
+                    TServiceConnectionInfo serviceConnInfo( serviceId, serviceType, 0, 0 );
+                    GetConnectionInfo( serviceConnInfo );
+                    // existing snap overrides iap
+                    if( serviceConnInfo.iSNAPId != 0 )
+                        {
+                        TInt wlanIaps( 0 );
+                        TInt allIaps( 0 );
+                        TInt error( KErrNone );
+                        TRAP( error, 
+                            {
+                            wlanIaps = iCommDbWatcher->GetIapCountFromSnap( serviceConnInfo.iSNAPId, ETrue, ETrue );
+                            allIaps = iCommDbWatcher->GetIapCountFromSnap( serviceConnInfo.iSNAPId, EFalse );
+                            } );
+                        
+                        // in case of possibility -> WLAN ALR we need to keep the scan active
+                        // in case of possibility -> do not disable wlan scan if there is only one iap 
+                        // and the iap is wlan
+                        if( KErrNone == error )
+                            {
+                            if( 1 <= allIaps && 0 < wlanIaps )
+                                {
+                                disableWlanScan = EFalse;
+                                break;
+                                }
+                            }
+                        }
+                    else if( serviceConnInfo.iIapId != 0 )
+                        {
+                        TInt error( KErrNone );
+                        TBool isWlanIap( EFalse );
+                        
+                        TRAP( error, isWlanIap = iCommDbWatcher->IsWlanApL( serviceConnInfo.iIapId ) )
+                        CCHLOGSTRING2( "CCCHServiceHandler::DisableWlanScan: error: %d", error );
+                        
+                        if( KErrNone == error)
+                            {
+                            //in case the iap is wlan type, scan is not deactivated
+                            if( isWlanIap )
+                                {
+                                disableWlanScan = EFalse;
+                                break;
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        if( !disableWlanScan )
+            {
+            break;
+            }
+        }            
+    if( disableWlanScan )
+        {
+        CCHLOGSTRING( "CCCHServiceHandler::DisableWlanScan disabling wlan scan..." );
+        
+        TRAP_IGNORE( iWlanExtension->DisableWlanScanL() ) ;
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::DisableWlanScan: OUT" );
+    }
+    
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::SetConnectionInfo
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::SetConnectionInfo( 
+    const TServiceConnectionInfo aServiceConnInfo )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::SetConnectionInfo: IN" );
+    TInt error( KErrNotFound );
+    CCHLOGSTRING2( "CCCHServiceHandler::SetConnectionInfo: serviceId %d",
+        aServiceConnInfo.iServiceSelection.iServiceId );
+    CCHLOGSTRING2( "CCCHServiceHandler::SetConnectionInfo: iType %d",
+        aServiceConnInfo.iServiceSelection.iType );
+    CCHLOGSTRING2( "CCCHServiceHandler::SetConnectionInfo: iSNAPId %d",
+        aServiceConnInfo.iSNAPId );
+    CCHLOGSTRING2( "CCCHServiceHandler::SetConnectionInfo: iIapId %d",
+        aServiceConnInfo.iIapId );
+    CCHLOGSTRING2( "CCCHServiceHandler::SetConnectionInfo: iReserved %d",
+        aServiceConnInfo.iReserved );
+
+    if ( KErrNotFound != 
+        ( error = FindService( aServiceConnInfo.iServiceSelection.iServiceId ) ) )
+        {
+        TInt index( error );
+        TRAP( error, iServices[ index ]->SetConnectionInfoL( 
+            aServiceConnInfo ) );
+        StartPluginUnloadTimer( );
+        CCHLOGSTRING2
+            ( "CCCHServiceHandler::SetConnectionInfo: error: %d", error );
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::SetConnectionInfo: OUT" );
+    return error;
+    }
+    
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::GetConnectionInfo
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::GetConnectionInfo( 
+    TServiceConnectionInfo& aServiceConnInfo )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::GetConnectionInfo: IN" );
+    TInt error( KErrNotFound );
+    
+    if ( KErrNotFound != 
+        ( error = FindService( aServiceConnInfo.ServiceId() ) ) )
+        {
+        TInt index( error );
+        TRAP( error, iServices[ index ]->GetConnectionInfoL( 
+                aServiceConnInfo ) );
+        StartPluginUnloadTimer( );
+        CCHLOGSTRING2
+            ( "CCCHServiceHandler::GetConnectionInfo: error: %d", error );
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::GetConnectionInfo: OUT" );
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::UsesWlanIapL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::UsesWlanIap( 
+    const TServiceSelection& aServiceSelection )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::UsesWlanIap: IN" );
+    TBool isWlanIap( EFalse );
+    TServiceConnectionInfo serviceConnInfo(
+            aServiceSelection.iServiceId, aServiceSelection.iType, 0, 0 );
+    CCHLOGSTRING3( "CCCHServiceHandler::UsesWlanIap: service:%d, type:%d",
+            aServiceSelection.iServiceId, aServiceSelection.iType );
+    
+    TInt error = GetConnectionInfo( serviceConnInfo );
+    
+    if( KErrNone == error )
+        {
+        
+        CCHLOGSTRING3( "CCCHServiceHandler::UsesWlanIap: snap:%d, snap:%d",
+                serviceConnInfo.iSNAPId, serviceConnInfo.iIapId );
+        if( 0 != serviceConnInfo.iSNAPId )
+            {
+            CCHLOGSTRING( "CCCHServiceHandler::UsesWlanIapL: SNAP in use" );
+            TInt count( 0 );
+            TRAP( error, count = iCommDbWatcher->GetIapCountFromSnap( serviceConnInfo.iSNAPId, ETrue ));
+            if( KErrNone == error && 0 < count )
+                {
+                isWlanIap = ETrue;
+                }
+            }
+        else if( 0 != serviceConnInfo.iIapId )
+            {
+            CCHLOGSTRING( "CCCHServiceHandler::UsesWlanIapL: IAP in use" );
+           
+            TRAP( error, isWlanIap = iCommDbWatcher->IsWlanApL( serviceConnInfo.iIapId ) );
+            CCHLOGSTRING2( "CCCHServiceHandler::UsesWlanIap: error: %d", error );
+            }
+
+
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::UsesWlanIap: OUT, value=%d", isWlanIap );
+    return isWlanIap;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::IsConnectionDefined
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::IsConnectionDefinedL( 
+    const TServiceSelection& aServiceSelection ) 
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::IsConnectionDefined: IN" );
+    TBool isOk( EFalse );
+    __ASSERT_DEBUG( aServiceSelection.iType != ECCHUnknown, User::Panic( KNullDesC, KErrGeneral ) );
+    TServiceConnectionInfo serviceConnInfo(
+            aServiceSelection.iServiceId, aServiceSelection.iType, 0, 0 );
+    CCHLOGSTRING3( "CCCHServiceHandler::IsConnectionDefined: service:%d, type:%d",
+            aServiceSelection.iServiceId, aServiceSelection.iType );
+    
+    TInt error = GetConnectionInfo( serviceConnInfo );
+    User::LeaveIfError( error );
+    
+    CCHLOGSTRING3( "CCCHServiceHandler::IsConnectionDefined: snap:%d, snap:%d",
+            serviceConnInfo.iSNAPId, serviceConnInfo.iIapId );
+    if( 0 != serviceConnInfo.iSNAPId )
+        {
+        TInt count( 0 );
+        count = iCommDbWatcher->GetIapCountFromSnap( serviceConnInfo.iSNAPId, EFalse, ETrue );
+        CCHLOGSTRING( "CCCHServiceHandler::IsConnectionDefined: SNAP in use" );
+        if( KErrNone == error && 0 < count )
+            {
+            isOk = ETrue;
+            }
+        }
+    else if( 0 != serviceConnInfo.iIapId )
+        {
+        CCHLOGSTRING( "CCCHServiceHandler::IsConnectionDefined: IAP in use" );
+        isOk = ETrue;
+        }
+
+    CCHLOGSTRING2( "CCCHServiceHandler::IsConnectionDefined: OUT, value=%d", isOk );
+    return isOk;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::IsServiceConnectivityDefined
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::IsServiceConnectivityDefinedL( 
+    const TServiceSelection& aServiceSelection ) 
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::IsServiceConnectivityDefined: IN" );
+    
+    TBool isOk( EFalse );
+    TInt error( KErrNone );
+    TInt index = FindService( aServiceSelection.iServiceId );
+    if ( KErrNotFound != index )
+        {
+        if( ECCHUnknown == aServiceSelection.iType )
+            {
+            for( TInt i = 0; i < iServices[ index ]->SubserviceCount(); i++ )
+                {
+                TRAP( error, isOk = IsConnectionDefinedL( 
+                        TServiceSelection( aServiceSelection.iServiceId, 
+                        iServices[ index ]->GetSubserviceType( i ) ) ) ) ;
+                if( isOk )
+                    {
+                    error = KErrNone;
+                    break;
+                    }
+                }
+            }
+        else
+            {
+            TRAP( error, isOk = IsConnectionDefinedL( aServiceSelection ) );
+            }    
+        }
+    CCHLOGSTRING3( 
+        "CCCHServiceHandler::IsServiceConnectivityDefined: OUT, value=%d, error=%d", isOk, error );
+    User::LeaveIfError( error );
+    return isOk;
+    }
+
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::HasWlanIap
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TBool CCCHServiceHandler::HasWlanIap( 
+    const TServiceSelection& aServiceSelection )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::HasWlanIap: IN" );
+    
+    TBool isWlanIap( EFalse );
+    TInt index = FindService( aServiceSelection.iServiceId );
+    if ( KErrNotFound != index )
+        {
+        if( ECCHUnknown == aServiceSelection.iType )
+            {
+            for( TInt i = 0; i < iServices[ index ]->SubserviceCount(); i++ )
+                {
+                isWlanIap = UsesWlanIap( 
+                        TServiceSelection( aServiceSelection.iServiceId, 
+                        iServices[ index ]->GetSubserviceType( i ) ) ) ;
+                if( isWlanIap )
+                    {
+                    break;
+                    }
+                }
+            }
+        else
+            {
+            isWlanIap = UsesWlanIap( aServiceSelection );
+            }    
+        StartPluginUnloadTimer( );
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::HasWlanIap: OUT, value=%d", isWlanIap );
+    return isWlanIap;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::ServiceCountL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::ServiceCountL( RMessage2 aMessage ) const
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::ServiceCountL: IN" );
+    
+    TPckgBuf<TUint32> pckgServiceCount;
+    aMessage.ReadL( 0, pckgServiceCount );
+    TCCHSubserviceType type( 
+        static_cast<TCCHSubserviceType>( aMessage.Int1() ) );
+    
+    if ( ECCHUnknown == type )
+        {
+        // Count of services
+        pckgServiceCount() = iServer.SPSHandler().GetServicesCountL();
+        // Service count back to the client
+        aMessage.WriteL( 0, pckgServiceCount );
+        }
+    else
+        {
+        // Count of services which contains subservices
+        pckgServiceCount() = ServiceCount( type );
+        // Service count back to the client
+        aMessage.WriteL( 0, pckgServiceCount );
+        }        
+    
+    CCHLOGSTRING( "CCCHServiceHandler::ServiceCountL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::GetServicesL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::GetServicesL( RMessage2 aMessage ) const
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::GetServicesL: IN" );
+    TInt count =  iServices.Count();
+    TInt index( KErrNotFound );
+    if ( count )
+        {
+        TUint32 serviceId = aMessage.Int0();
+        TCCHSubserviceType type ( ECCHUnknown );
+        type = static_cast<TCCHSubserviceType>( aMessage.Int1() );
+        
+        if ( KErrNotFound == aMessage.Int0() )
+            {
+            serviceId = KErrNone;
+            }
+        else if ( serviceId != KErrNone )
+            {
+            count = 1;
+            }
+                    
+        CArrayFixFlat<TCCHService>* serviceArray = 
+            new( ELeave )CArrayFixFlat<TCCHService>( count );
+        CleanupStack::PushL( serviceArray );
+        
+        TCCHService service;
+        // Get all services
+        if ( KErrNone == serviceId )
+            {
+            if ( type == ECCHUnknown )
+                {
+                for ( TInt i( 0 ); i < count; i++ )
+                    {
+                    iServices[ i ]->FillServiceInfo( service );
+                    serviceArray->AppendL( service );
+                    }    
+                }
+            else
+                {
+                for ( TInt i( 0 ); i < count; i++ )
+                    {
+                    if ( iServices[ i ]->SubserviceExist( type ) )
+                        {
+                        iServices[ i ]->FillServiceInfo( service );
+                        serviceArray->AppendL( service );
+                        }                    
+                    }
+                }
+            }
+        // Get specified service
+        else 
+            {
+            if ( type == ECCHUnknown )
+                {
+                index = FindService( serviceId );
+                if ( KErrNotFound != index )
+                    {
+                    iServices[ index ]->FillServiceInfo( service );
+                    serviceArray->AppendL( service );
+                    }
+                }
+            else
+                {
+                TServiceSelection selection( serviceId, type ); 
+                index = ServiceExist( selection );
+                if ( KErrNotFound != index )
+                    {
+                    iServices[ index ]->FillServiceInfo( service );
+                    serviceArray->AppendL( service );
+                    }
+                }
+            }
+        
+        TUint32 length = serviceArray->Count() * sizeof( TCCHService );
+        
+        if ( length )
+            {
+            TPtrC8 servicePtr;
+            servicePtr.Set( 
+                reinterpret_cast<TText8*>( &( *serviceArray )[ 0 ] ), 
+                    length );
+            aMessage.WriteL( 2, servicePtr );                     
+            }
+        else
+            {
+            User::Leave( KErrNotFound );
+            }            
+            
+        CleanupStack::PopAndDestroy( serviceArray );
+        }
+    else
+        {
+        User::Leave( KErrNotFound );
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::GetServicesL: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::GetServiceState
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//    
+TInt CCCHServiceHandler::GetServiceState( const RMessage2 aMessage )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::GetServiceStateL: IN" );
+        
+    TUint32 serviceId( 0 );
+    TCCHSubserviceType type ( ECCHUnknown );
+    TPckgBuf<TCCHSubserviceState> status;
+    serviceId = aMessage.Int0();
+    type = static_cast<TCCHSubserviceType>( aMessage.Int1() );
+    
+    TInt error( FindService( serviceId ) );
+    TInt errorState = KErrNone;
+    
+    if ( KErrNotFound != error )
+        {
+        TInt index( error );
+        TRAP( error, 
+            {
+            aMessage.ReadL( 2, status );
+            errorState = iServices[ index ]->GetStatus( type, status() );
+            if( errorState == KErrNone )
+                {
+                aMessage.WriteL( 2, status );
+                }
+            } );
+        if( KErrNone == error )
+            {
+            if( errorState == KErrNone )
+                {
+                error = iServices[ index ]->GetError( type );
+                }
+            else
+                {
+                error = errorState;
+                }
+            }
+        StartPluginUnloadTimer( );
+        }
+    
+    CCHLOGSTRING2( 
+        "CCCHServiceHandler::GetServiceStateL: return %d OUT", error );
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::GetServiceState
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//    
+TCCHSubserviceState CCCHServiceHandler::ServiceState(
+        const TUint aServiceId )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::ServiceState: IN" );
+    
+    TCCHSubserviceState state( ECCHUninitialized );
+    TInt error( FindService( aServiceId ) );
+    
+    if ( KErrNotFound != error )
+        {
+        state = iServices[ error ]->GetState();
+        }
+    
+    CCHLOGSTRING2( 
+        "CCCHServiceHandler::ServiceState: return %d OUT", state );
+    return state;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::GetServiceInfo
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//    
+TInt CCCHServiceHandler::GetServiceInfo( const RMessage2 aMessage )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::GetServiceInfo: IN" );
+    TBuf<KCCHMaxProtocolNameLength> buffer;
+
+    TPckgBuf<TServiceConnectionInfo> serviceConnInfoPckg;
+
+    TInt error = KErrNone;
+    TRAP( error, 
+        { 
+        aMessage.ReadL( 0, serviceConnInfoPckg );
+        } );
+        
+    if( error ) 
+        {
+        return error;
+        }
+   
+    TServiceConnectionInfo conninfo;
+     
+    conninfo.iServiceSelection.iServiceId = serviceConnInfoPckg().iServiceSelection.iServiceId;
+    conninfo.iServiceSelection.iType      = serviceConnInfoPckg().iServiceSelection.iType;
+    conninfo.iServiceSelection.iParameter = serviceConnInfoPckg().iServiceSelection.iParameter;
+  
+    error = ServiceExist( conninfo.iServiceSelection );
+    
+    if ( KErrNotFound != error )
+        {
+        TInt index( error );
+
+        if( conninfo.iServiceSelection.iParameter == ECchServiceInfo )
+            {
+            TRAP( error, 
+                {
+                iServices[ index ]->GetServiceInfoL( 
+                    buffer, conninfo.iServiceSelection.iType );
+                aMessage.WriteL( 1, buffer );
+                } );
+            }
+        StartPluginUnloadTimer( );
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::GetServiceInfo: return %d OUT", error );
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::ReserveService
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//    
+TInt CCCHServiceHandler::ReserveService( const RMessage2 aMessage ) 
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::ReserveService: IN" );
+    
+    TServiceSelection serviceSelection(aMessage.Int0(), 
+        static_cast<TCCHSubserviceType>( aMessage.Int1() ) );
+    
+    TInt error( ServiceExist( serviceSelection ) );
+    
+    if ( KErrNotFound != error )
+        {
+        TInt index( error );
+        TRAP( error, 
+            {
+            iServices[ index ]->ReserveServiceL( 
+                serviceSelection.iType );
+            } );
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::ReserveService: return %d OUT", error );
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::FreeService
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//    
+TInt CCCHServiceHandler::FreeService( const RMessage2& aMessage )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::FreeService: IN" );
+    
+    TServiceSelection serviceSelection(aMessage.Int0(), 
+        static_cast<TCCHSubserviceType>( aMessage.Int1() ) );
+    
+    TInt error( ServiceExist( serviceSelection ) );
+    
+    if ( KErrNotFound != error )
+        {
+        TInt index( error );
+        TRAP( error, 
+            {
+            iServices[ index ]->FreeServiceL( 
+                serviceSelection.iType );
+            } );
+        }
+    CCHLOGSTRING2( "CCCHServiceHandler::FreeService: return %d OUT", error );        
+    return error;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::IsReserved
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::IsReserved( RMessage2 aMessage ) const
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::IsReserved: IN" );
+    
+    
+    TServiceSelection serviceSelection(aMessage.Int0(),
+        static_cast<TCCHSubserviceType>( aMessage.Int1() ) );
+    TInt error( KErrNone );
+            
+    TPckgBuf<TBool> pckgIsReserved;
+    TRAP( error, aMessage.ReadL( 2, pckgIsReserved ) );
+    
+    error = ServiceExist( serviceSelection );
+    
+    if ( KErrNotFound != error )
+        {
+        TInt index( error );
+        TRAP( error, 
+            {
+            pckgIsReserved() = iServices[ index ]->IsReservedL( 
+                serviceSelection.iType );
+            } );
+        }
+        
+    
+    if ( KErrNotFound != error )
+        {
+        // Service's reference count back to the client
+        TRAP( error, aMessage.WriteL( 2, pckgIsReserved ) );
+        }
+     
+    
+    CCHLOGSTRING( "CCCHServiceHandler::IsReserved: OUT" );
+    }
+    
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::ServiceExist
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::ServiceExist( TServiceSelection aSelection ) const
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::ServiceExist: IN" );
+    TBool exist( EFalse );
+    TInt index( FindService( aSelection.iServiceId ) );
+    
+    if ( KErrNotFound != index )
+        {
+        exist = iServices[ index ]->SubserviceExist( aSelection.iType );
+        }    
+    CCHLOGSTRING( "CCCHServiceHandler::ServiceExist: OUT" );
+    return !exist ? KErrNotFound : index;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::FindService
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::FindService( TUint32 aServiceId ) const
+    {
+    TBool exist( EFalse );
+    TInt index( KErrNotFound );
+    CCHLOGSTRING2( "CCCHServiceHandler::FindService: serviceId %d",
+        aServiceId );
+    for ( TInt i( 0 ); i < iServices.Count() && !exist; i++ )
+        {
+        exist = iServices[ i ]->GetServiceId() == aServiceId;
+        index = i;
+        }
+    return !exist ? KErrNotFound : index;
+    }
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::HandleNotifyChange
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::HandleNotifyChange( TServiceId aServiceId )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::HandleNotifyChange: IN" );
+    TServiceSelection selection;
+    selection.iServiceId = aServiceId;
+    TInt index( ServiceExist( selection ) );
+    TRAPD( err, 
+        {
+        if ( KErrNotFound != index )
+            {
+            iServices[ index ]->UpdateL( ETrue );
+            }
+        else
+            {
+            TCCHService service;
+            iServer.SPSHandler().GetServiceInfoL( aServiceId, service );
+            AddServiceL( service );
+            } 
+        } );
+    
+    //Check if service is already marked as enabled, and enable it
+    if ( KErrNone == err )
+        {
+        index = ServiceExist( selection );
+        if ( KErrNotFound != index )
+            {
+            CCHLOGSTRING( "CCCHServiceHandler::HandleNotifyChange: service found" );
+            if( iServices[ index ]->StartupFlagSet() && 
+                ECCHEnabled != iServices[ index ]->GetState() )
+                {
+                CCHLOGSTRING( "CCCHServiceHandler::HandleNotifyChange: enabling..." );
+                iCancelNotify = EFalse;
+                EnableService( selection, EFalse );
+                iCancelNotify = ETrue;
+                }
+            }
+        }
+    
+    // If service has removed, err must be other than none 
+    // and we have to update all services
+    if ( KErrNone != err )
+        {
+        TRAP_IGNORE( UpdateL( ETrue ) );
+        }
+    CCHLOGSTRING( "CCCHServiceHandler::HandleNotifyChange: OUT" );
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::EnableNotifyChange
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::EnableNotifyChange()
+    {
+    TRACE_ENTRY_POINT;
+    // Subscribe to service change notifies    
+    TRAP_IGNORE( iNotifier->NotifyChangeL( iServiceIds ) );
+    TRACE_EXIT_POINT;
+    }
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::DisableNotifyChange
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::DisableNotifyChange()
+    {
+    TRACE_ENTRY_POINT;
+    iNotifier->Cancel();
+    TRACE_EXIT_POINT;
+    }
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::ServiceCount
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::ServiceCount( const TCCHSubserviceType aType ) const
+    {
+    CCHLOGSTRING2( "CCCHServiceHandler::ServiceCount: type: %d",aType );
+    
+    TInt count( 0 );
+    
+    for ( TInt i( 0 ); i < iServices.Count(); i++ )
+        {
+        if ( KErrNotFound != iServices[ i ]->FindSubservice( aType ) )
+            {
+            count++;    
+            }
+        }
+    
+    CCHLOGSTRING2( "CCCHServiceHandler::ServiceCount: count: %d", count );
+    
+    return count;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::HandleError
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::HandleError( TInt /*aError*/ )
+    {
+    
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::HandleWLANIapAdded
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::HandleWLANIapAdded( TInt aSNAPId )
+    {
+    CCHLOGSTRING( "CCCHServiceHandler::HandleWLANIapAdded: IN" );
+    TBool startScan( EFalse );
+    TCCHSubserviceState serviceState( ECCHUninitialized );
+    TCCHSubserviceType serviceType( ECCHUnknown );
+        
+    // go through all services & subservices
+    for( TInt i = 0; i < iServices.Count(); i++ )
+        {
+        for ( TInt j = 0; j < iServices[ i ]->SubserviceCount(); j++ )
+            {
+            serviceType = iServices[ i ]->GetSubserviceType( j );
+            TInt error = iServices[ i ]->GetStatus( serviceType, serviceState );
+            
+            if( KErrNone == error )
+                {
+                // if we have a connecting or enabled service 
+                if( !iServer.FeatureManager().OfflineMode() &&
+                    ( ECCHConnecting == serviceState || ECCHEnabled == serviceState ) )
+                    {
+                    TUint serviceId = iServices[ i ]->GetServiceId();
+                    TServiceConnectionInfo serviceConnInfo( serviceId, serviceType, 0, 0 );
+                    GetConnectionInfo( serviceConnInfo );
+                    
+                    // with a snap with new wlan iap, we start wlan scan
+                    if( aSNAPId == serviceConnInfo.iSNAPId && 0 != aSNAPId )
+                        {
+                        startScan = ETrue;                    
+                        }
+                    }
+                }
+            }
+        }
+    if( startScan )        
+        {
+        CCHLOGSTRING( "CCCHServiceHandler::HandleWLANIapAdded; starting wlan scan" );
+        TRAP_IGNORE( iWlanExtension->ForceEnableWlanScanL() );
+        iServer.ConnMonHandler().ScanNetworks( ETrue );
+        }
+	CCHLOGSTRING( "CCCHServiceHandler::HandleWLANIapAdded: OUT" );
+	}
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::GetSubserviceTypesL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::GetSubserviceTypesL( 
+    const TUint aServiceId, 
+    RArray<TCCHSubserviceType>& aSubserviceTypes ) const
+    {
+    TInt index( FindService( aServiceId ) );
+    if ( KErrNotFound != index )
+        {
+        aSubserviceTypes.Reset();
+        for ( TInt i( 0 ); i < iServices[ index ]->SubserviceCount(); i++ )
+            {
+            CCHLOGSTRING2( "    Service contains subservice: %d", 
+                iServices[ index ]->GetSubserviceType( i ) );
+            
+            aSubserviceTypes.Append( 
+                    iServices[ index ]->GetSubserviceType( i ) );
+            }
+        }
+    else
+        {
+        User::Leave( KErrNotFound );
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::SetStartupFlag
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+TInt CCCHServiceHandler::SetStartupFlag(
+    TServiceSelection aSelection,
+    TBool aLoadAtStartUp ) const
+    {
+    TInt exist( FindService( aSelection.iServiceId ) );
+    if ( KErrNotFound != exist )
+        {
+        exist = iServices[ exist ]->SetStartupFlag( 
+            aSelection.iType, aLoadAtStartUp ); 
+        }
+    return exist;
+    }
+
+// ---------------------------------------------------------------------------
+// CCCHServiceHandler::HandleRestartL
+// (other items were commented in a header).
+// ---------------------------------------------------------------------------
+//
+void CCCHServiceHandler::HandleRestartL()
+    {
+    // In restart situation all services and subservices goes to 
+    // disabled state, after restart we will make reregistration 
+    CCHLOGSTRING( "CCHServiceHandler::HandleRestartL() IN" );
+    for ( TInt i( 0 ); i < iServices.Count(); i++ )
+        {
+        for ( TInt j( 0 ); j < iServices[ i ]->SubserviceCount(); j++ )
+            {
+            iServices[ i ]->GetSubserviceL( 
+                iServices[ i ]->GetSubserviceType( j ) ).SetError( KErrCancel );
+            iServices[ i ]->GetSubserviceL( 
+                iServices[ i ]->GetSubserviceType( j ) ).SetState( ECCHDisabled );
+            iServices[ i ]->GetSubserviceL( 
+                iServices[ i ]->GetSubserviceType( j ) ).StatusChanged();
+            }
+        }
+    CCHLOGSTRING( "CCHServiceHandler::HandleRestartL() OUT" );
+    }
+
+// ========================== OTHER EXPORTED FUNCTIONS =======================
+
+//  End of File