// 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 FILES
#include <featmgr/featurenotifier.h>
#include "featmgrdebug.h"
#include <featmgr/featurecmn.h>
#include "featmgrclient.h"
// ============================= LOCAL FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// FindByUid
// Returns Zero if UIDs do match.
// -----------------------------------------------------------------------------
//
static TInt FindByUid( const TUid* aFeature, const TUid& aItem )
{
if ( aFeature->iUid == aItem.iUid )
{
return 1;
}
return 0;
}
// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CFeatureNotifier::CFeatureNotifier()
// -----------------------------------------------------------------------------
//
CFeatureNotifier::CFeatureNotifier( MFeatureObserver& aObserver ) :
CActive( EPriorityStandard ),
iObserver( aObserver )
{
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::NewL()
// Two-phased constructor.
// -----------------------------------------------------------------------------
//
EXPORT_C CFeatureNotifier* CFeatureNotifier::NewL( MFeatureObserver& aObserver )
{
CFeatureNotifier* self = new( ELeave ) CFeatureNotifier( aObserver );
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop( self );
return self;
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::ConstructL
// -----------------------------------------------------------------------------
//
void CFeatureNotifier::ConstructL()
{
FUNC_LOG
iFeatMgrClient = new (ELeave) RFeatMgrClient;
// Connect to Feature Manager server
TInt err( iFeatMgrClient->Connect() );
User::LeaveIfError(err);
CActiveScheduler::Add( this );
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::~CFeatureNotifier()
// -----------------------------------------------------------------------------
//
EXPORT_C CFeatureNotifier::~CFeatureNotifier()
{
FUNC_LOG
if( iFeatMgrClient )
{
iFeatMgrClient->RequestNotifyCancelAll();
iFeatMgrClient->Close();
delete iFeatMgrClient;
}
Cancel();
iFeatures.Close();
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::NotifyRequest(TUid)
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CFeatureNotifier::NotifyRequest( TUid aFeature )
{
if(IsActive())
{
return KErrAlreadyExists;
}
iFeatures.Reset();
iFeatures.Append( aFeature );
TInt err = iFeatMgrClient->RequestNotification( iFeatures, iFeatureChanged, iStatus );
if ( err == KErrNone )
{
SetActive();
}
return err;
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::NotifyRequest(RFeatureUidArray&)
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CFeatureNotifier::NotifyRequest( RFeatureUidArray& aFeatures )
{
if(IsActive())
{
return KErrAlreadyExists;
}
iFeatures.Reset();
TInt count = aFeatures.Count();
for(TInt i = 0; i < count; i++ )
{
// Do not append duplicate entries
const TUid& uid( aFeatures[i] );
TInt index = iFeatures.Find( uid, FindByUid );
if( index == KErrNotFound )
{
iFeatures.Append( uid );
}
}
TInt err = iFeatMgrClient->RequestNotification( iFeatures, iFeatureChanged, iStatus );
if ( err == KErrNone )
{
SetActive();
}
return err;
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::NotifyCancel(TUid aFeature)
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CFeatureNotifier::NotifyCancel( TUid aFeature )
{
TInt err( KErrNotFound );
TInt count = iFeatures.Count();
for(TInt i = 0; i < count; i++ )
{
if( iFeatures[i].iUid == aFeature.iUid )
{
err = iFeatMgrClient->RequestNotifyCancel( aFeature );
if( err == KErrNone )
{
iFeatures.Remove( i );
// If this is the last feature in the list, then also cancel the Active Object
if( 0 == iFeatures.Count() )
{
Cancel();
}
break;
}
}
}
return err;
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::NotifyCancelAll()
// -----------------------------------------------------------------------------
//
EXPORT_C TInt CFeatureNotifier::NotifyCancelAll()
{
iFeatures.Reset();
TInt err = iFeatMgrClient->RequestNotifyCancelAll( );
Cancel();
return err;
}
/**
Gets the number of features in the server's array.
This API is only for internal use and testing purposes.
@return The number of features on the server for debug builds, otherwise it returns KErrNotSupported in release builds.
@internalComponent
*/
EXPORT_C TInt CFeatureNotifier::NumberOfNotifyFeatures()
{
#ifdef EXTENDED_FEATURE_MANAGER_TEST
TInt count = iFeatMgrClient->NumberOfNotifyFeatures();
return count;
#else
return KErrNotSupported;
#endif
}
/**
Gets the number of heap cells in the thread.
This API is only for internal use and testing purposes.
@return The number of heap cells for debug build, otherwise it returns KErrNotSupported in release builds.
@internalComponent
*/
EXPORT_C TInt CFeatureNotifier::CountAllocCells()
{
#ifdef EXTENDED_FEATURE_MANAGER_TEST
TInt count = iFeatMgrClient->CountAllocCells();
return count;
#else
return KErrNotSupported;
#endif
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::RunL()
// -----------------------------------------------------------------------------
//
void CFeatureNotifier::RunL( )
{
FUNC_LOG
TInt status = iStatus.Int();
if( status < 0 )
{
// Got an error
if( status != KErrCancel )
{
iObserver.HandleNotifyError( status );
}
return;
}
// iStatus >= 0 means it contains the change type
TFeatureChangeType changeType = static_cast<TFeatureChangeType>(status);
// If the feature was deleted, remove it from the array of features with notifications requested
if( changeType == EFeatureFeatureDeleted )
{
TInt index = iFeatures.Find( iFeatureChanged, FindByUid );
if( index != KErrNotFound )
{
iFeatures.Remove( index );
}
}
// Should we validate whether iFeatureChanged matches
// to any UID in the array of requested features?
TFeatureEntry feature( iFeatureChanged );
if( iFeatures.Count() > 0 )
{
// Asynchronously resubscribe notify request
iFeatMgrClient->ReRequestNotification( iFeatureChanged, iStatus );
// Next inform client about changed feature
// Should we validate whether iFeatureChanged matches
// to any UID in the array of requested features
iObserver.HandleNotifyChange( changeType, feature );
// Set us active
SetActive();
}
else
{
// All features with notifications requested were deleted,
// so don't need to resubscribe notify request -
// just notify client about the deleted feature
iObserver.HandleNotifyChange( changeType, feature );
}
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::DoCancel()
// -----------------------------------------------------------------------------
//
void CFeatureNotifier::DoCancel( )
{
}
// -----------------------------------------------------------------------------
// CFeatureNotifier::RunError()
// -----------------------------------------------------------------------------
//
TInt CFeatureNotifier::RunError( TInt aError )
{
iObserver.HandleNotifyError( aError );
return KErrNone;
}
// End of File