--- /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 <ecom/ecom.h>
+#include <centralrepository.h>
+
+#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<RImplInfoPtrArray*>( 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<CCFActionPlugInThread*>( 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<TCFActionLoaderInfo*>( 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<MCFActionOwner*>( 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