featuremgmt/featuremgr/src/serverexe/featmgrfeatureregistry.cpp
changeset 0 08ec8eefde2f
child 9 667e88a979d7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/featuremgmt/featuremgr/src/serverexe/featmgrfeatureregistry.cpp	Fri Jan 22 11:06:30 2010 +0200
@@ -0,0 +1,1551 @@
+// 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 <ecom/ecom.h>
+#include <e32uid.h>
+#include <f32file.h>
+#include <e32property.h>
+#include <sacls.h>
+#include "featmgrconfiguration.h"
+#include "featmgrfeatureregistry.h"
+#include "featmgrserver.h"
+#include "featmgrdebug.h"
+
+#define MAXSWIOPS 50
+#define SWITIMEOUT 15000000
+
+// CONSTANTS
+_LIT( KZFeaturesFileNameMatch, "feature*" );
+_LIT( KCRuntimeFeaturesFileName, "features.dat" );
+#ifdef EXTENDED_FEATURE_MANAGER_TEST
+_LIT( KZFeaturesDir, "C:\\Private\\102836E5\\" );
+_LIT( KCFeatMgrPrivatePath, "?:\\Private\\102836E5\\runtime\\" );
+#else
+_LIT( KZFeaturesDir, "Z:\\Private\\10205054\\" );
+_LIT( KCFeatMgrPrivatePath, "?:\\Private\\10205054\\" );
+#endif // EXTENDED_FEATURE_MANAGER_TEST
+
+const TUint32 KDefaultData( 0x00000000 );
+// Feature file header constants. 
+// First 4 bytes of config file: ASCII f-e-a-t followed by file version and flags.
+const TUint32 KFileType( 0x74616566 );
+const TUint16 KFileVersion( 1 );
+const TUint16 KFileFlags( 0 );
+
+
+// ============================= LOCAL FUNCTIONS ===============================
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::CFeatMgrFeatureRegistry
+// -----------------------------------------------------------------------------
+//
+CFeatMgrFeatureRegistry::CFeatMgrFeatureRegistry( RFs& aFs,
+    MFeatMgrRegistryObserver& aObserver  )
+    :
+    iObserver( aObserver ),
+    iFs( aFs ),
+    iSWICacheFeature( EFalse ),
+    iSWIStatus( ESWIComplete ),
+    iSWIProcessId( 1 ),
+    iOomOccured(EFalse)
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::ConstructL()
+    {
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CFeatMgrFeatureRegistry* CFeatMgrFeatureRegistry::NewL( RFs& aFs, 
+    MFeatMgrRegistryObserver& aObserver )
+    {
+    CFeatMgrFeatureRegistry* self = 
+        new( ELeave ) CFeatMgrFeatureRegistry( aFs, aObserver );
+    
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// Destructor
+// -----------------------------------------------------------------------------
+//
+CFeatMgrFeatureRegistry::~CFeatMgrFeatureRegistry()
+    {
+    FUNC_LOG
+    
+    iFeatureList.Close();
+    iRangeList.Close();
+    iFeatureListBackup.Close();    
+    iSWICachedOperations.Close();
+    if( iSWIListener )
+    	{
+        delete iSWIListener;    	
+    	}
+    if( iSWITimer )
+    	{
+    	delete iSWITimer;
+    	}
+    }
+
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::IsFeatureSupported
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::IsFeatureSupported( TFeatureServerEntry& aFeature )
+    {
+    TInt err( KErrNotFound );
+    const TInt index = SearchFeature( aFeature.FeatureUid() );
+    
+    if ( index == KErrNotFound )
+        {
+        // Check whether feature in supported ranges
+        TInt count( iRangeList.Count() );
+        TUid uid( aFeature.FeatureUid() );
+        for( TInt i = 0; i < count; i++ )
+            {
+            if( (uid.iUid >= iRangeList[i].iLowUid.iUid) && 
+                (uid.iUid <= iRangeList[i].iHighUid.iUid) )
+                {
+                TBitFlags32 flags( 0 );
+                flags.Assign( EFeatureSupported, KFeatureSupported );
+                TFeatureServerEntry entry( aFeature.FeatureUid(), flags, KDefaultData );
+                aFeature = entry;
+                err = KFeatureSupported;
+                break;
+                }
+            }
+        }
+    else if( IsFlagSet( index, EFeatureUninitialized ) )
+        {
+        // Supported status bit is not taken into account if feature not yet initialized
+        err = KErrNotReady;
+        }
+    else if ( (index < iFeatureList.Count()) && IsFlagSet( index, EFeatureSupported ) )
+        {
+        TBitFlags32 flags = iFeatureList[index].FeatureFlags();
+        flags.Assign( EFeatureSupported, KFeatureSupported );
+        TUint32 data = iFeatureList[index].FeatureData();
+        TFeatureServerEntry entry( aFeature.FeatureUid(), flags, data );
+        aFeature = entry;
+        err = KFeatureSupported;
+        }
+    else
+        {
+        err = KFeatureUnsupported;
+        }
+
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::AddFeature
+// -----------------------------------------------------------------------------
+//
+TInt CFeatMgrFeatureRegistry::AddFeature( TFeatureServerEntry& aFeature, TUint aPrcId )
+    {
+    TInt err( KErrAccessDenied );
+    
+    if( iSWIProcessId == aPrcId && iSWICacheFeature )
+		{
+		err = SWICacheCommand(ESWIAddFeat, aFeature);
+		}
+    else
+    	{
+        const TInt index = SearchFeature( aFeature.FeatureUid() );
+	
+	    if ( index == KErrNotFound )
+	        {
+	        TBitFlags32 flags( aFeature.FeatureFlags() );
+	        flags.Set( EFeatureRuntime );
+	
+	        //Check the feature falg is valid
+	        TRAP(err, err = ValidateRuntimeFeatureFlagL(flags));
+	        if (err != KErrNone)
+	            return err;
+	
+	        TFeatureServerEntry entry( aFeature.FeatureUid(), flags, aFeature.FeatureData() );	       
+			err = iFeatureList.InsertInOrder( entry, FindByUid );
+	        if ( err == KErrNone )
+	            {
+	            TFeatureChangeType changeType( EFeatureFeatureCreated );
+	            err = HandleChange( entry, changeType );
+	            }
+	        }
+	    else
+	        {
+	        err = KErrAlreadyExists;
+	        }
+	    
+	    INFO_LOG("CFeatMgrFeatureRegistry::AddFeature - Features directly stored in registry");
+    	}
+    
+    LOG_IF_ERROR1( err, "CFeatMgrFeatureRegistry::AddFeature - result %d", err );
+
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::DeleteFeature
+// -----------------------------------------------------------------------------
+//
+TInt CFeatMgrFeatureRegistry::DeleteFeature( TUid aFeature, TUint aPrcId  )
+    {
+    TInt err( KErrAccessDenied );
+	
+    if( iSWIProcessId == aPrcId && iSWICacheFeature )
+    	{
+    	err = SWICacheCommand(ESWIDeleteFeat, aFeature);
+    	}
+    else
+    	{
+	    // Check if the feature is runtime
+	    TInt index = SearchFeature( aFeature );
+	    if ( index == KErrNotFound )
+	        {
+	        return KErrNotFound;
+	        }
+	    if ( !iFeatureList[index].FeatureFlags().IsSet(EFeatureRuntime) )
+	        {
+	        return KErrAccessDenied;
+	        }
+	
+	    TFeatureServerEntry entry = iFeatureList[index];
+	    
+    	iFeatureList.Remove( index );
+        TFeatureChangeType changeType( EFeatureFeatureDeleted );
+        err = HandleChange( entry, changeType );
+        
+        INFO_LOG("CFeatMgrFeatureRegistry::DeleteFeature - Features deleted directly from registry");
+        }
+    
+    LOG_IF_ERROR1( err, "CFeatMgrFeatureRegistry::DeleteFeature - result %d", err );
+    
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SetFeature
+//This method cannot set feature flag range in DSR unless it is added to before
+//using CFeatMgrFeatureRegistry::AddFeature()
+// -----------------------------------------------------------------------------
+//	
+TInt CFeatMgrFeatureRegistry::SetFeature( TUid aFeature, TInt aEnable, const TUint32 *aData, TUint aPrcId  )
+    {
+    FUNC_LOG
+
+    TInt err( KErrNone );
+    
+    if( iSWIProcessId == aPrcId && iSWICacheFeature )
+    	{
+		TBitFlags32 flags(0);
+    	flags.Assign( EFeatureSupported, aEnable );
+    	TFeatureServerEntry entry( aFeature, flags, *aData );    
+	    err = SWICacheCommand(ESWISetFeatAndData, entry);
+    	}
+    else 
+    	{
+	    TInt index;
+	
+	    // Validate feature exists and is modifiable
+	    err = ValidateFeature( aFeature, index );
+	
+	    if ( err != KErrNone )
+	        {
+			return err;
+	        }
+	
+	    if ( (index >= 0 && index < iFeatureList.Count()) )
+	        {
+        	TBitFlags32 flags = iFeatureList[index].FeatureFlags();
+	        TUint32 data = iFeatureList[index].FeatureData();
+	        TFeatureChangeType changeType( EFeatureStatusUpdated );
+
+	        // Update "supported" info according to request
+	        if( (aEnable == EFeatureSupportEnable) || (aEnable == EFeatureSupportDisable) )
+	            {
+	            INFO_LOG1( "CFeatMgrFeatureRegistry::SetFeature() - aEnable %d", aEnable );
+	            flags.Assign( EFeatureSupported, aEnable );
+	            }
+	        // When setting feature, always unset "uninitialized" bit
+	        flags.Assign( EFeatureUninitialized, 0 );
+
+	        // Update data whenever applied
+	        if( aData )
+	            {
+	            INFO_LOG1( "CFeatMgrFeatureRegistry::SetFeature() - aData %d", aData );
+	            data = *aData;
+
+	            if( aEnable == EFeatureSupportUntouch )
+	                {
+	                changeType = EFeatureDataUpdated;
+	                }
+	            else
+	                {
+	                changeType = EFeatureStatusDataUpdated;
+	                }
+	            }
+
+	        TFeatureServerEntry entry( aFeature, flags, data );
+	        //Check if the feature will actually change
+	        if(iFeatureList[index].FeatureFlags() == flags && iFeatureList[index].FeatureData() == data )
+	        	{
+	        	//No change were made, set change type to EFeatureNoChange
+	        	changeType = EFeatureNoChange;
+	        	}
+	        else
+	        	{
+	        	// Set the feature entry in list with updated information
+	        	iFeatureList[index].Set(entry);
+	        	}
+
+	        err = HandleChange( entry, changeType );
+	        }
+    	}
+    
+    LOG_IF_ERROR1( err, "CFeatMgrFeatureRegistry::SetFeature - result %d", err );
+
+    return err;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::HandleChange
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::HandleChange( TFeatureServerEntry& aFeature, 
+    TFeatureChangeType aType )
+    {
+    FUNC_LOG
+    
+    TInt err( KErrNone );
+    
+    // Update feature file, when feature is specified as persisted.
+    if ( aFeature.FeatureFlags().IsSet( EFeaturePersisted ) )
+        {
+        TRAP( err, UpdateRuntimeFeaturesFileL( aFeature, aType ) );
+        LOG_IF_ERROR1( err, "CFeatMgrFeatureRegistry::HandleChange - update error %d", err );
+    
+        // It is questionnable whether we should remove the feature from iFeatureList.
+        // However, feature is usable until device is powered down and features reloaded.
+        // if ( err == KErrNone )
+        }
+    
+    // It is also questionnable whether we should suppress notification in case file 
+    // update failed.
+    // if ( err == KErrNone )
+    iObserver.HandleFeatureChange( aFeature, aType );
+    
+    return err;
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ValidateFeature
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::ValidateFeature( TUid aFeature, TInt &aIndex )
+    {
+    TInt err( KErrNone );
+    
+    aIndex = SearchFeature( aFeature );
+     
+    if ( aIndex == KErrNotFound )
+        {
+        err = KErrNotFound;
+        }
+    else if ( !IsFlagSet( aIndex, EFeatureModifiable ) )
+        {
+        err = KErrAccessDenied;
+        }
+    
+    return err;
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::FindByUid
+// Returns Zero if UIDs do match.
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::FindByUid( const TUid *aFeature, 
+    const TFeatureServerEntry& aItem )
+    {
+    if ( aFeature->iUid < aItem.FeatureUid().iUid )
+        {
+        return -1;
+        }
+    else if ( aFeature->iUid > aItem.FeatureUid().iUid )
+        {
+        return 1;
+        }
+
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::FindByUid
+// Returns Zero if UIDs do match.
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::FindByUid( const TFeatureServerEntry& aFeature, 
+    const TFeatureServerEntry& aItem )
+    {
+    if ( aFeature.FeatureUid().iUid < aItem.FeatureUid().iUid )
+        {
+        return -1;
+        }
+    else if ( aFeature.FeatureUid().iUid > aItem.FeatureUid().iUid )
+        {
+        return 1;
+        }
+
+    return 0;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SearchFeature
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::SearchFeature( TUid aFeature )
+    {
+    const TUid& uid( aFeature );
+    return iFeatureList.FindInOrder( uid, FindByUid );
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::IsFlagSet
+// -----------------------------------------------------------------------------
+//  
+TBool CFeatMgrFeatureRegistry::IsFlagSet( TInt aIndex, TFeatureFlags aFlag )
+    {
+    TBool isSet( EFalse );
+    if( aIndex < iFeatureList.Count() )
+        {
+        isSet = iFeatureList[aIndex].FeatureFlags().IsSet(aFlag);
+        }
+        
+    return isSet;
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SupportedFeatures
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::SupportedFeaturesL( RFeatureUidArray& aSupportedFeatures )
+    {
+    FUNC_LOG
+    
+    TInt count = iFeatureList.Count();
+    
+    for ( TInt i = 0; i < count; i++ )
+        {
+        if( IsFlagSet( i, EFeatureSupported) )
+            {
+            aSupportedFeatures.AppendL( iFeatureList[i].FeatureUid() );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::NumberOfSupportedFeatures
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::NumberOfSupportedFeatures()
+    {
+    FUNC_LOG
+    
+    TInt count = iFeatureList.Count();
+    TInt countSupported(0);
+    
+    for ( TInt i = 0; i < count; i++ )
+        {
+        if( IsFlagSet( i, EFeatureSupported) )
+            {
+            countSupported++;
+            }
+        }
+    
+    return countSupported;
+    }
+
+// -----------------------------------------------------------------------------
+
+TInt CFeatMgrFeatureRegistry::ResetFeatures()
+    {
+    FUNC_LOG
+    
+    // backup the feature list before it is destroyed
+    iFeatureListBackup.Reset();
+    TInt count = iFeatureList.Count();
+    
+    for( TInt i=0; i < count; i++ )
+        {
+        iFeatureListBackup.Append( iFeatureList[i] );
+        }
+    
+    // destroy the feature list
+    iFeatureList.Reset();
+    iFeatureList.Close();
+    
+    iRangeList.Reset();
+    iRangeList.Close();
+
+    return( 0 );
+    }
+
+/**
+ * Get the fully qualified path and filename to the features.dat
+ * data file.
+ */ 
+TFileName CFeatMgrFeatureRegistry::GetFeaturesFilePathAndName( void )
+	{
+    TFileName path( KCFeatMgrPrivatePath );
+
+    path[0] = iFs.GetSystemDriveChar();
+    path.Append( KCRuntimeFeaturesFileName );
+
+    return path;
+	}
+
+// CFeatMgrFeatureRegistry::ReadFeatureFilesL
+// Reads platform and product feature files. 
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::ReadFeatureFilesL()
+    {
+    FUNC_LOG    
+    
+    // Read feature files from Z
+    ReadFilesFromDirL( KZFeaturesDir );
+
+    //check that there is at least one DSR 
+    if (!iRangeList.Count()) 
+    	{
+    	_LIT( KPanicCategory, "FeatMgrServer" );
+    	ERROR_LOG( "CFeatMgrFeatureRegistry::ReadFilesFromDirL() - no DSR found in ROM; this indicates a system integration error  - going to panic" );
+    	User::Panic( KPanicCategory, EPanicNoDSR );    
+    	}
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ReadFilesFromDirL
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::ReadFilesFromDirL( const TDesC& aDirName )
+    {
+	_LIT( KPanicCategory, "FEATMGR-READFILE" );
+
+    CDir* dir = NULL; 
+    TInt err( KErrNone );
+
+    err = iFs.GetDir( aDirName, KEntryAttNormal, ESortByName, dir );
+    CleanupStack::PushL( dir );
+
+    if( err == KErrNone )
+        {
+        err = ReadFiles( aDirName, dir );
+        if ( err != KErrNone )
+            {            
+            ERROR_LOG1( "CFeatMgrFeatureRegistry::ReadFilesFromDirL() - err %d ", err );
+            User::Leave( err );    
+            }
+        }  
+    else if( err == KErrPathNotFound )
+    	{
+    	__ASSERT_ALWAYS( EFalse, User::Panic( KPanicCategory, EPanicNoFeatureFiles) );
+    	}
+	else
+        {            
+        ERROR_LOG1( "CFeatMgrFeatureRegistry::ReadFilesFromDirL() - err %d ", err );
+        User::Leave( err );    
+        }
+    
+    CleanupStack::PopAndDestroy( dir );
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ReadRuntimeFeaturesL
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::ReadRuntimeFeaturesL( TBool &aFeaturesReady )
+    {
+    TFileName path( KCFeatMgrPrivatePath );
+    path[0] = iFs.GetSystemDriveChar();
+    path.Append( KCRuntimeFeaturesFileName );
+
+    TInt err( KErrNone );
+    TRAP( err, ReadFileL( path ) );
+
+    if ((err == KErrCorrupt) || (err == KErrArgument))
+    	{
+    	iFs.Delete(path);
+    	aFeaturesReady = ETrue;
+    	}
+    else if ( err != KErrNone && err != KErrNotFound && err != KErrPathNotFound )
+        {  
+        ERROR_LOG1( "CFeatMgrFeatureRegistry::ReadRuntimeFeatures - ReadFileL returned err %d", err );
+        User::Leave( err );
+        }
+    else
+        {
+        aFeaturesReady = ETrue;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ReadFiles
+// -----------------------------------------------------------------------------
+//  
+TInt CFeatMgrFeatureRegistry::ReadFiles( const TDesC& aPath, CDir* aDir )
+    {
+    TInt fileCount = aDir->Count();
+    TFileName fileName;
+    TInt err( KErrNotFound );
+    
+    for ( TInt file = 0; file < fileCount; file++ )
+        {
+        TInt match = (*aDir)[file].iName.MatchC( KZFeaturesFileNameMatch );
+        if( match != KErrNotFound )
+            {
+            fileName.Copy(aPath);
+            fileName.Append((*aDir)[file].iName);
+
+            INFO_LOG1( "CFeatMgrFeatureRegistry::ReadFiles - file: %S", &fileName );
+            TRAP( err, ReadFileL( fileName ) );
+            LOG_IF_ERROR2( err, "CFeatMgrFeatureRegistry::ReadFiles - file: %S, err %d", 
+                &fileName, err );
+            
+            // Return error if reading of any feature file fails.
+            if( err != KErrNone )
+                {
+                break;
+                }
+            }
+        }
+
+    return( err );
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ReadFileL
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::ReadFileL( const TDesC& aFullPath )
+    {
+    FUNC_LOG
+   
+    TUint32 count;
+ 	RFileReadStream readStream;
+
+ 	// Open the file and attach to stream 
+    User::LeaveIfError( readStream.Open( iFs, aFullPath, EFileRead ) );
+    CleanupClosePushL( readStream );
+    TUint32 countDSRs;
+    
+    //Validate the header
+    ValidateHeaderL( readStream, count, countDSRs );
+
+    RArray<TFeatureServerEntry> tempFeatureArray;
+    CleanupClosePushL( tempFeatureArray );
+    
+    //Find the directory that the feature file is contained in. 
+    TFileName dirName(aFullPath);
+    TChar toFind = '\\';
+    dirName.Delete((dirName.LocateReverse(toFind)+1), dirName.Length() );
+    TBool runtimeFile = EFalse;
+    if (dirName.Compare(KZFeaturesDir) != 0) //Location of the feature file.
+    	{
+    	runtimeFile = ETrue;
+    	}
+    
+    tempFeatureArray.ReserveL(count);
+    
+	for(TInt i = 0; i < count; i++)
+        {
+        TFeatureServerEntry entry;
+        entry.InternalizeL( readStream );
+        
+        //Check for feature flag errors
+        TBitFlags32 flags =  entry.FeatureFlags();
+        TInt err = KErrNone;
+        
+        //Validate the flags
+        // This validation is done in this read function because the validation functions used
+        // are called in other places were this validation is not appropriate. 
+        if (runtimeFile)
+        	{
+        	if (!flags.IsSet(EFeatureRuntime)) //Check to see if the Runtime flag is set if it is not then the feature should have been read in from the rom. 
+        		{
+        		if (SearchFeature( entry.FeatureUid() ) == KErrNotFound )// Check to see if the feature has been read in previously from the rom.
+        			{
+        			User::Leave(KErrCorrupt); 
+        			}
+        		else //The feature has not been read in previously from the rom file and is therefore invalid. The file is deemed to be corrupt
+        			{
+        			ValidateRuntimeFeatureFlagL(flags);   
+            		}
+        		}
+        	else //Flag set the feature is runtime this is then validated as normal
+        		{
+        		ValidateRuntimeFeatureFlagL(flags);    	
+        		}
+
+        	}
+        else //File is not as runtime file.
+        	{
+        	err = ValidateFeatureFlag(flags);
+        	}
+        
+        //If a feature flag defined in system drive (c:) is invalid, it will not be added to Feature Manager 
+        if ( (err != KErrNone) && flags.IsSet(EFeatureRuntime) )
+        	{
+        	continue;
+       		}
+        
+        tempFeatureArray.Insert( entry, i);
+        
+        }
+
+    // Reserve memory if list still empty
+    if( !iFeatureList.Count() )
+        {
+        iFeatureList.ReserveL( tempFeatureArray.Count() );
+        }
+
+    // Read features from temp array
+    for(TInt i = 0; i < tempFeatureArray.Count(); i++)
+        {
+        TFeatureServerEntry entry = tempFeatureArray[i];
+ 
+        TInt index = SearchFeature( entry.FeatureUid() );
+        
+        if( index == KErrNotFound)
+            {
+            User::LeaveIfError( iFeatureList.InsertInOrder( entry, FindByUid ) );
+            }
+        else
+            {
+            INFO_LOG1( "CFeatMgrFeatureRegistry::ReadFileL - replacing uid 0x%08x",
+                iFeatureList[index].FeatureUid().iUid );
+            // Set the feature if it is not previously blacklisted
+            if ( !IsFlagSet( index, EFeatureBlackListed ) )
+                {
+                iFeatureList[index].Set(entry);
+                }
+            }
+        }
+    
+    // Reserve memory if DSR list still empty
+    if( !iRangeList.Count() )
+        {
+        iRangeList.ReserveL( countDSRs );
+        }
+    
+    // Read default supported ranges from file
+    for(TInt i = 0; i < countDSRs; i++)
+        {
+        TDefaultRange range;
+        range.iLowUid = TUid::Uid( readStream.ReadUint32L() );
+        range.iHighUid = TUid::Uid( readStream.ReadUint32L() );
+        iRangeList.AppendL( range );
+        if( iRangeList[i].iLowUid.iUid > iRangeList[i].iHighUid.iUid )
+            {
+            ERROR_LOG( "CFeatMgrFeatureRegistry::ReadFileL - invalid supported range" );
+            iRangeList.Remove( i );
+            User::Leave( KErrCorrupt );
+            }
+        }
+
+#if defined(FEATMGR_INFO_LOG_ENABLED)
+    count = iFeatureList.Count();
+    INFO_LOG1( "CFeatMgrFeatureRegistry::ReadFileL - feature entries: %d", count );
+    for(TInt i = 0; i < count; i++)
+        {
+        INFO_LOG3( "CFeatMgrFeatureRegistry::ReadFileL - uid 0x%08x, flags %d, data %d",
+            iFeatureList[i].FeatureUid().iUid, iFeatureList[i].FeatureFlags().iFlags, 
+            iFeatureList[i].FeatureData() );
+        }
+
+    count = iRangeList.Count();
+    INFO_LOG1( "CFeatMgrFeatureRegistry::ReadFileL - supported ranges: %d", count );
+    for(TInt i = 0; i < count; i++)
+        {
+        INFO_LOG2( "CFeatMgrFeatureRegistry::ReadFileL - low 0x%08x, high 0x%08x",
+            iRangeList[i].iLowUid, iRangeList[i].iHighUid );
+        }
+#endif
+
+    CleanupStack::PopAndDestroy( &tempFeatureArray);
+    CleanupStack::PopAndDestroy( &readStream );
+
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ValidateHeaderL
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::ValidateHeaderL( RFileReadStream &aStream, 
+    TUint32& aCount, TUint32& aCountDSRs )
+    {
+    FUNC_LOG
+
+    TUint32 identifier = aStream.ReadUint32L();
+    TUint16 fileVersion = aStream.ReadUint16L();
+    TUint16 fileFlags = aStream.ReadUint16L();
+    aCount = aStream.ReadUint32L();
+    aCountDSRs = aStream.ReadUint32L();
+        
+    // Carry out simple verification of file content
+    if((identifier != KFileType) || fileVersion != KFileVersion || 
+        fileFlags != KFileFlags )
+        {
+        User::Leave( KErrCorrupt );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::UpdateRuntimeFeaturesFileL
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::UpdateRuntimeFeaturesFileL( TFeatureServerEntry& aFeature,
+		TFeatureChangeType aType )
+    {
+    FUNC_LOG
+
+    // Opens a file containing a stream and prepares the stream for writing.
+    TInt err( KErrNone );
+    RFileWriteStream writeStream;
+    TFileName path( KCFeatMgrPrivatePath );
+    path[0] = iFs.GetSystemDriveChar();
+    path.Append( KCRuntimeFeaturesFileName );
+
+    err = writeStream.Open( iFs, path, EFileWrite  ); 
+    CleanupClosePushL( writeStream );
+    
+    if( err == KErrPathNotFound || err == KErrNotFound )
+    	{
+        // Create folder and file.
+    	if ( err == KErrPathNotFound )
+    		{
+    		path = KCFeatMgrPrivatePath;
+    		path[0] = iFs.GetSystemDriveChar();
+		    User::LeaveIfError( iFs.MkDirAll( path ) );
+            path.Append( KCRuntimeFeaturesFileName );
+    		}
+        User::LeaveIfError( writeStream.Create( iFs, path, EFileWrite ) );
+        
+        // Write header and entry
+        RFeatureServerArray temp(1);
+        CleanupClosePushL( temp );
+        temp.Append( aFeature );
+        WriteHeaderAndEntriesL( writeStream, temp );
+        CleanupStack::PopAndDestroy( &temp );
+        CleanupStack::PopAndDestroy( &writeStream );
+        }
+    else if( err == KErrNone )
+	    {
+	    // Close write- and open readstream
+	    CleanupStack::PopAndDestroy( &writeStream );
+        RFileReadStream readStream;
+        User::LeaveIfError( readStream.Open( iFs, path, EFileRead ) );
+        CleanupClosePushL( readStream );
+
+        // Read entries from file to temporary array
+        TUint32 count;
+        TUint32 countDSRs;
+        ValidateHeaderL( readStream, count, countDSRs );
+        TUint32 granularity = 8;
+        if (count>granularity) 
+        	{
+        	granularity=count;
+        	}
+        RFeatureServerArray temp(granularity);
+        CleanupClosePushL( temp );
+        for(TInt i = 0; i < count; i++)
+            {
+            TFeatureServerEntry entry;
+            entry.InternalizeL( readStream );
+            temp.AppendL( entry );
+            }
+        // Close read-stream and handle temp array in cleanup stack
+        CleanupStack::Pop( &temp );
+        CleanupStack::PopAndDestroy( &readStream );
+        CleanupClosePushL( temp );
+
+        // Set or insert a new entry in to the array
+        const TUid& uid( aFeature.FeatureUid() );
+        TInt index = temp.FindInOrder( uid, FindByUid );
+        if( index != KErrNotFound )
+            {         
+            if ( aType != EFeatureFeatureDeleted )
+            	{
+            	temp[index].Set( aFeature);
+            	}
+            else
+            	{
+            	temp.Remove( index );
+            	}
+            }
+        else
+            {
+            User::LeaveIfError( temp.InsertInOrder( aFeature, FindByUid ) );
+            }
+		
+		//Create a Temporary File
+		RFileWriteStream writeStreamTemp;
+		const TPtrC KTestFile=_L("TFEATURES.DAT");
+        TFileName tempPath( KCFeatMgrPrivatePath );
+	    tempPath[0] = iFs.GetSystemDriveChar();
+    	tempPath.Append( KTestFile );
+    	User::LeaveIfError(writeStreamTemp.Replace( iFs,  tempPath, EFileWrite ));
+    	CleanupClosePushL( writeStreamTemp);
+    	WriteHeaderAndEntriesL( writeStreamTemp, temp );
+    	writeStreamTemp.CommitL();
+    	CleanupStack::PopAndDestroy(&writeStreamTemp);
+        CleanupStack::PopAndDestroy( &temp );
+        User::LeaveIfError(iFs.Replace(tempPath,path));		
+       
+	    }
+    else
+        {
+        ERROR_LOG1( "CFeatMgrFeatureRegistry::UpdateRuntimeFeatures - err %d", err );
+        User::Leave( err );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::WriteHeaderAndEntriesL
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::WriteHeaderAndEntriesL( RFileWriteStream &aStream, 
+    RFeatureServerArray& aArray )
+    {
+    FUNC_LOG
+
+    TInt count( aArray.Count() );
+    aStream.WriteUint32L( KFileType );
+    aStream.WriteUint16L( KFileVersion );
+    aStream.WriteUint16L( KFileFlags );
+    aStream.WriteUint32L( count );
+    aStream.WriteUint32L( 0 );
+    for(TInt i = 0; i < count; i++)
+        {
+        aArray[i].ExternalizeL( aStream );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::MergePluginFeatures
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::MergePluginFeatures( 
+        RArray<FeatureInfoCommand::TFeature>& aList )
+    {
+    FUNC_LOG
+    
+    TInt count = aList.Count();
+
+    for ( TInt i = 0; i < count; i++ )
+        {
+        const TUid uid( TUid::Uid( aList[i].iFeatureID ) );
+        TInt index = SearchFeature( uid );
+        
+        if(index != KErrNotFound)
+            {
+            if ( !IsFlagSet( index, EFeatureBlackListed ) )
+                {
+                // Update support-status bit
+                TBitFlags32 flags( iFeatureList[index].FeatureFlags() );
+                flags.Assign( EFeatureSupported, aList[i].iValue);
+                
+                // Set existing entry in array
+                TFeatureServerEntry entry( uid, flags, iFeatureList[index].FeatureData());
+                iFeatureList[index].Set(entry);
+                }
+            else
+                {
+                INFO_LOG1( "CFeatMgrFeatureRegistry::MergePluginFeatures - 0x%08x blacklisted",
+                    iFeatureList[i].FeatureUid().iUid );
+                }
+            }
+        else
+            {
+            TBitFlags32 flags;
+            flags.Assign( EFeatureSupported, aList[i].iValue);
+            // Insert new entry in array
+            TFeatureServerEntry newFeature( uid, flags, KDefaultData );
+            TInt err = iFeatureList.InsertInOrder( newFeature, FindByUid );
+            INFO_LOG2( "CFeatMgrFeatureRegistry::MergePluginFeatures - 0x%08x insert result %d",
+                newFeature.FeatureUid().iUid, err );
+            }
+        }
+    }
+    
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::MergePluginFeatures
+// -----------------------------------------------------------------------------
+//  
+void CFeatMgrFeatureRegistry::MergePluginFeatures( RFeatureArray& aList )
+    {
+    FUNC_LOG
+    
+    TInt count = aList.Count();
+
+    for ( TInt i = 0; i < count; i++ )
+        {
+        //Check for feature flag errors
+        ValidateFeatureFlag(aList[i].FeatureFlags()) ; 
+        const TUid uid( aList[i].FeatureUid() );
+        TInt index = SearchFeature( uid );
+        
+        if( index != KErrNotFound )
+            {
+            if ( !IsFlagSet( index, EFeatureBlackListed ) )
+                {
+                // Set existing entry in array with new info and data
+                TFeatureServerEntry entry( uid, aList[i].FeatureFlags(), aList[i].FeatureData() );
+                iFeatureList[index].Set(entry);
+                }
+            else
+                {
+                INFO_LOG1( "CFeatMgrFeatureRegistry::MergePluginFeatures - 0x%08x blacklisted",
+                    iFeatureList[i].FeatureUid().iUid );
+                }
+            }
+        else
+            {
+            // Insert new entry in array
+            TFeatureServerEntry newFeature( uid, aList[i].FeatureFlags(), aList[i].FeatureData() );
+            TInt err = iFeatureList.InsertInOrder( newFeature, FindByUid );
+            INFO_LOG2( "CFeatMgrFeatureRegistry::MergePluginFeatures - 0x%08x insert result %d",
+                newFeature.FeatureUid().iUid, err );
+            }
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::ValidateFeatureFlag
+// Following are the rule to check err in the ROM defined feature flags
+// Rule 1) If a feature flag is blacklisted then setting any of modifiable, persisted, Un-initialised bit will be an error
+// Rule 2) If a feature flag is non blacklisted, non modifiable  setting any of Un-initialised, Persisted bit will be an error
+// -----------------------------------------------------------------------------
+//  
+   
+TInt CFeatMgrFeatureRegistry::ValidateFeatureFlag(TBitFlags32 aFlags)
+	{
+	_LIT( KPanicCategory, "FEATMGR-FLAGS" );
+
+	
+	if(!aFlags.IsSet(EFeatureRuntime)) //ROM defined feature flag error check
+		{
+		//Rule 1
+		if(aFlags.IsSet(EFeatureBlackListed) )
+	    	{
+	    	 if(aFlags.IsSet(EFeatureModifiable) || aFlags.IsSet(EFeaturePersisted) || aFlags.IsSet(EFeatureUninitialized) )
+	    	 	{
+	    	 	//error 
+	    	 	__ASSERT_ALWAYS(EFalse, User::Panic( KPanicCategory, EFmpInvalidFeatureBitFlagsRule1));
+                return KErrArgument;
+	    	  	}
+	    	}
+	    	
+	    //Rule 2    	
+	    if (!aFlags.IsSet(EFeatureModifiable))
+	       	{
+	       	if (aFlags.IsSet(EFeaturePersisted) || aFlags.IsSet(EFeatureUninitialized) )
+	       	 	{
+	        	//error 
+	        	__ASSERT_ALWAYS(EFalse, User::Panic( KPanicCategory, EFmpInvalidFeatureBitFlagsRule2));
+                return KErrArgument;
+	        	}	
+	        }
+		}
+	else // Runtime feature this should not be in the rom
+		{		
+		__ASSERT_ALWAYS(EFalse, User::Panic( KPanicCategory, EPanicInvalidFeatureInfo));
+		return KErrArgument;
+		}
+	return KErrNone;
+	}
+
+/**
+ * This function is used to validate feature flags that are read from the features file on the ffs.
+ * This function is also used to validate feature flags that are modified or added with the execption of MergePluginFeatures.
+ * This validation compares the flags against a set of rules. This ffs file needs to be validate separately from the 
+ * rom file. If the rom validation method is used a panic can occur which is appropriate for checking the rom but not
+ * for the ffs.  
+ * This does not validate the dsr ranges. 
+ * The following are the rules to check for errors in the run time defined feature flags
+ * Rule 1)Blacklisting of a run-time defined feature flag is an error 
+ * Rule 2)Un-initialised feature flag should be modifiable.   
+ * Funtion returns KErrArgument if a rule is broken otherwise KErrNone
+ */
+TInt CFeatMgrFeatureRegistry::ValidateRuntimeFeatureFlagL(TBitFlags32 aFlags)
+	{
+	
+	//Rule 1 (Blacklisting of run-time defined feature aFlags is not allowed)
+	if(aFlags.IsSet(EFeatureBlackListed) ) 
+    	{
+		//error 
+    	User::Leave( KErrArgument );
+    	}
+    	
+    //Rule 2 (non modifiable run-time feature aFlags should initialised
+	if(!aFlags.IsSet(EFeatureModifiable) && aFlags.IsSet(EFeatureUninitialized) )
+	 	{
+	 	//error 
+	 	User::Leave( KErrArgument );
+	 	}
+	
+	return KErrNone;	
+	}
+
+
+/**
+ * After restore, some features might have changed. This function will examine
+ * the differences between the old feature set and the newly restored feature set
+ * to discover if any changes have taken place: then it will handle the required
+ * notifications for new, deleted and changed featuers.
+ */
+TInt CFeatMgrFeatureRegistry::HandleRestoredFeatureNotificationsL( void )
+	{
+	// All comparisons are between the new list iFeatureList and the old list iFeatureListBackup
+	TInt new_count = iFeatureList.Count();
+	TInt old_count = iFeatureListBackup.Count();
+	
+	// Three lists, defining the differences between the two arrays
+	RArray<TFeatureServerEntry> added;
+	RArray<TFeatureServerEntry> removed;
+	RArray<TFeatureServerEntry> changed;
+
+	// Regarding the newer iFeatureList array
+	// Get the features according to the "new" iFeatureList array
+	for( TInt i=0; i < new_count; i++ )
+		{
+	    // If not set, the feature flag is a ROM or plug-in
+	    if( iFeatureList[i].FeatureFlags().IsSet(EFeatureRuntime) )
+	        {
+	        TUid uid( iFeatureList[i].FeatureUid() );
+		    TInt index = iFeatureListBackup.FindInOrder( uid, FindByUid );
+		    
+			// KErrNotFound, if no matching object can be found
+			if( KErrNotFound == index )
+				{
+				// Recently added feature
+				added.Append( iFeatureList[i] );
+				}
+			else
+				{
+				// Get the features in iFeatureList that have recently been altered
+		        TFeatureServerEntry old_item = iFeatureListBackup[index];
+		        TFeatureServerEntry new_item = iFeatureList[i];
+		        TUint32 old_flags = old_item.FeatureFlags().Value();
+		        TUint32 new_flags = new_item.FeatureFlags().Value();
+		        unsigned long int old_data = old_item.FeatureData();
+		        unsigned long int new_data = new_item.FeatureData();
+	        	// if any thing has changed, then add it to our list.
+		        // there is no != overload for TBitFlags32
+				if( !( old_flags == new_flags) || !( old_data == new_data) )
+					{
+					// changed in the "new" iFeatureList array
+					changed.Append( iFeatureList[i] );
+					}
+				}
+		
+	        } // end if ! EFeatureRuntime
+		} // end loop
+
+
+	// Regarding the older iFeatureListBackup array
+	// Get the features according to the "old" iFeatureListBackup array
+	for( TInt i=0; i < old_count; i++ )
+		{
+	    // If not set, the feature flag is a ROM or plug-in
+	    if( iFeatureListBackup[i].FeatureFlags().IsSet(EFeatureRuntime) )
+	        {
+	        TUid uid( iFeatureListBackup[i].FeatureUid() );
+		    TInt index = iFeatureList.FindInOrder( uid, FindByUid );
+		    
+			// KErrNotFound, if no matching object can be found
+			if( KErrNotFound == index )
+				{
+				// Recently removed feature
+				removed.Append( iFeatureListBackup[i] );
+				}
+			// the else has already been completed in previous loop
+		
+	        } // end if ! EFeatureRuntime
+		} // end loop
+	
+	TInt size_added 	= added.Count();
+	TInt size_changed 	= changed.Count();
+	TInt size_removed 	= removed.Count();
+
+	// notify the added features
+    for( TInt i = 0; i < size_added; i++ )
+        {
+        TFeatureServerEntry entry( added[i].FeatureUid(), added[i].FeatureFlags(), added[i].FeatureData() );
+        TFeatureChangeType changeType( EFeatureFeatureCreated );
+        iObserver.HandleFeatureChange( entry, changeType );
+        }
+
+	// notify the changed features
+    for( TInt i = 0; i < size_changed; i++ )
+        {
+        TFeatureServerEntry entry( changed[i].FeatureUid(), changed[i].FeatureFlags(), changed[i].FeatureData() );
+        TFeatureChangeType changeType( EFeatureStatusUpdated );
+        iObserver.HandleFeatureChange( entry, changeType );        
+        }
+
+	// notify the delete features
+    for( TInt i = 0; i < size_removed; i++ )
+        {
+        TFeatureServerEntry entry( removed[i].FeatureUid(), removed[i].FeatureFlags(), removed[i].FeatureData() );
+        TFeatureChangeType changeType( EFeatureFeatureDeleted );
+        iObserver.HandleFeatureChange( entry, changeType );
+        }
+	
+	return( 0 );
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWIStart
+// -----------------------------------------------------------------------------
+//
+TInt CFeatMgrFeatureRegistry::SWIStart(TUint aSWIProcessId)
+	{
+	FUNC_LOG
+	
+	// If a previous call to SWIStart was made then return an error indicating that SWI
+	// is already running. This assures that no two exes will enable the caching
+	// mechanism at the same time.
+	if( iSWICacheFeature )
+		{
+		INFO_LOG( "CFeatMgrFeatureRegistry::SWIStart - Already in use");
+		return KErrInUse;
+		}
+	
+	RProperty propertyHndl;
+	TInt err =propertyHndl.Attach(KUidSystemCategory, KSAUidSoftwareInstallKeyValue);
+	if (KErrNone != err)
+		{
+		return err;
+		}
+	TInt val = -1;
+	err = propertyHndl.Get(val);
+	propertyHndl.Close();
+
+	if( KErrNone == err )
+		{
+		// If an installation/uninstallation has started and no finishing status has been set for it
+		if( ((val&ESASwisInstall) || (val&ESASwisUninstall)) && !(val&ESASwisStatusNone) )
+			{
+			// Set a flag to tell FeatMgr that features modified from this point onwards
+		    // until a call to SWIEnd must be cached.
+		    iSWICacheFeature = ETrue;
+		    // SWI installation/uninstallation is in progress
+		    iSWIStatus = ESWIInstalling;
+		    // Set the ID of the process issuing Feature Manager commands to be cached
+			iSWIProcessId = aSWIProcessId;
+			// Start listening to P&S install property
+		    TRAP(err, iSWIListener = CSWIListener::NewL(this));
+		    if (KErrNone != err)
+		    	{
+		    	return err;
+		    	}
+		    
+		    // Start the timer to handle the case of the launched exe hanging or not calling SWIEnd
+		    // after SWIStart
+		    TRAP(err, iSWITimer = CSWITimer::NewL(TTimeIntervalMicroSeconds32(SWITIMEOUT), this));
+		    if (KErrNone != err)
+		    	{
+		    	return err;
+		    	}
+		    	
+		    INFO_LOG( "CFeatMgrFeatureRegistry::SWIStart - err KErrNone");
+		    return KErrNone;
+			}
+		}
+	INFO_LOG( "CFeatMgrFeatureRegistry::SWIStart - err KErrNotReady");
+
+	return KErrNotReady;
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWIEnd
+// -----------------------------------------------------------------------------
+//
+TInt CFeatMgrFeatureRegistry::SWIEnd(TUint aSWIProcessId)
+	{
+	FUNC_LOG
+
+	// reset the number of operations cached
+	iSWIOperations = 0;
+	
+	// If it is the same process that made a call to SWIStart and caching is in progress
+	if( iSWIProcessId == aSWIProcessId && iSWICacheFeature )
+		{
+		if( iSWIStatus == ESWIAborted )
+			{
+			SWIReset();
+			
+			INFO_LOG( "CFeatMgrFeatureRegistry::SWIEnd - SWIStatus = ESWIAborted");
+			return KErrNone;
+			}
+		else if( iSWIStatus == ESWIInstalling )
+			{
+			// Stop time-out
+			if( iSWITimer )
+				{
+				delete iSWITimer;
+				iSWITimer = NULL;
+				}
+			// Stop caching
+			iSWICacheFeature = EFalse;			
+			
+			TInt err = KErrGeneral;
+
+			if( !iOomOccured )
+				{
+				if( iAddFeatCount>0 )
+					{
+					err = iFeatureList.Reserve(iFeatureList.Count() + iAddFeatCount);
+                    if (err == KErrNoMemory)
+                         {
+                         iSWIStatus = ESWIOutOfMemory;
+                         }
+					}
+				}
+			else
+				{
+				err = KErrNoMemory;
+				iSWIStatus = ESWIOutOfMemory;
+				}
+			
+			INFO_LOG( "CFeatMgrFeatureRegistry::SWIEnd - SWIStatus = ESWIInstalling");
+			return err;
+			}
+		}
+
+	INFO_LOG( "CFeatMgrFeatureRegistry::SWIEnd - err KErrNotReady");
+	return KErrNotReady;
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWICacheCommand
+// -----------------------------------------------------------------------------
+//
+TInt CFeatMgrFeatureRegistry::SWICacheCommand(TSWIOperationCat aOptCat, TFeatureServerEntry aFeature)
+	{
+	FUNC_LOG
+	
+	TInt err;
+
+	if (iSWIOperations >= MAXSWIOPS)
+		{
+		err = KErrArgument;
+		}
+	else if (iOomOccured)
+		{
+		err = KErrNoMemory;
+		}
+	else
+		{
+		if( aOptCat == ESWIAddFeat )
+			{
+			++iAddFeatCount;
+			}		
+		TSWICachedOperation operation;
+		operation.iFeatEntry = aFeature;
+		operation.iCat = aOptCat;
+    	err = iSWICachedOperations.Append(operation);
+    	if( err == KErrNoMemory)
+    		{
+    		iOomOccured = ETrue;
+    		}
+    	else if( err == KErrNone )
+    		{
+    		++iSWIOperations;
+    		}
+		}
+	return err;
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::CommitSWIFeatChanges
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::CommitSWIFeatChanges()
+	{
+	FUNC_LOG
+	
+	// Commit all cached features.
+	if( !iSWICacheFeature )
+		{
+		TInt count = iSWICachedOperations.Count();
+
+		for( TInt i=0; i<count; ++i )
+			{
+			TSWIOperationCat optCat = iSWICachedOperations[i].iCat;
+	
+			switch(optCat)
+				{
+			case ESWIAddFeat:
+				{
+				AddFeature( iSWICachedOperations[i].iFeatEntry, 0 );
+				}
+				break;
+			case ESWIDeleteFeat:
+				{
+				DeleteFeature( iSWICachedOperations[i].iFeatEntry.FeatureUid() );
+				}
+				break;
+			case ESWISetFeatAndData:
+				{
+				TUint32 data = iSWICachedOperations[i].iFeatEntry.FeatureData();				
+				SetFeature( iSWICachedOperations[i].iFeatEntry.FeatureUid(),
+							iSWICachedOperations[i].iFeatEntry.FeatureFlags().Value(),
+							&data);
+		    	}
+				break;
+			case ESWISetFeatData:
+				{
+				TUint32 data = iSWICachedOperations[i].iFeatEntry.FeatureData();
+				SetFeature(iSWICachedOperations[i].iFeatEntry.FeatureUid(),
+							EFeatureSupportUntouch,&data);
+				}
+				break;
+			default:
+				break;
+				};
+			}
+		
+		INFO_LOG( "CFeatMgrFeatureRegistry::CommitSWIFeatChanges - Committing completed");
+		}
+	SWIReset();
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWIReset
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::SWIReset()
+	{
+	// Clear cached-features array
+	iSWICachedOperations.Close();
+
+	// Reset caching flag
+	iSWICacheFeature = EFalse;
+	
+	// Reset SWI process Id
+	iSWIProcessId = 1;
+	
+	// Reset SWI completion status
+	iSWIStatus = ESWIComplete;
+
+	// Reset the check for "out of memory" condition
+	iOomOccured = EFalse;
+	
+	// Reset the operations counter
+	iSWIOperations = 0;
+	
+	// No need to listen to P&S insall property any more
+	delete iSWIListener;
+	iSWIListener = NULL;
+	
+	// Stop time-out
+	if( iSWITimer )
+		{
+		delete iSWITimer;
+		iSWITimer = NULL;
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWIAborted
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::SWIAborted()
+	{
+	FUNC_LOG
+	
+	// If abort occured before SWIEnd is called
+	if( iSWICacheFeature )
+		{
+		INFO_LOG( "CFeatMgrFeatureRegistry::SWIAborted - Abort occured before SWIEnd was called");
+		iSWIStatus = ESWIAborted;
+		}
+	else
+		{
+		INFO_LOG( "CFeatMgrFeatureRegistry::SWIAborted - Abort occured after SWIEnd was called");
+		SWIReset();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWITimedOut
+// -----------------------------------------------------------------------------
+//
+void CFeatMgrFeatureRegistry::SWITimedOut()
+	{
+	FUNC_LOG
+	
+	if( iSWICacheFeature )
+		{
+		INFO_LOG( "CFeatMgrFeatureRegistry::SWITimedOut - Timeout expired");
+		SWIReset();
+		}
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWICacheStarted
+// -----------------------------------------------------------------------------
+//
+TBool CFeatMgrFeatureRegistry::SWICacheStarted()
+	{
+	return iSWICacheFeature;
+	}
+
+// -----------------------------------------------------------------------------
+// CFeatMgrFeatureRegistry::SWICacheStatus
+// -----------------------------------------------------------------------------
+//
+TBool CFeatMgrFeatureRegistry::SWICacheStatusOOM()
+	{
+	if( iSWIStatus == ESWIOutOfMemory )
+		{
+		return ETrue;
+		}
+	return EFalse;
+	}
+	
+//  End of File