contextengine/src/contextengineao.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Fri, 19 Feb 2010 23:14:48 +0200
branchRCL_3
changeset 3 6752808b2036
parent 0 c53acadfccc6
permissions -rw-r--r--
Revision: 201003 Kit: 201007

/*
* Copyright (c) 2007-2009 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:
*
*/


#include <sbdefs.h>
#include <e32property.h>

#include "contextengineao.h"
#include "contextengine.h"
#include "contextsnapshotitem.h"
#include "harvesterlog.h"
#include "mdsutils.h"
#include "harvesterdata.h"
#include "propertywatcher.h" 
#include "harvestercommon.h"

// ---------------------------------------------------------------------------
// Default constructor for first phase construction.
// ---------------------------------------------------------------------------
//
CContextEngineAO::CContextEngineAO( 
		MContextInitializationObserver* aInitObserver,
		MContextSnapshotObserver* aSnapshotObserver ) : 
		CActive( KHarvesterPriorityContextEngine ), 
		iInitializationObserver( aInitObserver ), 
		iContextSnapshotObserver ( aSnapshotObserver ),
		iUninitializedPluginsCount( 0 ),
		iPluginSnapshotsLacking( 0 ),
		iItem( NULL ),
	    iState( EInitialization ),
	    iInitializationError( KErrNone ),
	    iSnapshotError( KErrNone ),
	    iMdESession( NULL ),
	    iPropertyWatcher( NULL ),
	    iLastPlugin( EFalse )
    {
    WRITELOG( "CContextEngineAO::CContextEngineAO" ); // DEBUG INFO
    }

// ---------------------------------------------------------------------------
// Standard NewL.
// ---------------------------------------------------------------------------
//
CContextEngineAO* CContextEngineAO::NewL(
    MContextInitializationObserver* aInitObserver,
    MContextSnapshotObserver* aSnapshotObserver )
    {
    WRITELOG( "CContextEngineAO::NewL" ); // DEBUG INFO

    CContextEngineAO* self = new (ELeave) CContextEngineAO( aInitObserver, aSnapshotObserver );
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop( self );
    return self;
    }

// ---------------------------------------------------------------------------
// 2nd phase construction.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::ConstructL()
    {
    WRITELOG( "CContextEngineAO::ConstructL" ); // DEBUG INFO

    CActiveScheduler::Add( this );

    iPropertyWatcher = CPropertyWatcher::GetInstanceL();
      
  	// Want to listen when backup/restore starts.
  	// Calls NotifyKeyL when key's state has changed. 
  	iPropertyWatcher->ListenKeyChangesL( 
  			KUidSystemCategory,
  			conn::KUidBackupRestoreKey, this );
      
    
    if ( !iInitializationObserver )
        {
        InitializeL();
        iState = EReady;
        }
    else  // same thing asyncronously
        {
        iState = EInitialization;
        SetActive();
        TRequestStatus* status = &iStatus;
        User::RequestComplete( status, KErrNone ); // "kick-start" this AO
        }
    }
// ---------------------------------------------------------------------------
// Destructor.
// ---------------------------------------------------------------------------
//
CContextEngineAO::~CContextEngineAO()
    {
    WRITELOG( "CContextEngineAO::~CContextEngineAO" ); // DEBUG INFO

    Cancel();

    MdsUtils::CleanupPtrArray<CContextPlugin>( &iPlugins );
	
    if( iPropertyWatcher )
		{
		
	 	iPropertyWatcher->StopListeningKeyChanges( 
	  			KUidSystemCategory,
	  			conn::KUidBackupRestoreKey, this );
		
		iPropertyWatcher->Delete(); // Release connection to TLS object.
		}
    }

// ---------------------------------------------------------------------------
// Set MdeSession for context engine plugins.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::SetMdeSession( CMdESession* aSession )
    {
    iMdESession = aSession;

    const TInt count( iPlugins.Count() );
    for ( TInt i = 0; i < count; ++i )
        {
        iPlugins[i]->SetMdeSession( *aSession );
        }
    }

// ---------------------------------------------------------------------------
// Start taking a context snapshot (for multiple objects).
// ---------------------------------------------------------------------------
//
void CContextEngineAO::StartSnapshot( CContextSnapshotItem* aItem )
    {
    WRITELOG( "CContextEngineAO::StartSnapshot" ); // DEBUG INFO
    iItem = aItem;
    if ( !aItem ) return;
    if ( !aItem->GetItem() && !aItem->GetItemArray() )
        {
        // no items to do the snapshot for... stop.
        aItem->GetObserver()->ContextSnapshotStatus( KErrNone );
        }

    iSnapshotError = KErrNone;
    iPluginSnapshotsLacking = iPlugins.Count(); // reset, no snapshots taken yet

    if ( iPluginSnapshotsLacking <= 0 )
    	{
    	iState = EReady;
    	iContextSnapshotObserver->ContextSnapshotStatus( KErrNone );    
    	}
    iLastPlugin = EFalse;
    
    iState = ESnapshot;
    SetActive();
    TRequestStatus* status = &iStatus;
    User::RequestComplete( status, KErrNone ); // "kick-start" this AO
    }

