convergedcallengine/spsettings/src/spsettingsengine.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:15:03 +0100
branchRCL_3
changeset 20 987c9837762f
parent 19 7d48bed6ce0c
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c)  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:  Service Provider Settings API's engine.
*
*/


#include <centralrepository.h>
#include <e32property.h>
#include <featmgr.h>
#include <settingsinternalcrkeys.h>
#include <cenrepdatabaseutil.h>

#include "spsettingsengine.h"
#include "spentry.h"
#include "spproperty.h"
#include "spcrkeys.h"
#include "spdefinitions.h"
#include "spdefaultvalues.h"


#include "spsapilogger.h" // For logging

const TInt KSPPredefinedCount = 2;


// ======== MEMBER FUNCTIONS ========

// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CSPSettingsEngine::CSPSettingsEngine()
    {
    }


// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::ConstructL()
    {
    XSPSLOGSTRING( "CSPSettingsEngine::ConstructL() - IN" );
    
    iCenRepUtils = CCenRepDatabaseUtil::NewL( KCRUidSPSettings, 
                                            KSPStartKey,
                                            KSPColIncrement,         
                                            KSPColMask, 
                                            KServiceIdCounter,
                                            KSPColCount );

    XSPSLOGSTRING( "CSPSettingsEngine::ConstructL() - OUT" );
    }


// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CSPSettingsEngine* CSPSettingsEngine::NewL()
    {
    CSPSettingsEngine* self = CSPSettingsEngine::NewLC();
    CleanupStack::Pop( self );
    return self;
    }


// ---------------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------------
//
CSPSettingsEngine* CSPSettingsEngine::NewLC()
    {
    CSPSettingsEngine* self = new( ELeave ) CSPSettingsEngine;
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }


// ---------------------------------------------------------------------------
// Destructor
// ---------------------------------------------------------------------------
//
CSPSettingsEngine::~CSPSettingsEngine()
    {
    XSPSLOGSTRING( "CSPSettingsEngine::~CSPSettingsEngine() - IN" );
    
    delete iCenRepUtils;

    XSPSLOGSTRING( "CSPSettingsEngine::~CSPSettingsEngine() - OUT" );
    }


// ---------------------------------------------------------------------------
// Begins transaction in repository.
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::BeginTransactionLC()
    {
    XSPSLOGSTRING( "CSPSettingsEngine::BeginTransaction() - IN" );

    iCenRepUtils->BeginTransactionL();
    
    XSPSLOGSTRING( "CSPSettingsEngine::BeginTransaction() - OUT" );
    
    return KErrNone;
    
    }


// ---------------------------------------------------------------------------
// Commits changes in repository.
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::CommitTransaction()
    {
    XSPSLOGSTRING( 
        "CSPSettingsEngine::CommitTransaction() - IN" );

    iCenRepUtils->CommitTransaction();
    
    XSPSLOGSTRING( "CSPSettingsEngine::CommitTransaction() - OUT" );

    return KErrNone;
    }


// ---------------------------------------------------------------------------
// Rollback changes in repository.
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::RollbackTransaction()
    {
    XSPSLOGSTRING( 
        "CSPSettingsEngine::RollbackTransaction() - IN" );

    iCenRepUtils->RollbackTransaction();
    
    XSPSLOGSTRING( "CSPSettingsEngine::RollbackTransaction() - OUT" );

    }

void CSPSettingsEngine::ConvertSpEntryToCenRepArrayL( const CSPEntry& aEntry, 
                                                     RIpAppPropArray& aArray )
    {
    CCenRepDatabaseProperty* property = CCenRepDatabaseProperty::NewLC();
    
    property->SetName( EServiceName );
    property->SetValue( aEntry.GetServiceName() );
    User::LeaveIfError( aArray.Append( property ) );
    CleanupStack::Pop( property );
    
    TInt count = aEntry.PropertyCount();
    const RPropertyArray& entryArray = aEntry.GetAllProperties();
    
    ConvertSpArrayToCenRepArrayL( entryArray, aArray );
    }
    
