idlefw/src/framework/aipluginfactory.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:53:46 +0300
branchRCL_3
changeset 130 67f2ed48ad91
parent 118 8baec10861af
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
* Copyright (c) 2005-2006 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:  Content plugin manager class for Active idle framework.
*
*/

// System includes
#include <ecom/ecom.h>
#include <ecom/implementationinformation.h>

// User includes
#include <aisystemuids.hrh>
#include <aifwpublisherinfo.h>
#include <hscontentpublisher.h>
#include <hspublisherinfo.h>
#include <aicontentobserver.h>
#include <aiuicontroller.h>
#include "caicpscommandbuffer.h"
#include "aiuicontrollermanager.h"
#include "aistatemanager.h"
#include "aipluginfactory.h"
#include "debug.h"

// Constants
const TUid KDeviceStatusPluginUid = 
    { AI_UID_ECOM_IMPLEMENTATION_CONTENTPUBLISHER_DEVSTAPLUGIN };

const TUid KProfilePluginUid =
    { AI_UID_ECOM_IMPLEMENTATION_CONTENTPUBLISHER_PROFILEPLUGIN };

const TUid KSapiPluginImplUid = { 0x20019594 };                
const TUid KWrtPluginImplUid = { 0x200286DD };                          

_LIT( KDeviceStatusPluginName, "DeviceStatus" );
_LIT( KProfilePluginName, "Profile" );

const TInt KQueueStartInterval( 500000 );

// ======== LOCAL FUNCTIONS ========
// ----------------------------------------------------------------------------
// IsRecyclable()
//
// ----------------------------------------------------------------------------
//
TBool IsRecyclable( const THsPublisherInfo& aInfo )
    {
    if ( ( aInfo.Name() == KProfilePluginName && 
        aInfo.Uid() == KProfilePluginUid ) ||
        ( aInfo.Name() == KDeviceStatusPluginName &&
        aInfo.Uid() == KDeviceStatusPluginUid ) )
        {
        return ETrue;
        }
    
    return EFalse;
    }

// ----------------------------------------------------------------------------
// IsSapiOrWrt()
//
// ----------------------------------------------------------------------------
//
TBool IsSapiOrWrt( const THsPublisherInfo& aInfo )
    {
    return ( aInfo.Uid() == KSapiPluginImplUid || 
             aInfo.Uid() == KWrtPluginImplUid );             
    }

// ----------------------------------------------------------------------------
// CleanupResetAndDestroy()
//
// ----------------------------------------------------------------------------
//
template< class T >
static void CleanupResetAndDestroy( TAny* aObj )
    {        
    static_cast< T* >( aObj )->ResetAndDestroy();    
    }

// ----------------------------------------------------------------------------
// CleanupResetAndDestroyPushL()
//
// ----------------------------------------------------------------------------
//
template< class T >
static void CleanupResetAndDestroyPushL( T& aArray )
    {
    CleanupStack::PushL( 
        TCleanupItem( &CleanupResetAndDestroy< T >, &aArray ) );
    }
    
// ======== MEMBER FUNCTIONS ========    

