diff -r 000000000000 -r ff3b6d0fd310 convergedcallengine/cce/src/ccceplugin.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/convergedcallengine/cce/src/ccceplugin.cpp Tue Feb 02 01:11:09 2010 +0200 @@ -0,0 +1,680 @@ +/* +* 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: Handles plugin +* +*/ + + +// INCLUDE FILES +#include +#include "ccceplugin.h" +#include "cconvergedcallprovider.h" +#include "cccelogger.h" +#include "cccecallcontainer.h" +#include "cccetransfercontroller.h" +#include "mccpcall.h" +#include "mccpcscall.h" +#include "mcceobserver.h" +#include "cccecall.h" +#include "mccecallobserver.h" +#include "ccceconferencecall.h" + +#include "mccpplugindeathobserver.h" +#include "mccpssobserver.h" +#include "mccessobserver.h" +#include "mccptransferprovider.h" +#include "tccecallindex.h" + +#include +#include "mccpdtmfprovider.h" + + + +// ======== MEMBER FUNCTIONS ======== +// ----------------------------------------------------------------------------- +// NewL() +// ----------------------------------------------------------------------------- +// +CCCEPlugin* CCCEPlugin::NewL( const TUid& aPluginUID, + MCCEObserver& aObserver, + CCCECallContainer& aCallContainer, + MCCPPluginDeathObserver& aDeathObserver, + CCCETransferController& aTransferController ) + { + CCCEPlugin* self = new (ELeave) CCCEPlugin( aPluginUID, + aObserver, + aCallContainer, + aDeathObserver, + aTransferController ); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CCCEPluginManager() +// ----------------------------------------------------------------------------- +// +CCCEPlugin::CCCEPlugin( const TUid& aPluginUID, + MCCEObserver& aObserver, + CCCECallContainer& aCallContainer, + MCCPPluginDeathObserver& aDeathObserver, + CCCETransferController& aTransferController ) + : iObserver( aObserver ), + iCallContainer( aCallContainer ), + iTransferController( aTransferController ), + iDeathObserver( aDeathObserver ), + iPluginId( aPluginUID ), + iReleaseWhenIdle( ETrue ) + { + + } + +// ----------------------------------------------------------------------------- +// ConstructL() +// ----------------------------------------------------------------------------- +// +void CCCEPlugin::ConstructL() + { + FeatureManager::InitializeLibL(); + + iPlugin = CConvergedCallProvider::NewL( iPluginId ); + + if(iPlugin) + { + CCELOGSTRING("CCCEPlugin::GetPluginL: Initialize" ); + iPlugin->InitializeL( *this, *this ); + } + } + +// ----------------------------------------------------------------------------- +// ~CCCEPluginManager() +// ----------------------------------------------------------------------------- +// +CCCEPlugin::~CCCEPlugin() + { + delete iPlugin; + FeatureManager::UnInitializeLib(); + } + +// ----------------------------------------------------------------------------- +// Dtmf +// ----------------------------------------------------------------------------- +// +MCCPDTMFProvider& CCCEPlugin::GetDtmfProviderL( + const MCCPDTMFObserver& aObserver ) + { + if( !iDtmfProvider ) + { + iDtmfProvider = iPlugin->DTMFProviderL( aObserver ); + + if( !iDtmfProvider ) + { + CCELOGSTRING("CCCEPlugin::GetDtmfProviderL: Plugin does not support dtmf, leaving with KErrNotSupported" ); + // maybe api should be changed to leave with error code instead of returning null + User::Leave(KErrNotSupported); + } + } + + return *iDtmfProvider; + } + +// ----------------------------------------------------------------------------- +// Return protocol interface object of wanted type. +// ----------------------------------------------------------------------------- +// +CConvergedCallProvider* CCCEPlugin::GetPluginL() const + { + return iPlugin; + } + +// ----------------------------------------------------------------------------- +// Primary emergency call objects are created construct time +// ----------------------------------------------------------------------------- +// +void CCCEPlugin::InitialiseEmergencyCallL(MCCPCallObserver& aEmergencyCallObserver) + { + iEmergencyCall = + iPlugin->NewEmergencyCallL( 0, KNullDesC, aEmergencyCallObserver ); + } + +// ----------------------------------------------------------------------------- +// Get emergency call handle. +// ----------------------------------------------------------------------------- +// +MCCPEmergencyCall* CCCEPlugin::GetEmergencyCall() const + { + return iEmergencyCall; + } + +// --------------------------------------------------------------------------- +// CCCEPlugin::Type() +// --------------------------------------------------------------------------- +// +TUid CCCEPlugin::Type() const + { + return iPluginId; + } + +// --------------------------------------------------------------------------- +// Returns ETrue if plugin can be relesed if idle +// --------------------------------------------------------------------------- +// +TBool CCCEPlugin::ReleaseWhenIdle() + { + return iReleaseWhenIdle; + } + +// --------------------------------------------------------------------------- +// Set ETrue if plugin should stay permanently in memory +// --------------------------------------------------------------------------- +// +void CCCEPlugin::SetReleaseWhenIdle(TBool aReleaseWhenIdle ) + { + iReleaseWhenIdle = aReleaseWhenIdle; + } + +// --------------------------------------------------------------------------- +// From class MCCPCSObserver +// --------------------------------------------------------------------------- +// +void CCCEPlugin::MoCallCreated( MCCPCall& aCall ) + { + CCELOGSTRING("CCCEPlugin::MoCallCreated" ); + + TBool callAllowed = EFalse; + + //CCELOGSTRING2(" cceparams->iCallType = %d", aCall->Parameters().CallType() ); + + callAllowed = ( IsCallAllowed() >= 0 ); + + + CCCECall* call = NULL; + if( callAllowed ) + { + call = iCallContainer.GetNextFreeCall(); + } + + if( call ) + { + TRAPD( error, + call->SetConvergedCallL( &aCall, iPluginId ) ); + + // set observer for the passed call + TRAP_IGNORE( aCall.AddObserverL(*call) ); + + // Error handling + if( error ) + { + CCELOGSTRING( + "CCCEPlugin::MoCallCreated:Canceled" ); + aCall.Cancel(); + call->Release(); + } + else + { + CCELOGSTRING( + "CCCEPlugin::MoCallCreated:Forwarded" ); + // Sets new call index. Normally the call itself + // sets the value, but in the case when external client has + // created the call we need to set it here, because + // the call is already ongoing. + call->SetNewCallIndex(); + iObserver.MOCallCreated( *call ); + } + + } + else + { + CCELOGSTRING( "CCCEPlugin::MoCallCreated:Error, CCECall not found" ); + aCall.Cancel(); + iCallContainer.ReleaseCall( aCall, iPluginId ); + } + } + +// --------------------------------------------------------------------------- +// From class MCCPCSObserver +// CCCEPlugin::DataPortName() +// --------------------------------------------------------------------------- +// +void CCCEPlugin::DataPortName( TName& aPortName ) + { + CCELOGSTRING( "CCCEPlugin::DataPortName" ); + iObserver.DataPortName( aPortName ); + } + +// --------------------------------------------------------------------------- +// From class MCCPCSObserver +// --------------------------------------------------------------------------- +// +void CCCEPlugin::ConferenceCallCreated( MCCPConferenceCall& aConferenceCall ) + { + CCELOGSTRING("CCCEPlugin::ConferenceCallCreated IN" ); + if( !iCallContainer.ConferenceCall().SetOngoingConferenceCall( + aConferenceCall, iPluginId ) ) + { + iObserver.ConferenceCallCreated( iCallContainer.ConferenceCall() ); + } + else + { + iPlugin->ReleaseConferenceCall( aConferenceCall ); + } + + CCELOGSTRING("CCCEPlugin::ConferenceCallCreated OUT" ); + } + +// --------------------------------------------------------------------------- +// CCCEPlugin::IsCallAllowed() +// --------------------------------------------------------------------------- +// +TInt CCCEPlugin::IsCallAllowed() const + { + CCCECall* call; + TInt activeNonConferenceCalls = 0; + CCPCall::TCallState callState; + + for( TInt i = 0; i < KCCECallObjects; i++ ) + { + call = iCallContainer.GetCall( i ); + + if( call->IsInUse() && + !iCallContainer.ConferenceCall().IsPartOfConference( *call ) ) + { + callState = call->State(); + + CCELOGSTRING2( "CCCEPlugin::IsCallAllowed:Active call found: State = %d", + callState ); + + switch( callState ) + { + case CCPCall::EStateQueued: + case CCPCall::EStateRinging: + case CCPCall::EStateConnecting: + { + CCELOGSTRING( "CCCEPlugin::IsCallAllowed: KErrGeneral" ); + // No other calls allowed + } + return KErrGeneral; + case CCPCall::EStateDialling: + { + // Dialling -> Cancel it + // Telephone UI spec: chapter 3.1.4 + call->HangUp(); + } + break; + case CCPCall::EStateDisconnecting: + { + // Disconnecting -> do nothing + } + break; + default: + { + // Active/Hold -> Call can be on waiting state + activeNonConferenceCalls++; + } + break; + } + + if( activeNonConferenceCalls >= KCCEMaxNumberOfCalls ) + { + CCELOGSTRING( "CCCEPlugin::IsCallAllowed: KErrOverflow" ); + return KErrOverflow; + } + + } + } + // In addition to checks made here call should not be allowed + // when emergency call is ongoing. This is done in + // CCCECallContainer::GetNextFreeCall() + + CCELOGSTRING( "CCCEPlugin::IsCallAllowed: ETrue" ); + return activeNonConferenceCalls; + } + +// --------------------------------------------------------------------------- +// CCCEPlugin::IsDataCallAllowed() +// --------------------------------------------------------------------------- +// +TBool CCCEPlugin::IsDataCallAllowed() const + { + CCELOGSTRING( "CCCEPlugin::IsDataCallAllowed()" ); + CCCECall* call = NULL; + TInt callCount = 0; + CCPCall::TCallState callState; + for( TInt i = 0; i < KCCECallObjects; i++ ) + { + call = iCallContainer.GetCall( i ); + callState = call->State(); + if( CCPCall::EStateIdle != callState && + !iCallContainer.ConferenceCall().IsPartOfConference( *call ) ) + { + callCount++; + } + } + + if( iCallContainer.ConferenceCall().State() != + MCCEConferenceCallObserver::ECCEConferenceIdle ) + { + callCount++; + } + + // In addition to checks made here call should not be allowed + // when emergency call is ongoing. This is done in + // CCCECallContainer::GetNextFreeCall() + + CCELOGSTRING2( "CCCEPlugin::IsDataCallAllowed() callCount=%d", callCount ); + // Data call cannot be allowed if there is three or more calls ongoing + return ( callCount < KCCEMaxNumberOfCalls ); + } + +// --------------------------------------------------------------------------- +// From class MCCPObserver +// --------------------------------------------------------------------------- +// +void CCCEPlugin::ErrorOccurred( const TCCPError aError ) + { + CCELOGSTRING2("CCCEPlugin::ErrorOccurred: Error = %d", aError ); + + switch (aError) + { + case ECCPIncomingCallFailed: + { + if( iReleaseWhenIdle ) + { + iDeathObserver.CCPPluginInitialisationFailed(iPluginId, aError); + } + } + break; + case ECCPRegistrationFailed: + { + iDeathObserver.CCPPluginInitialisationFailed(iPluginId, aError); + } + break; + default: + { + CCELOGSTRING("CCCEPlugin::ErrorOccurred: Default"); + } + break; + } + } + +// --------------------------------------------------------------------------- +// From class MCCPObserver +// --------------------------------------------------------------------------- +// +void CCCEPlugin::IncomingCall( MCCPCall* aCall, MCCPCall& aTempCall ) + { + CCELOGSTRING("CCCEPlugin::IncomingCall():IN"); + CCELOGSTRING3(" originalcall: aTempCall=0x%x transfercall: aCall=0x%x", &aTempCall, aCall ); + + if( !aCall || aCall == &aTempCall ) + { + CCELOGSTRING("CCCEPlugin::IncomingCall(MCCPCall*,MCCPCall&) - Error: Invalid parameters!"); + return; + } + + iTransferController.TransferCallIncoming( aCall, &aTempCall ); + CCELOGSTRING("CCCEPlugin::IncomingCall():OUT"); + } + +// --------------------------------------------------------------------------- +// From class MCCPObserver +// --------------------------------------------------------------------------- +// +void CCCEPlugin::IncomingCall( MCCPCall* aCall ) + { + CCELOGSTRING( "CCCEPlugin::IncomingCall" ); + + if( !aCall ) + { + CCELOGSTRING("CCCEPlugin::IncomingCall(MCCPCall*) - Error: incoming call pointer was null!"); + return; + } + + CCCECall* call = NULL; + TInt nonConferenceCalls = IsCallAllowed(); + + if( nonConferenceCalls >= 0 ) + { + call = iCallContainer.GetNextFreeCall(); + } + + if( call ) + { + TRAPD( error, + call->SetConvergedCallL( aCall, iPluginId ) ); + + // Order call to ringing state + // Requires no active calls and conference call must be idle + if( nonConferenceCalls == 0 && + iCallContainer.ConferenceCall().State() == + MCCEConferenceCallObserver::ECCEConferenceIdle ) + { + CCELOGSTRING( "CCCEPlugin::IncomingCall:No active calls" ); + error = aCall->Ringing(); + } + else + { + CCELOGSTRING( "CCCEPlugin::IncomingCall:One active call" ); + error = aCall->Queue(); + } + + // Error handling + if( error ) + { + CCELOGSTRING2( "CCCEPlugin::IncomingCall: Error = %d", error ); + aCall->Reject(); + call->Release(); + } + else + { + CCELOGSTRING( "CCCEPlugin::IncomingCall:No errors occurred-> inform phoneengine" ); + iObserver.IncomingCall( *call ); + } + } + else + { + CCELOGSTRING( "CCCEPlugin::IncomingCall:Error, CCECall not found" ); + aCall->Reject(); + iCallContainer.ReleaseCall( *aCall, iPluginId ); + } + } + +// --------------------------------------------------------------------------- +// From class MCCPObserver +// --------------------------------------------------------------------------- +// +void CCCEPlugin::CallCreated( MCCPCall* aNewTransferCall, + MCCPCall* aOriginator, + TBool aAttented ) + { + CCELOGSTRING2("CCCEPlugin::CallCreated():IN aAttended=%d",aAttented); + CCELOGSTRING3(" TransferCall: aNewTransferCall=0x%x OriginalCall: aOriginator=0x%x", + aNewTransferCall, aOriginator ); + + if ( !aNewTransferCall || aNewTransferCall == aOriginator ) + { + CCELOGSTRING("CCCETransferController::HandleTransferRequest() Error: Invalid parameters!"); + return; + } + + if ( aAttented ) + { + iTransferController.HandleRemoteTransferRequest( aNewTransferCall, + aOriginator, aAttented ); + } + else + { + TInt nonConferenceCalls = IsCallAllowed(); + + if ( nonConferenceCalls == 0 || nonConferenceCalls == 1 ) + { + iTransferController.HandleRemoteTransferRequest( aNewTransferCall, + aOriginator, aAttented ); + } + else + { + // Reject unattended transfer + CCELOGSTRING( "CCCEPlugin::CallCreated(): reject transfer" ); + CCCECall* originator = iCallContainer.GetCall( aOriginator ); + TRAP_IGNORE( aOriginator->TransferProviderL(*originator)->AcceptTransfer(EFalse) ); + iCallContainer.ReleaseCall( *aNewTransferCall ); + } + } + + CCELOGSTRING( "CCCEPlugin::CallCreated():OUT" ); + } + + +// --------------------------------------------------------------------------- +// CCCEPlugin::BarringEventOccurred +// --------------------------------------------------------------------------- +// +void CCCEPlugin::BarringEventOccurred( const MCCPSsObserver::TCCPSsBarringEvent aBarringEvent ) + { + CCELOGSTRING2("CCCEPlugin::BarringEventOccurred():IN event=%d",aBarringEvent ); + + if( iCallContainer.SsObserver() ) + { + // one to one mapping at the moment can be casted directly, change if mapping gets out of sync + iCallContainer.SsObserver()->BarringEventOccurred( + (MCCESsObserver::TCCESsBarringEvent)aBarringEvent ); + } + else + { + CCELOGSTRING( "CCCEPlugin::BarringEventOccurred: Event ignored no observer is set!" ); + } + + CCELOGSTRING( "CCCEPlugin::BarringEventOccurred:OUT" ); + } + + +// --------------------------------------------------------------------------- +// CCCEPlugin::CLIEventOccurred +// --------------------------------------------------------------------------- +// +void CCCEPlugin::CLIEventOccurred( const MCCPSsObserver::TCCPSsCLIEvent aCallLineEvent ) + { + CCELOGSTRING2("CCCEPlugin::CLIEventOccurred():IN event=%d",aCallLineEvent ); + + if( iCallContainer.SsObserver() ) + { + // one to one mapping at the moment can be casted directly, change if mapping gets out of sync + iCallContainer.SsObserver()->CLIEventOccurred( + (MCCESsObserver::TCCESsCLIEvent)aCallLineEvent ); + } + else + { + CCELOGSTRING( "CCCEPlugin::CLIEventOccurred: Event ignored no observer is set!" ); + } + + CCELOGSTRING( "CCCEPlugin::CLIEventOccurred:OUT" ); + } + + +// --------------------------------------------------------------------------- +// CCCEPlugin::BarringEventOccurred +// --------------------------------------------------------------------------- +// +void CCCEPlugin::CallForwardEventOccurred( + const MCCPSsObserver::TCCPSsCallForwardEvent aCallForwardEvent, + const TDesC& aRemoteAddress ) + { + CCELOGSTRING2("CCCEPlugin::CallForwardEventOccurred():IN event=%d",aCallForwardEvent ); + + if( iCallContainer.SsObserver() ) + { + // one to one mapping at the moment can be casted directly, change if mapping gets out of sync + iCallContainer.SsObserver()->CallForwardEventOccurred( + (MCCESsObserver::TCCESsCallForwardEvent)aCallForwardEvent, + aRemoteAddress ); + } + else + { + CCELOGSTRING( "CCCEPlugin::CallForwardEventOccurred: Event ignored no observer is set!" ); + } + + CCELOGSTRING( "CCCEPlugin::CallForwardEventOccurred:OUT" ); + + } + + +// --------------------------------------------------------------------------- +// CCCEPlugin::CallCugEventOccurred +// --------------------------------------------------------------------------- +// +void CCCEPlugin::CallCugEventOccurred( const MCCPSsObserver::TCCPSsCugEvent aCugEvent ) + { + CCELOGSTRING2("CCCEPlugin::CallCugEventOccurred():IN event=%d",aCugEvent ); + + if( iCallContainer.SsObserver() ) + { + // one to one mapping at the moment can be casted directly, change if mapping gets out of sync + iCallContainer.SsObserver()->CallCugEventOccurred( + (MCCESsObserver::TCCESsCugEvent)aCugEvent ); + } + else + { + CCELOGSTRING( "CCCEPlugin::CallCugEventOccurred: Event ignored no observer is set!" ); + } + + CCELOGSTRING( "CCCEPlugin::CallCugEventOccurred:OUT" ); + } + +// --------------------------------------------------------------------------- +// CCCEPlugin::NotifyCurrentActiveALSLine +// --------------------------------------------------------------------------- +// +void CCCEPlugin::NotifyCurrentActiveALSLine( TInt aLine ) + { + CCELOGSTRING2("CCCEPlugin::NotifyCurrentActiveALSLine():IN line=%d",aLine ); + + if( iCallContainer.SsObserver() ) + { + iCallContainer.SsObserver()->NotifyCurrentActiveALSLine(aLine); + } + else + { + CCELOGSTRING( "CCCEPlugin::NotifyCurrentActiveALSLine: Event ignored no observer is set!" ); + } + + CCELOGSTRING( "CCCEPlugin::NotifyCurrentActiveALSLine():OUT" ); + } + +// --------------------------------------------------------------------------- +// CCCEPlugin::IsCsPlugin +// --------------------------------------------------------------------------- +// +TBool CCCEPlugin::IsCsPlugin( MCCPCall& aCall ) + { + TBool isCsPlugin( EFalse ); + if ( FeatureManager::FeatureSupported( KFeatureIdFfVoiceCallContinuity ) ) + { + if ( aCall.Parameters().CallType() != CCPCall::ECallTypePS ) + { + isCsPlugin = ETrue; + } + } + else + { + if( iPluginId == KCSProviderUid ) + { + isCsPlugin = ETrue; + } + } + return isCsPlugin; + } + +// end of file