void CSPSettingsEngine::ConvertSpArrayToCenRepArrayL( const RPropertyArray& aSpArray,
                                                      RIpAppPropArray& aCenRepArray )
    {
    TInt count = aSpArray.Count();
    for( TInt i = 0; i < count; i++ )
        {
        CSPProperty* spProperty = aSpArray[i];
        CCenRepDatabaseProperty* property = CCenRepDatabaseProperty::NewLC();
        property->SetName( spProperty->GetName() );
        
        RBuf value;
        value.CreateL( KSPMaxDesLength );
        CleanupClosePushL( value);
        User::LeaveIfError( spProperty->GetValue( value ) );
        User::LeaveIfError( property->SetValue( value ) );
        CleanupStack::PopAndDestroy( &value );
        
        User::LeaveIfError( aCenRepArray.Append( property ) );
        CleanupStack::Pop( property );
        }
    }
    
void CSPSettingsEngine::CleanupPointerArray(  TAny* aPointer )
	{
	RIpAppPropArray* array = static_cast<RIpAppPropArray*>( aPointer );
	array->ResetAndDestroy();
	}

// ---------------------------------------------------------------------------
// Stores new service provider settings entry
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::AddEntryL( CSPEntry& aEntry )
    {
    XSPSLOGSTRING( "CSPSettingsEngine::AddEntryL() - IN" );
    
    // check the service name is not empty
    if( aEntry.GetServiceName().Length() == 0 )
    	{
    	User::LeaveIfError( KErrArgument );
    	}

    // construct RIpAppPropArray
    RIpAppPropArray array;
	TCleanupItem cleanup( CSPSettingsEngine::CleanupPointerArray, &array );
	CleanupStack::PushL( cleanup );
    
    ConvertSpEntryToCenRepArrayL( aEntry, array );

    // Create new unique service ID
    TInt newId = 0;
    iCenRepUtils->AddEntryL( newId, array );
    aEntry.SetServiceId( newId );
    
    CleanupStack::PopAndDestroy( &array );
    
    XSPSLOGSTRING( "CSPSettingsEngine::AddEntryL() - OUT" );
    }

// ---------------------------------------------------------------------------
// Find service provider settings entry by service ID
// ---------------------------------------------------------------------------
//
 TInt CSPSettingsEngine::FindEntryL( TServiceId aServiceId, CSPEntry& aEntry )
    {
    XSPSLOGSTRING2( "CSPSettingsEngine::FindEntryL( %d ) - IN", aServiceId );
    
    RIpAppPropArray array;
	TCleanupItem cleanup( CSPSettingsEngine::CleanupPointerArray, &array );
	CleanupStack::PushL( cleanup );

    TInt err = iCenRepUtils->FindEntryL( aServiceId, array );
    
    if( err == KErrNone )
        {
        TInt count = array.Count();

        for( TInt i = 0; i < count; i++ )
            {
            CCenRepDatabaseProperty* property = array[i];
            
            if( property->GetName() == EServiceName )
                {
                User::LeaveIfError( aEntry.SetServiceName( property->GetDesValue() ) );
                }
            else
                {
                CSPProperty* spProperty = CSPProperty::NewLC();
                User::LeaveIfError( spProperty->SetName( (TServicePropertyName)( property->GetName() )));
                User::LeaveIfError( spProperty->SetValue( property->GetDesValue() ));
                
                User::LeaveIfError( aEntry.AddPropertyL( *spProperty ));
                CleanupStack::PopAndDestroy( spProperty );
                }
            }
        }
    CleanupStack::PopAndDestroy( &array );
    
    aEntry.SetServiceId( aServiceId );
    
    XSPSLOGSTRING2( "CSPSettingsEngine::FindEntryL( %d ) - OUT", aServiceId );
    
    return err;
    }