// ----------------------------------------------------------------------------
// CAiPluginFactory::CAiPluginFactory()
//
// ----------------------------------------------------------------------------
//
CAiPluginFactory::CAiPluginFactory( CAiUiControllerManager& aManager )
    : CTimer( CActive::EPriorityUserInput - 1 ), 
      iUiControllerManager( aManager ), iAllowFlush( ETrue )
    {
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::~CAiPluginFactory()
//
// ----------------------------------------------------------------------------
//
CAiPluginFactory::~CAiPluginFactory()
    {
    Cancel();
    
    delete iStarter;
    
    delete iCommandBuffer;
    
    iLoadQueue.Reset();
    iDestroyQueue.Reset();
    
    // All publishers should be already deleted from CAiFw::HandleUiShutdown       
    iPublishers.ResetAndDestroy();
    
    iEComPlugins.ResetAndDestroy();        
    
    REComSession::FinalClose();
    }
    
// ----------------------------------------------------------------------------
// CAiPluginFactory::NewL()
//
// ----------------------------------------------------------------------------
//
CAiPluginFactory* CAiPluginFactory::NewL( CAiUiControllerManager& aManager )
    {
    return new ( ELeave ) CAiPluginFactory( aManager ); 
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::ConstructL()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::ConstructL()
    {             
    ListImplementationsL();
    
    iCommandBuffer = CAiCpsCommandBuffer::NewL();
    
    // Ensure interface is available
    iCommandBuffer->GetCPSInterfaceL();
    
    CActiveScheduler::Add( this );
    
    CTimer::ConstructL();
    
    iStarter = CPeriodic::NewL( CActive::EPriorityIdle );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::ListImplementationsL()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::ListImplementationsL()
    {
    iEComPlugins.ResetAndDestroy();
    
    REComSession::ListImplementationsL( 
        KInterfaceUidHsContentPlugin, iEComPlugins );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::LoadPlugin()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::LoadPlugin( const TAiFwPublisherInfo& aInfo )
    {    
    const THsPublisherInfo& info( aInfo.Info() );
    
    for ( TInt i = 0; i < iDestroyQueue.Count(); i++ )
        {
        if ( iDestroyQueue[i] == info )
            {
            iDestroyQueue.Remove( i );
            break;
            }
        }
           
    if ( IsSapiOrWrt( info ) || IsRecyclable( info ) || !PluginByInfo( info ) )
        {
        TBool append( ETrue );
        
        for ( TInt i = 0; i < iLoadQueue.Count(); i++ )       
            {
            if ( iLoadQueue[i] == info )
                {                
                append = EFalse;
                break;
                }
            }    
                
        // Plugin is not in load queue and is not currently loaded
        if( append )
            {                               
            iLoadQueue.Append( aInfo );
                        
            HandleQueueChanged();
            }    
        }    
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DestroyPlugin()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::DestroyPlugin( const TAiFwPublisherInfo& aInfo )
    {
    const THsPublisherInfo& info( aInfo.Info() );
           
    for ( TInt i = 0; i < iLoadQueue.Count(); i++ )
        {
        if ( iLoadQueue[i] == info )
            {
            iLoadQueue[i].Callback( KErrCancel );
            
            iLoadQueue.Remove( i );                       
            break;
            }
        }
        
    if ( PluginByInfo( info ) )
        {
        TBool append( ETrue );
        
        for ( TInt i = 0; i < iDestroyQueue.Count(); i++ )
            {
            if ( iDestroyQueue[i] == info )
                {
                append = EFalse;
                break;
                }        
            }
        
        // Plugin is not in destroy queue and is currently loaded
        if ( append )
            {                       
            iDestroyQueue.Append( aInfo );
            
            HandleQueueChanged();
            }    
        } 
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::HandleQueueChanged()
// 
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::HandleQueueChanged()
    {
    __PRINTS( "CAiPluginFactory::HandleQueueChanged" );

    if ( iLoadQueue.Count() == 0 && iDestroyQueue.Count() == 0 )
        {
        __PRINTS( "CAiPluginFactory::HandleQueueChanged - done, queues empty" );
        
        return;
        }
            
    Cancel();
    iStarter->Cancel();

    __PRINTS( "CAiPluginFactory::HandleQueueChanged, iStarter->Start()" );

    if ( iLoadQueue.Count() == 1 && iDestroyQueue.Count() == 0 &&
        iLoadQueue[0].Reason() == EAiFwPluginStartup )
        {
        ProcessQueue( this );
        }
    else
        {
        iStarter->Start( KQueueStartInterval, 0, 
            TCallBack( ProcessQueue, this ) );        
        }               

    __PRINTS( "CAiPluginFactory::HandleQueueChanged - done" );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DoCreatePlugin()
//
// ----------------------------------------------------------------------------
//
TInt CAiPluginFactory::DoCreatePlugin( 
    const TAiFwPublisherInfo& aPublisherInfo )
    {
    __PRINTS( "*** CAiPluginFactory::DoCreatePlugin: Start ***" );

    const THsPublisherInfo& info( aPublisherInfo.Info() );
    
    if ( IsRecyclable( info ) )
        {
        CHsContentPublisher* plugin( PluginByUid( info.Uid() ) );

        if ( plugin )
            {
            if ( info.Namespace() == KNullDesC8 )
                {
                // No namespace available
                __PRINTS( "*** CAiPluginFactory::CreatePlugin: Done -\
                               Failed to Load Plug-in: KErrNotSupported ***" );
                return KErrNotSupported;
                }

            // Plugin already exists, update its namespace
            THsPublisherInfo& pubinfo( 
                const_cast< THsPublisherInfo& >( plugin->PublisherInfo() ) );

            pubinfo.iNamespace.Copy( info.Namespace() );

            __PRINTS( "*** CAiPluginFactory::CreatePlugin: Done -\
                           Plugin recycled ***" );

            return KErrNone;
            }
        }

    TBool implFound( EFalse );

    for( TInt i = 0; i < iEComPlugins.Count(); i++ )
        {
        CImplementationInformation* information( iEComPlugins[i] );

        if( information->ImplementationUid() == info.Uid() )
            {
            implFound = ETrue;
            break;
            }
        }
    
    if( info.Namespace() == KNullDesC8 || !implFound )
        {
        // No namespace available or no ecom implementation available
        __PRINTS( "*** CAiPluginFactory::CreatePlugin: Done -\
                       Failed to Load Plug-in: KErrNotSupported ***" );
        
        return KErrNotSupported;
        }
           
    CHsContentPublisher* plugin( PluginByInfo( info ) );

    if( plugin )
        {
        __PRINTS( "*** CAiPluginFactory::CreatePlugin: Done -\
                       No need to Load Plug-in: KErrAlreadyExists ***" );
        
        return KErrAlreadyExists;
        }

    TInt err( KErrNone );

    TRAP( err, DoCreatePluginL( aPublisherInfo ) );
    
    __PRINTS( "*** CAiPluginFactory::CreatePlugin: Done - Load Plug-in ***" );

    return err;
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DoDestroyPlugin()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::DoDestroyPlugin( 
    const TAiFwPublisherInfo& aPublisherInfo )                             
    {
    __PRINTS( "*** CAiPluginFactory::DoDestroyPlugin: Start ***" );
    
    const THsPublisherInfo& info( aPublisherInfo.Info() );
      
    if ( IsRecyclable( info ) )
        {
        // Don't destroy recyclable plugin
        __PRINTS( "*** CAiPluginFactory::DestroyPlugin: Done - Keeping recyclable Plug-in ***" );
        
        return;
        }
   
    if ( IsSapiOrWrt( info ) )
        {
        if ( aPublisherInfo.Reason() == EAiFwPageShutdown )
            {
            // Don't destroy sapi or wrt plugin when page is changed        
            __PRINTS( "*** CAiPluginFactory::DestroyPlugin: Done - Keeping SAPI/WRT plugin ***" );
            
            return;
            }
        }
               
    CHsContentPublisher* plugin( PluginByInfo( info ) );
    
    if ( plugin )
        {
        iPublishers.Remove( iPublishers.Find( plugin ) );
        
        delete plugin;
        plugin = NULL;            
        }
    
    __PRINTS( "*** CAiPluginFactory::DestroyPlugin: Done ***" );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DestroyPlugin()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::DestroyPlugin( const TUid& aUid )
    {
    __PRINTS( "*** CAiPluginFactory::DestroyPlugin: Start ***" );
    
    CHsContentPublisher* plugin( PluginByUid( aUid ) );
    
    if ( plugin )
        {                
        iPublishers.Remove( iPublishers.Find( plugin ) );
        
        __PRINT( __DBG_FORMAT( 
            "CAiPluginFactory::DestroyPlugin: name: %S" ), 
                &plugin->PublisherInfo().Name() ); 

        delete plugin;
        plugin = NULL;                
        }
    
    __PRINTS( "*** CAiPluginFactory::DestroyPlugin: Done ***" );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DestroyAllPlugins()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::DestroyAllPlugins()
    {       
    Cancel();
    iStarter->Cancel();
    
    iLoadQueue.Reset();
    iDestroyQueue.Reset();
           
    for ( TInt i = 0; i < iPublishers.Count(); i++ )
        {
        CHsContentPublisher* plugin( iPublishers[i] );
    
        // Do shutdown state transition
        iStateManager->StopPlugin( *plugin, EAiFwSystemShutdown );        
        }    
    
    FlushCommandBuffer();
    
    // Finally get rid of all plugins
    iPublishers.ResetAndDestroy();
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DoCreatePluginL()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::DoCreatePluginL(
    const TAiFwPublisherInfo& aPublisherInfo )
    {       
    const THsPublisherInfo& info( aPublisherInfo.Info() );
    
    __PRINT( __DBG_FORMAT( "\t[I]\t Loading plug-in uid=%x name=%S"), 
    info.Uid(), &(info.Name() ) );

    iPublishers.ReserveL( iPublishers.Count() + 1 );
    
    CHsContentPublisher* plugin( NULL );
    
    __TIME( "CAiPluginFactory::CreatePluginL Create plug-in:",                                  
    plugin = CHsContentPublisher::NewL( info ) );            
    
    CleanupStack::PushL( plugin );
    
    if ( IsSapiOrWrt( info ) )
        {
        plugin->SetProperty( CHsContentPublisher::ECpsCmdBuffer, 
            static_cast< MAiCpsCommandBuffer* >( iCommandBuffer ) );    
        }
    
    __TIME( "FW: Subscribe content observers",    
    SubscribePluginL( *plugin, info ) );             
                                                      
    __TIME( "FW: Configure Plugin",
    ConfigurePluginL( *plugin, info ) );
    
    // Take plugin's ownership
    iPublishers.Append( plugin );
    CleanupStack::Pop( plugin );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::SubscribePluginL()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::SubscribePluginL(
    CHsContentPublisher& aContentPublisher,        
    const THsPublisherInfo& aPublisherInfo )    
    {
    RPointerArray< CAiUiController >& 
        controllers( iUiControllerManager.UiControllers() );
            
    for( TInt i = 0; i < controllers.Count(); i++ )
        {
        MAiContentObserver& observer( 
            controllers[i]->GetContentObserver() );
        
        if ( observer.RequiresSubscription( aPublisherInfo ) )
            {
			// Subscribe observer only if it understands the plugin
            aContentPublisher.SubscribeL( observer );
            }                   
        }
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::ConfigurePluginL()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::ConfigurePluginL(     
    CHsContentPublisher& aContentPublisher,
    const THsPublisherInfo& aPublisherInfo )
    {    
    RAiSettingsItemArray settings;
    CleanupResetAndDestroyPushL( settings );
    
    RPointerArray< CAiUiController >& 
        controllers( iUiControllerManager.UiControllers() );
    
    for( TInt i = 0; i < controllers.Count(); i++ )
        {
        // Get settings for plug-in        
        controllers[i]->GetSettingsL( aPublisherInfo, settings );
        }
    
    // Configure plug-in with its settings
    aContentPublisher.ConfigureL( settings );
    
    CleanupStack::PopAndDestroy( &settings );    
    }
        
// ----------------------------------------------------------------------------
// CAiPluginFactory::PluginByInfo()
// Gets plugin by publisher info. Only this overload returns the exact match
// ----------------------------------------------------------------------------
//
CHsContentPublisher* CAiPluginFactory::PluginByInfo( 
    const THsPublisherInfo& aPublisherInfo ) const
    {       
    for( TInt i = 0; i < iPublishers.Count(); i++ )
        {         
        const THsPublisherInfo& info( iPublishers[i]->PublisherInfo() ); 
                                                                             
        if( aPublisherInfo == info ) 
            {
            return iPublishers[i];
            }
        }
    
    return NULL;
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::PluginByUid()
// Gets plugin by UID
// ----------------------------------------------------------------------------
//
CHsContentPublisher* CAiPluginFactory::PluginByUid( const TUid& aUid ) const
    {
    for( TInt i = 0; i < iPublishers.Count(); i++ )
        {
        const THsPublisherInfo& info( iPublishers[i]->PublisherInfo() );
                                                               
        if( info.Uid() == aUid )
            {
            return iPublishers[i];            
            }
        }
    
    return NULL;        
    }
    
// ----------------------------------------------------------------------------
// CAiPluginFactory::PluginByName()
// Gets plugin by name
// ----------------------------------------------------------------------------
//
CHsContentPublisher* CAiPluginFactory::PluginByName( 
    const TDesC& aName ) const
    {
    for( TInt i = 0; i < iPublishers.Count(); i++ )
        {
        const THsPublisherInfo& info( iPublishers[i]->PublisherInfo() );
                                                               
        if( info.Name() == aName )
            {
            return iPublishers[i];            
            }
        }
    
    return NULL;    
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::Publishers()
//
// ----------------------------------------------------------------------------
//
RPointerArray< CHsContentPublisher >& CAiPluginFactory::Publishers() const
    {
    return iPublishers;
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::SetStateManager()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::SetStateManager( CAiStateManager* aStateManager )
    {
    iStateManager = aStateManager;
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::FlushCommandBuffer()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::FlushCommandBuffer()
    {
    __PRINTS( "CAiPluginFactory::FlushCommandBuffer" );
    
    if ( iCommandBuffer && iAllowFlush && !IsActive() )
        {
        iCommandBuffer->Flush();
        }
    
    __PRINTS( "CAiPluginFactory::FlushCommandBuffer - done" );
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::ProcessQueue()
//
// ----------------------------------------------------------------------------
//
/* static */ TInt CAiPluginFactory::ProcessQueue( TAny* aAny )
    {
    CAiPluginFactory* self = static_cast< CAiPluginFactory* >( aAny );
    
    self->iStarter->Cancel();
    
    if ( !self->IsActive() )
        {
        self->After( 0 );
        }
    
    return KErrNone;
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::RunL()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::RunL()
    {
    __PRINTS( "CAiPluginFactory::RunL" );
    
    if ( iStarter->IsActive() )
        {
        __PRINTS( "CAiPluginFactory::RunL - done, iStarter->IsActive()" );
        
        return;
        }
    
    iAllowFlush = EFalse;
           
    if ( iDestroyQueue.Count() > 0 )
        {        
        TAiFwPublisherInfo info( iDestroyQueue[ 0 ] );         
        iDestroyQueue.Remove( 0 );
               
        // Resolve plugin
        CHsContentPublisher* plugin( PluginByInfo( info.Info() ) ); 

        if ( plugin )
            {                  
            // Do shutdown state transition
            iStateManager->StopPlugin( *plugin, info.Reason() );
            
            // Destroy plugin
            DoDestroyPlugin( info );                        
            }        
        }
    else if ( iLoadQueue.Count() > 0 )
        {
        TAiFwPublisherInfo info( iLoadQueue[ 0 ] );            
        iLoadQueue.Remove( 0 );
    
        // Create plugin
        TInt retval( DoCreatePlugin( info ) );
        
        if ( retval == KErrNone || retval == KErrAlreadyExists )
            {
            CHsContentPublisher* plugin( PluginByInfo( info.Info() ) );
            
            if( plugin )
                {
                // Do startup state transition    
                iStateManager->StartPlugin( *plugin, info.Reason() );                
                }    
            else
                {
                retval = KErrNotFound;
                }            
            }
        
        info.Callback( retval );
        }

    iAllowFlush = ETrue;
    
    After( 0 );
    
    if ( iLoadQueue.Count() == 0 && iDestroyQueue.Count() == 0 )
        {
        __PRINTS( "CAiPluginFactory::RunL - queues now empty" );
        
        Cancel();
        
        FlushCommandBuffer();                             
        }
    
    __PRINTS( "CAiPluginFactory::RunL - done" );    
    }

// ----------------------------------------------------------------------------
// CAiPluginFactory::DoCancel()
//
// ----------------------------------------------------------------------------
//
void CAiPluginFactory::DoCancel()
    {
    __PRINTS( "CAiPluginFactory::DoCancel" );       
    }

// End of file