convergedcallengine/cce/src/cccecallcontainer.cpp
changeset 0 ff3b6d0fd310
child 12 ae8abd0db65c
child 43 7d48bed6ce0c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/convergedcallengine/cce/src/cccecallcontainer.cpp	Tue Feb 02 01:11:09 2010 +0200
@@ -0,0 +1,1369 @@
+/*
+* Copyright (c) 2006-2008 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:  class of call objects
+*
+*/
+
+
+//  INCLUDE FILES
+#include "cccecallcontainer.h"
+#include "mccpcall.h"
+#include "mccpcscall.h"
+#include "mcceobserver.h"
+#include "mccessobserver.h"
+#include "cccecall.h" 
+#include "cccelogger.h"
+#include "ccceutility.h"
+#include "ccceconferencecall.h"
+#include "ccceemergencycall.h"
+#include "cccedtmf.h"
+#include "cccetransfercontroller.h"
+#include "cconvergedcallprovider.h"
+#include "ccceextension.h"
+#include "cccepluginmanager.h"
+#include "cccedurationtimer.h"
+#include "cccecallinfomediator.h"
+
+#include <featmgr.h>
+
+//CONSTANTS
+const TInt KCSServiceId = 1;
+
+// ======== MEMBER FUNCTIONS ========
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CCCECallContainer::CCCECallContainer( MCCEObserver& aObserver ): iMCCEObserver(&aObserver)
+    {
+    // Initialize callinfo call ids
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        iCallInfoCallId[ i ] = KErrNotFound;
+        }
+    
+    }
+
+// ---------------------------------------------------------------------------
+// Construct object
+// ---------------------------------------------------------------------------
+//
+void CCCECallContainer::ConstructL()
+    {
+	FeatureManager::InitializeLibL();
+    iCallStateMediator = CCCECallInfoMediator::NewL( *this );
+    
+    CreateCallDataArraysL();
+ 
+    iTransferController = CCCETransferController::NewL( *this );
+    iPluginManager = CCCEPluginManager::NewL( *this, *iTransferController );
+    iEmergencyCall =  CCCEEmergencyCall::NewL(*this, *iPluginManager);
+    iPluginManager->SetEmergencyCallObserver(*iEmergencyCall);
+    iExtension = CCCEExtension::NewL(*iPluginManager );
+    iConferenceCall = CCCEConferenceCall::NewL( *this, *iPluginManager );
+    if( iMCCEObserver )
+        {
+        iPluginManager->SetObserver(*iMCCEObserver);
+        }
+ 
+    // AirTime Timer
+    iCSDuration = CCCEDurationTimer::NewL();
+    iPSDuration = CCCEDurationTimer::NewL();
+    
+    iIdle = CIdle::NewL( CActive::EPriorityIdle );
+    }
+    
+// ---------------------------------------------------------------------------
+// Default Symbian constructor
+// ---------------------------------------------------------------------------
+//
+CCCECallContainer* CCCECallContainer::NewL( MCCEObserver& aObserver )
+    {
+    CCCECallContainer* self = new( ELeave ) CCCECallContainer(aObserver);
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CCCECallContainer::~CCCECallContainer()
+    {
+    delete iConferenceCall;
+    delete iEmergencyCall;
+    delete iDtmf;
+    delete iExtension;
+    delete iPluginManager;
+    delete iTransferController;
+        
+    if( iCallArray )
+        {
+        iCallArray->ResetAndDestroy();
+        delete iCallArray;
+        }
+    
+    delete iCallStateMediator;
+        
+    iCallstoRelease.Reset();
+    iCallstoRelease.Close();
+    
+    delete iCSDuration;
+    delete iPSDuration;
+    
+    
+    if( iIdle )
+        {
+        iIdle->Cancel();
+        delete iIdle;
+        }
+    FeatureManager::UnInitializeLib();
+    }
+// -----------------------------------------------------------------------------
+// SetObserver()
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::SetObserver( MCCEObserver& aObserver, MCCESsObserver& aSsObserver )
+    {
+    iMCCEObserver = &aObserver;
+    iMCCESsObserver = &aSsObserver;
+    iPluginManager->SetObserver(aObserver );
+    }
+
+// -----------------------------------------------------------------------------
+// Create call objects
+// CS objects are located in the beginning of array and VoIP objects after those
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::CreateCallDataArraysL()
+    {
+    CCCECall* call = NULL;
+    TInt callIndex = 0;
+
+    iCallArray = new ( ELeave ) CArrayPtrFlat<CCCECall>( KCCECallObjects );
+
+    for( callIndex = 0; callIndex < KCCECallObjects; callIndex++ )
+        {
+        call = CCCECall::NewLC( *this, callIndex );
+        iCallArray->AppendL( call );
+        CleanupStack::Pop( call );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Swap PS and CS air duration timers
+// Is called after handover, when call type has changed
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::AirTimeDurationSwap(
+                           const CCPCall::TCallType aNewCallType)
+	{
+    CCELOGSTRING("CCCECallContainer::AirTimeDurationSwap(): IN");
+    
+    CCCECall* call = NULL;
+    TInt calls(0);
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->State() == CCPCall::EStateConnected ||
+             call->State() == CCPCall::EStateHold  )
+            {
+            calls ++;
+            }
+        }
+
+    if( CCPCall::EStateConnected == iEmergencyCall->State() )
+        {
+        calls ++;
+        }
+    
+    if( 1 == calls )
+    	{
+    	// After handover we will have only one active call
+    	// If we have more or less, timer swapping will not happend
+	    if (aNewCallType == CCPCall::ECallTypePS )
+	    	{
+	    	CCELOGSTRING2("CCCECallContainer::AirTimeDurationSwap(): CS Stops, PS restarts from %d",
+	    			iCSDuration->NumberOfBeats() );
+	    	iCSDuration->Stop();
+	    	iPSDuration->RestartAirTimeDuration(iCSDuration->NumberOfBeats());
+	    	iCSDuration->Reset();
+	    	}
+	    else
+	    	{
+	    	CCELOGSTRING2("CCCECallContainer::AirTimeDurationSwap(): PS Stops, CS restarts from %d",
+	    			iPSDuration->NumberOfBeats() );
+	    	iPSDuration->Stop();
+	    	iCSDuration->RestartAirTimeDuration(iPSDuration->NumberOfBeats());
+	    	iPSDuration->Reset();
+	    	}
+    	}
+    CCELOGSTRING("CCCECallContainer::AirTimeDurationSwap(): OUT");
+	}
+	
+// ---------------------------------------------------------------------------
+// AirTimeDurationStop()
+// ---------------------------------------------------------------------------
+//
+void CCCECallContainer::AirTimeDurationStop( CCCECall* /*aCall*/ ) const
+    {
+    CCELOGSTRING("CCCECallContainer::AirTimeDurationStop(): IN");
+    CCCECall* call = NULL;
+    TInt csCalls=0;
+    TInt psCalls=0;
+
+    // Check if any other calls    
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->State() == CCPCall::EStateConnected ||
+             call->State() == CCPCall::EStateHold  )
+            {           
+            if ( IsCsPlugin( call, EFalse ) )
+                {
+                csCalls++;
+                CCELOGSTRING2("   AirTimeDurationStop() csCalls=%d ", csCalls);
+                }
+            // ps call found
+            else
+                {
+                psCalls++;
+                CCELOGSTRING2("   AirTimeDurationStop() psCalls=%d ", psCalls);
+                }
+            }
+        }
+        
+    if( CCPCall::EStateConnected == iEmergencyCall->State() )
+        {
+        if(  CCPCall::ECallTypePS == iEmergencyCall->Parameters().CallType() )
+            {
+            psCalls++;
+            }
+        else
+            {
+            csCalls++;
+            }
+        }
+        
+           
+    // No other cs calls found
+    if( !csCalls )
+        {
+        CCELOGSTRING("   AirTimeDurationStop() stop CS timer");
+        iCSDuration->Stop();
+        }
+           
+    // No other ps calls found
+    if( !psCalls )
+        {
+        CCELOGSTRING("   AirTimeDurationStop() stop PS timer");
+        iPSDuration->Stop();
+        }
+ 
+        
+    CCELOGSTRING("CCCECallContainer::AirTimeDurationStop(): IN");
+    }
+
+// ---------------------------------------------------------------------------
+// AirTimeDurationStart()
+// ---------------------------------------------------------------------------
+//
+void CCCECallContainer::AirTimeDurationStart( CCCECall* /*aCall*/ ) const
+    {
+    CCELOGSTRING("CCCECallContainer::AirTimeDurationStart(): IN");
+    CCCECall* call = NULL;
+    TInt csCalls=0;
+    TInt psCalls=0;
+
+    // Check if any other calls    
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->State() == CCPCall::EStateConnected ||
+             call->State() == CCPCall::EStateHold  )
+            { 	   
+            if ( IsCsPlugin( call, EFalse ) )
+                {
+                csCalls++;
+                CCELOGSTRING2("   AirTimeDurationStart() csCalls=%d ", csCalls);
+                }
+            // ps call found
+            else
+                {
+                psCalls++;
+                CCELOGSTRING2("   AirTimeDurationStart() pscalls=%d ", psCalls);
+                }
+            }
+        }
+        
+    if( CCPCall::EStateConnected == iEmergencyCall->State() )
+        {
+        if(  CCPCall::ECallTypePS == iEmergencyCall->Parameters().CallType() )
+            {
+            psCalls++;
+            }
+        else
+            {
+            csCalls++;
+            }
+        }
+        
+    // No other cs calls found
+    if( csCalls )
+        {
+        iCSDuration->StartAirTimeDuration();
+        }
+    // No other ps calls found
+    if( psCalls )
+        {
+        iPSDuration->StartAirTimeDuration();
+        }
+    CCELOGSTRING("CCCECallContainer::AirTimeDurationStart(): OUT");
+    }
+
+// ---------------------------------------------------------------------------
+// From base class MCCECallArray
+// ---------------------------------------------------------------------------
+//
+MCCECallInfo* CCCECallContainer::EmergencyCallInfo() const
+    {
+    return iEmergencyCall;
+    }
+
+// ---------------------------------------------------------------------------
+// From base class MCCECallArray
+// ---------------------------------------------------------------------------
+//
+MCCECallInfo* CCCECallContainer::CallInfo( TInt aIndex ) const  
+    {
+    return iCallArray->At( aIndex );
+    }
+
+// ---------------------------------------------------------------------------
+// From base class MCCECallArray
+// ---------------------------------------------------------------------------
+//  
+TInt CCCECallContainer::MaxNumberOfCalls() const
+    {
+    return iCallArray->Count();
+    }
+
+// ---------------------------------------------------------------------------
+// Add calls to be removed, and start releasing if not already running
+// ---------------------------------------------------------------------------
+//
+void CCCECallContainer::ScheduleReleaseCall( MCCPCall& aCalltoRemove, const TUid aUid )
+    {
+    TCallReleaseEntry entry;
+    entry.iCallToRelease = &aCalltoRemove;
+    entry.iUid = aUid;
+    iCallstoRelease.Append(entry);
+    if (!iIdle->IsActive())
+        {
+        iIdle->Start( TCallBack(ReleaseCalls,this) );
+        }
+    }
+
+// ---------------------------------------------------------------------------
+// Callback to CIdle class to actually release calls
+// ---------------------------------------------------------------------------
+// 
+TInt CCCECallContainer::ReleaseCalls( TAny* aCallContainer )
+    {
+    CCCECallContainer* container = 
+        static_cast< CCCECallContainer* >( aCallContainer );
+        container->DoReleaseCalls();
+   
+    return KErrNone;
+    }
+    
+// ---------------------------------------------------------------------------
+// Callback to CIdle class to actually release calls
+// ---------------------------------------------------------------------------
+//     
+void CCCECallContainer::DoReleaseCalls()
+    {
+    CCELOGSTRING("CCCECallContainer::DoReleaseCalls()")
+    while( iCallstoRelease.Count() > 0 )
+        {
+        CConvergedCallProvider* plugin = NULL;
+        TUid pluginUid = iCallstoRelease[0].iUid;
+        TRAP_IGNORE( plugin = iPluginManager->GetPluginL( pluginUid ) );
+        if( plugin )
+            {
+            // release call
+            plugin->ReleaseCall( *iCallstoRelease[0].iCallToRelease );
+            
+            // first check can we indicate plugin release
+            if( !iEmergencyCall->IsInProgress() &&
+                iPluginManager->ReleaseWhenIdle( pluginUid ) &&
+                pluginUid != iConferenceCall->ImplementationUid() )
+                {
+                // 2nd step
+                if( 0 == CountCalls( pluginUid ) )
+                    {
+                    TBool releasePlugin = ETrue;
+                    // and last test
+                    if( 1 < iCallstoRelease.Count() )
+                        {
+                        for( TInt a = 1; a < iCallstoRelease.Count(); a++ )
+                            {
+                            if( iCallstoRelease[a].iUid == pluginUid )
+                                {
+                                releasePlugin = EFalse;
+                                }
+                            }
+                        }
+                    
+                    if( releasePlugin )
+                        {
+                        iPluginManager->RemovePlugin( pluginUid );
+                        }
+                    }
+                }
+            }
+        iCallstoRelease.Remove(0);
+        }
+  
+    };
+
+// ---------------------------------------------------------------------------
+// ConferenceCallL()
+// ---------------------------------------------------------------------------
+//
+CCCEConferenceCall& CCCECallContainer::ConferenceCallL( 
+    const MCCEConferenceCallObserver& aObserver )
+    {
+    if( iConferenceCall )
+        {
+        iConferenceCall->SetObserver( 
+            const_cast<MCCEConferenceCallObserver&>( aObserver ) );
+        }
+    else
+        {
+        iConferenceCall = CCCEConferenceCall::NewL( *this, *iPluginManager );
+        iConferenceCall->SetObserver( 
+            const_cast<MCCEConferenceCallObserver&>( aObserver ) );
+        }
+    return *iConferenceCall;
+    }
+
+// ---------------------------------------------------------------------------
+// ConferenceCall()
+// ---------------------------------------------------------------------------
+//
+CCCEConferenceCall& CCCECallContainer::ConferenceCall() const
+    {
+    return *iConferenceCall;
+    }
+
+// ---------------------------------------------------------------------------
+// DtmfInterfaceL()
+// ---------------------------------------------------------------------------
+//
+CCCEDtmf& CCCECallContainer::DtmfInterfaceL( 
+    const MCCEDtmfObserver& aObserver )
+    {
+    if( iDtmf )
+        {
+        iDtmf->SetObserver( aObserver );
+        }
+    else
+        {
+        iDtmf = CCCEDtmf::NewL( *this, *iPluginManager );
+        iDtmf->AddObserverL( aObserver );
+        }
+    return *iDtmf;
+    }
+
+// ---------------------------------------------------------------------------
+// ExtensionInterfaceL()
+// ---------------------------------------------------------------------------
+// 
+
+MCCEExtensionInterface& CCCECallContainer::ExtensionInterfaceL(
+        const MCCEExtensionObserver& aObserver )
+    {
+    if( iExtension )
+        {
+        iExtension->AddObserverL( aObserver );
+        }
+    else
+        {
+        iExtension = CCCEExtension::NewL(*iPluginManager );
+        iExtension->AddObserverL( aObserver ); 
+        }
+    return *iExtension;
+    }
+  
+// ---------------------------------------------------------------------------
+// GetNextFreeCall()
+// ---------------------------------------------------------------------------
+//
+CCCECall* CCCECallContainer::GetNextFreeCall() const
+    {
+    CCCECall* call = NULL;
+    if ( !iEmergencyCall->IsInProgress())
+        {
+        for (TInt i = 0; i < KCCECallObjects; i++ )
+            {
+            call = GetCall( i );
+
+            if ( !call->IsInUse() )
+                {
+                CCELOGSTRING("CCCE::GetNextFreeCall: Call found");
+                break;
+                }
+            }
+        }
+  
+    return call;
+    }
+  
+// ---------------------------------------------------------------------------
+// GetCall()
+// ---------------------------------------------------------------------------
+//
+CCCECall* CCCECallContainer::GetCall( CCPCall::TCallState aCallState, 
+    CCCECall* aSkippedCall ) const
+    {
+    CCCECall* call = NULL;
+    CCPCall::TCallState callState = CCPCall::EStateIdle;
+
+    for (TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+
+        // Skip given call
+        if ( call == aSkippedCall )
+            {
+            continue;
+            }
+
+
+        callState = call->State();
+        if ( callState == aCallState )
+            {
+            return call;
+            }
+
+        }
+
+    return NULL;
+    }
+
+// -----------------------------------------------------------------------------
+// Open new MCCP call and bind it to MCCECall
+// -----------------------------------------------------------------------------
+//
+ MCCECall& CCCECallContainer::OpenNewCallL(
+    const TDesC&                        aNumber,
+    const CCCECallParameters& aCallParameters,
+    const MCCECallObserver&             aCallObserver )
+    {
+    CCCECall* call = GetNextFreeCall();
+    
+    if(call)
+        {
+        CleanupReleasePushL( *call );
+        
+        MCCPCall* convergedCall = NULL;
+        // This block could be put to own method in transfercontroller
+        if( iTransferController->TransferCall() &&
+            CCCETransferController::ECCETypeUnattended == 
+            iTransferController->OngoingTransferType() && 
+            aNumber == iTransferController->TransferCall()->RemoteParty() )
+            {
+            CCELOGSTRING("CCCE::OpenNewCallL: Use transfer call");
+            convergedCall = iTransferController->TransferCall();        
+            // For MO transfer call observer needs to be set 
+            convergedCall->AddObserverL( *call );
+            call->SetTransferController( iTransferController ); 
+            
+            convergedCall->SetParameters( aCallParameters );
+            }
+        else
+            {
+            CCELOGSTRING2("CCCE::OpenNewCallL: ServiceId = %d", aCallParameters.ServiceId() );
+            CConvergedCallProvider* plugin = 
+                iPluginManager->GetPluginL( aCallParameters.ServiceId() );
+            convergedCall = plugin->NewCallL(aCallParameters, aNumber, *call);
+            }
+        
+        if(convergedCall)
+            {
+            CCELOGSTRING("CCCE::OpenNewCallL: Set converged call to engine call");
+            call->SetConvergedCallL( convergedCall, convergedCall->Uid() );
+            call->SetObserver( aCallObserver );
+            
+            CCELOGSTRING("CCCE::OpenNewCallL():OUT");
+            }
+        else
+            {
+            CCELOGSTRING("CCCE::OpenNewCallL():No converged call:OUT");
+            User::Leave( KErrGeneral );
+            }
+        CleanupStack::Pop( call );
+        }
+    else
+        {
+        CCELOGSTRING("CCCE::OpenNewCallL():No call:OUT");
+        User::Leave( KErrGeneral );
+        }
+
+    return *call;
+    }
+// -----------------------------------------------------------------------------
+// ReleaseCall
+// -----------------------------------------------------------------------------
+//
+TInt CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRelease, const TUid aUid )
+    {
+    
+    CCELOGSTRING("CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRemove, const TUid aUid )");
+    ScheduleReleaseCall(aCalltoRelease,aUid);
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// ReleaseCall
+// -----------------------------------------------------------------------------
+//
+TInt CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRelease)
+    {
+    CCELOGSTRING("CCCECallContainer::ReleaseCall( MCCPCall& aCalltoRelease )");
+    TUid pluginUid = aCalltoRelease.Uid();
+    return ReleaseCall(aCalltoRelease, pluginUid);
+    }
+
+// -----------------------------------------------------------------------------
+// Get emergencycall
+// -----------------------------------------------------------------------------
+//
+ MCCECall& CCCECallContainer::EmergencyCall( const MCCECallObserver& aCallObserver )
+    {
+    iEmergencyCall->SetObserver(aCallObserver);
+    return *iEmergencyCall;
+    }
+
+// -----------------------------------------------------------------------------
+// Get call object by call MCCPCall 
+// -----------------------------------------------------------------------------
+//
+CCCECall* CCCECallContainer::GetCall( const MCCPCall* aMCCPCall ) const
+    {
+    CCCECall* call = NULL;
+    
+    for( TInt i = 0; i < iCallArray->Count(); i++ )
+        {        
+        call = iCallArray->At(i);
+        
+        if( aMCCPCall == &call->GetCCPCall() )
+            {
+            CCELOGSTRING("CCCECallContainer::GetCall: Call found");
+            break;
+            }
+            
+        call = NULL;
+        }
+    
+    return call;
+    }    
+
+// ---------------------------------------------------------------------------
+// GetCall()
+// ---------------------------------------------------------------------------
+//
+TInt CCCECallContainer::GetCall( TUid aImplementationUid, 
+    RPointerArray<CCCECall>& aCallArray ) const
+    {
+    CCCECall* call = NULL;
+
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->IsInUse() )
+            {
+            if( call->ImplementationUid() == aImplementationUid )
+                {
+                aCallArray.Append(call);
+                }
+            }
+        }
+
+    return aCallArray.Count();
+    }
+
+// ---------------------------------------------------------------------------
+// IsAnyActiveOrConnectingCall()
+// ---------------------------------------------------------------------------
+//
+TInt CCCECallContainer::GetActiveOrConnectingCalls(
+    RPointerArray<MCCECallInfo>& aCallArray ) const
+    {
+    CCPCall::TCallState callState = CCPCall::EStateIdle;
+    CCCECall* call = NULL;
+    TInt err = KErrNotFound;
+    TInt i = 0;
+
+    for ( i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->IsInUse() )
+            {
+            callState = call->State();
+            if ( callState == CCPCall::EStateDialling ||
+                 callState == CCPCall::EStateConnecting ||
+                 callState == CCPCall::EStateConnected )
+                {
+                aCallArray.Append( call );
+                err = KErrNone;
+                }
+            }
+        }
+    
+    if( iEmergencyCall->IsInProgress() )
+        {
+        callState = iEmergencyCall->State();
+        if ( callState == CCPCall::EStateDialling ||
+             callState == CCPCall::EStateConnecting ||
+             callState == CCPCall::EStateConnected )
+            {
+            aCallArray.Append( iEmergencyCall );
+            err = KErrNone;
+            }
+        }
+        
+    return err;
+    }
+
+// ---------------------------------------------------------------------------
+// IsAnyActiveOrConnectingCall()
+// ---------------------------------------------------------------------------
+//
+TInt CCCECallContainer::CountCalls( TUid aImplementationUid ) const
+    {
+    CCCECall* call = NULL;
+    TInt i = 0;
+    TInt count=0;
+    
+    for ( i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->IsInUse() )
+            {
+            if( call->ImplementationUid() == aImplementationUid )
+                {
+                count++;
+                }
+            }
+        }
+
+    if( iEmergencyCall->IsInProgress() )
+        {
+        if( iEmergencyCall->ImplementationUid() == aImplementationUid )
+            {
+            count++;
+            }
+        }
+    
+    return count;
+    }
+
+// ---------------------------------------------------------------------------
+// CountCsCalls()
+// ---------------------------------------------------------------------------
+//
+TInt CCCECallContainer::CountCsCalls( TUid aImplementationUid ) const
+    {
+    TInt count=0;
+    CCCECall* call = NULL;
+    TInt i = 0;
+        
+    for ( i = 0; i < KCCECallObjects; i++ )
+        {
+        call = GetCall( i );
+        if ( call->IsInUse() )
+            {
+            if( call->ImplementationUid() == aImplementationUid && 
+              ( call->Parameters().CallType() !=  CCPCall::ECallTypePS ) )
+                {
+                count++;
+                }
+            }
+        }
+    
+    return count;
+    }
+
+// ---------------------------------------------------------------------------
+// GetCallWithActiveRequest()
+// ---------------------------------------------------------------------------
+//
+CCCECall* CCCECallContainer::GetCallWithActiveRequest( CCCECall* aCall ) const
+    {
+    CCCECall* call = NULL;
+    for( TInt i = 0; i < iCallArray->Count(); i++ )
+        {        
+
+        if( CCCECall::ECCENone != iCallArray->At(i)->Request() )
+            {
+            CCELOGSTRING( "CCCECallContainer::GetCallWithRequest: Call found" );
+            if( iCallArray->At(i) != aCall )
+                {
+                call = iCallArray->At(i);
+                }
+            }
+        }
+
+    return call;
+    }
+
+// ---------------------------------------------------------------------------
+// GetNonConferenceCall()
+// ---------------------------------------------------------------------------
+//
+CCCECall* CCCECallContainer::GetNonConferenceCall() const
+    {
+    CCCECall* call = NULL;
+    for( TInt i = 0; i < iCallArray->Count(); i++ )
+        {        
+        if( iCallArray->At(i)->IsInUse() )
+            {
+            if( !iConferenceCall->IsPartOfConference( *iCallArray->At(i) ) )
+                {
+                CCELOGSTRING( "CCCECallContainer::GetNonConferenceCall: Call found" );
+                call = iCallArray->At(i);
+                break;
+                }
+            }
+        }
+
+    return call;
+    }
+    
+// -----------------------------------------------------------------------------
+// Handle Conference status changes.
+// If dial was pending for hold and hold is received, continue dial.
+// -----------------------------------------------------------------------------
+//
+
+void CCCECallContainer::HandleConferenceStatusChange( 
+        MCCEConferenceCallObserver::TCCEConferenceCallState aStatus )
+    {
+  
+    CCELOGSTRING2("CCCECallContainer::HandleConferenceStatusChange: %d", aStatus );    
+    CCCECall* callWithRequest = GetCallWithActiveRequest( NULL );
+
+    switch ( aStatus )
+        {
+        case MCCEConferenceCallObserver::ECCEConferenceIdle:
+            if ( callWithRequest &&
+                 callWithRequest->Request() == CCCECall::ECCEReplaceActive &&
+                 !GetCall( CCPCall::EStateConnected, callWithRequest ) )
+                {
+                callWithRequest->DoPendingRequest();
+                }
+            break;
+        
+        case MCCEConferenceCallObserver::ECCEConferenceHold:
+            if( iConferenceCall->EnumerateCalls() != 0 )
+                {
+                // Swap 1/2 point ( two calls in hold ) if there isnt connected call allready
+                CCCECall* call = GetNonConferenceCall();
+                if( call && 
+                    call->State() == CCPCall::EStateHold )
+                    {
+                    if( call->ImplementationUid() == KCSProviderUid && 
+                        iConferenceCall->ImplementationUid() == KCSProviderUid )
+                        {
+                        // If there is two cs calls do nothing
+                        }
+                    else
+                        {
+                        call->ResumeNoNotify();
+                        }
+
+                    break;
+                    }
+                
+                // Answer new call when one(ringing) ongoing
+                // Answer new call when one(queued) ongoing
+                // Dial new call when one ongoing
+                if( callWithRequest )
+                    {
+                    callWithRequest->DoPendingRequest();
+                    }
+                }
+            break;
+        case MCCEConferenceCallObserver::ECCEConferenceActive:
+        
+            // Swap completed
+            if( callWithRequest )
+                {
+                callWithRequest->RequestComplete( ECCPErrorNone );
+                }
+        default:
+            break;
+
+        }       
+    }
+
+// -----------------------------------------------------------------------------
+// Updates the call information API clients.
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::HandleEmergencyCallStatusChange(
+    CCECallEnums::TNotifyType aNotify )
+    {
+    CCELOGSTRING("CCCECallContainer::HandleEmergencyCallStatusChange(): IN");
+    if ( aNotify != CCECallEnums::ENoNotify )
+        {
+        iCallStateMediator->UpdateCallInfos();
+        }
+    CCELOGSTRING("CCCECallContainer::HandleEmergencyCallStatusChange(): OUT");
+    }
+
+// -----------------------------------------------------------------------------
+// Handle call status changes.
+// If dial was pending for hold and hold is received, continue dial.
+// If swap is active, and hold was received for wanted object, start resume other call
+// If swap is active, and resume was received for wanted call, complete swap request
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::HandleCallStatusChange( 
+    CCPCall::TCallState aState, 
+    CCCECall* aCall,
+    CCECallEnums::TNotifyType aNotify )
+    {
+    CCELOGSTRING( "CCCECallContainer::HandleCallStatusChange(): IN" );
+    CCCECall* call = NULL;
+    TInt error = KErrNone;
+    CCCECall* callWithRequest = GetCallWithActiveRequest( aCall );
+
+    switch ( aState )
+        {
+        case CCPCall::EStateConnected:
+            AirTimeDurationStart( aCall );
+        
+            // Swap completed
+            if( callWithRequest )
+                {
+                callWithRequest->RequestComplete( ECCPErrorNone );
+                }
+            break;
+
+        case CCPCall::EStateIdle:
+            AirTimeDurationStop( aCall );
+            
+            if ( callWithRequest &&
+                callWithRequest->Request() == CCCECall::ECCEReplaceActive &&
+                !iConferenceCall->IsPartOfConference( *aCall ) &&
+                !GetCall( CCPCall::EStateConnected, aCall ) )
+                {
+                error = callWithRequest->DoPendingRequest();
+                }
+            break;
+            
+        case CCPCall::EStateHold:
+            // Check if there is conference call
+            if( iConferenceCall->EnumerateCalls() != 0 )
+                {
+                // Do nothing when there is only cscalls
+
+                if ( IsCsPlugin( aCall, ETrue ) )
+                	{
+                	
+                    break;
+                    }
+                    
+                // If call or conferencecall isn`t cscall then do conference swap
+                if( iConferenceCall->State() == MCCEConferenceCallObserver::ECCEConferenceHold &&
+                        !iConferenceCall->IsPartOfConference( *aCall ) )
+                    {
+                    iConferenceCall->Swap();
+                    }
+                break;
+                }
+        
+            // Swap 1/2 point ( two calls in hold ) if there isnt connected call allready
+            call = GetCall( CCPCall::EStateHold, aCall );
+            if( call && !GetCall( CCPCall::EStateConnected, aCall ) )
+                {
+                
+                if ( IsCsPlugin( call, EFalse ) && IsCsPlugin( aCall, EFalse ) )
+                    {
+                    // If there is two cs calls do nothing
+                    }
+                else
+                    {
+                    error = call->ResumeNoNotify();
+                    }
+
+                break;
+                }
+
+            // Answer new call when one(ringing) ongoing
+            // Answer new call when one(queued) ongoing
+            // Dial new call when one ongoing. NOTICE: Idle!
+            if( callWithRequest )
+                {
+                error = callWithRequest->DoPendingRequest();
+                }
+            break;
+
+        default:
+            CCELOGSTRING2("CCCECallContainer::HandleCallStatusChange: \
+                Unhandled state = %d", aState );
+            break;
+        }
+        
+    if( error != KErrNone )
+        {
+        // Do some error handling
+        }
+    if ( aNotify != CCECallEnums::ENoNotify )
+        {
+        iCallStateMediator->UpdateCallInfos();
+        }
+    CCELOGSTRING( "CCCECallContainer::HandleCallStatusChange(): OUT" );
+    }
+
+// -----------------------------------------------------------------------------
+// contained call has failed
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::ErrorOccurred( CCCECall* aCall, TCCPError aError )
+    {
+    
+    CCCECall* callWithRequest = GetCallWithActiveRequest( aCall );
+    if( callWithRequest )
+        {
+        // When swap fails try to resume call with request
+        if( callWithRequest->Request() == CCCECall::ECCESwap && 
+            aCall != callWithRequest && 
+            !GetCall( CCPCall::EStateConnected, NULL ) )
+            {
+            callWithRequest->ResumeNoNotify();
+            }
+        if( aError == ECCPLocalHoldFail && 
+            callWithRequest->Request() == CCCECall::ECCEDial &&
+            CCPCall::ECallTypePS != callWithRequest->Parameters().CallType() )
+            {
+            callWithRequest->RequestComplete( ECCPErrorAlreadyInUse );
+            }
+        else
+            {
+            callWithRequest->RequestComplete( aError );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Search for first available callinfo call id and save it to array.
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::ReserveCallInfoCallId( TInt aCallId )
+    {
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        if ( KErrNotFound == iCallInfoCallId[ i ] )
+            {
+            iCallInfoCallId[ i ] = aCallId;
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Release call's call id.
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::ReleaseCallInfoCallId( TInt aCallId )
+    {
+    // Clear CallInfoCallId from array.
+    for ( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        if ( iCallInfoCallId[ i ] == aCallId )
+            {
+            iCallInfoCallId[ i ] = KErrNotFound;
+            break;
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Get call object by call id
+// -----------------------------------------------------------------------------
+//
+CCCECall* CCCECallContainer::GetCall( TInt aCallId ) const
+    {
+    if(iCallArray->Count()>aCallId)
+        {
+        return iCallArray->At( aCallId );
+        }
+    else
+        {
+        return NULL;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Get call durations
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::GetAirTimeDuration( TTimeIntervalSeconds& aCSDuration, 
+        TTimeIntervalSeconds& aPSDuration)
+    {
+    CCELOGSTRING("CCCECallContainer::GetAirTimeDuration()");
+    aCSDuration = iCSDuration->NumberOfBeats();
+    aPSDuration = iPSDuration->NumberOfBeats();
+    }
+    
+// -----------------------------------------------------------------------------
+// TerminateAllButRingingAndQueuedCalls
+// -----------------------------------------------------------------------------
+//    
+void CCCECallContainer::TerminateAllButRingingAndQueuedCalls()
+    {
+    CCELOGSTRING("CCCECallContainer::TerminateAllButRingingAndQueuedCalls():IN");
+    
+    for( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        CCCECall* call = GetCall( i );
+        if( call->IsInUse() && 
+            call->State() != CCPCall::EStateQueued && 
+            call->State() != CCPCall::EStateRinging &&
+            !iConferenceCall->IsPartOfConference( *call ) )
+            {
+            // Quiet hangup
+            switch( call->State() )
+                {
+                case CCPCall::EStateDialling:
+                    call->GetCCPCall().Cancel();
+                    break;
+                case CCPCall::EStateAnswering:
+                    call->GetCCPCall().Reject();
+                    break;
+                default:
+                    call->GetCCPCall().HangUp();
+                    break;
+                }
+            
+            }
+        }
+
+    if( iConferenceCall->EnumerateCalls() )
+        {
+        iConferenceCall->HangUp();
+        }
+
+        
+    CCELOGSTRING("CCCECallContainer::TerminateAllButRingingAndQueuedCalls():OUT");
+    }
+// -----------------------------------------------------------------------------
+// TerminateAllCalls
+// -----------------------------------------------------------------------------
+//    
+void CCCECallContainer::TerminateAllCalls()
+    {
+    CCELOGSTRING("CCCECallContainer::TerminateAllCalls():IN");
+    
+    for( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        CCCECall* call = GetCall( i );
+        
+        if( call->IsInUse() && 
+            !iConferenceCall->IsPartOfConference( *call ) )
+            {
+            // Quiet hangup
+            switch( call->State() )
+                {
+                case CCPCall::EStateDialling:
+                    call->GetCCPCall().Cancel();
+                    break;
+                case CCPCall::EStateAnswering:
+                case CCPCall::EStateRinging:
+                case CCPCall::EStateQueued:
+                    call->GetCCPCall().Reject();
+                    break;
+                default:
+                    call->GetCCPCall().HangUp();
+                    break;
+                }
+            }
+        
+        }
+
+    if( iConferenceCall->EnumerateCalls() )
+        {
+        iConferenceCall->HangUp();
+        }
+
+    CCELOGSTRING("CCCECallContainer::TerminateAllCalls():OUT");
+    }
+
+// -----------------------------------------------------------------------------
+// TerminateAllVoIPCalls
+// -----------------------------------------------------------------------------
+//
+void CCCECallContainer::TerminateAllVoIPCalls()
+    {
+    CCELOGSTRING("CCCECallContainer::TerminateAllVoIPCalls():IN");
+
+    for( TInt i = 0; i < KCCECallObjects; i++ )
+        {
+        CCCECall* call = GetCall( i );
+        
+        //Only VoIP calls are terminated
+        if( call->IsInUse() && 
+                !iConferenceCall->IsPartOfConference( *call ) && 
+                !IsCsPlugin( call, ETrue ) )
+            {
+            // Quiet hangup
+            switch( call->State() )
+                {
+                case CCPCall::EStateDialling:
+                    call->GetCCPCall().Cancel();
+                    break;
+                case CCPCall::EStateAnswering:
+                case CCPCall::EStateRinging:
+                case CCPCall::EStateQueued:
+                    call->GetCCPCall().Reject();
+                    break;
+                default:
+                    call->GetCCPCall().HangUp();
+                    break;
+                }
+            }
+
+        }
+    
+    //Hang up VoIP conference
+    if( iConferenceCall->EnumerateCalls() &&
+            iConferenceCall->Parameters().CallType() == 
+            CCPCall::ECallTypePS )
+        {
+        iConferenceCall->HangUp();
+        }
+
+    CCELOGSTRING("CCCECallContainer::TerminateAllVoIPCalls():OUT");
+    }
+
+// -----------------------------------------------------------------------------
+// Return CCE observer
+// -----------------------------------------------------------------------------
+//    
+MCCEObserver* CCCECallContainer::CCEObserver()
+    {
+    return iMCCEObserver;
+    }
+
+// -----------------------------------------------------------------------------
+// Return ss observer
+// -----------------------------------------------------------------------------
+//    
+MCCESsObserver* CCCECallContainer::SsObserver()
+    {
+    return iMCCESsObserver;
+    }
+
+
+
+// -----------------------------------------------------------------------------
+// GetLifeTime()
+// -----------------------------------------------------------------------------
+// 
+TBool CCCECallContainer::GetLifeTime( TDes8& aLifeTimeInfo )
+	{
+    CCELOGSTRING("CCCE::GetLifeTime()");
+    
+	CConvergedCallProvider* plugin = NULL;
+	
+    TRAP_IGNORE( plugin = iPluginManager->GetPluginL(KCSServiceId));
+    
+    if( plugin )
+    	{
+    	plugin->GetLifeTime(aLifeTimeInfo);
+    	}
+	else
+		{
+    	CCELOGSTRING("CCCE::GetLifeTime() - CS plugin not found!");
+    	return EFalse;
+		}
+
+   	return ETrue;
+    }
+
+// -----------------------------------------------------------------------------
+// GetCSInfo()
+// -----------------------------------------------------------------------------
+// 
+TBool CCCECallContainer::GetCSInfo( CSInfo& aCSInfo )
+	{
+    CCELOGSTRING("CCCE::GetCSInfo()");
+
+	CConvergedCallProvider* plugin = NULL;
+	
+	TRAP_IGNORE( plugin = iPluginManager->GetPluginL(KCSServiceId));
+        
+    
+    if( plugin )
+    	{
+    	plugin->GetCSInfo(aCSInfo);
+    	}
+	else
+		{
+    	CCELOGSTRING("CCCE::GetCSInfo() - CS plugin not found!");
+    	return EFalse;
+		}
+
+   	return ETrue;
+	}
+
+// ---------------------------------------------------------------------------
+// CCCECallContainer::IsCsPlugin
+// ---------------------------------------------------------------------------
+//
+TBool CCCECallContainer::IsCsPlugin(CCCECall* aCall, TBool aConference ) const
+    {
+    TBool isCsPlugin( EFalse );
+    if ( FeatureManager::FeatureSupported( KFeatureIdFfVoiceCallContinuity ) )
+        {
+        if ( aCall->Parameters().CallType() != 
+                CCPCall::ECallTypePS )
+            {
+            isCsPlugin = ETrue;
+            if( aConference &&
+                iConferenceCall->Parameters().CallType() == 
+                    CCPCall::ECallTypePS )
+                {
+                isCsPlugin = EFalse;
+                }
+            }
+        }
+    else
+        {
+        if( aCall->ImplementationUid() == KCSProviderUid )
+            {
+            isCsPlugin = ETrue;
+            }
+        }
+    return isCsPlugin;
+    }
+
+
+//end of file