// ---------------------------------------------------------------------------
// Update existing service provider settings entry
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::UpdateEntryL( const CSPEntry& aEntry )
    {
    XSPSLOGSTRING( "CSPSettingsEngine::UpdateEntry() - IN" );

    TServiceId serviceId( aEntry.GetServiceId() );

    // Leave if there is no service ID 
    if ( KSPNoId == serviceId || aEntry.GetServiceName().Length() == 0 )
        {
        User::Leave( KErrArgument );
        }

    // construct RIpAppPropArray
    RIpAppPropArray array;
	TCleanupItem cleanup( CSPSettingsEngine::CleanupPointerArray, &array );
	CleanupStack::PushL( cleanup );
    
    ConvertSpEntryToCenRepArrayL( aEntry, array );

    TInt err = iCenRepUtils->UpdateEntryL( (TInt) serviceId, array );
    
    CleanupStack::PopAndDestroy( &array );
	
    XSPSLOGSTRING( "CSPSettingsEngine::UpdateEntry() - OUT" );
    
    return err;
    }

	
// ---------------------------------------------------------------------------
// Deletes service provider settings entry by service ID
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::DeleteEntryL( TServiceId aServiceId )
    {
    XSPSLOGSTRING2( "CSPSettingsEngine::DeleteEntryL(%d) - IN", aServiceId );

    TInt err = iCenRepUtils->DeleteEntryL( aServiceId );
    
    XSPSLOGSTRING2( "CSPSettingsEngine::DeleteEntryL(%d) - OUT", aServiceId );
    
    return err;
    }


// ---------------------------------------------------------------------------
// Search property of service provider settings entry by property name
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::FindPropertyL( TServiceId aServiceId, 
    								   TServicePropertyName aPropertyName, 
    								   CSPProperty& aProperty )
    {
    XSPSLOGSTRING2( "CSPSettingsEngine::FindPropertyL(%d) - IN", aServiceId );

    CCenRepDatabaseProperty* cenrepProperty = CCenRepDatabaseProperty::NewLC();
    TInt err = iCenRepUtils->FindPropertyL( aServiceId, aPropertyName, *cenrepProperty );
    
    if( err == KErrNone )
        {
        User::LeaveIfError( aProperty.SetName( aPropertyName ) );
        User::LeaveIfError( aProperty.SetValue( cenrepProperty->GetDesValue()));
        }
        
    CleanupStack::PopAndDestroy( cenrepProperty );
    
    XSPSLOGSTRING2( "CSPSettingsEngine::FindPropertyL(%d) - OUT", aServiceId );
    
    return err;
    }


// ---------------------------------------------------------------------------
// Add or update properties of service provider settings entry
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::AddOrUpdatePropertiesL( TServiceId aServiceId,
												const RPropertyArray& aPropertyArray )
    {
    XSPSLOGSTRING2( "CSPSettingsEngine::AddOrUpdatePropertiesL(%d) - IN", aServiceId );

    // construct RIpAppPropArray
    RIpAppPropArray array;
	TCleanupItem cleanup( CSPSettingsEngine::CleanupPointerArray, &array );
	CleanupStack::PushL( cleanup );
    
    ConvertSpArrayToCenRepArrayL( aPropertyArray, array );
    
    TInt err = iCenRepUtils->AddOrUpdatePropertiesL( aServiceId, array );    

    CleanupStack::PopAndDestroy( &array );
    
    XSPSLOGSTRING2( 
        "CSPSettingsEngine::AddOrUpdatePropertiesL(%d) - OUT", aServiceId );
        
    return err;
    }


