--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sysstatemgmt/systemstatemgr/cmd/src/ssmcommandlistresourcereaderimpl.cpp Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,834 @@
+// 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 "ssmcommandlistresourcereaderimpl.h"
+
+#include <bautils.h>
+#include <barsc2.h>
+#include <ssm/ssmcommandlist.h>
+#include <ssm/ssmconditionalcallback.h>
+
+#include <ssm/ssmcommandfactory.h>
+#include <ssm/ssmcommand.h>
+#include "ssmcommandbase.h"
+#include "ssmcommandparameters.h"
+#include "ssmcommandlistinterface.h"
+#include "ssmdebug.h"
+#include "ssmpanic.h"
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+#include "ssmcommandlistimpl.h"
+#endif
+
+CSsmCommandListResourceReaderImpl* CSsmCommandListResourceReaderImpl::NewL(RFs& aFs, const TDesC& aCommandListPath, MSsmConditionalCallback& aConditionalCallback)
+ {
+ CSsmCommandListResourceReaderImpl* self = new(ELeave) CSsmCommandListResourceReaderImpl();
+ CleanupStack::PushL(self);
+ self->ConstructL(aFs, aCommandListPath, aConditionalCallback);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSsmCommandListResourceReaderImpl::CSsmCommandListResourceReaderImpl()
+ {
+ }
+
+CSsmCommandListResourceReaderImpl::~CSsmCommandListResourceReaderImpl()
+ {
+ delete iPreparer;
+ delete iInitialiser;
+ delete iResourcePool;
+ }
+
+void CSsmCommandListResourceReaderImpl::ConstructL(RFs& aFs, const TDesC& aCommandListPath, MSsmConditionalCallback& aConditionalCallback)
+ {
+ iResourcePool = new(ELeave) CResourcePool;
+ iInitialiser = CInitialiser::NewL(aFs, aCommandListPath, *iResourcePool);
+ iPreparer = new(ELeave) CPreparer(*iResourcePool, aConditionalCallback);
+ }
+
+void CSsmCommandListResourceReaderImpl::Initialise(TRequestStatus& aStatus)
+ {
+ __ASSERT_ALWAYS(!Busy(), PanicNow(KPanicCmdResourceReader, EInUse1));
+ iInitialiser->Start(aStatus);
+ }
+
+void CSsmCommandListResourceReaderImpl::InitialiseCancel()
+ {
+ iInitialiser->Cancel();
+ }
+
+void CSsmCommandListResourceReaderImpl::PrepareCommandList(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmState& aState, TRequestStatus& aStatus)
+ {
+ __ASSERT_ALWAYS(!Busy(), PanicNow(KPanicCmdResourceReader, EInUse2));
+ iPreparer->Start(aCommandList, aCommandListId, aState, aStatus);
+ }
+
+void CSsmCommandListResourceReaderImpl::PrepareCommandList(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmSwp& aSwp, TRequestStatus& aStatus)
+ {
+ __ASSERT_ALWAYS(!Busy(), PanicNow(KPanicCmdResourceReader, EInUse3));
+ iPreparer->Start(aCommandList, aCommandListId, aSwp, aStatus);
+ }
+
+void CSsmCommandListResourceReaderImpl::PrepareCommandListCancel()
+ {
+ iPreparer->Cancel();
+ }
+
+TBool CSsmCommandListResourceReaderImpl::IsCommandListReady() const
+ {
+ // enables caller to find out if the command list they passed
+ // to PrepareCommandList is fully prepared or not
+ return iPreparer->IsCommandListReady();
+ }
+
+TBool CSsmCommandListResourceReaderImpl::Busy() const
+ {
+ return iInitialiser->IsActive() || iPreparer->IsActive();
+ }
+
+void CSsmCommandListResourceReaderImpl::GetCommandListIdsL(RArray<TInt>& aArray) const
+ {
+ iResourcePool->GetCommandListIdsL(aArray);
+ }
+
+// CResourcePool
+CSsmCommandListResourceReaderImpl::CResourcePool::CResourcePool()
+ {
+ }
+
+CSsmCommandListResourceReaderImpl::CResourcePool::~CResourcePool()
+ {
+ iMappings.Close();
+ iResourceFiles.ResetAndDestroy();
+ iResourceFileNames.ResetAndDestroy();
+ }
+
+TBool CSsmCommandListResourceReaderImpl::CResourcePool::IsEmpty() const
+ {
+ return !(iMappings.Count() > 0);
+ }
+
+void CSsmCommandListResourceReaderImpl::CResourcePool::Reset()
+ {
+ iMappings.Reset();
+ iResourceFiles.ResetAndDestroy();
+ iResourceFileNames.ResetAndDestroy();
+ }
+
+void CSsmCommandListResourceReaderImpl::CResourcePool::AppendL(const CResourceFile* aResourceFile)
+ {
+ iResourceFiles.AppendL(aResourceFile);
+ }
+
+void CSsmCommandListResourceReaderImpl::CResourcePool::AppendL(const TDesC& aFileName)
+ {
+ HBufC* name = aFileName.AllocLC();
+ iResourceFileNames.AppendL(name);
+ CleanupStack::Pop(name);
+ }
+
+
+void CSsmCommandListResourceReaderImpl::CResourcePool::AppendL(const TMapping& aMapping)
+ {
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ //check if the mapping already exists
+ TInt index = iMappings.Find(aMapping);
+ if (index != KErrNotFound)
+ {
+ DEBUGPRINT2(_L("Duplicate Substate found at index: %d"), index);
+ }
+ TInt err = iMappings.InsertInSignedKeyOrderAllowRepeats(aMapping);
+#else
+ TInt err = iMappings.InsertInSignedKeyOrder(aMapping);
+ if(KErrAlreadyExists == err)
+ {
+ PanicNow(KPanicCmdResourceReader, EDuplicateSubstateInCommandList);
+ }
+#endif
+ User::LeaveIfError(err);
+ }
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+// This function will get all the mappings which have the same commandlistId's (substates) into aMappingArray
+void CSsmCommandListResourceReaderImpl::CResourcePool::UpdateMappingArrayL(TInt aCommandListId, RArray<TMapping>& aMappingArray) const
+ {
+ aMappingArray.Reset();
+ TMapping mapping(aCommandListId, 0, NULL);
+ const TInt mappingCount = iMappings.Count();
+ TInt mappingIndex = iMappings.FindL(mapping);
+
+ for(; mappingIndex < mappingCount; ++mappingIndex)
+ {
+ aMappingArray.AppendL(iMappings[mappingIndex]);
+ if ((mappingIndex >= (mappingCount - 1)) || (iMappings[mappingIndex].iCommandListId !=
+ iMappings[mappingIndex + 1].iCommandListId))
+ {
+ //Breaking as it reached end of array or completed appending the mappings for
+ //the given commandlist id
+ break;
+ }
+ }
+ DEBUGPRINT3(_L("Mapping Array for substate %d Contains %d entries"), iMappings[mappingIndex].iCommandListId, aMappingArray.Count());
+ }
+
+#else
+CSsmCommandListResourceReaderImpl::TMapping CSsmCommandListResourceReaderImpl::CResourcePool::MappingL(TInt aCommandListId) const
+ {
+ TMapping mapping(aCommandListId, 0, NULL);
+ const TInt index = iMappings.FindL(mapping);
+ return iMappings[index];
+ }
+
+#endif
+void CSsmCommandListResourceReaderImpl::CResourcePool::GetCommandListIdsL(RArray<TInt>& aArray) const
+ {
+ TInt count = iMappings.Count();
+ __ASSERT_ALWAYS(count > 0, PanicNow(KPanicCmdResourceReader, ENotInitialized3));
+ if (aArray.Count() != 0)
+ {
+ SSMLOGLEAVE(KErrArgument);
+ }
+ aArray.ReserveL(count);
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ TInt i = 0;
+ for(i = 0; i < iMappings.Count() - 1 ; ++i)
+ {
+ if(iMappings[i].iCommandListId != iMappings[i+1].iCommandListId)
+ {
+ aArray.AppendL(iMappings[i].iCommandListId);
+ }
+ }
+ //append the last element anyway as it is already compared
+ aArray.AppendL(iMappings[i].iCommandListId);
+ aArray.Compress();
+
+ DEBUGPRINT2(_L("The number of substates in resource files : %d"),iMappings.Count() );
+ DEBUGPRINT2(_L("The number of substates after filtering duplicates : %d"),aArray.Count());
+#else
+ for(TInt i = 0; i < count; ++i)
+ {
+ aArray.AppendL(iMappings[i].iCommandListId);
+ }
+#endif
+ }
+
+const TDesC& CSsmCommandListResourceReaderImpl::CResourcePool::FileNameForResourceFileL(const CResourceFile* aResourceFile) const
+ {
+ TInt count = iResourceFiles.Count();
+ for(TInt i = 0; i < count; ++i)
+ {
+ if(iResourceFiles[i] == aResourceFile)
+ {
+ return *iResourceFileNames[i];
+ }
+ }
+ SSMLOGLEAVE(KErrNotFound);
+ return KNullDesC16();
+ }
+
+// CActiveBase
+CSsmCommandListResourceReaderImpl::CActiveBase::CActiveBase(TInt aPriority)
+ :CActive(aPriority), iAction(EIdle)
+ {
+ }
+
+CSsmCommandListResourceReaderImpl::CActiveBase::~CActiveBase()
+ {
+ }
+
+void CSsmCommandListResourceReaderImpl::CActiveBase::Start()
+ {
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete(status, KErrNone);
+ SetActive();
+ }
+
+void CSsmCommandListResourceReaderImpl::CActiveBase::CompleteClientRequest(TInt aReason)
+ {
+ if (iRequestStatus)
+ {
+ User::RequestComplete(iRequestStatus, aReason);
+ iRequestStatus = NULL;
+ }
+ }
+
+// CInitialiser
+CSsmCommandListResourceReaderImpl::CInitialiser* CSsmCommandListResourceReaderImpl::CInitialiser::NewL(RFs& aFs, const TDesC& aCommandListPath, CResourcePool& aResourcePool)
+ {
+ CInitialiser* self = new(ELeave) CInitialiser(aFs, aResourcePool);
+ CleanupStack::PushL(self);
+ self->ConstructL(aCommandListPath);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+CSsmCommandListResourceReaderImpl::CInitialiser::CInitialiser(RFs& aFs, CResourcePool& aResourcePool)
+ :CActiveBase(EPriorityStandard), iFs(aFs), iResourcePool(aResourcePool)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CSsmCommandListResourceReaderImpl::CInitialiser::~CInitialiser()
+ {
+ Cancel();
+ ResetToUninitialisedState();
+ iPath.Close();
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ iSystemDrivePath.Close();
+#endif
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::ResetToUninitialisedState()
+ {
+ delete iResourceFileEntries;
+ iResourceFileEntries = NULL;
+ iEntryIndex = 0;
+ iResourcePool.Reset();
+ iAction = EIdle;
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ delete iRssFileEntriesInSysDrive;
+ iRssFileEntriesInSysDrive = NULL;
+#endif
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::ConstructL(const TDesC& aCommandListPath)
+ {
+ if (aCommandListPath.Length() == 0)
+ {
+ SSMLOGLEAVE(KErrArgument);
+ }
+ iPath.CreateL(aCommandListPath);
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ // get the system drive char and create system drive path
+ TChar systemDriveChar = iFs.GetSystemDriveChar();
+ //append the system drive
+ iSystemDrivePath.CreateL(iPath.MaxLength());
+ iSystemDrivePath.Append(systemDriveChar);
+ //append the system drive path which is same as ROM drive path minus ROM drive char
+ iSystemDrivePath.Append(iPath.Right(iPath.Length()-1));
+#endif
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::Start(TRequestStatus& aStatus)
+ {
+ __ASSERT_ALWAYS(iRequestStatus == NULL, PanicNow(KPanicCmdResourceReader, EInUse1));
+ aStatus = KRequestPending;
+ iRequestStatus = &aStatus;
+
+ iAction = EInitialiseFirstStep;
+ CActiveBase::Start();
+ }
+
+/**
+@panic ENonNullResourceFileEntries if the Resource File Entries is Not Null
+@panic ENullResourceFileEntries if the Resource File Entries is Null
+@panic EInvalidRunLAction if the RunL Action is invalid
+*/
+void CSsmCommandListResourceReaderImpl::CInitialiser::RunL()
+ {
+ SSMLOGLEAVEIFERROR(iStatus.Int());
+
+ switch (iAction)
+ {
+ case EInitialiseFirstStep:
+ DoInitialiseFirstStepL();
+ break;
+ case EInitialiseNextStep:
+ DoInitialiseNextStepL();
+ break;
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ case EInitialiseSysDriveStep:
+ DoInitialiseSysDriveStepL();
+ break;
+#endif
+ default:
+ PanicNow(KPanicCmdResourceReader, EInvalidRunLAction);
+ break;
+ }
+
+ if (iAction == EIdle)
+ {
+ CompleteClientRequest(KErrNone); // must not leave between here and end of RunL
+ return;
+ }
+
+ CActiveBase::Start(); // run again
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::DoCancel()
+ {
+ // iStatus is always completed before this object is set active, so no need to complete iStatus with KErrCancel
+ CompleteClientRequest(KErrCancel);
+ ResetToUninitialisedState();
+ }
+
+TInt CSsmCommandListResourceReaderImpl::CInitialiser::RunError(TInt aError)
+ {
+ DEBUGPRINT2(_L("Resource reader initialiser reason (%d)"), aError);
+ CompleteClientRequest(aError);
+ ResetToUninitialisedState();
+ return KErrNone;
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::DoInitialiseFirstStepL()
+ {
+ if (!iResourcePool.IsEmpty())
+ {
+ // already initialised, don't count this as an error
+ iAction = EIdle;
+ return;
+ }
+
+ // get list of command list resource filenames
+ TFileName path(iPath);
+ _LIT(KStar, "*");
+ path.Append(KStar);
+ const TUid KUidResourceFile = {0x101f4a6b};
+ __ASSERT_ALWAYS(iResourceFileEntries == NULL, PanicNow(KPanicCmdResourceReader, ENonNullResourceFileEntries));
+ // The error cannot be KErrPathNotFound as fallback will be used if there is not startup path
+ // Even if there are no resource files, this succeeds
+ // User::LeaveIfError handles other error conditions
+ User::LeaveIfError(iFs.GetDir(path, TUidType(KUidResourceFile, TUid::Uid(KUidSsmCommandListResourceFile)), ESortNone, iResourceFileEntries));
+ iEntryIndex = iResourceFileEntries->Count();
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ DEBUGPRINT2(_L("Number of resource files in ROM Drive : %d"),iEntryIndex );
+ // Now, get list of command list resource filenames from system drive too
+ TFileName sysPath(iSystemDrivePath);
+ sysPath.Append(KStar);
+ TInt err = (iFs.GetDir(sysPath, TUidType(KUidResourceFile, TUid::Uid(KUidSsmCommandListResourceFile)), ESortNone, iRssFileEntriesInSysDrive));
+ if (KErrNone == err)
+ {
+ iSysDriveEntryIndex = iRssFileEntriesInSysDrive->Count();
+ DEBUGPRINT2(_L("Number of resource files in System Drive : %d"),iSysDriveEntryIndex );
+ }
+ // all other error conditions are ignored as there is no compulsion for resource files to be present on system drive
+ else if(KErrPathNotFound == err)
+ {
+ //the path for SCLs on system drive does not exist
+ DEBUGPRINT1(_L("System Drive does not contain command lists"));
+ }
+ if(iEntryIndex == 0 && iSysDriveEntryIndex == 0)
+ {
+ DEBUGPRINT3(_L("Command list resource file directories (%S) and (%S) do not contain any command list resource files"), &path, &sysPath);
+ SSMLOGLEAVE(KErrNotFound);
+ }
+#else
+ if (iEntryIndex == 0)
+ {
+ DEBUGPRINT2(_L("Command list resource file directory (%S) does not contain any command list resource files"), &path);
+ SSMLOGLEAVE(KErrNotFound);
+ }
+#endif
+ iAction = EInitialiseNextStep;
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::DoInitialiseNextStepL()
+ {
+ __ASSERT_ALWAYS(iResourceFileEntries != NULL, PanicNow(KPanicCmdResourceReader, ENullResourceFileEntries));
+ if (iEntryIndex--)
+ {
+ TFileName filename(iPath);
+ filename.Append((*iResourceFileEntries)[iEntryIndex].iName);
+ CResourceFile* const resourceFile = OpenResourceFileL(filename);
+ ParseFileL(resourceFile);
+ }
+
+ else
+ {
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ iAction = EInitialiseSysDriveStep;
+#else
+ // initialisation complete
+ iAction = EIdle;
+#endif
+ delete iResourceFileEntries;
+ iResourceFileEntries = NULL;
+ }
+ }
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+void CSsmCommandListResourceReaderImpl::CInitialiser::DoInitialiseSysDriveStepL()
+ {
+ if (iSysDriveEntryIndex--)
+ {
+ TFileName filename(iSystemDrivePath);
+ filename.Append((*iRssFileEntriesInSysDrive)[iSysDriveEntryIndex].iName);
+ CResourceFile* const resourceFile = OpenResourceFileL(filename);
+ ParseFileL(resourceFile);
+ }
+ else
+ {
+ // initialisation complete
+ iAction = EIdle;
+ delete iRssFileEntriesInSysDrive;
+ iRssFileEntriesInSysDrive = NULL;
+ }
+ }
+#endif
+CResourceFile* CSsmCommandListResourceReaderImpl::CInitialiser::OpenResourceFileL(const TDesC& aFileName)
+ {
+
+ // open the resource file
+ RFile file;
+ CleanupClosePushL(file);
+ User::LeaveIfError(file.Open(iFs, aFileName, EFileRead | EFileShareReadersOnly));
+
+ // read entire resource file into a buffer
+ TInt fileSize;
+ User::LeaveIfError(file.Size(fileSize));
+ RBuf8 buf;
+ buf.CreateL(fileSize);
+ CleanupClosePushL(buf);
+ User::LeaveIfError(file.Read(buf));
+
+ // create a CResourceFile from the buffer and add it to array (the CResourceFile takes its own copy of the buffer)
+ CResourceFile* const resourceFile = CResourceFile::NewL(buf);
+ CleanupStack::PushL(resourceFile);
+ iResourcePool.AppendL(resourceFile);
+ CleanupStack::Pop(resourceFile);
+ iResourcePool.AppendL(aFileName);
+ CleanupStack::PopAndDestroy(&buf);
+ CleanupStack::PopAndDestroy(&file);
+ return resourceFile;
+ }
+
+void CSsmCommandListResourceReaderImpl::CInitialiser::ParseFileL(CResourceFile* aResourceFile)
+ {
+ // read root resource
+ RResourceReader rootReader;
+ const TInt KRootResourceId = 1;
+ rootReader.OpenLC(aResourceFile, KRootResourceId);
+ const TSsmResourceVersion version = static_cast<TSsmResourceVersion>(rootReader.ReadInt16L());
+ if (version != ESsmInitialVersion)
+ {
+ SSMLOGLEAVE(KErrNotSupported);
+ }
+ const TInt reserved1 = rootReader.ReadInt16L(); // skip SSM_COMMAND_LIST_ROOT.reserved1
+ const TInt commandListMappingResourceId = rootReader.ReadInt32L();
+ if (commandListMappingResourceId <= 0)
+ {
+ DEBUGPRINT1(_L("Command list resource file contains no mappings"));
+ SSMLOGLEAVE(KErrNotFound);
+ }
+ CleanupStack::PopAndDestroy(&rootReader);
+
+ // read mapping resource
+ RResourceReader mappingReader;
+ mappingReader.OpenLC(aResourceFile, commandListMappingResourceId);
+ const TInt mappingCount = mappingReader.ReadInt16L();
+ if (!mappingCount)
+ {
+ DEBUGPRINT1(_L("Command list resource file contains no mappings"));
+ SSMLOGLEAVE(KErrNotFound);
+ }
+ for (TInt i = 0; i < mappingCount; i++)
+ {
+ // add each mapping to the pool
+ TUint commandListId = mappingReader.ReadUint32L();
+ TInt resourceId = mappingReader.ReadInt32L();
+ TMapping mapping(commandListId, resourceId, aResourceFile);
+ iResourcePool.AppendL(mapping);
+ }
+ CleanupStack::PopAndDestroy(&mappingReader);
+ }
+
+// CPreparer
+CSsmCommandListResourceReaderImpl::CPreparer::CPreparer(const CResourcePool& aResourcePool, MSsmConditionalCallback& aConditionalCallback)
+ :CActiveBase(EPriorityStandard), iResourcePool(aResourcePool), iConditionalCallback(aConditionalCallback), iSwpChange(0, 0), iMapping(0, 0, NULL)
+ {
+ CActiveScheduler::Add(this);
+ }
+
+CSsmCommandListResourceReaderImpl::CPreparer::~CPreparer()
+ {
+ Cancel();
+ ResetReadyForNextPrepare();
+ }
+
+void CSsmCommandListResourceReaderImpl::CPreparer::Start(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmState& aState, TRequestStatus& aStatus)
+ {
+ __ASSERT_ALWAYS(iRequestStatus == NULL, PanicNow(KPanicCmdResourceReader, EInUse2));
+ __ASSERT_ALWAYS(!iResourcePool.IsEmpty(), PanicNow(KPanicCmdResourceReader, ENotInitialized));
+ aStatus = KRequestPending;
+ iRequestStatus = &aStatus;
+
+ iCommandList = &aCommandList;
+ iCommandListId = aCommandListId;
+ iState = aState;
+ iCommandListReady = EFalse;
+
+ iAction = EPrepareFirstStep;
+ CActiveBase::Start();
+ }
+
+void CSsmCommandListResourceReaderImpl::CPreparer::Start(MSsmCommandList& aCommandList, TInt aCommandListId, const TSsmSwp& aSwp, TRequestStatus& aStatus)
+ {
+ __ASSERT_ALWAYS(iRequestStatus == NULL, PanicNow(KPanicCmdResourceReader, EInUse3));
+ __ASSERT_ALWAYS(!iResourcePool.IsEmpty(), PanicNow(KPanicCmdResourceReader, ENotInitialized2));
+ aStatus = KRequestPending;
+ iRequestStatus = &aStatus;
+
+ iCommandList = &aCommandList;
+ iCommandListId = aCommandListId;
+ iSwpChange = aSwp;
+ iCommandListReady = EFalse;
+
+ iAction = EPrepareFirstStep;
+ CActiveBase::Start();
+ }
+
+/**
+@panic EInvalidRunLAction if the RunL Action is invalid
+*/
+void CSsmCommandListResourceReaderImpl::CPreparer::RunL()
+ {
+ SSMLOGLEAVEIFERROR(iStatus.Int());
+
+ switch (iAction)
+ {
+ case EPrepareFirstStep:
+ DoPrepareFirstStepL();
+ break;
+ case EPrepareNextStep:
+ DoPrepareNextStepL();
+ break;
+ default:
+ PanicNow(KPanicCmdResourceReader, EInvalidRunLAction);
+ break;
+ }
+
+ if (iAction == EIdle)
+ {
+ CompleteClientRequest(KErrNone); // must not leave between here and end of RunL
+ return;
+ }
+
+ CActiveBase::Start(); // run again
+ }
+
+void CSsmCommandListResourceReaderImpl::CPreparer::DoCancel()
+ {
+ // iStatus is always completed before this object is set active, so no need to complete iStatus with KErrCancel
+ CompleteClientRequest(KErrCancel);
+ ResetReadyForNextPrepare();
+ }
+
+TInt CSsmCommandListResourceReaderImpl::CPreparer::RunError(TInt aError)
+ {
+ DEBUGPRINT2(_L("Resource reader preparer reason (%d)"), aError);
+ CompleteClientRequest(aError);
+ ResetReadyForNextPrepare();
+ return KErrNone;
+ }
+
+TBool CSsmCommandListResourceReaderImpl::CPreparer::IsCommandListReady()
+ {
+ // enables caller to find out if the command list they passed
+ // to PrepareCommandList is fully prepared or not
+ if (iCommandListReady)
+ {
+ iCommandListReady = EFalse;
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+void CSsmCommandListResourceReaderImpl::CPreparer::ResetReadyForNextPrepare()
+ {
+ iListReader.Close();
+ iCommandIndex = 0;
+ iCommandListReady = EFalse;
+ iAction = EIdle;
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ iCommandIndexInRssFile.Reset();
+ iMappingArray.Reset();
+#endif
+ }
+
+
+void CSsmCommandListResourceReaderImpl::CPreparer::DoPrepareFirstStepL()
+ {
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ iCurrentCommandListInMapping = 0;
+ iResourcePool.UpdateMappingArrayL(iCommandListId,iMappingArray);
+ TInt substateCount = iMappingArray.Count();
+ iCommandIndexInRssFile.ReserveL(substateCount);
+
+ // get number of commands from all the lists
+ for(TInt substateIndex = 0; substateIndex < substateCount; ++substateIndex )
+ {
+ iListReader.OpenL(iMappingArray[substateIndex].iResourceFile, iMappingArray[substateIndex].iResourceId);
+ //advancing the pointer to point to number of commands in list
+ iListReader.AdvanceL(sizeof(TInt32));
+ iCommandIndexInRssFile.AppendL(iListReader.ReadUint16L());
+ iCommandIndex += iCommandIndexInRssFile[substateIndex];
+ iListReader.Close();
+ }
+ //open the first resource id and read the commands.
+ iListReader.OpenL(iMappingArray[iCurrentCommandListInMapping].iResourceFile, iMappingArray[iCurrentCommandListInMapping].iResourceId);
+ // the delay between the commands is read from only the frist command list. In case of other lists, it is ignored.
+ iCommandList->SetDelayBetweenCommands(iListReader.ReadInt32L());
+ iCommandList->SetResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMappingArray[iCurrentCommandListInMapping].iResourceFile));
+ //skip reading command count again and jump to command resourceId
+ iListReader.AdvanceL(sizeof(TUint16));
+#else
+ iMapping = iResourcePool.MappingL(iCommandListId);
+ iListReader.OpenL(iMapping.iResourceFile, iMapping.iResourceId);
+ iCommandList->SetDelayBetweenCommands(iListReader.ReadInt32L());
+ iCommandIndex = iListReader.ReadUint16L(); // command count
+
+ // Set up the resource file name for this list
+ iCommandList->SetResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMapping.iResourceFile));
+#endif
+
+ // Set up the conditional callback
+ iCommandList->SetConditionalCallback(iConditionalCallback);
+
+ iAction = EPrepareNextStep;
+ }
+
+void CSsmCommandListResourceReaderImpl::CPreparer::DoPrepareNextStepL()
+ {
+ const TInt KBatchSize = 5; // Max number of commands prepared per RunL, this may need to be adjusted if responsiveness is a problem
+ iBatchIndex = KBatchSize;
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ TBool inProgress = ETrue;
+ while (inProgress && iBatchIndex --)
+ {
+ if (iCommandIndexInRssFile[iCurrentCommandListInMapping] == 0 )
+ {
+ //the current command list is parsed and all commands added
+ // go to the next commnad list
+ ++iCurrentCommandListInMapping;
+
+ if ( (iCurrentCommandListInMapping+1) > iCommandIndexInRssFile.Count() )
+ {
+ // all command lists are processed. Set the inProgress flag to "EFalse"
+ inProgress = EFalse;
+ break;
+ }
+ else
+ {
+ //open the next resource id and read the commands
+ iListReader.Close();
+ iListReader.OpenL(iMappingArray[iCurrentCommandListInMapping].iResourceFile, iMappingArray[iCurrentCommandListInMapping].iResourceId);
+ // skipping delay between commands as it is already set from first rss file
+ iListReader.AdvanceL(sizeof(TInt32));
+ iCommandList->SetResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMappingArray[iCurrentCommandListInMapping].iResourceFile));
+ //skip reading command count again and jump to command resourceId
+ iListReader.AdvanceL(sizeof(TUint16));
+ }
+ }
+ DEBUGPRINT2A("The value of RssFile's current command is %d ", iCommandIndexInRssFile[iCurrentCommandListInMapping]);
+#else
+ while(iCommandIndex && iBatchIndex--)
+ {
+ --iCommandIndex; // Note: can't decrement in while expression above, incase iBatchIndex is zero
+#endif
+ // open command resource
+ const TInt commandResourceId = iListReader.ReadInt32L();
+ DEBUGPRINT2A("Reading command resource id %x", commandResourceId);
+ RResourceReader commandReader;
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ commandReader.OpenLC(iMappingArray[iCurrentCommandListInMapping].iResourceFile, commandResourceId);
+#else
+ commandReader.OpenLC(iMapping.iResourceFile, commandResourceId);
+#endif
+ // read conditional imformation
+ const TInt conditionalInfoResourceId = commandReader.ReadInt32L();
+
+ // read command type
+ const TSsmCommandType type = static_cast<TSsmCommandType>(commandReader.ReadInt16L());
+ commandReader.RewindL(sizeof(TInt16)); // commands expect reader to be pointing to the command type
+
+ // construct command and add to command list
+ TRAPD(err, AddCommandToListL(type, commandReader, conditionalInfoResourceId));
+ if(KErrNone != err)
+ {
+ DEBUGPRINT2A("Failed to add command of type: %d", type);
+ }
+ SSMLOGLEAVEIFERROR(err);
+ CleanupStack::PopAndDestroy(&commandReader);
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ --(iCommandIndexInRssFile[iCurrentCommandListInMapping]);
+ --iCommandIndex;
+#endif
+ }
+
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ if (inProgress == EFalse || iCommandIndex == 0) // list preparation complete
+#else
+ if (iCommandIndex == 0) // list preparation complete
+#endif
+ {
+ ResetReadyForNextPrepare();
+ iCommandListReady = ETrue;
+ }
+ }
+
+void CSsmCommandListResourceReaderImpl::CPreparer::AddCommandToListL(TSsmCommandType aType, RResourceReader& aCommandReader, TInt aConditionalInfoResourceId)
+ {
+ // construct command from resource and add to list
+ CSsmCommandBase* cmd = NULL;
+
+ switch (aType)
+ {
+ case ESsmCmdPublishSwp:
+ {
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ TSsmCommandParameters params(aCommandReader, iMappingArray[iCurrentCommandListInMapping].iResourceFile, aConditionalInfoResourceId, iSwpChange);
+#else
+ TSsmCommandParameters params(aCommandReader, iMapping.iResourceFile, aConditionalInfoResourceId, iSwpChange);
+#endif
+ cmd = SsmCommandFactory::ConstructCommandFromResourceLC(aType, params);
+ break;
+ }
+ case ESsmCmdPublishSystemState:
+ {
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ TSsmCommandParameters params(aCommandReader, iMappingArray[iCurrentCommandListInMapping].iResourceFile, aConditionalInfoResourceId, iState);
+#else
+ TSsmCommandParameters params(aCommandReader, iMapping.iResourceFile, aConditionalInfoResourceId, iState);
+#endif
+ cmd = SsmCommandFactory::ConstructCommandFromResourceLC(aType, params);
+ break;
+ }
+ default:
+ {
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ TSsmCommandParameters params(aCommandReader, iMappingArray[iCurrentCommandListInMapping].iResourceFile, aConditionalInfoResourceId);
+#else
+ TSsmCommandParameters params(aCommandReader, iMapping.iResourceFile, aConditionalInfoResourceId);
+#endif
+ cmd = SsmCommandFactory::ConstructCommandFromResourceLC(aType, params);
+ break;
+ }
+ }
+#ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
+ // Load the resource file if there is conditional information
+ if( cmd && cmd->ConditionalInformation() != 0 )
+ {
+ //Only if there is conditional information, we will set the command's resource filename
+ cmd->SetCommandResourceFileNameL(iResourcePool.FileNameForResourceFileL(iMappingArray[iCurrentCommandListInMapping].iResourceFile));
+ }
+#endif
+ //In the case of flexible merge the commands are appended in the commandlist based on priority.
+ iCommandList->AppendL(cmd);
+ CleanupStack::Pop(cmd);
+ }
+
+