contextframework/cfw/src/cfactivatorengine/CFActivatorEngineActionPluginManager.cpp
/*
* 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