// ---------------------------------------------------------------------------
// Returns count of stored service provider settings entries
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::SettingsCountL()
    {
    XSPSLOGSTRING( "CSPSettingsEngine::SettingsCount() - IN" );

    TInt result( 0 );

    TInt err = iCenRepUtils->EntryCountL( result );
    
    if( err == KErrNone )
        {
        if( result >= KSPPredefinedCount )
            {
            result--;
            }
        err = result;
        }
    else
        {
        err = 0;
        }
    
    XSPSLOGSTRING2( "CSPSettingsEngine::SettingsCount(%d) - OUT", result );

    return err;
    }



// ---------------------------------------------------------------------------
// Search stored service IDs of service provider settings entries
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::FindServiceIdsL( RIdArray& aServiceIds )
    {
    XSPSLOGSTRING( "CSPSettingsEngine::FindServiceIdsL() - IN" );

    RArray<TInt> cenrepArray;
    CleanupClosePushL( cenrepArray );
    
    TInt err = iCenRepUtils->FindEntryIdsL( cenrepArray );
    
    for( TInt i = 0; i < cenrepArray.Count(); i++ )
        {
        TServiceId id = (TServiceId)cenrepArray[i];
        if( id != KSPDefaultVoIPServiceId )
            {
            User::LeaveIfError( aServiceIds.Append( id ));
            }
        }

    CleanupStack::PopAndDestroy( &cenrepArray );
    
    XSPSLOGSTRING( "CSPSettingsEngine::FindServiceIdsL() - OUT" );
    
    return err;
    }


// ---------------------------------------------------------------------------
// Search service names by given service IDs
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::FindServiceNamesL( RIdArray& aServiceIds,
    CDesCArray& aServiceNames )
    {
    XSPSLOGSTRING( "CSPSettingsEngine::FindServiceNamesL() - IN" );
    
    CCenRepDatabaseProperty* property = CCenRepDatabaseProperty::NewLC();
    TInt count = aServiceIds.Count();
    for( TInt i = 0; i < count; i++ )
        {
        TInt id = ( TInt )aServiceIds[i];
        
        TInt err = iCenRepUtils->FindPropertyL( id, EServiceName, *property );
        if( err == KErrNone )
            {
            aServiceNames.AppendL( property->GetDesValue() );
            }
        else
            {
            aServiceIds.Remove( i ); // Remove non-existent ID
            count--;
            i--; // Do not increment index
            }
        }

    CleanupStack::PopAndDestroy( property );
    
    XSPSLOGSTRING( "CSPSettingsEngine::FindServiceNamesL() - OUT" );
    }

void CSPSettingsEngine::PropertyNameArrayFromItemTypeL( TSPItemType aPropertyType, 
                                                        RPropertyNameArray& aNameArray )
    {
    switch ( aPropertyType )
        {
        case EItemTypeVoIPSubProperty:
            {
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPSettingsId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPPreferredSNAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPPreferredIAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPTemporaryIAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPRelNumber ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPBrandDataUri ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPBrandIconUri ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPAddrScheme ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVoIPEnabled ) );
            break;
            }
        case EItemTypePresenceSubProperty:
            {
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresenceSettingsId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresencePreferredSNAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresencePreferredIAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresencePresentityIDFieldType ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresenceLaunchMethod ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresenceLaunchUid ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresenceAddrScheme ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresenceEnabled ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyPresenceRequestPreference ) );
            break;
            }
        case EItemTypeIMSubProperty:
            {
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMSettingsId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMPreferredSNAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMPreferredIAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMLaunchMethod ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMLaunchUid ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMAddrScheme ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyIMEnabled ) );
            break;
            }
        case EItemTypeVMBXSubProperty:
            {
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXSettingsId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXPreferredSNAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXPreferredIAPId ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXMWISubscribeInterval ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXLaunchMethod ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXLaunchUid ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXListenAddress ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXMWIAddress ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXBrandIconUri ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXAddrScheme ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXListenRegister ) );
            User::LeaveIfError( aNameArray.Append( ESubPropertyVMBXEnabled ) );
            break;
            }
        default:
            {
            User::Leave( KErrArgument );
            break;
            }
        }
    }
    
