diff -r 000000000000 -r 8c5d936e5675 profilesservices/ProfileEngine/EngSrc/CProfileEngineImplDynamicProfiles.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/profilesservices/ProfileEngine/EngSrc/CProfileEngineImplDynamicProfiles.cpp Thu Dec 17 08:52:52 2009 +0200 @@ -0,0 +1,626 @@ +/* +* Copyright (c) 2002 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: Implementation of the CProfileEngineImpl. +* +*/ + + + +// INCLUDE FILES +#include "CProfileEngineImpl.h" +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "CProfilesNamesArrayImpl.h" +#include "CProfileImpl.h" +#include "CProfileNameImpl.h" +#include "ProfileEngUtils.h" +#include "MProfileSetName.h" +#include "ProfileEng.hrh" +#include "ProfileEngPanic.h" +#include "ProfileEngineConstants.h" +#include "ProfileEnginePrivateCRKeys.h" + +namespace + { + const TInt KProfileGeneratedNameTailLength( 4 ); + _LIT( KFirstParenthesis, "(" ); + } + +// ============================= LOCAL FUNCTIONS =============================== + +void GenerateProfileName( TDes& aProfileName, const MProfilesNamesArray& aProfileNames ) + { + _LIT( KEndParenthesis, ")" ); + _LIT( KZero, "0" ); + TInt counter( 1 ); + TBuf rootName( aProfileName ); + while( aProfileNames.FindByName( aProfileName ) != KErrNotFound && + counter <= KProfilesMaxNumberOfDynamicProfiles ) + { + aProfileName.Copy( rootName ); + aProfileName.Append( KFirstParenthesis ); + if( counter < 10 ) + { + aProfileName.Append( KZero ); + } + TBuf number; + number.Num( counter ); + aProfileName.Append( number ); + aProfileName.Append( KEndParenthesis ); + ++counter; + } + } + +// ----------------------------------------------------------------------------- +// HandleProfileRemoved +// +// Updates the given central repository value from the given file, when a +// profile is removed. This is used for those central repository keys that +// contain a profile id as a value, and if a deleted profile is +// currently assigned to the central repository value, it is resetted to the +// given default value. +// ----------------------------------------------------------------------------- +// +void HandleProfileRemoved( const TInt aRemovedProfileId, + const TInt aValuePlusDelta, + CRepository& aCenRep, + const TUint aKey, + const TInt aDefaultValue ) + { + if ( ( aValuePlusDelta ) == aRemovedProfileId ) + { + aCenRep.Set( aKey, aDefaultValue ); + } + } + +// ----------------------------------------------------------------------------- +// CreateIntSettingForNewProfileL +// +// Creates a new integer Central Repository key for the new profile and +// initialises it by copying the default value to it. +// +// ----------------------------------------------------------------------------- +// +void CreateIntSettingForNewProfileL( CRepository& aRepository, TInt aSettingId, + TInt aProfileId ) + { + TInt val; + User::LeaveIfError( + aRepository.Get( + ProfileEngUtils::ResolveKey( aSettingId, + KProEngDefaultProfileId ), val ) ); + TInt err( + aRepository.Create( + ProfileEngUtils::ResolveKey( aSettingId, aProfileId ), + val ) ); + if( ( err != KErrNone ) && ( err != KErrAlreadyExists ) ) + { + User::Leave( err ); + } + } + +// ----------------------------------------------------------------------------- +// CreateStringSettingForNewProfileL +// +// Creates a new string Central Repository key for the new profile and +// initialises it by copying the default value to it. +// +// ----------------------------------------------------------------------------- +// +void CreateStringSettingForNewProfileL( CRepository& aRepository, + TInt aSettingId, TInt aProfileId, + const TDesC& aNewProfileName, + TPtr& aStringPtr ) + { + if( aSettingId != KProEngProfileName ) + { + User::LeaveIfError( + aRepository.Get( + ProfileEngUtils::ResolveKey( aSettingId, + KProEngDefaultProfileId ), aStringPtr ) ); + } + else + { + aStringPtr = aNewProfileName; + } + TInt err( + aRepository.Create( + ProfileEngUtils::ResolveKey( aSettingId, aProfileId ), + aStringPtr ) ); + if( ( err != KErrNone ) && ( err != KErrAlreadyExists ) ) + { + User::Leave( err ); + } + } + +// ----------------------------------------------------------------------------- +// CreateBinSettingForNewProfileL +// +// Creates a new binary Central Repository key for the new profile and +// initialises it by copying the default value to it. +// +// ----------------------------------------------------------------------------- +// +void CreateBinSettingForNewProfileL( CRepository& aRepository, TInt aSettingId, + TInt aProfileId, TPtr8& aBinPtr ) + { + User::LeaveIfError( + aRepository.Get( + ProfileEngUtils::ResolveKey( aSettingId, + KProEngDefaultProfileId ), aBinPtr ) ); + TInt err( + aRepository.Create( + ProfileEngUtils::ResolveKey( aSettingId, aProfileId ), + aBinPtr ) ); + if( ( err != KErrNone ) && ( err != KErrAlreadyExists ) ) + { + User::Leave( err ); + } + } + +// ----------------------------------------------------------------------------- +// GetSettingsForProfile +// +// Gets all the settings of the profile with given id from Central Repository. +// ----------------------------------------------------------------------------- +// +TInt GetSettingsForProfile( CRepository& aRepository, + RArray& aSettings, + TInt aId ) + { + const TUint32 KId( aId << 24 ); + const TUint32 KMask( 0xFF000000 ); + TInt error( 0 ); + TRAP( error, error = aRepository.FindL( KId, KMask, aSettings ) ); + return error; + } + +// ----------------------------------------------------------------------------- +// DeleteSettingsForProfile +// +// Deletes all the settings of the profile with given id from Central Repository +// Tries to delete all without checking if a deletion fails. +// ----------------------------------------------------------------------------- +// +void DeleteSettingsForProfile( CRepository& aRepository, + RArray& aSettings ) + { + for( TInt i( aSettings.Count() - 1 ); i >= 0; --i ) + { + aRepository.Delete( aSettings[i] ); // ignore errors + } + } + +// ----------------------------------------------------------------------------- +// CreateSettingsForNewProfileL +// +// Creates new Central Repository keys for the new profile and initialises them +// by copying the default values to them. +// +// ----------------------------------------------------------------------------- +// +void CreateSettingsForNewProfileL( CRepository& aRepository, TInt aProfileId, + const TDesC& aNewProfileName, + TResourceReader& aReader ) + { + User::LeaveIfError( aRepository.StartTransaction( + CRepository::EReadWriteTransaction ) ); + + // This only be used after normal RFS(restore factory settings), If there was + // user created profile before normal RFS, and the normal RFS only restore + // KProEngUsedIds, the settings of user created profile are in CenRep still. + // So we should delete the remain settings and create new one. + RArray settings; + if ( !GetSettingsForProfile( aRepository, settings, aProfileId ) ) + { + DeleteSettingsForProfile( aRepository, settings ); + } + settings.Close(); + + HBufC* stringVal = HBufC::NewL( + NCentralRepositoryConstants::KMaxUnicodeStringLength ); + CleanupStack::PushL( stringVal ); + TPtr stringValPtr = stringVal->Des(); + HBufC8* binVal = HBufC8::NewL( + NCentralRepositoryConstants::KMaxBinaryLength ); + CleanupStack::PushL( binVal ); + TPtr8 binValPtr = binVal->Des(); + + TInt numOfElements( aReader.ReadInt16() ); + + for( TInt i( 0 ) ; i < numOfElements ; ++i ) + { + TInt settingId( aReader.ReadInt32() ); + TInt keyType( aReader.ReadInt32() ); + switch( keyType ) + { + case EProfileSettingKeyTypeInt: + { + CreateIntSettingForNewProfileL( aRepository, settingId, + aProfileId ); + break; + } + case EProfileSettingKeyTypeString: + { + CreateStringSettingForNewProfileL( aRepository, settingId, + aProfileId, + aNewProfileName, + stringValPtr ); + break; + } + case EProfileSettingKeyTypeBin: + { + CreateBinSettingForNewProfileL( aRepository, settingId, + aProfileId, binValPtr ); + + break; + } + case EProfileSettingKeyTypeReal: // no settings of this type + default: + { + break; + } + } + } + + CleanupStack::PopAndDestroy( 2 ); // stringVal, binVal + + // Update the used ids value (this is done last so that we can get the + // repository back in a legal state (by deleting the settings just + // created)). + TBuf8< KProfilesMaxNumberOfDynamicProfiles > idBuf; + ProfileEngUtils::GetBinarySettingL( aRepository, KProEngUsedIds, idBuf ); + idBuf.Append( aProfileId ); + User::LeaveIfError( aRepository.Set( KProEngUsedIds, idBuf ) ); + + TUint32 ignore( 0 ); + User::LeaveIfError( aRepository.CommitTransaction( ignore ) ); + } + +// ----------------------------------------------------------------------------- +// DeleteProfileIdFromList +// +// ----------------------------------------------------------------------------- +// +void DeleteProfileIdFromList( CRepository& aRepository, TInt aId, TDes8& aIdBuf ) + { + TInt numOfIds = aIdBuf.Length(); + for( TInt idx( 0 ); idx < numOfIds; ++idx ) + { + if( aIdBuf[ idx ] == aId ) + { + aIdBuf.Delete( idx, 1 ); + aRepository.Set( KProEngUsedIds, aIdBuf ); + break; + } + } + } + +void DoDeleteProfileL( CRepository& aCenRep, TInt aId ) + { + RArray settings; + User::LeaveIfError( GetSettingsForProfile( aCenRep, settings, aId ) ); + + TBuf8< 4 * KProfilesMaxNumberOfDynamicProfiles > idBuf; // One id is 4-bytes long + ProfileEngUtils::GetBinarySettingL( aCenRep, KProEngUsedIds, idBuf ); + + User::LeaveIfError( aCenRep.StartTransaction( + CRepository::EReadWriteTransaction ) ); + DeleteSettingsForProfile( aCenRep, settings ); + settings.Reset(); + DeleteProfileIdFromList( aCenRep, aId, idBuf ); + + TInt headsetVal( 0 ); + TInt loopsetVal( 0 ); + TInt ttyVal( 0 ); + TInt btVal( 0 ); + TUint32 ignore( 0 ); + TRAPD( error, + CRepository* cr = CRepository::NewL( KCRUidProfileSettings ); + CleanupStack::PushL( cr ); + User::LeaveIfError( cr->Get( KSettingsHeadsetDefaultProfile, headsetVal ) ); + User::LeaveIfError( cr->Get( KSettingsLoopsetDefaultProfile, loopsetVal ) ); + User::LeaveIfError( cr->Get( KSettingsTTYDefaultProfile, ttyVal ) ); + User::LeaveIfError( cr->Get( KSettingsBTDefaultProfile, btVal ) ); + User::LeaveIfError( cr->StartTransaction( + CRepository::EReadWriteTransaction ) ); + // -1 is a mystery, consult general settings team: + // 0 ( = general profile ) is the default profile used with all the + // accessories: + HandleProfileRemoved( aId, headsetVal-1, *cr, + KSettingsHeadsetDefaultProfile, 0 ); + HandleProfileRemoved( aId, loopsetVal-1, *cr, + KSettingsLoopsetDefaultProfile, 0 ); + HandleProfileRemoved( aId, ttyVal-1, *cr, + KSettingsTTYDefaultProfile, 0 ); + HandleProfileRemoved( aId, btVal-1, *cr, + KSettingsBTDefaultProfile, 0 ); + User::LeaveIfError( cr->CommitTransaction( ignore ) ); + + CleanupStack::PopAndDestroy(); // delete cr: + ); + + if( error ) + { + aCenRep.RollbackTransaction(); // ignore error + User::Leave( error ); + } + + User::LeaveIfError( aCenRep.CommitTransaction( ignore ) ); + } + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CProfileEngineImpl::DeleteProfileL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CProfileEngineImpl::DeleteProfileL( TInt aId ) + { + iMutex.Wait(); + TInt activeProfileId( ActiveProfileId() ); + + if( activeProfileId < 0 ) + { + iMutex.Signal(); + User::Leave( activeProfileId ); + } + + // Do not allow delete active profile + if( aId == activeProfileId ) + { + iMutex.Signal(); + return KErrAbort; + } + // Do not allow delete default profile + if( IsDefaultProfile( aId ) ) + { + iMutex.Signal(); + return KErrAbort; + } + + TRAPD( error, DoDeleteProfileL( *iCenRep, aId ) ); + iMutex.Signal(); + User::LeaveIfError( error ); + return KErrNone; + } + +// ----------------------------------------------------------------------------- +// CProfileEngineImpl::CreateProfileL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +MProfileExtended* CProfileEngineImpl::CreateProfileL() + { + if( SysUtil::FFSSpaceBelowCriticalLevelL( iFs ) ) + { + User::Leave( KErrDiskFull ); + } + + // Create profile ID + CProfilesNamesArrayImpl* profileNameArray = CProfilesNamesArrayImpl::NewLC(); + + iMutex.Wait(); + TRAPD( error, ReadProfilesNamesL( profileNameArray ) ); + if( error ) + { + iMutex.Signal(); + User::Leave( error ); + } + + if( profileNameArray->MdcaCount() - // current profile count + iProfileLocalisedNames->MdcaCount() >= // default profile count + KProfilesMaxNumberOfDynamicProfiles ) // max dynamic profiles + { + // Max number of dynamic profiles + CleanupStack::PopAndDestroy(); // profileNameArray + iMutex.Signal(); + return NULL; + } + + TInt profileId( KErrNotFound ); + // Find first free id + TInt lastDynamicProfileId( KProfileBaseDynamicProfileId + + KProfilesMaxNumberOfDynamicProfiles ); + + for( TInt i( KProfileBaseDynamicProfileId ); i < lastDynamicProfileId; ++i ) + { + TInt index( profileNameArray->FindById( i ) ); + if( index == KErrNotFound ) + { + profileId = i; + break; + } + } + + if( profileId == KErrNotFound ) + { + CleanupStack::PopAndDestroy(); // profileNameArray + iMutex.Signal(); + return NULL; + } + + TBuf profileName; + TRAP( error, + ReadNewProfileNameFromResourceL( R_NEW_PROFILE, profileName ) ); + if( error ) + { + iMutex.Signal(); + User::Leave( error ); + } + + GenerateProfileName( profileName, *profileNameArray ); + CleanupStack::PopAndDestroy(); // profileNameArray + + TResourceReader rsReader; + CProfileImpl* newProfile = NULL; + TRAP( error, + ReadResourceInBufferLC( R_PROFILE_SETTINGS, rsReader ); + CreateSettingsForNewProfileL( *iCenRep, profileId, + profileName, rsReader ); + CleanupStack::PopAndDestroy(); // ReadResourceInBufferLC + + // Create and store new profile + newProfile = CProfileImpl::NewLC( *iFs ); + newProfile->InternalizeL( *iCenRep, profileId ); + + CleanupStack::Pop(); // newProfile + ); + + iMutex.Signal(); + User::LeaveIfError( error ); + + return newProfile; + } + +// ----------------------------------------------------------------------------- +// CProfileEngineImpl::ReadNewProfileNameFromResourceL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CProfileEngineImpl::ReadNewProfileNameFromResourceL( TInt aResourceId, + TDes& aProfileName ) + { + TResourceReader rsReader; + ReadResourceInBufferLC( aResourceId, rsReader ); + + TPtrC profileName( rsReader.ReadTPtrC() ); + aProfileName.Copy( profileName ); + + CleanupStack::PopAndDestroy(); // ReadResourceInBufferLC + } + +// ----------------------------------------------------------------------------- +// CProfileEngineImpl::ReadNewProfileNameFromResourceL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +CProfileNameImpl* CProfileEngineImpl::ReadNewProfileNameFromResourceLC() + { + TBuf profileName; + ReadNewProfileNameFromResourceL( R_NEW_PROFILE, profileName ); + + TBuf shortName; + ReadNewProfileNameFromResourceL( R_NEW_PROFILE_SHORT, shortName ); + + TBuf naviName; + ReadNewProfileNameFromResourceL( R_NEW_PROFILE_NAVI, naviName ); + + TBuf titleName; + ReadNewProfileNameFromResourceL( R_NEW_PROFILE_TITLE, titleName ); + + CProfileNameImpl* localizedName = + CProfileNameImpl::NewLC( 0, profileName, shortName, + naviName, titleName ); + + return localizedName; + } + +// ----------------------------------------------------------------------------- +// CProfileEngineImpl::ReadDynamicProfilesNamesL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CProfileEngineImpl::ReadDynamicProfilesNamesL( + CProfilesNamesArrayImpl* aProfilesNames, + CProfileNameImpl& aNameTemplate ) + { + TBuf8< NCentralRepositoryConstants::KMaxBinaryLength > idBuf; + ProfileEngUtils::GetBinarySettingL( *iCenRep, KProEngUsedIds, idBuf ); + TInt len = idBuf.Length(); + + if( len == 0 ) + { + return; // No user-created profiles, just return + } + + CProfileNameImpl* localizedName = ReadNewProfileNameFromResourceLC(); + + for( TInt i( 0 ); i < len; ++i ) + { + aNameTemplate.InternalizeL( *iCenRep, idBuf[i] ); + if( !aNameTemplate.IsProfileNameChanged() ) + { + TInt idxOfParenthesis( + aNameTemplate.Name().Find( KFirstParenthesis ) ); + if( idxOfParenthesis != KErrNotFound ) + { + TBuf uniquePart = + aNameTemplate.Name().Mid( idxOfParenthesis, + KProfileGeneratedNameTailLength ); + aNameTemplate.SetLocalizedProfileNameL( *localizedName, + uniquePart ); + } + else + { + aNameTemplate.SetLocalizedProfileNameL( *localizedName, + KNullDesC() ); + } + } + + CProfileNameImpl* nameImpl = + CProfileNameImpl::NewLC( aNameTemplate ); + + User::LeaveIfError( aProfilesNames->InsertInOrder( nameImpl ) ); + CleanupStack::Pop(); // nameImpl + } + + CleanupStack::PopAndDestroy( localizedName ); + } + +// ----------------------------------------------------------------------------- +// CProfileEngineImpl::SetLocalizedNameForDynamicProfileL +// +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CProfileEngineImpl::SetLocalizedNameForDynamicProfileL( + CProfileImpl& aProfile ) + { + CProfileNameImpl* localizedName = ReadNewProfileNameFromResourceLC(); + + TInt idxOfParenthesis( + aProfile.ProfileName().Name().Find( KFirstParenthesis ) ); + if( idxOfParenthesis != KErrNotFound ) + { + TBuf uniquePart = + aProfile.ProfileName().Name().Mid( idxOfParenthesis, + KProfileGeneratedNameTailLength ); + aProfile.SetLocalizedProfileNameL( *localizedName, uniquePart ); + } + else + { + aProfile.SetLocalizedProfileNameL( *localizedName, + KNullDesC() ); + } + + CleanupStack::PopAndDestroy( localizedName ); + } + +// End of File +