diff -r 000000000000 -r 3553901f7fa8 telephonyserverplugins/simtsy/src/CSimCallForwarding.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/telephonyserverplugins/simtsy/src/CSimCallForwarding.cpp Tue Feb 02 01:41:59 2010 +0200 @@ -0,0 +1,1089 @@ +// Copyright (c) 2001-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: +// Implements the functionality required to provide clients with +// callforwarding status and registration information. +// +// + +/** + @file +*/ + +#include +#include "CSimCallForwarding.h" +#include "CSimPhone.h" +#include "Simlog.h" + +const TInt KSettingListGranularity=5; // < The granularity used for parameter list arrays. +const TInt KInvalidTimeout = -1; // Value used when timeout period does not matter +const TInt KMobServiceIndxStart = 1; +const TInt KMobServiceIndxEnd = 6; + +CSimCallForwarding* CSimCallForwarding::NewL(CSimPhone* aPhone) +/** + * Standard two-phase constructor. + * @param aPhone The parent phone object. + * @return CSimNetworkStatus The new network status class. + */ + { + CSimCallForwarding* self=new(ELeave) CSimCallForwarding(aPhone); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(); + return self; + } + +CSimCallForwarding::CSimCallForwarding(CSimPhone* aPhone) + : iPhone(aPhone) +/** + * Trivial first phase construction. + * @param aPhone The parent phone object. + */ + { + } + +void CSimCallForwarding::ConstructL() + /** + Second phase of 2-Phase Constructor + Retrieves all the Call forwarding and Identity services tags from the config file + */ + { + LOGCALL1("Starting to parse Call Forwarding config parameters..."); + + iIdentityServiceStatus=new(ELeave) CArrayFixFlat(KSettingListGranularity); + + iGetCFStatus = new(ELeave) CArrayPtrFlat(1); + FindAndCreateCFListL(); + + // Read in the Identity services information + TInt count=CfgFile()->ItemCount(KIdentityServiceStatus); + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + for(TInt i=0;iItem(KIdentityServiceStatus,i); + if(!item) + break; + + TInt status, service; + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,service); + if(ret!=KErrNone) + { + LOGPARSERR("service",ret,0,&KIdentityServiceStatus); + continue; + } + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,status); + if(ret!=KErrNone) + { + LOGPARSERR("status",ret,1,&KIdentityServiceStatus); + continue; + } + + TIdentityServiceStatus identityServiceStatus; + identityServiceStatus.iService = static_cast(service); + identityServiceStatus.iStatus = static_cast(status); + iIdentityServiceStatus->AppendL(identityServiceStatus); + } + + LOGCALL1("...Finished parsing Call Forwarding config parameters..."); + } + +CSimCallForwarding::~CSimCallForwarding() + /** + Destroy all the objects constructed. + */ + { + if (iIdentityServiceStatus != NULL) + { + iIdentityServiceStatus->Delete(0,iIdentityServiceStatus->Count()); + delete iIdentityServiceStatus; + } + delete iCFList; + if (iGetCFStatus) + iGetCFStatus->ResetAndDestroy(); + delete iGetCFStatus; + } + + +TInt CSimCallForwarding::ExtFunc(const TTsyReqHandle aReqHandle,const TInt aIpc, const TDataPackage& aPckg) + { + /** + Handles all the Call forwarding APIs + @param aReqHandle to the request + @param Ipc unique identifier of the method to call + @param aPckg contains arguments of the method to call + */ + TAny* dataPtr = aPckg.Ptr1(); + TAny* dataPtr2 = aPckg.Ptr2(); + + // The following requests can be completed even if the completion of another request is pending. + switch(aIpc) + { + case EMobilePhoneSetCallForwardingStatus: + return SetCallForwardingStatus(aReqHandle, + reinterpret_cast(dataPtr), + reinterpret_cast(dataPtr2)); + case EMobilePhoneNotifyCallForwardingStatusChange: + return NotifyCallForwardingStatusChange(aReqHandle, reinterpret_cast(dataPtr)); + case EMobilePhoneGetIdentityServiceStatus: + return GetIdentityServiceStatus(aReqHandle, + reinterpret_cast(dataPtr), + reinterpret_cast(dataPtr2)); + case EMobilePhoneGetCallForwardingStatusPhase1: + return GetCallForwardingStatusPhase1(aReqHandle, + REINTERPRET_CAST(CRetrieveMobilePhoneCFList::TGetCallForwardingRequest*, dataPtr), + REINTERPRET_CAST(TInt*, dataPtr2)); + case EMobilePhoneGetCallForwardingStatusPhase2: + return GetCallForwardingStatusPhase2(aReqHandle, + REINTERPRET_CAST(RMobilePhone::TClientId*, dataPtr), aPckg.Des2n()); + default: + break; + } + return KErrNotSupported; + } + +TInt CSimCallForwarding::CancelService(const TInt aIpc, const TTsyReqHandle aReqHandle) + /** + Cancels Call forwarding requests + @param ipc request to cancel + @param aReqHandle Handle to the request + */ + { + switch(aIpc) + { + case EMobilePhoneSetCallForwardingStatus: + return SetCallForwardingStatusCancel(aReqHandle); + case EMobilePhoneNotifyCallForwardingStatusChange: + return NotifyCallForwardingStatusChangeCancel(aReqHandle); + case EMobilePhoneGetIdentityServiceStatus: + return GetIdentityServiceStatusCancel(aReqHandle); + default: + break; + } + return KErrNone; + } + +void CSimCallForwarding::FindAndCreateCFListL() + { + /** + Creates the Call forwarding list from the config file + */ + LOGCALL1("CSimPhone::FindAndCreateCFListL"); + RMobilePhone::TMobilePhoneCFInfoEntryV1 entry; + + if(iCFList) + delete iCFList; + iCFList=NULL; + + iCFList = CMobilePhoneCFList::NewL(); + TInt count=CfgFile()->ItemCount(KCFList); + const CTestConfigItem* item=NULL; + TInt ret=KErrNone; + + LOGCALL1("Starting to Load and Parse CFList Config parameters"); + + TInt i; + for(i=0;iItem(KCFList,i); + if(!item) + break; + + TPtrC8 number; + TInt condition, serviceGroup, status, timeout; // valid for CFRNy only + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,0,condition); + if(ret!=KErrNone) + { + LOGPARSERR("condition",ret,0,&KCFList); + continue; + } + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,1,serviceGroup); + if(ret!=KErrNone) + { + LOGPARSERR("serviceGroup",ret,1,&KCFList); + continue; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,2,status); + if(ret!=KErrNone) + { + LOGPARSERR("status",ret,2,&KCFList); + continue; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,3,timeout); + if(ret!=KErrNone) + { + LOGPARSERR("timeout",ret,3,&KCFList); + continue; + } + + ret=CTestConfig::GetElement(item->Value(),KStdDelimiter,4,number); + if(ret!=KErrNone) + { + LOGPARSERR("number",ret,4,&KCFList); + continue; + } + + entry.iServiceGroup=(RMobilePhone::TMobileService)serviceGroup; + entry.iNumber.iTelNumber.Copy(number); + entry.iTimeout=timeout; + entry.iCondition=(RMobilePhone::TMobilePhoneCFCondition)condition; + entry.iStatus=(RMobilePhone::TMobilePhoneCFStatus)status; + iCFList->AddEntryL(entry); + }//end for + + //CFlist must define entries for each condition even if unknown + //fill up table if it misses conditions: + + RArray serviceArray; + //voice, auxVoice, data, packet, fax, sms, all; + + CleanupClosePushL(serviceArray); + + RMobilePhone::TMobilePhoneCFInfoEntryV1 extraEntry; + + for (TInt j=1;j<5;j++)//loop conditions + { + TInt serviceFound=EFalse; + TInt index; + extraEntry.iCondition=static_cast(j); + serviceArray.Reset(); + for(TInt h=0;h<8;h++) + { + serviceArray.Append(EFalse); + } + + for (TInt k=0;kGetEntryL(k); + if(entry.iCondition==static_cast(j)) + { + index = (TInt)entry.iServiceGroup; + serviceArray[index]=ETrue; + } + } + + if (!serviceArray[7])//(all services) + { + for (TInt l=1;l<7;l++) + { + if (serviceArray[l]) + serviceFound=ETrue; + } + //no service defined for this condition + if(!serviceFound) + { + extraEntry.iServiceGroup=RMobilePhone::EAllServices; + extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered; + iCFList->AddEntryL(extraEntry); + } + //some services defined in table + else + { + for (TInt m=1;m<7;m++) + { + if (!serviceArray[m]) + { + extraEntry.iServiceGroup=static_cast(m); + extraEntry.iStatus=RMobilePhone::ECallForwardingStatusNotRegistered; + iCFList->AddEntryL(extraEntry); + } + }//end for + }//end else + }//end if + }//end for + + CleanupStack::PopAndDestroy(&serviceArray); //Destroying serviceArray to free the memory + } + +TInt CSimCallForwarding::GetIdentityServiceStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneIdService* aService, RMobilePhone::TMobilePhoneIdServiceStatus* aStatus) + /** + Gets the status of the identity services + @param aReqHandle handle to the request + @param aService service that the client is interested in + @param aStatus of the identity service + */ + { + RMobilePhone::TMobilePhoneIdServiceStatus status; + status = RMobilePhone::EIdServiceUnknown; + TInt count = iIdentityServiceStatus->Count(); + for(TInt i=0; iAt(i).iService == *aService) + { + status = iIdentityServiceStatus->At(i).iStatus; + break; + } + } + *aStatus = status; + iPhone->ReqCompleted(aReqHandle, KErrNone); + return KErrNone; + } + +TInt CSimCallForwarding::GetIdentityServiceStatusCancel(const TTsyReqHandle aReqHandle) + /** + Cancels the request to get the status of the identity services + @param aReqHandle hadle to the request + */ + { + iPhone->ReqCompleted(aReqHandle,KErrCancel); + return KErrNone; + } + +TInt CSimCallForwarding::NotifyCallForwardingStatusChange(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF) + /** + Requests to be notified of call forwarding status change + @param aReqHandle handle to the request + @param aCF condition for which the client wants to be notified + */ + { + __ASSERT_ALWAYS(!iCFNotification.iCFChangeInfoNotificationPending,SimPanic(ENotificationReqAlreadyOutstanding)); + + iCFNotification.iCFChangeInfoNotificationPending=ETrue; + iCFNotification.iCFChangeInfoReqHandle=aReqHandle; + iCFNotification.iCurrentCFCondition=aCF; + LOGCALL1("Finished CSimCallForwarding::NotifyCallForwardingStatusChange"); + return KErrNone; + } + +TInt CSimCallForwarding::NotifyCallForwardingStatusChangeCancel(const TTsyReqHandle aReqHandle) + /** + Cancels the request to be notified of call forwarding status change + @param aReqHandle handle to the request + */ + { + if(iCFNotification.iCFChangeInfoNotificationPending) + { + iCFNotification.iCFChangeInfoNotificationPending=EFalse; + iPhone->ReqCompleted(aReqHandle,KErrCancel); + } + return KErrNone; + } + +TInt CSimCallForwarding::SetCallForwardingStatus(const TTsyReqHandle aReqHandle, RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aInfo) + /** + Sets the status of call forwarding + @param aReqHandle handle to the request + @param aCF condition for which the client wants to set the status + @param aInfo value of Call forwarding to set + */ + { + TRAPD(err, UpdateCFListL(aCF,aInfo)); + if ( err != KErrNone ) + { + iPhone->ReqCompleted(aReqHandle,err); + return KErrNone; + } + + if(iCFNotification.iCFChangeInfoNotificationPending) + { + *(iCFNotification.iCurrentCFCondition)=*aCF; + iCFNotification.iCFChangeInfoNotificationPending=EFalse; + iPhone->ReqCompleted(iCFNotification.iCFChangeInfoReqHandle,KErrNone); + } + + iPhone->ReqCompleted(aReqHandle,err); + LOGCALL1("Finished CSimCallForwarding::SetCallForwardingStatus"); + return KErrNone; + } + +TInt CSimCallForwarding::SetCallForwardingStatusCancel(const TTsyReqHandle aReqHandle) + /** + Cancels the request to set the status of call forwarding + @param aReqHandle handle to the request + */ + { + iPhone->ReqCompleted(aReqHandle,KErrCancel); + return KErrNone; + } + + +TInt CSimCallForwarding::GetCallForwardingStatusPhase1(const TTsyReqHandle aTsyReqHandle, + CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData, + TInt* aBufSize) + { + /** + 1st phase retrieval of the status of call forwarding + @param aTsyReqHandle handle to the request + @param aReqData contains details of the request + @param aBufSize size of the buffer the client needs to allocate for phase 2 + */ + LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1"); + TInt ret=KErrNone; + + // for forwarding we cannot querry for all conditions; + // conditions - specific + // services - individual and all + if ((aReqData->iCondition==RMobilePhone::ECallForwardingUnspecified) + || (aReqData->iCondition==RMobilePhone::ECallForwardingAllCases) + || (aReqData->iCondition==RMobilePhone::ECallForwardingAllConditionalCases)) + { + iPhone->ReqCompleted(aTsyReqHandle,KErrArgument); + } + else + { + TInt leaveCode=KErrNone; + TRAP(leaveCode, ret=ProcessGetCallForwardingStatusPhase1L(aTsyReqHandle, aReqData, aBufSize);); + if (leaveCode != KErrNone) + iPhone->ReqCompleted(aTsyReqHandle,leaveCode); + } + LOGCALL1("CSimPhone::GetCallForwardingStatusPhase1"); + return ret; + } + +TInt CSimCallForwarding::ProcessGetCallForwardingStatusPhase1L(const TTsyReqHandle aTsyReqHandle, + CRetrieveMobilePhoneCFList::TGetCallForwardingRequest* aReqData, + TInt* aBufSize) + { + /** Retrieve call forwarding status of each line from phone, + store each CF status response as a list entry, + stream the list and then return size of this buffer to client + @param aReqHandle Handle to the request + @param aReqData information about the request + @param aBufSize Size of the buffer the client has to allocate for the 2nd pahase + */ + + LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L"); + + CMobilePhoneCFList* list=CMobilePhoneCFList::NewL(); + CleanupStack::PushL(list); + + TInt cnt=0;//Only interested by entries with a particular condition + TInt maxNum=iCFList->Enumerate(); + TBool isAllGroups = (aReqData->iServiceGroup == RMobilePhone::EAllServices); + for(TInt i=0;iGetEntryL(i); + + // Check that the data structure is supported by the simulated TSY version + TInt err = iPhone->CheckSimTsyVersion(entry); + if(err != KErrNone) + { + iPhone->ReqCompleted(aTsyReqHandle, err); + return KErrNone; + } + + if((entry.iCondition == aReqData->iCondition) + &&(entry.iStatus != RMobilePhone::ECallForwardingStatusNotRegistered)) + { + if ( !isAllGroups && (entry.iServiceGroup != aReqData->iServiceGroup)) + { + continue; + } + list->AddEntryL(entry); + cnt++; + } + } + // Store the streamed list and the client ID + CListReadAllAttempt* read=CListReadAllAttempt::NewL(aReqData->iClient,aTsyReqHandle); + CleanupStack::PushL(read); + + read->iListBuf = list->StoreLC(); + CleanupStack::Pop(); // pop the CBufBase allocated by StoreLC + + iGetCFStatus->AppendL(read); + CleanupStack::Pop(read); // pop the CListReadAllAttempt + + // return the CBufBase’s size to client + *aBufSize=(read->iListBuf)->Size(); + + CleanupStack::PopAndDestroy(list); // pop&destroy list + + // Complete first phase of list retrieval + iPhone->ReqCompleted(aTsyReqHandle,KErrNone); + LOGCALL1("CSimPhone::ProcessGetCallForwardingStatusPhase1L"); + return KErrNone; + } + +TInt CSimCallForwarding::GetCallForwardingStatusPhase2(const TTsyReqHandle aTsyReqHandle, + RMobilePhone::TClientId* aClient, TDes8* aBuf) + /** + 2nd phase retrieval of the status of call forwarding + @param aTsyRqHandle handle to the request + @param aClient pointer to the client + @param aBuf buffer that contains the call forwarding list + */ + { + LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2"); + CListReadAllAttempt* read=NULL; + // Find the get detected network attempt from this client + for (TInt i=0; iCount(); ++i) + { + read = iGetCFStatus->At(i); + if ((read->iClient.iSessionHandle==aClient->iSessionHandle) && + (read->iClient.iSubSessionHandle==aClient->iSubSessionHandle)) + { + TPtr8 bufPtr((read->iListBuf)->Ptr(0)); + // Copy the streamed list to the client + aBuf->Copy(bufPtr); + delete read; + iGetCFStatus->Delete(i); + iPhone->ReqCompleted(aTsyReqHandle,KErrNone); + return KErrNone; + } + } + // Should handle error case of not finding the matching client from read all phase 1 + LOGCALL1("CSimPhone::GetCallForwardingStatusPhase2"); + return KErrNotFound; + } + + +TInt CSimCallForwarding::GetCallForwardingStatusCancel(const TTsyReqHandle aTsyReqHandle) + { + /** + Cancel the request to retrieve the status of call forwarding + @param aTsyReqHandle handle to the request + */ + LOGCALL1("CSimPhone::GetCallForwardingStatusCancel"); + iPhone->ReqCompleted(aTsyReqHandle,KErrNone); + // Remove the read all attempt from iGetCFStatus + CListReadAllAttempt* read=NULL; + for (TInt i=0; iCount(); ++i) + { + read = iGetCFStatus->At(i); + if (read->iReqHandle == aTsyReqHandle) + { + delete read; + iGetCFStatus->Delete(i); + break; + } + } + iPhone->ReqCompleted(aTsyReqHandle,KErrCancel); + LOGCALL1("CSimPhone::GetCallForwardingStatusCancel"); + return KErrNone; + } + +void CSimCallForwarding::UpdateCFListL(RMobilePhone::TMobilePhoneCFCondition* aCF, + RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo ) + { + /** + Modifies the status of call forwarding + @param aCF condition + @param aCFInfo details of the request + */ + User::LeaveIfNull(aCF); + User::LeaveIfNull(aCFInfo); + + if (*aCF == RMobilePhone::ECallForwardingUnspecified) + { + // not supported - tell user it is a wrong argument + User::Leave(KErrArgument); + } + + if ((*aCF == RMobilePhone::ECallForwardingAllCases) + ||(*aCF == RMobilePhone::ECallForwardingAllConditionalCases)) + { + // not supported - tell user it is a wrong argument + User::Leave(KErrNotSupported); + } + + switch (aCFInfo->iAction) + { + case RMobilePhone::EServiceActionRegister: + RegisterL(aCF, aCFInfo); + break; + + case RMobilePhone::EServiceActionActivate: + ActivateL(aCF, aCFInfo); + break; + + case RMobilePhone::EServiceActionInvoke: + // currently not supported + // tell user it is a wrong argument + User::Leave(KErrArgument); + break; + + case RMobilePhone::EServiceActionDeactivate: + DeactivateL(aCF, aCFInfo); + break; + + case RMobilePhone::EServiceActionErase: + EraseL(aCF, aCFInfo); + break; + + case RMobilePhone::EServiceActionUnspecified: + default: + // not supported - tell user it is a wrong argument + User::Leave(KErrArgument); + break; + } + } + + +inline void SplitOneCFEntryIntoSeparateGroupsL(CMobilePhoneCFList* aCFList, + RMobilePhone::TMobilePhoneCFInfoEntryV1& aOrigEntry, + RMobilePhone::TMobileService aExceptServiceGroup) + { + /* + Splits one entry valid for all basic service groups into individual entries + and places them into a CMobilePhoneCFList. This excludes one service group. + @param aCBList The list to which to store the entries + @param aOrigEntry The original entry; details of which should be passed to individual group entries + @param aExceptServiceGroup The group which has to be avoided + */ + // we have to split the entry into entries + // per group with the same condition; excluding the specified service group + RMobilePhone::TMobilePhoneCFInfoEntryV1 anotherEntry(aOrigEntry); + + RMobilePhone::TMobileService service; + + for (TInt i = KMobServiceIndxStart;i <= KMobServiceIndxEnd;i++) + { + service=static_cast(i); + + if( service != aExceptServiceGroup ) + { + anotherEntry.iServiceGroup=service; + aCFList->AddEntryL(anotherEntry); + } + }//end for (another) + } + + +void CSimCallForwarding::UpdateCFQuiescentCondition(TBool aActivate, + RMobilePhone::TMobilePhoneCFCondition aCF) + { + // only the Call Forward Unconditional can alter any other CF condition + if(aCF == RMobilePhone::ECallForwardingUnconditional) + { + TBool cFBChangeRequired = EFalse; + + RMobilePhone::TMobilePhoneCFInfoEntryV1 theEntry; + + const TInt count = iCFList->Enumerate(); + + // look for any instances of the ECallForwardingBusy + for (TInt indx=0; indx < count; indx++) + { + theEntry = iCFList->GetEntryL(indx); + + if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy && + (theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive || + theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent)) + { + cFBChangeRequired = ETrue; + } + } + + if(cFBChangeRequired) + { + // retain prev version of the list in local variable and in Cleanup stack + CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL(); + CleanupStack::PushL(thePrevCFList); + + // copy existing data into the temp storage + for (TInt indx=0; indx < count; indx++) + { + thePrevCFList->AddEntryL(iCFList->GetEntryL(indx)); + } + + delete iCFList; + iCFList = NULL; + + // create a new version and hold it in the class member + iCFList = CMobilePhoneCFList::NewL(); + + // get a hold of it in a local variable + CMobilePhoneCFList* theNewCFList = iCFList; + + for(TInt indx=0; indx < count; indx++) + { + theEntry = thePrevCFList->GetEntryL(indx); + + if(theEntry.iCondition == RMobilePhone::ECallForwardingBusy) + { + if(aActivate) + { + if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusActive) + { + theEntry.iStatus = RMobilePhone::ECallForwardingStatusQuiescent; + } + } + else + { + if(theEntry.iStatus == RMobilePhone::ECallForwardingStatusQuiescent) + { + theEntry.iStatus = RMobilePhone::ECallForwardingStatusActive; + } + } + } + theNewCFList->AddEntryL(theEntry); + } + + // now delete the old memory + CleanupStack::PopAndDestroy(thePrevCFList); + } + } + } + +void CSimCallForwarding::ActivateL(RMobilePhone::TMobilePhoneCFCondition* aCF, + RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo ) + { + // NOTE: An assumption is made that the calling method has checked the parameters + // are not NULL. + RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry; + + theNewEntry.iCondition = *aCF; + theNewEntry.iServiceGroup = aCFInfo->iServiceGroup; + theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive; + theNewEntry.iNumber = aCFInfo->iNumber; + + if (*aCF == RMobilePhone::ECallForwardingNoReply) + { + theNewEntry.iTimeout = aCFInfo->iTimeout; + } + else + { + theNewEntry.iTimeout = KInvalidTimeout; + } + + + // retain prev version of the list in local variable and in Cleanup stack + CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL(); + CleanupStack::PushL(thePrevCFList); + + const TInt count = iCFList->Enumerate(); + + TBool CFUActive = EFalse; + + // copy existing data into the temp storage + for (TInt indx = 0; indx < count; indx++) + { + thePrevCFList->AddEntryL(iCFList->GetEntryL(indx)); + + RMobilePhone::TMobilePhoneCFInfoEntryV1 copyEntry = iCFList->GetEntryL(indx); + + if(copyEntry.iCondition == RMobilePhone::ECallForwardingUnconditional && + copyEntry.iStatus == RMobilePhone::ECallForwardingStatusActive) + { + CFUActive = ETrue; + } + } + + delete iCFList; + iCFList = NULL; + + // create a new version and hold it in the class member + iCFList = CMobilePhoneCFList::NewL(); + + // get a hold of it in a local variable + CMobilePhoneCFList* theNewCFList = iCFList; + + TBool callForwardActivated = EFalse; + + RMobilePhone::TMobilePhoneCFInfoEntryV1 entry; + + for (TInt i = 0; i < count; i++) + { + entry = thePrevCFList->GetEntryL(i); + + if(theNewEntry.iCondition == entry.iCondition) + { + if(theNewEntry.iServiceGroup == entry.iServiceGroup) + { + // only activate service if previously in a not active state + if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive) + { + if(entry.iCondition == RMobilePhone::ECallForwardingBusy && CFUActive != EFalse) + { + // do nothing, condition's service will not be activated as callforwarding + // unconditional is active + } + else + { + entry.iStatus = RMobilePhone::ECallForwardingStatusActive; + callForwardActivated = ETrue; + } + } + } + else if(entry.iServiceGroup == RMobilePhone::EAllServices) + { + if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive) + { + SplitOneCFEntryIntoSeparateGroupsL(theNewCFList, + entry, + theNewEntry.iServiceGroup); + + callForwardActivated = ETrue; + entry = theNewEntry; + } + } + } + + theNewCFList->AddEntryL(entry); + } + + if(callForwardActivated) + { + // only need to check quiescent status if an activation has occurred + UpdateCFQuiescentCondition(ETrue, theNewEntry.iCondition); + } + + CleanupStack::PopAndDestroy(thePrevCFList); + } + +void CSimCallForwarding::RegisterL(RMobilePhone::TMobilePhoneCFCondition* aCF, RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo) + { + TInt count = iCFList->Enumerate(); + RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry; + + theNewEntry.iCondition = *aCF; + theNewEntry.iServiceGroup = aCFInfo->iServiceGroup; + theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive; + + theNewEntry.iNumber = aCFInfo->iNumber; + if (*aCF == RMobilePhone::ECallForwardingNoReply) + { + theNewEntry.iTimeout = aCFInfo->iTimeout; + } + else + { + theNewEntry.iTimeout = KInvalidTimeout; + } + + // retain prev version of the list in local variable and in Cleanup stack + CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL(); + CleanupStack::PushL(thePrevCFList); + // copy existing data into the temp storage + for (TInt indx=0; indxAddEntryL(iCFList->GetEntryL(indx)); + } + delete iCFList; + iCFList = NULL; + // create a new version and hold it in the class member + iCFList = CMobilePhoneCFList::NewL(); + // get a hold of it in a local variable + CMobilePhoneCFList* theNewCFList = iCFList; + + if (theNewEntry.iServiceGroup==RMobilePhone::EAllServices) + { + //nothing for all conds + + //action is to Regiser (and activate)AllServices with a particular condition; + //Only copy entries with a different condition + //entries with same condition should not be copied as they will + //be represented by 1 with allservices + for (TInt i = 0; iGetEntryL(i); + + if (entry.iCondition != theNewEntry.iCondition) + // check if the existing entry is encompassed by the new one + theNewCFList->AddEntryL(entry); + } + theNewCFList->AddEntryL(theNewEntry); + } + else + { + //ActivateOne; + for (TInt i = 0; iGetEntryL(i); + + if (theNewEntry.iCondition==entry.iCondition + && entry.iServiceGroup==theNewEntry.iServiceGroup) + { + theNewCFList->AddEntryL(theNewEntry); + continue; + } + if (entry.iCondition != theNewEntry.iCondition + || (entry.iCondition == theNewEntry.iCondition + && entry.iServiceGroup != theNewEntry.iServiceGroup + && entry.iServiceGroup != RMobilePhone::EAllServices)) + { + theNewCFList->AddEntryL(entry); + continue; + } + + if(theNewEntry.iCondition==entry.iCondition + && entry.iServiceGroup==RMobilePhone::EAllServices) + { + + SplitOneCFEntryIntoSeparateGroupsL( + theNewCFList, + entry, + theNewEntry.iServiceGroup + ); + + theNewCFList->AddEntryL(theNewEntry); + }//end if + }//end for + }//end else + // now delete the old memory + CleanupStack::PopAndDestroy(thePrevCFList); + } + +void CSimCallForwarding::DeactivateL(RMobilePhone::TMobilePhoneCFCondition* aCF, + RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo ) + { + // NOTE: An assumption is made that the calling method has checked the parameters + // are not NULL. + + RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry; + + theNewEntry.iCondition = *aCF; + theNewEntry.iServiceGroup = aCFInfo->iServiceGroup; + theNewEntry.iStatus= RMobilePhone::ECallForwardingStatusNotActive; + + // retain prev version of the list in local variable and in Cleanup stack + CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL(); + CleanupStack::PushL(thePrevCFList); + + const TInt count = iCFList->Enumerate(); + + // copy existing data into the temp storage + for (TInt indx = 0; indx < count; indx++) + { + thePrevCFList->AddEntryL(iCFList->GetEntryL(indx)); + } + + delete iCFList; + iCFList = NULL; + + // create a new version and hold it in the class member + iCFList = CMobilePhoneCFList::NewL(); + + // get a hold of it in a local variable + CMobilePhoneCFList* theNewCFList = iCFList; + + TBool callForwardDeactivated = EFalse; + + RMobilePhone::TMobilePhoneCFInfoEntryV1 entry; + + //Deactivate will deactivate active entries + for (TInt indx = 0; indx < count; indx++) + { + entry = thePrevCFList->GetEntryL(indx); + + if(entry.iCondition == theNewEntry.iCondition) + { + if(entry.iServiceGroup == theNewEntry.iServiceGroup) + { + if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive) + { + entry.iStatus = RMobilePhone::ECallForwardingStatusNotActive; + callForwardDeactivated = ETrue; + } + } + else if(entry.iServiceGroup == RMobilePhone::EAllServices) + { + if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive) + { + SplitOneCFEntryIntoSeparateGroupsL(theNewCFList, + entry, + theNewEntry.iServiceGroup); + + entry = theNewEntry; + callForwardDeactivated = ETrue; + } + } + } + + theNewCFList->AddEntryL(entry); + }//end for + + // this method will check if any de-activation has caused another Condition to become + // cleared of the quiescent state + if(callForwardDeactivated) + { + // pass a FALSE to the function to notify of a service de-activation + UpdateCFQuiescentCondition(EFalse, theNewEntry.iCondition); + } + + // now delete the old memory + CleanupStack::PopAndDestroy(thePrevCFList); + } + +void CSimCallForwarding::EraseL(RMobilePhone::TMobilePhoneCFCondition* aCF, + RMobilePhone::TMobilePhoneCFChangeV1* aCFInfo ) + { + // NOTE: An assumption is made that the calling method has checked the parameters + // are not NULL. + + RMobilePhone::TMobilePhoneCFInfoEntryV1 theNewEntry; + + theNewEntry.iCondition = *aCF; + theNewEntry.iServiceGroup = aCFInfo->iServiceGroup; + theNewEntry.iNumber.iTelNumber.Copy(KEmptyString); + theNewEntry.iTimeout = KErrNotFound; + theNewEntry.iStatus = RMobilePhone::ECallForwardingStatusNotRegistered; + + // retain prev version of the list in local variable and in Cleanup stack + CMobilePhoneCFList* thePrevCFList = CMobilePhoneCFList::NewL(); + CleanupStack::PushL(thePrevCFList); + + const TInt count = iCFList->Enumerate(); + + // copy existing data into the temp storage + for (TInt indx = 0; indx < count; indx++) + { + thePrevCFList->AddEntryL(iCFList->GetEntryL(indx)); + } + + delete iCFList; + iCFList = NULL; + + // create a new version and hold it in the class member + iCFList = CMobilePhoneCFList::NewL(); + + // get a hold of it in a local variable + CMobilePhoneCFList* theNewCFList = iCFList; + + RMobilePhone::TMobilePhoneCFInfoEntryV1 entry; + + for(TInt i = 0; i < count; i++) + { + entry = thePrevCFList->GetEntryL(i); + + if(entry.iCondition == theNewEntry.iCondition) + { + if(entry.iServiceGroup == theNewEntry.iServiceGroup) + { + if(entry.iStatus == RMobilePhone::ECallForwardingStatusNotActive) + { + entry = theNewEntry; + } + } + else if(entry.iServiceGroup == RMobilePhone::EAllServices) + { + if(entry.iStatus == RMobilePhone::ECallForwardingStatusActive) + { + SplitOneCFEntryIntoSeparateGroupsL(theNewCFList, + entry, + theNewEntry.iServiceGroup); + + entry = theNewEntry; + } + } + } + theNewCFList->AddEntryL(entry); + } + + // now delete the old memory + CleanupStack::PopAndDestroy(thePrevCFList); + } + +const CTestConfigSection* CSimCallForwarding::CfgFile() +/** + * Returns a pointer to the current configuration file section. + * + * @return CTestConfigSection A pointer to the current configuration file data section. + */ + { + return iPhone->CfgFile(); + } + +