// ---------------------------------------------------------------------------
// Return loaded plugin count.
// ---------------------------------------------------------------------------
//
TInt CContextEngineAO::PluginCount()
    {
    return iPlugins.Count();
    }

// ---------------------------------------------------------------------------
// From CActive.
// Start/continue taking a context snapshot (for multiple objects).
// Ask a snapshot from one plugin at a time.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::RunL()
	{
#ifdef _DEBUG
    WRITELOG1( "CContextEngineAO::RunL iStatus: %d", iStatus.Int() ); // DEBUG INFO
#endif

    if ( iState == EInitialization )
        {
        InitializeL();
        }
    else if ( iState == ESnapshot )
        {
        if ( iStatus.Int() != KErrNone )
            {
            return;
            }

        if ( iPluginSnapshotsLacking > 0 )
            {
            TInt i = iPlugins.Count() - iPluginSnapshotsLacking;
            if( iPluginSnapshotsLacking == 1 )
                {
                iLastPlugin = ETrue;
                }
            if ( iItem->GetItemArray() ) 
                {
                iPlugins[i]->ContextSnapshot( *this, *iItem->GetItemArray() );  
                }                               // CContextEngineAO is instance of
            else                                // MContextPluginObserver
                {
                iPlugins[i]->ContextSnapshot( *this, *iItem->GetItem() );
                }
            iPluginSnapshotsLacking--;
            }
        }
    }