// ---------------------------------------------------------------------------
// 
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::FindSubServicePropertiesL( TServiceId aServiceId, 
	TSPItemType aPropertyType,
    RPropertyArray& aPropertyArray )
    {
    XSPSLOGSTRING2( 
        "CSPSettingsEngine::FindSubServicePropertiesL( %d ) - IN", aServiceId );

    RPropertyNameArray nameArray;
    CleanupClosePushL( nameArray );
    
    PropertyNameArrayFromItemTypeL( aPropertyType, nameArray );
    TInt count = nameArray.Count();
    TInt id = (TInt) aServiceId;
    
    CCenRepDatabaseProperty* property = CCenRepDatabaseProperty::NewLC();
    
    for( TInt i = 0; i < count; i++ )
        {
        TUint32 name = nameArray[i];
        TInt err = iCenRepUtils->FindPropertyL( id, name, *property );
        if( err == KErrNone )
            {
            CSPProperty* spProperty = CSPProperty::NewLC();
            User::LeaveIfError( spProperty->SetName( (TServicePropertyName)(property->GetName())) );
            User::LeaveIfError( spProperty->SetValue( property->GetDesValue() ));
            
            User::LeaveIfError( aPropertyArray.Append( spProperty ));
            CleanupStack::Pop( spProperty );
            }
        }
        
    CleanupStack::PopAndDestroy( property );
    CleanupStack::PopAndDestroy( &nameArray );
    
    XSPSLOGSTRING( "CSPSettingsEngine::FindSubServicePropertiesL() - OUT" );
    
    return KErrNone;
    }

// ---------------------------------------------------------------------------
// Deletes service properties
// ---------------------------------------------------------------------------
//
TInt CSPSettingsEngine::DeleteServicePropertiesL( TServiceId aServiceId,
    											  const RPropertyNameArray& aNameArray  )
    {
    XSPSLOGSTRING2( 
        "CSPSettingsEngine::FindSubServicePropertyL( %d ) - IN", aServiceId );

    RArray<TUint32> nameArray;
    CleanupClosePushL( nameArray );
    TInt count = aNameArray.Count();
    
    for( TInt i = 0; i < count; i++ )
        {
        TUint32 name = (TUint32)( aNameArray[i] );
        User::LeaveIfError( nameArray.Append( name ) );
        }
        
    TInt id = (TInt)aServiceId;
    TInt err = iCenRepUtils->DeletePropertiesL( id, nameArray );
    
    CleanupStack::PopAndDestroy( &nameArray );
    
    XSPSLOGSTRING( "CSPSettingsEngine::FindSubServicePropertyL() - OUT" );
    
    return err;
    }

// ---------------------------------------------------------------------------
// Find service IDs with same properties
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::FindServiceIdsFromPropertiesL( const RPropertyArray& aPropertyArray, 
													   RIdArray& aServiceIds )
	{
	XSPSLOGSTRING( "CSPSettingsEngine::FindServiceIdsFromPropertiesL() - IN" );
	
    RArray<TInt> entryIds;
    CleanupClosePushL( entryIds );
    
    RIpAppPropArray array;
	TCleanupItem cleanup( CSPSettingsEngine::CleanupPointerArray, &array );
	CleanupStack::PushL( cleanup );
    
    // todo custom cleanup stack
    ConvertSpArrayToCenRepArrayL( aPropertyArray, array );  
    
    TInt err = iCenRepUtils->FindEntryIdsFromPropertiesL( array, entryIds );
    if( err == KErrNone )
        {
        TInt count = entryIds.Count();
        for( TInt i = 0; i < count; i++ )
            {
            TServiceId id = (TServiceId)entryIds[i];
            if( id != KSPDefaultVoIPServiceId )
                {
                User::LeaveIfError( aServiceIds.Append( id ) );
                }
            }
        }
        
    CleanupStack::PopAndDestroy( &array );
    CleanupStack::PopAndDestroy( &entryIds );
    
	XSPSLOGSTRING( "CSPSettingsEngine::FindServiceIdsFromPropertiesL() - OUT" );
	}



