diff -r 000000000000 -r ff3b6d0fd310 convergedcallengine/cce/src/cccepluginmanager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/convergedcallengine/cce/src/cccepluginmanager.cpp Tue Feb 02 01:11:09 2010 +0200 @@ -0,0 +1,703 @@ +/* +* Copyright (c) 2006-2007 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: Handles plugins / threads +* +*/ + + +// INCLUDE FILES +#include "cccepluginmanager.h" +#include "mccedtmfobserver.h" +#include "ccceplugin.h" +#include "cccelogger.h" +#include "cccecallcontainer.h" +#include "ccceemergencycall.h" +#include "cccecall.h" +#include "mccpdtmfprovider.h" +#include "cconvergedcallprovider.h" +#include "icmapi.h" +#include "cccespsettingshandler.h" + + + +// ======== MEMBER FUNCTIONS ======== +// ----------------------------------------------------------------------------- +// NewL() +// ----------------------------------------------------------------------------- +// +CCCEPluginManager* CCCEPluginManager::NewL( + CCCECallContainer& aCallContainer, + CCCETransferController& aTransferController ) + { + CCCEPluginManager* self = new (ELeave) CCCEPluginManager( + aCallContainer, + aTransferController ); + + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +// ----------------------------------------------------------------------------- +// CCCEPluginManager() +// ----------------------------------------------------------------------------- +// +CCCEPluginManager::CCCEPluginManager( + CCCECallContainer& aCallContainer, + CCCETransferController& aTransferController ) : + CActive( EPriorityStandard ), + iCallContainer( aCallContainer ), + iTransferController( aTransferController ) + { + iPluginArray.Reset(); + } + +// ----------------------------------------------------------------------------- +// ConstructL() +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::ConstructL() + { +#if 0 +// capabilities still todo here + + static _LIT_SECURITY_POLICY_PASS( KAllowAllPolicy ); + static _LIT_SECURITY_POLICY_C2( KICMPolicy, + ECapabilityNetworkControl, + ECapabilityWriteDeviceData); + + + // define first property to be integer type + TInt err = RProperty::Define( KPSUidICMIncomingCall, + KPropertyKeyICMPluginUID, RProperty::EInt, KAllowAllPolicy, KICMPolicy ); +#else + // define first property to be integer type + TInt err = RProperty::Define( KPSUidICMIncomingCall, + KPropertyKeyICMPluginUID, RProperty::EInt ); +#endif + + if ( err != KErrAlreadyExists ) + { + User::LeaveIfError( err ); + } + + User::LeaveIfError( iProperty.Attach( KPSUidICMIncomingCall, + KPropertyKeyICMPluginUID ) ); + CActiveScheduler::Add(this); + RunL(); + + iIdle = CIdle::NewL( EPriorityIdle ); + iIdle->Start( TCallBack(DoAfterBoot,this) ); + + iSPSettings = CCCESPSettingsHandler::NewL( *this ); + } + +// ----------------------------------------------------------------------------- +// ~CCCEPluginManager() +// ----------------------------------------------------------------------------- +// +CCCEPluginManager::~CCCEPluginManager() + { + delete iSPSettings; + + if( iIdle ) + { + iIdle->Cancel(); + delete iIdle; + iIdle = NULL; + } + + iPluginArray.ResetAndDestroy(); + iPluginArray.Close(); + + iPluginsToClose.ResetAndDestroy(); + iPluginsToClose.Close(); + + iAlternativeEmergencyPlugins.Reset(); + iAlternativeEmergencyPlugins.Close(); + + Cancel(); + iProperty.Close(); + + REComSession::FinalClose(); + + } + +// ----------------------------------------------------------------------------- +// RunL() +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::RunL() + { + // TODO If there is two calls arriving same time. How ICM can handle it? + + CCELOGSTRING("CCCEPluginManager::RunL()" ); + // resubscribe before processing new value to prevent missing updates + iProperty.Subscribe( iStatus ); + SetActive(); + // property updated, get new value + + TInt keyValue; + if ( iProperty.Get( keyValue ) == KErrNotFound ) + { + // property deleted, do necessary actions here... + } + else + { + if( keyValue ) + { + TUid pluginId = TUid::Uid(keyValue); + + CCELOGSTRING2("CCCEPluginManager::RunL: IncomingCallAPI = %d", + pluginId.iUid ); + // use new value ... + GetPluginL( pluginId ); + } + } + } + +// ----------------------------------------------------------------------------- +// SetObserver() +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::SetObserver( const MCCEObserver& aObserver ) + { + iObserver = &aObserver; + } + +// ----------------------------------------------------------------------------- +// SetObserver() +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::SetEmergencyCallObserver(MCCPCallObserver& aEmergencyCallObserver) + { + iEmergencyCallObserver = &aEmergencyCallObserver; + } + +// ----------------------------------------------------------------------------- +// DoAfterBoot() +// ----------------------------------------------------------------------------- +// +TInt CCCEPluginManager::DoAfterBoot( TAny* aPluginManager ) + { + CCELOGSTRING("CCCEPluginManager::DoAfterBoot()" ); + + CCCEPluginManager* manager = + static_cast< CCCEPluginManager* >( aPluginManager ); + TRAP_IGNORE(manager->LoadBootPluginsL()); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// Remove unneeded plug-ins +// ----------------------------------------------------------------------------- +// +TInt CCCEPluginManager::RemovePlugins( TAny* aPluginManager ) + { + CCELOGSTRING("CCCEPluginManager::RemovePlugins()" ); + + CCCEPluginManager* manager = + static_cast< CCCEPluginManager* >( aPluginManager ); + TRAP_IGNORE(manager->iPluginsToClose.ResetAndDestroy()); + + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// ServiceEnabledL +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::ServiceEnabledL( TUid aImplementationUid ) + { + CCELOGSTRING("CCCEPluginManager::ServiceEnabledL" ); + CConvergedCallProvider* provider = GetPluginL( aImplementationUid ); + + if( provider ) + { + CCCEPlugin* plugin( NULL ); + for( TInt i=0; iType(); + + if( oldPlugin.iUid == aImplementationUid.iUid ) + { + plugin = iPluginArray[i]; + // set plugin to stay in memory + plugin->SetReleaseWhenIdle( EFalse ); + i = iPluginArray.Count(); + } + } + } + else + { + User::Leave( KErrGeneral ); + } + } + +// ----------------------------------------------------------------------------- +// ServiceDisabledL +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::ServiceDisabledL( TUid aImplementationUid ) + { + CCELOGSTRING("CCCEPluginManager::ServiceDisabledL" ); + CCCEPlugin* plugin( NULL ); + for( TInt i=0; iType(); + + if( oldPlugin.iUid == aImplementationUid.iUid ) + { + plugin = iPluginArray[i]; + i = iPluginArray.Count(); + } + } + + if( !plugin ) + { + CCELOGSTRING("CCCEPluginManager:: No plugin found" ); + User::Leave( KErrNotFound ); + } + else if( iCallContainer.CountCalls( aImplementationUid ) ) + { + CCELOGSTRING("CCCEPluginManager:: Plugin found with ongoing calls" ); + plugin->SetReleaseWhenIdle( ETrue ); + } + else + { + CCELOGSTRING("CCCEPluginManager:: Plugin found" ); + plugin->SetReleaseWhenIdle( ETrue ); + RemovePlugin( aImplementationUid ); + } + } + +// ----------------------------------------------------------------------------- +// Load EBootstrapCallProvider marked or enabled plugins +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::LoadBootPluginsL() + { + //List implementations +#ifdef _DEBUG + RImplInfoPtrArray implementations; + CConvergedCallProvider::ListImplementationsL(implementations); + CCELOGSTRING2("CCCEPluginManager::GetPluginL: %d Implementation(s) found", + implementations.Count() ); + + for( TInt i=0; iImplementationUid().iUid, &info->DisplayName() ); + CCELOGSTRING3("CCCEPluginManager::GetPluginL: ->RomBased = %d, RomOnly = %d", + info->RomBased(), info->RomOnly() ); + } + + implementations.ResetAndDestroy(); + implementations.Close(); +#endif // _DEBUG + + RIdArray serviceIDArray; + CleanupClosePushL( serviceIDArray ); + iSPSettings->GetServicesL( serviceIDArray ); + const TInt serviceCount = serviceIDArray.Count(); + iPrimaryEmergencyCallPlugin = NULL; + TInt err = KErrNone; + + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginsL: Service count: %d", serviceCount ); + for( TInt service = 0; service < serviceCount; service++ ) + { + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginsL: Processing service: %d", service ); + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginsL: ServiceID: %d", serviceIDArray[service] ); + + TRAP( err, LoadBootPluginL( serviceIDArray[service] ) ) + + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginsL: Result %i", err ); + } + + CleanupStack::PopAndDestroy(); + } + +// ----------------------------------------------------------------------------- +// Load EBootstrapCallProvider marked or enabled plugin +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::LoadBootPluginL( TInt aServiceId ) + { + const TUid id = iSPSettings->ImplementationUidL( aServiceId ); + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginL: Plugin id: %i", id ); + + const TInt mask = iSPSettings->CapabilitiesL( aServiceId ); + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginL: Service mask: %d", mask ); + + const TBool enabled = iSPSettings->IsEnabledL( aServiceId ); + CCELOGSTRING2("CCCEPluginManager::LoadBootPluginL: VoIP enabled: %i", enabled ); + + const TBool emergencyCall = mask & ESupportsEmergencyCall; + CCELOGSTRING2( + "CCCEPluginManager::LoadBootPluginL: Support EmergencyCall: %i", emergencyCall ); + + if( mask & EBootstrapCallProvider || enabled ) + { + CCELOGSTRING("CCCEPluginManager::LoadBootPluginL: Bootable plugin found" ); + ServiceEnabledL( id ); + } + + if( emergencyCall ) + { + if( !iPrimaryEmergencyCallPlugin ) + { + CCCEPlugin* plugin( NULL ); + for( TInt i=0; iType(); + + if( oldPlugin.iUid == id.iUid ) + { + plugin = iPluginArray[i]; + i = iPluginArray.Count(); + } + } + + if( plugin ) + { + CCELOGSTRING("CCCEPluginManager::LoadBootPluginL: Initialise primary emergency call" ); + plugin->InitialiseEmergencyCallL( *iEmergencyCallObserver ); + iPrimaryEmergencyCallPlugin = plugin; + } + else + { + CCELOGSTRING("CCCEPluginManager::LoadBootPluginL: append plugin to alternative emergency array" ); + AddToAlternativeEmergencyArray( id ); + } + } + else + { + CCELOGSTRING("CCCEPluginManager::LoadBootPluginL: append plugin to alternative emergency array" ); + AddToAlternativeEmergencyArray( id ); + } + } + } + +// ----------------------------------------------------------------------------- +// DoCancel() +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::DoCancel() + { + CCELOGSTRING("CCCEPluginManager::DoCancel()" ); + iProperty.Cancel(); + } + +// ----------------------------------------------------------------------------- +// Return Primary emergency call +// ----------------------------------------------------------------------------- +// +MCCPEmergencyCall* CCCEPluginManager::PrimaryEmergencyCall() + { + MCCPEmergencyCall* call (NULL); + if( iPrimaryEmergencyCallPlugin ) + { + call = iPrimaryEmergencyCallPlugin->GetEmergencyCall(); + } + return call; + } + +// ----------------------------------------------------------------------------- +// Return Primary emergency call plugin uid +// ----------------------------------------------------------------------------- +// +TUid CCCEPluginManager::PrimaryEmergencyCallUid() const + { + TUid id( KNullUid ); + + if( iPrimaryEmergencyCallPlugin ) + { + id = iPrimaryEmergencyCallPlugin->Type(); + } + + return id; + } + +// ----------------------------------------------------------------------------- +// Get array of know emergency plugins +// ----------------------------------------------------------------------------- +// +RArray& CCCEPluginManager::AlternativeEmergencyPlugins() + { + CCELOGSTRING("CCCEPluginManager::AlternativeEmergencyPlugins "); + RImplInfoPtrArray implementations; + TRAP_IGNORE( CConvergedCallProvider::ListImplementationsL(implementations) ); + iAlternativeEmergencyPlugins.Reset(); + + for( TInt i=0; iImplementationUid()); + AddToAlternativeEmergencyArray(info->ImplementationUid()); + } + + implementations.ResetAndDestroy(); + implementations.Close(); + + return iAlternativeEmergencyPlugins; + } + +// ----------------------------------------------------------------------------- +// Add new plugin to array. Do not allow duplicates +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::AddToAlternativeEmergencyArray( TUid aUid ) + { + if( iPrimaryEmergencyCallPlugin && + ( iPrimaryEmergencyCallPlugin->Type().iUid == aUid.iUid ) ) + { + CCELOGSTRING("CCCEPluginManager::AddToAlternativeEmergencyArray: Is Primary emergency plugin "); + } + else if( iAlternativeEmergencyPlugins.Find( aUid ) == KErrNotFound ) + { + CCELOGSTRING("CCCEPluginManager::AddToAlternativeEmergencyArray: New plugin. Append to array "); + iAlternativeEmergencyPlugins.Append( aUid ); + } + else + { + CCELOGSTRING("CCCEPluginManager::AddToAlternativeEmergencyArray: Is already in Alternative Plugins "); + } + + } +// ----------------------------------------------------------------------------- +// Return protocol interface object of wanted service ID +// ----------------------------------------------------------------------------- +// +CConvergedCallProvider* CCCEPluginManager::GetPluginL( TUint32 aServiceId ) + { + CCELOGSTRING2("CCCEPluginManager::GetPluginL: Get plugin for servce id %d", aServiceId); + TUid id( KNullUid ); + + id = iSPSettings->ImplementationUidL( aServiceId ); + + if( !id.iUid ) + { + CCELOGSTRING("CCCEPluginManager::GetPluginL: PluginId not found"); + User::Leave( KErrNotFound ); + } + + return GetPluginL( id ); + } + +// ----------------------------------------------------------------------------- +// Return protocol interface object of wanted type. +// ----------------------------------------------------------------------------- +// +CConvergedCallProvider* CCCEPluginManager::GetPluginL( const TUid& aType ) + { + CCCEPlugin* plugin = NULL; + + //Is plugin started? + CCELOGSTRING2("CCCEPluginManager::GetPluginL: %d Implementation(s) running", + iPluginArray.Count() ); + + // Checked if ie. VoIP Plugins is supported + iSPSettings->IsPluginSupportedL( aType ); + + for( TInt i=0; iType(); + CCELOGSTRING2("CCCEPluginManager::GetPluginL: existing plugin = %d", + oldPlugin.iUid ); + + if( oldPlugin.iUid == aType.iUid ) + { + CCELOGSTRING("CCCEPluginManager::GetPluginL: Plugin found" ); + plugin = iPluginArray[i]; + } + } + + if (!plugin) + { + //Start plugin + CCELOGSTRING("CCCEPluginManager::GetPluginL: New Plugin" ); + CCELOGSTRING2("CCCEPluginManager::GetPluginL: Plugin Uid = %d", + aType.iUid ); + plugin = CCCEPlugin::NewL( + aType, const_cast(*iObserver), + iCallContainer, *this, iTransferController ); + + CleanupStack::PushL(plugin); + CCELOGSTRING("CCCEPluginManager::GetPluginL: Append to array" ); + iPluginArray.AppendL( plugin ); + CleanupStack::Pop(); + } + + return plugin->GetPluginL(); + } + +// ----------------------------------------------------------------------------- +// remove protocol interface object of wanted type. +// ----------------------------------------------------------------------------- +// +void CCCEPluginManager::RemovePlugin( const TUid& aType ) + { + CCELOGSTRING2("CCCEPluginManager::RemovePlugin: %d Implementation(s) running", + iPluginArray.Count() ); + + TInt pluginCount = iPluginArray.Count(); + for (TInt a = pluginCount-1; a >= 0 ; a--) + { + if ( iPluginArray[a]->Type() == aType && + iPluginArray[a]->ReleaseWhenIdle() ) + { + // keep track that only one instance of pointer is in array + iPluginsToClose.InsertInAddressOrder(iPluginArray[a]); + CCELOGSTRING("CCCEPluginManager::RemovePlugin scheduled") + + if (!iIdle->IsActive()) + { + iIdle->Start( TCallBack(RemovePlugins,this) ); + } + iPluginArray.Remove(a); + iPluginArray.Compress(); + break; + } + } + } + + +// --------------------------------------------------------------------------- +// Returns ETrue if plugin can be relesed if idle +// --------------------------------------------------------------------------- +// +TBool CCCEPluginManager::ReleaseWhenIdle( const TUid aType ) + { + + TBool release = EFalse; + TInt pluginCount = iPluginArray.Count(); + for (TInt a = 0; a < pluginCount; a++) + { + if ( iPluginArray[a]->Type() == aType ) + { + release = iPluginArray[a]->ReleaseWhenIdle(); + break; + } + } + + CCELOGSTRING2("CCCEPluginManager::ReleaseWhenIdle returning %d ", (TInt) release); + return release; + } + +// ----------------------------------------------------------------------------- +// Return array of dtmf providers. +// ----------------------------------------------------------------------------- +// +MCCPDTMFProvider& CCCEPluginManager::DtmfProviderL( + const MCCPDTMFObserver& aObserver, + TUid aImplementationUid ) const + { + CCCEPlugin* plugin( NULL ); + + for( TInt i=0; iType().iUid == aImplementationUid.iUid ) + { + plugin = iPluginArray[i]; + i = iPluginArray.Count(); + } + } + + if ( !plugin ) + { + User::Leave( KErrNotFound ); + } + + return plugin->GetDtmfProviderL( aObserver ); + } + +// ----------------------------------------------------------------------------- +// From class MPluginObserver. +// +// ----------------------------------------------------------------------------- +// + +void CCCEPluginManager::CCPPluginDiedEvent(TUid aPluginId, TInt /*aDeathType*/, TInt /*aReason*/) + { + + CCELOGSTRING2("CCCEPluginManager::CCPPluginDiedEvent: %d", aPluginId.iUid ); + + RPointerArray calls; + + TInt count = iCallContainer.GetCall(aPluginId, calls); + CCELOGSTRING2("CCCEPluginManager::CCPPluginDiedEvent: %d calls found!", count); + for (TInt i = 0; i < count; i++) + { + calls[i]->ErrorOccurred( ECCPServerFailure, &calls[i]->GetCCPCall() ); + calls[i]->CallStateChanged( MCCPCallObserver::ECCPStateIdle, &calls[i]->GetCCPCall() ); + } + + calls.Close(); + + CCELOGSTRING("CCCEPluginManager::CCPPluginDiedEvent: Plugin calls terminated"); + + TInt pluginCount = iPluginArray.Count(); + for (TInt a = 0; a < pluginCount; a++) + { + if ( iPluginArray[a]->Type() == aPluginId ) + { + iPluginsToClose.Append(iPluginArray[a]); + if (!iIdle->IsActive()) + { + iIdle->Start( TCallBack(RemovePlugins,this) ); + } + iPluginArray.Remove(a); + iPluginArray.Compress(); + return; + } + } + } +// ----------------------------------------------------------------------------- +// From class MPluginObserver. +// +// ----------------------------------------------------------------------------- +// + +void CCCEPluginManager::CCPPluginInitialisationFailed(TUid aPluginUid, TInt /*aError*/) + { + + CCELOGSTRING2("CCCEPluginManager::CCPPluginInitialisationFailed: %d", aPluginUid.iUid ); + if (iCallContainer.CountCalls(aPluginUid)) + { + // there is active call, cannot close. + return; + } + + TInt pluginCount = iPluginArray.Count(); + for (TInt a = 0; a < pluginCount; a++) + { + if ( iPluginArray[a]->Type() == aPluginUid ) + { + iPluginsToClose.Append(iPluginArray[a]); + if (!iIdle->IsActive()) + { + iIdle->Start( TCallBack(RemovePlugins,this) ); + } + iPluginArray.Remove(a); + iPluginArray.Compress(); + return; + } + } + } + +// end of file