// ---------------------------------------------------------------------------
// From CActive.
// ---------------------------------------------------------------------------
//
#ifdef _DEBUG
TInt CContextEngineAO::RunError( TInt aError )
#else
TInt CContextEngineAO::RunError( TInt )
#endif
    {
    WRITELOG1( "CContextEngineAO::RunError with error code: %d", aError ); // DEBUG INFO
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// From CActive. 
// ---------------------------------------------------------------------------
//
void CContextEngineAO::DoCancel()
    {
    WRITELOG( "CContextEngineAO::DoCancel" ); // DEBUG INFO

    iPluginSnapshotsLacking = 0;
    iState = EReady;
    }

// ---------------------------------------------------------------------------
// From MContextPluginObserver.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::PluginInitializationStatus( TInt aErrorCode )
    {
    WRITELOG1( "CContextEngineAO::PluginInitializationStatus with error code: %d", aErrorCode ); // DEBUG INFO

    if ( aErrorCode != KErrNone && iInitializationError != KErrNone )
        {
        iInitializationError = aErrorCode;
        }

    iUninitializedPluginsCount--;
    if ( iUninitializedPluginsCount <= 0 )
        {
        iState = EReady;
        // notify the client application by using MContextSnapshotObserver's
        // method ContextInitializationStatus()
        // Notice! Error code of the last plugin is returned...
        if ( iInitializationObserver )
            {
            iInitializationObserver->ContextInitializationStatus( iInitializationError );
            }
        }
    }

// ---------------------------------------------------------------------------
// From MContextPluginObserver.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::PluginSnapshotStatus( CHarvesterData* aHD )
    {
    TInt errorCode = aHD->ErrorCode();
    WRITELOG1( "CContextEngineAO::PluginSnapshotStatus with error code: %d", errorCode ); // DEBUG INFO

    if ( errorCode != KErrNone && iSnapshotError != KErrNone )
        {
        aHD->SetErrorCode( errorCode );
        }
    
    if( iLastPlugin )
        {
        // Notice! Error code of the last plugin is returned...
        iContextSnapshotObserver->ContextSnapshotStatus( aHD );
        }

    if ( iPluginSnapshotsLacking <= 0 )
        {
        iState = EReady;
        }
    else 
        {  // do this again for the next plugin/harvest data object
        if( !IsActive() )
            {
            SetActive();
            TRequestStatus* status = &iStatus;
            User::RequestComplete( status, KErrNone ); // "kick-start" this AO
            }
        }
    }

// ---------------------------------------------------------------------------
// Called by CBlacklistBackupSubscriberAO when
// Backup&Restore is backing up or restoring.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::BackupRestoreStart()
    {
    // stop context plugins
    WRITELOG( "CContextEngineAO::BackupRestoreStart" );
 
    iPlugins.ResetAndDestroy(); // remove any existing plugins, just in case
    }

// ---------------------------------------------------------------------------
// Called by CBlacklistBackupSubscriberAO when
// Backup&Restore has finished backup or restore.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::BackupRestoreReady()
    {
    // restart plugins
    WRITELOG( "CContextEngineAO::BackupRestoreReady" );
    
    TRAP_IGNORE( InitializeL() );
    
    if ( iMdESession )
    	{
    	SetMdeSession( iMdESession );
    	}
    
    iState = EReady;
    
    }

// private methods

// ---------------------------------------------------------------------------
// Load context plugins to the "iPlugins" array.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::LoadPluginsL()
    {
    WRITELOG( "CContextEngineAO::LoadPluginsL" ); // DEBUG INFO

    if ( iPlugins.Count() > 0 )
        {
        iPlugins.ResetAndDestroy(); // remove any existing plugins, just in case
        }

    // read info about all implementations into infoArray
    RImplInfoPtrArray infoArray;
    TCleanupItem cleanupItem( MdsUtils::CleanupEComArray, &infoArray );
    CleanupStack::PushL( cleanupItem );
    
    CContextPlugin::ListImplementationsL( infoArray );

    CContextPlugin* plugin = NULL;
    TInt err = KErrNone;
    for ( TInt i = 0; i < infoArray.Count(); i++ )
        {
        TUid uid = infoArray[i]->ImplementationUid(); 
        TRAP( err, plugin = CContextPlugin::NewL( uid ) ); // create the plug-ins
        if ( err == KErrNone && plugin )
            {
            CleanupStack::PushL( plugin );
            iPlugins.AppendL( plugin );        // and add them to an array
            CleanupStack::Pop( plugin );
            }
        }

	CleanupStack::PopAndDestroy( &infoArray ); // infoArray, results in a call to CleanupEComArray		
    }

// ---------------------------------------------------------------------------
// Initialize this object. Thus load and initialize plugins.
// ---------------------------------------------------------------------------
//
void CContextEngineAO::InitializeL()
    {
    WRITELOG( "CContextEngineAO::InitializeL" ); // DEBUG INFO

    iInitializationError = KErrNone;
    LoadPluginsL();
    iUninitializedPluginsCount = iPlugins.Count(); // set this so we can later be sure that all
                                                   // plug-ins are initialized.
    if ( iUninitializedPluginsCount <= 0 ) // if no plugins were loaded
        {
        if ( iInitializationObserver )
            {
            iInitializationObserver->ContextInitializationStatus( KErrNone );
            }
        }

    const TInt KCount = iUninitializedPluginsCount;
    for ( TInt i = 0; i < KCount; i++ )
        {
        iPlugins[i]->Init( *this ); // CContextEngineAO is instance of MContextPluginObserver
        }
    }

// -----------------------------------------------------------------------------
// CRestoreWatcher::NotifyKeyL
// CPropertyWatcher's callback. From 
// -----------------------------------------------------------------------------
//
void CContextEngineAO::NotifyKeyL( 
		const TInt aKeyValue,
		const TUid aPropertyCategory,
		const TUint aKey )
	{
	WRITELOG("CContextEngineAO::NotifyKeyL() - begin");
	
	if( aPropertyCategory == KUidSystemCategory &&
			aKey == conn::KUidBackupRestoreKey ) 
		{
		HandleBackupRestoreKeyAction( aKeyValue );
		}
	
	
	WRITELOG("CContextEngineAO::NotifyKeyL() - end");
	}

// -----------------------------------------------------------------------------
// CContextEngineAO::HandleBackupKeyAction
// When user starts restore sets flag on.
// -----------------------------------------------------------------------------
//
void CContextEngineAO::HandleBackupRestoreKeyAction( const TUint aKeyValue )
	{	
	WRITELOG("CRestoreWatcher::HandleBackupKeyAction() - begin");
	
	TInt backupStateValue = aKeyValue;
	backupStateValue &= conn::KBURPartTypeMask;
	
	switch ( backupStateValue )
		{
		case conn::EBURBackupFull:
		case conn::EBURBackupPartial:
		case conn::EBURRestoreFull:
		case conn::EBURRestorePartial:
			{
			BackupRestoreStart();
			break;
			}
		
		case conn::EBURNormal:
		case conn::EBURUnset:
		default:
			{
			// backup or restore is completed, so resume normal operation.
       		BackupRestoreReady();
			}
		}	
	
	WRITELOG("CRestoreWatcher::HandleBackupKeyAction() - end");
	}