diff -r 000000000000 -r 2e3d3ce01487 contextframework/cfw/src/cfactivatorengine/CFActivatorEngineActionPluginManager.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/contextframework/cfw/src/cfactivatorengine/CFActivatorEngineActionPluginManager.cpp Tue Feb 02 10:12:00 2010 +0200 @@ -0,0 +1,619 @@ +/* +* 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: CCFActivatorEngineActionPluginManager class implementation. +* +*/ + + +#include +#include + +#include "ContextFrameworkPrivateCRKeys.h" +#include "CFActivatorEngineActionPluginManager.h" +#include "cfactionplugin.h" +#include "CFActionPluginImpl.h" +#include "cfactionindication.h" +#include "cftrace.h" +#include "cfactionpluginthread.h" +#include "CFActivator.h" +#include "cfcommon.h" +#include "cfasynccleanup.h" +#include "cfstartereventhandler.h" + +// CONSTANTS + +static const TInt KDefaultActionArrayGranularity = 5; + +// LOCAL CLASSES +/** +* Loader info +*/ +NONSHARABLE_CLASS( TCFActionLoaderInfo ) + { + public: + + TCFActionLoaderInfo( CImplementationInformation& aImplementationInfo, + CCFActivatorEngineActionPluginManager& aManager ): + iImplUid( aImplementationInfo.ImplementationUid() ), + iImplVersion( aImplementationInfo.Version() ), + iManager( aManager ) + { + } + + public: + + TUid iImplUid; + TInt iImplVersion; + CCFActivatorEngineActionPluginManager& iManager; + }; + +// LOCAL FUNCTIONS + +/** +* Clenup operation for RImplInfoPtrArray +*/ +LOCAL_C void CleanUpImplInfoArray( TAny* aParams ) + { + RImplInfoPtrArray* array = static_cast( aParams ); + array->ResetAndDestroy(); + } + +/** +* Push operation for RImplInfoPtrArray +*/ +LOCAL_C void CleanupPushImplInfoArrayL( RImplInfoPtrArray& aArray ) + { + TCleanupItem item( CleanUpImplInfoArray, &aArray ); + CleanupStack::PushL( item ); + } + + +// MEMBER FUNCTIONS + +CCFActivatorEngineActionPluginManager* CCFActivatorEngineActionPluginManager::NewL( + RActionCacheArray& aActionCache ) + { + FUNC_LOG; + + CCFActivatorEngineActionPluginManager* self = + CCFActivatorEngineActionPluginManager::NewLC( aActionCache ); + CleanupStack::Pop( self ); + return self; + } + +CCFActivatorEngineActionPluginManager* CCFActivatorEngineActionPluginManager::NewLC( + RActionCacheArray& aActionCache ) + { + FUNC_LOG; + + CCFActivatorEngineActionPluginManager* self = new( ELeave ) + CCFActivatorEngineActionPluginManager( aActionCache ); + CleanupStack::PushL( self ); + self->ConstructL(); + return self; + } + + +CCFActivatorEngineActionPluginManager::CCFActivatorEngineActionPluginManager( + RActionCacheArray& aActionCache ): + iActionCache( aActionCache ) + { + FUNC_LOG; + } + +CCFActivatorEngineActionPluginManager::~CCFActivatorEngineActionPluginManager() + { + FUNC_LOG; + + iCleanupList.ResetAndDestroy(); + iActionPlugInThreads.ResetAndDestroy(); + iLoaders.ResetAndDestroy(); + } + +void CCFActivatorEngineActionPluginManager::ConstructL() + { + FUNC_LOG; + } + +// METHODS + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::TriggerL +//---------------------------------------------------------------------------- +// +TBool CCFActivatorEngineActionPluginManager::TriggerL( + CCFActionIndication* aActionIndication ) + { + FUNC_LOG; + + TPtrC actionIdentifier( aActionIndication->Identifier() ); + CCFActionCacheElement* element = CCFActivator::ActionCacheElementExists( + actionIdentifier, iActionCache ); + if( element ) + { + MCFActionOwner* owner = element->Owner(); + if( owner ) + { + if( owner->ActionOwner() == MCFActionOwner::ECFInternalAction ) + { + CCFActionPlugInThread* action = + static_cast( owner ); + INFO_2( "Action id [%S] triggered from action plug-in [%x]", + &actionIdentifier, action->ImplementationUid() ); + action->TriggerL( aActionIndication ); + } + } + } + + return element ? ETrue : EFalse; + } + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::InitializePhaseL +//---------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::InitializePhaseL( + CCFPhaseBase::TCFPhaseId aPhaseId ) + { + FUNC_LOG; + + switch( aPhaseId ) + { + case CCFPhaseBase::ECFDeviceStarting: + { + InitDeviceStartingPhaseL(); + break; + } + case CCFPhaseBase::ECFLoadingPlugins: + { + InitLoadingPluginsPhaseL(); + break; + } + default: + { + break; + } + } + } + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::SetEventHandler +//---------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::SetEventHandler( MCFStarterEventHandler& aEventHandler ) + { + FUNC_LOG; + + iEventHandler = &aEventHandler; + } + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::InitDeviceStartingPhaseL +//---------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::InitDeviceStartingPhaseL() + { + FUNC_LOG; + + // List all plugins + RImplInfoPtrArray implInfoArray; + CleanupPushImplInfoArrayL( implInfoArray ); + REComSession::ListImplementationsL( KActionPluginUid, implInfoArray ); + + // Load activator engine configuration cenrep + CRepository* cenRep = CRepository::NewLC( KCRUidCFActionConf ); + TInt count = 0; + TInt err = cenRep->Get( KActionNumberOfMandatoryPlugIns, count ); + if( err == KErrNone && count ) + { + INFO_1( "Found %d action plug-in implementations from cenrep", count ); + TUint32 key = KActionNumberOfMandatoryPlugIns + 1; + for( TInt i = 0; i < count; i++ ) + { + TInt uid = 0; + err = cenRep->Get( key + i, uid ); + if( err == KErrNone && uid ) + { + CImplementationInformation* info = NULL; + for( TInt ii = 0; ii < implInfoArray.Count(); ii++ ) + { + info = implInfoArray[ii]; + if( info->ImplementationUid() == TUid::Uid( uid ) ) + { + // Implementation info found + break; + } + info = NULL; + } + if( info ) + { + TRAPD( err, LoadPlugInL( info->ImplementationUid(), info->Version() ) ); + if( err == KErrNone ) + { + INFO_1( "Loaded action plug-in [%x]", uid ); + } + else + { + ERROR_1( err, "Failed to load action plug-in [%x]", uid ); + } + } + } + else + { + INFO_2( "UID 0x%08x skipped, error code %d", uid, err ); + } + } + } + + // Clean up + CleanupStack::PopAndDestroy( cenRep ); + CleanupStack::PopAndDestroy( &implInfoArray ); + } + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::InitLoadingPluginsPhaseL +//---------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::InitLoadingPluginsPhaseL() + { + FUNC_LOG; + + UpdatePlugInsL(); + } + + +// --------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::UpdatePlugInsL +// --------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::UpdatePlugInsL() + { + FUNC_LOG; + + // List all plugins + RImplInfoPtrArray implInfoArray; + CleanupPushImplInfoArrayL( implInfoArray ); + REComSession::ListImplementationsL( KActionPluginUid, implInfoArray ); + + TInt allCount = implInfoArray.Count(); + TInt loadedCount = iActionPlugInThreads.Count(); + INFO_1( "Found %d action plug-in implementations from ecom", allCount ); + INFO_1( "%d action plug-ins currently loaded", loadedCount ); + + // Check if there were plugins installed + if( allCount >= loadedCount ) + { + for( TInt i = iActionPlugInThreads.Count() - 1; i >= 0; i-- ) + { + CCFActionPlugInThread* actionPluginThread = iActionPlugInThreads[i]; + for( TInt ii = 0; ii < implInfoArray.Count(); ii++ ) + { + CImplementationInformation* implInfo = implInfoArray[ii]; + if( implInfo->ImplementationUid() == + actionPluginThread->ImplementationUid() ) + { + TInt oldVer = actionPluginThread->Version(); + TInt newVer = implInfo->Version(); + + // Check if the version has increased + if( newVer > oldVer ) + { + // Cleanup old plug-in, new plug-in will be loaded + // asynchronously + ReleasePlugInL( actionPluginThread, ETrue ); + } + + delete implInfo; + implInfoArray.Remove( ii ); + break; + } + } + } + + // Check if the installed plugin was not an updgrade but a new plugin + for( TInt i = 0; i < implInfoArray.Count(); i++ ) + { + CImplementationInformation* implInfo = implInfoArray[i]; + + // Prepare loaders + PrepareLoaderL( *implInfo ); + } + + // Execute loaders + ExecuteLoaders(); + } + + // Check if there were plugins unistalled + else + { + for( TInt i = 0; i < iActionPlugInThreads.Count(); i++ ) + { + CCFActionPlugInThread* actionPluginThread = iActionPlugInThreads[i]; + actionPluginThread->SetMissing( ETrue ); + } + + // Check that which plugins are missing + for( TInt i = 0; i < implInfoArray.Count(); i++ ) + { + CImplementationInformation* implInfo = implInfoArray[i]; + for( TInt i = 0; i < iActionPlugInThreads.Count(); i++ ) + { + CCFActionPlugInThread* actionPluginThread = iActionPlugInThreads[i]; + if( actionPluginThread->ImplementationUid() == + implInfo->ImplementationUid() ) + { + actionPluginThread->SetMissing( EFalse ); + break; + } + } + } + + // Delete missing plugins + for( TInt i = iActionPlugInThreads.Count() - 1; i >= 0; i-- ) + { + CCFActionPlugInThread* actionPluginThread = iActionPlugInThreads[i]; + if( actionPluginThread->Missing() ) + { + INFO_2( "Removed uninstalled action plugin [%x], ver: [%d]", + actionPluginThread->ImplementationUid().iUid, + actionPluginThread->Version() ); + + ReleasePlugInL( actionPluginThread, EFalse ); + } + } + } + + // Cleanup + CleanupStack::PopAndDestroy( &implInfoArray ); + } + +// --------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::PrepareLoaderL +// --------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::PrepareLoaderL( CImplementationInformation& aImplementationInfo ) + { + FUNC_LOG; + TCFActionLoaderInfo* loaderInfo = new(ELeave)TCFActionLoaderInfo( aImplementationInfo, *this ); + CleanupStack::PushL( loaderInfo ); + TCallBack cb( LoaderCallBack, loaderInfo ); + CAsyncCallBack* loader = new( ELeave ) CAsyncCallBack( cb, CActive::EPriorityStandard ); + CleanupStack::PushL( loader ); + iLoaders.AppendL( loader ); + CleanupStack::Pop( loader ); + CleanupStack::Pop( loaderInfo ); + } + +// --------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::ExecuteLoaders +// --------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::ExecuteLoaders() + { + FUNC_LOG; + + for( TInt i = 0; i < iLoaders.Count(); i++ ) + { + CAsyncCallBack* loader = iLoaders[i]; + loader->CallBack(); + } + } + +// --------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::LoaderCallBack +// --------------------------------------------------------------------------- +// +TInt CCFActivatorEngineActionPluginManager::LoaderCallBack( TAny* aLoaderInfo ) + { + FUNC_LOG; + + TCFActionLoaderInfo* loaderInfo = static_cast( aLoaderInfo ); + CCFActivatorEngineActionPluginManager& manager = loaderInfo->iManager; + + TRAPD( err, manager.LoadPlugInL( loaderInfo->iImplUid, + loaderInfo->iImplVersion ) ); + if( err == KErrNone ) + { + INFO_2( "Loaded action plugin [%x], ver: [%d]", + loaderInfo->iImplUid.iUid, loaderInfo->iImplVersion ); + } + else + { + ERROR_2( err, "Failed to load action plugin [%x], ver: [%d]", + loaderInfo->iImplUid.iUid, loaderInfo->iImplVersion ); + } + + manager.iLoadedCount++; + + if( manager.iLoadedCount == manager.iLoaders.Count() ) + { + manager.iLoaders.ResetAndDestroy(); + manager.iLoadedCount = 0; + + if( manager.iEventHandler ) + { + manager.iEventHandler->HandleEvent( MCFStarterEventHandler::EActionPluginsLoaded ); + } + } + delete loaderInfo; + return KErrNone; + } + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::LoadPlugInL +//---------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::LoadPlugInL( TUid aUid, + TInt aImplVersion ) + { + FUNC_LOG; + + CCFActionPlugInThread* actionPluginThread + = CCFActionPlugInThread::NewLC( *this, aUid, aImplVersion ); + + AddNewActionsToCacheL( *actionPluginThread ); + + // Finally add the action plugin + iActionPlugInThreads.AppendL( actionPluginThread ); + CleanupStack::Pop( actionPluginThread ); + } + + +//---------------------------------------------------------------------------- +// CCFActivatorEngineActionPluginManager::SetImplPointer +//---------------------------------------------------------------------------- +// +void CCFActivatorEngineActionPluginManager::SetImplPointer( + CCFActionPlugIn& aActionPlugIn, + CCFActionPlugInImpl* aImpl) + { + FUNC_LOG; + + // utilizing friendship to set a private member variable + aActionPlugIn.iImpl = aImpl; + } + +//------------------------------------------------------------------------------ +// CCFActivatorEngineActionPluginManager::ReleasePlugIn +//------------------------------------------------------------------------------ +// +void CCFActivatorEngineActionPluginManager::ReleasePlugInL( + CCFActionPlugInThread* aActionPlugInThread, + TBool aUpgrade ) + { + FUNC_LOG; + + // Go through the action cache and set action as "inactive" if the + // release is not followed by an upgrade + if( !aUpgrade ) + { + MCFActionOwner* owner = static_cast( aActionPlugInThread ); + for( TInt i = 0; i < iActionCache.Count(); i++ ) + { + CCFActionCacheElement* element = iActionCache[i]; + if( element->Owner() == owner ) + { + // Action cache element found - set the owner inactive + element->SetOwner( NULL ); + } + } + } + // Run pending actions and start plug-in cleanup + aActionPlugInThread->RunPendingActions(); + CCFAsyncCleanup* cleanup = CCFAsyncCleanup::NewLC( aUpgrade, + *aActionPlugInThread, + *this ); + TInt err = iCleanupList.Append( cleanup ); + CleanupStack::Pop( cleanup ); + + // Check if there were an error while appending cleanup item + if( err != KErrNone ) + { + delete cleanup; + } + } + +//------------------------------------------------------------------------------ +// CCFActivatorEngineActionPluginManager::CleanupCompleted +//------------------------------------------------------------------------------ +// +void CCFActivatorEngineActionPluginManager::CleanupCompleted( + CCFAsyncCleanup* aCleanup ) + { + FUNC_LOG; + + // Search for the cleanup item and delete it + for( TInt i = 0; i < iCleanupList.Count(); i++ ) + { + CCFAsyncCleanup* cleanupItem = iCleanupList[i]; + if( cleanupItem == aCleanup ) + { + if( !cleanupItem->Upgrade() ) + { + // Cleanup was uninstall based, delete action thread + CCFActionPlugInThread* obsoleteThread = &cleanupItem->Thread(); + for( TInt ii = 0; ii < iActionPlugInThreads.Count(); ii++ ) + { + CCFActionPlugInThread* thread = iActionPlugInThreads[ii]; + if( thread == obsoleteThread ) + { + iActionPlugInThreads.Remove( ii ); + delete thread; + break; + } + } + } + iCleanupList.Remove( i ); + delete cleanupItem; + break; + } + } + } + + +//------------------------------------------------------------------------------ +// CCFActivatorEngineActionPluginManager::AddNewActionsToCacheL +//------------------------------------------------------------------------------ +// +void CCFActivatorEngineActionPluginManager::AddNewActionsToCacheL( + CCFActionPlugInThread& aActionPluginThread ) + { + FUNC_LOG; + + // Add new actions in the action cache + CDesCArrayFlat* actions = new( ELeave ) CDesCArrayFlat( + KDefaultActionArrayGranularity ); + CleanupStack::PushL( actions ); + aActionPluginThread.GetActionsL( *actions ); + + // Do not create double action ids + for( TInt i = 0 ; i < actions->Count(); i++ ) + { + TPtrC actionId( (*actions)[i] ); + CCFActionCacheElement* element = + CCFActivator::ActionCacheElementExists( actionId, iActionCache ); + if( element ) + { + // Check that owner uid is CFServer SID and the owner has not been set + if( element->OwnerUid() == KCFServerSid && !element->Owner() ) + { + // Assuming that plug-in has been upgraded + element->SetOwner( &aActionPluginThread ); + INFO_2( "Action id [%S] from action plug-in [%x] re-activated", + &actionId, aActionPluginThread.ImplementationUid() ); + } + else + { + // Action already defined + ERROR_2( KErrAlreadyExists, "Action id [%S] from action plug-in [%x] already defined", + &actionId, aActionPluginThread.ImplementationUid() ); + } + } + else + { + // new action id + element = CCFActionCacheElement::NewLC( actionId, + aActionPluginThread.SecurityPolicy( actionId ), + KCFServerSid, &aActionPluginThread ); + iActionCache.AppendL( element ); + CleanupStack::Pop( element ); + INFO_2( "Action id [%S] from action plug-in [%x] defined", + &actionId, aActionPluginThread.ImplementationUid() ); + } + } + + CleanupStack::PopAndDestroy( actions ); + } + +// End of file