// ---------------------------------------------------------------------------
// Check feature is supported or not
// ---------------------------------------------------------------------------
//
TBool CSPSettingsEngine::IsFeatureSupportedL( TSPServiceFeature aFeature,
                                              TBool aWriteAllowed )
	{
    XSPSLOGSTRING( "CSPSettingsEngine::IsFeatureSupportedL() - IN" );

    TBool ret = EFalse;
    
	// First check P&S key, if P&S key is defined, use the value from P&S key.
	// if not defined, then walk through all the sevices and check there is any service match
	TInt mask = 0;
	TInt value = 0;
	TInt psFlag = 0;
	TInt retProperty = 0;
	
    switch( aFeature )
    	{
    	case ESupportInternetCallFeature:
    		{
    		retProperty = RProperty::Get( KUidSystemCategory, KSPSupportInternetCallKey, psFlag );
    		if( retProperty == KErrNone && psFlag != KSPInitFeatureValue )
    			{
    			ret = psFlag;
    			}
    		else
    			{
				mask = ESupportsInternetCall | ESupportsAlphanumericAddressing | EIsVisibleInCallMenu;
				value = mask;
				ret = CheckFeatureL( mask, value );
				if ( aWriteAllowed )
				    {				    
				    User::LeaveIfError( RProperty::Set( KUidSystemCategory, 
				        KSPSupportInternetCallKey, ret ) );
				    }
    			}
    		
    		break;
    		}
    	case ESupportCallOutFeature:
    		{
    		retProperty = RProperty::Get( KUidSystemCategory, KSPSupportCallOutKey, psFlag );
    		if( retProperty == KErrNone && psFlag != KSPInitFeatureValue )
    			{
    			ret = psFlag;
    			}
    		else
    			{
				mask = ESupportsInternetCall | ESupportsMSISDNAddressing | EIsVisibleInCallMenu;
				value = mask;
				ret = CheckFeatureL( mask, value );
				if ( aWriteAllowed )
				    {				    
    				User::LeaveIfError( RProperty::Set( 
    				    KUidSystemCategory, 
    				    KSPSupportCallOutKey, ret ) );
				    }
    			}
    		break;
    		}
    	
    	case ESupportVoIPSSFeature:
    		{
    		retProperty = RProperty::Get( KUidSystemCategory, KSPSupportVoIPSSKey, psFlag );
    		if( retProperty == KErrNone && psFlag != KSPInitFeatureValue )
    			{
    			ret = psFlag;
    			}
    		else
    			{
				mask = ESupportVoIPSS;
				value = mask;
				ret = CheckFeatureL( mask, value );
				if ( aWriteAllowed )
				    {				    
    				User::LeaveIfError( RProperty::Set( 
    				    KUidSystemCategory, 
    				    KSPSupportVoIPSSKey, ret ) );
				    }
    			}
    		break;
    		}
    	
    	case ESupportVoIPFeature:
    		{
    		TBool bFeatureMgr = EFalse;
    		TBool bDynVoIP = EFalse;
    		TBool bSubVoIP = EFalse;
    		
    		//check FeatureManager
    		FeatureManager::InitializeLibL();
    		bFeatureMgr = FeatureManager::FeatureSupported( KFeatureIdCommonVoip );
    		FeatureManager::UnInitializeLib();
    		
    		//check dynamic voip flag
			CRepository* repository = CRepository::NewLC( KCRUidTelephonySettings );
			TInt value = 0;
			TInt err = repository->Get( KDynamicVoIP, value );
			if( value != 0 )
				{
				bDynVoIP = ETrue;
				}
			
			CleanupStack::PopAndDestroy( repository );
    		
    		//check subservice voip
			RIdArray serviceIds;
			CleanupClosePushL( serviceIds );
			FindServiceIdsL( serviceIds );
			CSPProperty* property = CSPProperty::NewLC();
			
			for( TInt i = 0; i < serviceIds.Count(); i++ )
				{
				TServiceId serviceId = serviceIds[i];
				TInt retProperty = FindPropertyL( serviceId, EPropertyVoIPSubServicePluginId, *property );
				if( retProperty == KErrNone )
					{
					bSubVoIP = ETrue;
					break;
					}
				}
			CleanupStack::PopAndDestroy( property );
			CleanupStack::PopAndDestroy( &serviceIds );
			
			ret = bFeatureMgr && bDynVoIP && bSubVoIP;
			
    		break;
    		}
		default:
			{
			User::Leave( KErrNotSupported );    	
			}
    	}
    
    XSPSLOGSTRING( "CSPSettingsEngine::IsFeatureSupportedL() - OUT" );

    return ret;
	}

