// 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