--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/devicediagnosticsfw/diagframework/src/diagpluginpoolimpl.cpp Thu Dec 17 09:07:52 2009 +0200
@@ -0,0 +1,623 @@
+/*
+* Copyright (c) 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: Implementation of Diagnostics Plug-in Pool
+*
+*/
+
+
+// CLASS DECLARATION
+#include "diagpluginpoolimpl.h"
+
+// SYSTEM INCLUDE FILES
+#include <ecom.h>
+#include <DiagPlugin.h>
+#include <DiagPluginPoolObserver.h>
+#include <DiagPluginConstructionParam.h>
+#include <DiagPluginPoolObserver.h>
+#include <DiagFrameworkDebug.h>
+#include <mmf/common/mmfcontrollerpluginresolver.h> // CleanupResetAndDestroyPushL
+
+// USER INCLUDE FILES
+#include "diagpluginloaderdependencyparser.h"
+#include "diagrootsuite.h"
+
+using namespace DiagPluginPool;
+using namespace DiagFwInternal;
+
+_LIT( KPanicCode, "PluginPool" );
+
+// ===========================================================================
+// PUBLIC MEMBER FUNCTIONS
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+CDiagPluginPoolImpl* CDiagPluginPoolImpl::NewL( MDiagPluginPoolObserver& aObserver )
+ {
+ LOGSTRING("");
+ CDiagPluginPoolImpl* self = CDiagPluginPoolImpl::NewLC( aObserver );
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// NewLC
+// ---------------------------------------------------------------------------
+//
+CDiagPluginPoolImpl* CDiagPluginPoolImpl::NewLC( MDiagPluginPoolObserver& aObserver )
+ {
+ CDiagPluginPoolImpl* self = new( ELeave )CDiagPluginPoolImpl( aObserver );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CDiagPluginPoolImpl::~CDiagPluginPoolImpl()
+ {
+ LOGSTRING("");
+ Cancel();
+ iPlugins.ResetAndDestroy();
+ iPlugins.Close();
+ REComSession::FinalClose();
+ }
+
+// ---------------------------------------------------------------------------
+// LoadAsyncL
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::LoadAsyncL()
+ {
+ LOGSTRING( "CDiagPluginPoolImpl::LoadAsyncL" )
+
+ ASSERT ( !iPluginsLoaded );
+ ASSERT ( !iPluginsLoading );
+
+ iPluginsLoading = ETrue;
+
+ iConstructionParamArray = GeneratePluginListL();
+
+ iTotalPluginsFound = iConstructionParamArray->Count();
+
+ // No plug-ins found
+ if ( ! iTotalPluginsFound )
+ {
+ DestroyConstructionParams();
+ User::Leave( KErrNotFound );
+ }
+
+ // Create root suite to define the hierarchy
+ MDiagSuitePlugin* rootSuite = CDiagRootSuite::NewL();
+ CleanupStack::PushL( rootSuite );
+ iPlugins.AppendL( rootSuite ); // ownership transfered
+ CleanupStack::Pop( rootSuite );
+
+ SetNextIteration();
+ }
+
+// ---------------------------------------------------------------------------
+// CreatePluginL
+// ---------------------------------------------------------------------------
+//
+MDiagPlugin* CDiagPluginPoolImpl::CreatePluginL( const TUid aUid )
+ {
+ TInt errorCode = KErrNone;
+
+ LOGSTRING2( "CDiagPluginPoolImpl::CreatePluginL %d\n", aUid.iUid )
+
+ // Create construction parameters list
+ RConstructionParamArray* constructionParamsArray = GeneratePluginListL();
+ CleanupStack::PushL( constructionParamsArray );
+ CleanupResetAndDestroyPushL( *constructionParamsArray );
+
+ MDiagPlugin* plugin = NULL;
+
+ // Find plug-in with matching UID
+ for ( TInt i=0; i<constructionParamsArray->Count(); i++ )
+ {
+ if ( ( *constructionParamsArray )[i]->Uid() == aUid )
+ {
+ plugin = CreatePluginFromConstructionParamsL( ( *constructionParamsArray )[i] );
+
+ // Construction params owned by plug-in so remove from list
+ constructionParamsArray->Remove(i);
+ break; //lint !e960 ok to break from for loop
+ }
+ }
+
+ if ( ! plugin )
+ {
+ errorCode = KErrNotFound;
+ }
+
+ CleanupStack::PopAndDestroy(); // *implInfoArray
+ CleanupStack::PopAndDestroy( constructionParamsArray );
+
+ User::LeaveIfError( errorCode );
+
+ return plugin;
+ }
+
+// ---------------------------------------------------------------------------
+// FindPlugin
+// ---------------------------------------------------------------------------
+//
+TInt CDiagPluginPoolImpl::FindPlugin( TUid aUid, MDiagPlugin*& aPlugin ) const
+ {
+ LOGSTRING2( "CDiagPluginPoolImpl::FindPlugin 0x%x\n", aUid.iUid )
+
+ aPlugin = NULL;
+
+ // Find plug-in with matching UID in pool
+ for ( TInt i=0; i<iPlugins.Count(); i++ )
+ {
+ if ( iPlugins[i]->Uid() == aUid )
+ {
+ aPlugin = iPlugins[i];
+ return KErrNone;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+// ---------------------------------------------------------------------------
+// FindPlugin
+// ---------------------------------------------------------------------------
+//
+TInt CDiagPluginPoolImpl::FindPlugin( const TDesC& aServiceName,
+ MDiagPlugin *& aPlugin ) const
+ {
+ LOGSTRING2( "CDiagPluginPoolImpl::FindPlugin \"%S\"\n", &aServiceName )
+
+ aPlugin = NULL;
+
+ // Find plug-in with matching service name in pool
+ for ( TInt i=0; i<iPlugins.Count(); i++ )
+ {
+ if ( iPlugins[i]->ServiceLogicalName() == aServiceName )
+ {
+ aPlugin = iPlugins[i];
+ return KErrNone;
+ }
+ }
+
+ return KErrNotFound;
+ }
+
+
+// ===========================================================================
+// PRIVATE CONSTRUCTORS
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// CDiagPluginPool
+// ---------------------------------------------------------------------------
+//
+CDiagPluginPoolImpl::CDiagPluginPoolImpl( MDiagPluginPoolObserver& aObserver )
+ // Priority is idle to allow plug-ins to load in background regardless of
+ // what UI priority is set to.
+ : CActive( EPriorityIdle ),
+ iObserver( aObserver ),
+ iErrorCode( KErrNone )
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::ConstructL()
+ {
+ CActiveScheduler::Add( this );
+ }
+
+
+// ===========================================================================
+// PRIVATE STATIC FUNCTIONS
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// ObtainImplementationInfoL
+// ---------------------------------------------------------------------------
+//
+CDiagPluginPoolImpl::RConstructionParamArray* CDiagPluginPoolImpl::GeneratePluginListL()
+ {
+
+ // Get list of plug-in implementation implementationInfo
+ RImplInfoPtrArray* implInfoArray = new( ELeave )RImplInfoPtrArray;
+
+ REComSession::ListImplementationsL( KDiagPluginInterfaceUid, *implInfoArray );
+
+ // Leave if no matching plug-ins found
+ if ( ! implInfoArray->Count() )
+ {
+ delete implInfoArray;
+ User::Leave( KErrNotFound );
+ }
+
+ CleanupStack::PushL( implInfoArray );
+ CleanupResetAndDestroyPushL( *implInfoArray );
+
+ RConstructionParamArray* constructionParamsArray = new(ELeave)RConstructionParamArray;
+ CleanupStack::PushL( constructionParamsArray );
+ CleanupResetAndDestroyPushL( *constructionParamsArray );
+ CDependencyParser* parser = CDependencyParser::NewLC();
+
+ // Iterate through implementation information array and create construction data for each
+ // plug-in. Insert into array by order number.
+ for ( TInt pluginIndex=0; pluginIndex < implInfoArray->Count(); pluginIndex++ )
+ {
+ CImplementationInformation* pluginImplementationInfo = ( *implInfoArray )[pluginIndex];
+
+ if ( !pluginImplementationInfo->RomBased() )
+ {
+#ifdef _DEBUG
+ LOGSTRING2( "CDiagPluginPoolImpl::GeneratePluginListL() "
+ L" Loading non-rom plug-in 0x%08x",
+ pluginImplementationInfo->ImplementationUid() );
+#else // #ifdef _DEBUG
+ // In non _DEBUG build, do not load plug-in that are not in ROM
+ // for security reasons. Continue to next plug-in.
+ //continue;
+#endif // #else _DEBUG
+ }
+
+ // Obtain depenency and other information from opaque data field
+ parser->ParseL( pluginImplementationInfo->OpaqueData(),
+ pluginImplementationInfo->DataType() );
+
+ CDiagPluginConstructionParam* constructionParams =
+ GenerateConstructionParamsLC( pluginImplementationInfo );
+
+ TInt orderNumber = constructionParams->Order();
+
+ // Find correct index to insert plug-in
+ TInt insertIndex;
+ for ( insertIndex=0; insertIndex<constructionParamsArray->Count(); insertIndex++ )
+ {
+ if ( orderNumber < (*constructionParamsArray)[insertIndex]->Order() )
+ {
+ break; //lint !e960 break OK here.
+ }
+ }
+
+ // Insert in order by order number
+ constructionParamsArray->InsertL(constructionParams,insertIndex);
+ CleanupStack::Pop(constructionParams);
+ }
+
+ // Clean up
+ CleanupStack::PopAndDestroy(parser);
+ CleanupStack::Pop(); // constructionParamsArray
+ CleanupStack::Pop(constructionParamsArray);
+ CleanupStack::PopAndDestroy(); // implInfoArray
+ CleanupStack::PopAndDestroy(implInfoArray);
+
+ return constructionParamsArray;
+ }
+
+// ---------------------------------------------------------------------------
+// GenerateConstructionParamsL
+// ---------------------------------------------------------------------------
+//
+CDiagPluginConstructionParam* CDiagPluginPoolImpl::GenerateConstructionParamsLC(
+ const CImplementationInformation* aInfo )
+ {
+ CDependencyParser* parser = CDependencyParser::NewLC();
+
+ // Obtain depenency and other information from opaque data field
+ parser->ParseL( aInfo->OpaqueData(), aInfo->DataType() );
+
+ CDiagPluginConstructionParam* params = CDiagPluginConstructionParam::NewL
+ (
+ parser->GetServiceProvided(),
+ parser->GetServicesRequired(),
+ parser->GetOrderNumber(),
+ aInfo->ImplementationUid(),
+ parser->GetParentUid()
+ );
+
+ CleanupStack::PopAndDestroy( parser );
+ CleanupStack::PushL( params );
+
+ return params;
+ }
+
+// ---------------------------------------------------------------------------
+// CreatePluginFromImplementationInfoL
+// ---------------------------------------------------------------------------
+//
+MDiagPlugin* CDiagPluginPoolImpl::CreatePluginFromConstructionParamsL(
+ const CDiagPluginConstructionParam* aParams )
+ {
+ MDiagPlugin* newPlugin = NULL;
+ TUid destructorIdKey;
+
+ // Call ECOM to load next plug-in
+ TAny* object = REComSession::CreateImplementationL( aParams->Uid(),
+ destructorIdKey,
+ ( TAny* )aParams );
+ if (!object)
+ User::Leave(KErrNotFound);
+
+ newPlugin = static_cast<MDiagPlugin*>( object );
+ newPlugin->SetDtorIdKey( destructorIdKey );
+ return newPlugin;
+ }
+
+// ===========================================================================
+// PRIVATE MEMBER FUNCTIONS
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// AddNewPluginToSuiteL
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::AddNewPluginToSuiteL(MDiagPlugin* aPlugin)
+ {
+ // Search the plug-in list for a matching suite plug-in and add this newly
+ // loaded plug-in to that corresponding suite. If a suite is not found,
+ // this plug-in will have no parent unless the parent suite is loaded
+ // at some later point.
+ for ( TInt pluginIndex = 0; pluginIndex < iPlugins.Count(); pluginIndex++ )
+ {
+
+ // Find matching parent suite
+ if ( aPlugin->ParentUid() == iPlugins[pluginIndex]->Uid() )
+ {
+ if ( iPlugins[pluginIndex]->Type() == MDiagPlugin::ETypeSuitePlugin )
+ {
+ // If parent is a suite, add child
+ MDiagSuitePlugin* parent = static_cast<MDiagSuitePlugin*>( iPlugins[pluginIndex] );
+
+ parent->AddChildL( aPlugin );
+ return;
+ }
+ else
+ {
+ // if parent is not a suite, leave
+ User::Leave( KErrCorrupt );
+ }
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// AddPluginsToNewSuiteL
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::AddPluginsToNewSuiteL(MDiagSuitePlugin* aPluginSuite)
+ {
+ // Search the plug-in list for plug-ins with matching parent suite.
+ for ( TInt pluginIndex = 0; pluginIndex < iPlugins.Count(); pluginIndex++ )
+ {
+ // Add any "orphan" plug-ins
+ if ( aPluginSuite->Uid() == iPlugins[pluginIndex]->ParentUid() )
+ {
+ aPluginSuite->AddChildL( iPlugins[pluginIndex] );
+ }
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// SetNextIteration
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::SetNextIteration()
+ {
+ TRequestStatus* status = &iStatus;
+
+ // Complete own request
+ User::RequestComplete( status, KErrNone );
+ SetActive();
+ }
+
+// ---------------------------------------------------------------------------
+// LoadNextPlugin
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::LoadNextPluginL()
+ {
+ // Get parameters to generate plug-in
+ CDiagPluginConstructionParam* constructionParams = ( *iConstructionParamArray )[ 0 ];
+ iCurrentPluginIndex++;
+ MDiagPlugin* newPlugin = NULL;
+
+ // Uid to report to application, defaults to NULL.
+ TUid reportedUid = TUid::Null();
+
+ // Create plug-in from ECOM structure
+ // Any parsing or ECOM error will be caught here
+ TRAPD( error, newPlugin = CreatePluginFromConstructionParamsL( constructionParams ) )
+
+ // Construction params are now owned by plug-in so remove from array
+ iConstructionParamArray->Remove( 0 );
+
+ LOGSTRING4( "CDiagPluginPoolImpl::LoadNextPluginL Plugin( %d/%d ): Error=%d\n",
+ iCurrentPluginIndex, iTotalPluginsFound, error )
+
+ // Check for error in plug-in creation
+ if ( error != KErrNone )
+ {
+ if ( iErrorCode == KErrNone )
+ {
+ // Sets error code to whatever was the first error encountered
+ iErrorCode = error;
+ }
+ }
+ else
+ {
+
+ CleanupDeletePushL( newPlugin );
+
+ // Add to plug-in pool
+ reportedUid = AddPluginToPoolLD( newPlugin );
+ newPlugin = NULL;
+ }
+
+ // Load is not complete
+ if ( iConstructionParamArray->Count() )
+ {
+
+ // Set next plug-in to load in next active scheduler cycle
+ SetNextIteration();
+
+ // Report progress to client
+ iObserver.LoadProgressL( iCurrentPluginIndex, iTotalPluginsFound, reportedUid );
+ }
+
+ // Load is complete
+ else
+ {
+ // Report load completed to client
+ iPluginsLoading = EFalse;
+ iPluginsLoaded = ETrue;
+
+ iObserver.LoadCompletedL( iErrorCode );
+
+ // Don't need implementation implementationInfo list anymore
+ DestroyConstructionParams();
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// DestroyConstructionParams
+// ---------------------------------------------------------------------------
+//
+TUid CDiagPluginPoolImpl::AddPluginToPoolLD( MDiagPlugin* aPlugin )
+ {
+
+ TUid reportedUid = TUid::Null();
+
+ // Add plug-in to list
+ if ( aPlugin->IsSupported() )
+ {
+ iPlugins.AppendL( aPlugin );
+
+ // Indicate to client that a plug-in was loaded with this UID
+ reportedUid = aPlugin->Uid();
+
+ // Update suite tree. If this is a plug-in, try to find parent
+ // suite and add. If this is a suite, try to find child plug-ins
+ // and add them.
+ AddNewPluginToSuiteL(aPlugin);
+
+ if ( aPlugin->Type() == MDiagPlugin::ETypeSuitePlugin )
+ {
+ MDiagSuitePlugin* pluginSuite =
+ static_cast<MDiagSuitePlugin*>(aPlugin);
+ AddPluginsToNewSuiteL( pluginSuite );
+ }
+
+ CleanupStack::Pop(); // aPlugin
+ }
+ else
+ {
+ LOGSTRING2( " Plugin UID 0x%x NOT SUPPORTED. Skipped", aPlugin->Uid().iUid )
+ CleanupStack::PopAndDestroy(); // aPlugin
+ }
+
+ return reportedUid;
+ }
+
+// ---------------------------------------------------------------------------
+// DestroyConstructionParams
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::DestroyConstructionParams( )
+ {
+ if ( iConstructionParamArray )
+ {
+ iConstructionParamArray->ResetAndDestroy();
+ delete iConstructionParamArray;
+ iConstructionParamArray = NULL;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// ResetAndNotify
+// ---------------------------------------------------------------------------
+//
+TInt CDiagPluginPoolImpl::ResetAndNotify(TInt aErrorCode)
+ {
+ // Reset load data
+ iCurrentPluginIndex = 0;
+ iPlugins.ResetAndDestroy();
+
+ iPluginsLoading = EFalse;
+
+ // Reset and delete implementation implementationInfo array
+ DestroyConstructionParams();
+
+ TRAPD( error, iObserver.LoadCompletedL( aErrorCode ) )
+
+ return error;
+ }
+
+
+
+// ===========================================================================
+// From CActive
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// RunL
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::RunL()
+ {
+ // Load a plug-in in active scheduler cycle
+ LoadNextPluginL();
+ }
+
+// ---------------------------------------------------------------------------
+// DoCancel
+// ---------------------------------------------------------------------------
+//
+void CDiagPluginPoolImpl::DoCancel()
+ {
+ LOGSTRING( "CDiagPluginPoolImpl::DoCancel" )
+
+ TInt error = ResetAndNotify(KErrCancel);
+
+ // Reset load data
+ if ( error )
+ {
+ User::Panic( KPanicCode(), error );
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// RunError
+// ---------------------------------------------------------------------------
+//
+TInt CDiagPluginPoolImpl::RunError( TInt aError )
+ {
+ // An unhandled exception occurs while running. Destroy all currently
+ // loaded plug-ins.
+
+ LOGSTRING2( "CDiagPluginPoolImpl::RunError %d", aError )
+
+ return ResetAndNotify( aError );
+ }
+
+// End of File
+