// ---------------------------------------------------------------------------
// When service table is changed, update the P&S key
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::UpdateSupportFeaturePSKeyL()
	{
	TInt mask = 0;
	TInt value = 0;
	TBool ret = EFalse;
	
	//ESupportInternetCallFeature
	//ESupportsInternetCall + ESupportsAlphanumericAddressing + EIsVisibleInCallMenu
	mask = ESupportsInternetCall | ESupportsAlphanumericAddressing | EIsVisibleInCallMenu;
	value = mask;
	ret = CheckFeatureL( mask, value );
	User::LeaveIfError( RProperty::Set( KUidSystemCategory, KSPSupportInternetCallKey, ret ) );
	
	//ESupportCallOutFeature
	//ESupportsInternetCall + ESupportsMSISDNAddressing + EIsVisibleInCallMenu
	mask = ESupportsInternetCall | ESupportsMSISDNAddressing | EIsVisibleInCallMenu;
	value = mask;
	ret = CheckFeatureL( mask, value );
	User::LeaveIfError( RProperty::Set( KUidSystemCategory, KSPSupportCallOutKey, ret ) );
	
	//ESupportVoIPSSFeature
	//ESupportVoIPSS
	mask = ESupportVoIPSS;
	value = mask;
	ret = CheckFeatureL( mask, value );
	User::LeaveIfError( RProperty::Set( KUidSystemCategory, KSPSupportVoIPSSKey, ret ) );
	}

// ---------------------------------------------------------------------------
// Walk through all the sevices and check there is any service match 
// ---------------------------------------------------------------------------
//
TBool CSPSettingsEngine::CheckFeatureL( TInt aMask, TInt aValue )
	{
	RArray<TInt> entryIds;
	CleanupClosePushL( entryIds );
	iCenRepUtils->FindEntryIdsL( entryIds );
	CCenRepDatabaseProperty* property = CCenRepDatabaseProperty::NewLC();
	TBool ret = EFalse;
	
	for( TInt i = 0; i < entryIds.Count(); i++ )
		{
		TInt entryId = entryIds[i];
		if( entryId == KSPDefaultVoIPServiceId )
		    {
		    continue;
		    }
		    
		TInt retProperty = iCenRepUtils->FindPropertyL( entryId, EPropertyServiceAttributeMask, *property );
		if( retProperty == KErrNone )
			{
			TInt maskValue = 0;
			TInt err = property->GetValue( maskValue );
			if( err == KErrNone )
				{
				if( ( maskValue & aMask ) == (aValue & aMask) )
					{
					// Find matched servcie
					ret = ETrue;
					break;
					}
				}
			}
		}
	
	CleanupStack::PopAndDestroy( property );
	CleanupStack::PopAndDestroy( &entryIds );
	return ret;
	}

// ---------------------------------------------------------------------------
// Check if it is VoIP Service ID
// ---------------------------------------------------------------------------
//
TBool CSPSettingsEngine::IsVoIPServiceL( TServiceId aServiceId )
    {
    TBool bIsVoIP = EFalse;
    
    CSPProperty* property = CSPProperty::NewLC();
    TInt err = FindPropertyL( aServiceId, EPropertyVoIPSubServicePluginId, *property );
    if( err == KErrNone )
        {
        bIsVoIP = ETrue;
        }
    CleanupStack::PopAndDestroy( property );
    
    return bIsVoIP;
    }

// ---------------------------------------------------------------------------
// Check if an array has call related property name in it
// ---------------------------------------------------------------------------
//
TBool CSPSettingsEngine::HasCallPropertyName( const RPropertyNameArray& aNameArray )
    {
    TBool bHasCall = EFalse;
    
    for( TInt i = 0; i < aNameArray.Count(); i++ )
        {
        TServicePropertyName name = aNameArray[i];
        if( name == EPropertyCTIPluginId ||
            name == EPropertyCLIPluginId ||
            name == EPropertyCallLoggingPluginId ||
            name == EPropertyCallStateIndicatorPluginId ||
            name == EPropertyCallMenuHandlerPluginId ||
            name == EPropertyCallProviderPluginId )
            {
            bHasCall = ETrue;
            break;
            }
        }
    
    return bHasCall;
    }
    
// ---------------------------------------------------------------------------
// Check if an array has VoIP or Vmbx related property name in it
// ---------------------------------------------------------------------------
//
TBool CSPSettingsEngine::HasVoIPAndVmbxPropertyName(  const RPropertyNameArray& aNameArray )
    {
    TBool bHasVoIPAndVmbx = EFalse;
    
    for( TInt i = 0; i < aNameArray.Count(); i++ )
        {
        TServicePropertyName name = aNameArray[i];
        if( name == EPropertyVoIPSubServicePluginId ||
            name == EPropertyVMBXSubServicePluginId ||
            name == ESubPropertyVoIPSettingsId ||
            name == ESubPropertyVoIPPreferredSNAPId ||
            name == ESubPropertyVoIPPreferredIAPId ||
            name == ESubPropertyVoIPTemporaryIAPId ||
            name == ESubPropertyVMBXSettingsId ||
            name == ESubPropertyVMBXPreferredSNAPId ||
            name == ESubPropertyVMBXPreferredIAPId ||
            name == ESubPropertyVMBXMWISubscribeInterval ||
            name == ESubPropertyVMBXLaunchMethod ||
            name == ESubPropertyVMBXLaunchUid ||
            name == ESubPropertyVoIPRelNumber ||
            name == ESubPropertyVoIPBrandDataUri ||
            name == ESubPropertyVoIPBrandIconUri ||
            name == ESubPropertyVoIPAddrScheme ||
            name == ESubPropertyVMBXListenAddress ||
            name == ESubPropertyVMBXMWIAddress ||
            name == ESubPropertyVMBXBrandIconUri ||
            name == ESubPropertyVMBXAddrScheme ||
            name == ESubPropertyVoIPEnabled ||
            name == ESubPropertyVMBXListenRegister ||
            name == ESubPropertyVMBXEnabled )
            {
            bHasVoIPAndVmbx = ETrue;
            break;
            }
        }
    
    return bHasVoIPAndVmbx;
    }

// ---------------------------------------------------------------------------
// Get Name array from Property array 
// ---------------------------------------------------------------------------
//
void CSPSettingsEngine::NameArrayFromPropertyArrayL( RPropertyNameArray& aNameArray, 
												const RPropertyArray& aPropertyArray )
    {
    aNameArray.Reset();
    
    for( TInt i = 0; i < aPropertyArray.Count(); i++ )
        {
        CSPProperty* property = aPropertyArray[i];
        TServicePropertyName name = property->GetName();
        User::LeaveIfError( aNameArray.Append( name ) );
        }
    }