diff -r 000000000000 -r ff3b6d0fd310 cellular/telephonysettings/src/PSetCallDivertingBase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/cellular/telephonysettings/src/PSetCallDivertingBase.cpp Tue Feb 02 01:11:09 2010 +0200 @@ -0,0 +1,880 @@ +/* +* Copyright (c) 2008-2008 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 CPSetCallDivertingBase class. +* +*/ + + +// INCLUDE FILES +#include "PSetCallDivertingBasicImpl.h" + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "PsetCallDiverting.h" +#include "PsetContainer.h" +#include "MPsetDivertObs.h" +#include "PsetTelephony.h" +#include "PSetPanic.h" +#include "MPsetRequestObs.h" +#include "PSetUtility.h" +#include "PhoneSettingsLogger.h" +#include "PsetSAObserver.h" +#include "PSetCallDivertingBase.h" + +// LOCAL CONSTANTS AND MACROS + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPSetCallDivertingBase::NewL +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CPSetCallDivertingBase* CPSetCallDivertingBase::NewL( + MPsetDivertObserver& aObserver, + RMobilePhone& aPhone, + CPsetCallDiverting* aDivert ) + { + CPSetCallDivertingBase* self = new ( ELeave ) CPSetCallDivertingBase( aPhone, aDivert ); + CleanupStack::PushL( self ); + self->ConstructL( aObserver ); + CleanupStack::Pop( self ); + return self; + } + +// --------------------------------------------------------------------------- +// CPSetCallDivertingBase::~CPSetCallDivertingBase +// --------------------------------------------------------------------------- +// +CPSetCallDivertingBase::~CPSetCallDivertingBase() + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::~CPSetCallDivertingBase"); + Cancel(); + + if ( iLine ) + { + iLine->Close(); + } + delete iLine; + + if ( iSsSettings ) + { + iSsSettings->Cancel( ESSSettingsAls, *this ); + iSsSettings->Close(); + } + delete iSsSettings; + delete iCfInterrogator; + + iReqObserver = NULL; + + delete iRepository; + + if ( iFeatureManagerInitialized ) + { + FeatureManager::UnInitializeLib(); + } + + __PHSLOGSTRING("[PHS]<-- CPSetCallDivertingBase::~CPSetCallDivertingBase"); + } + +// ----------------------------------------------------------------------------- +// CPSetCallDivertingBase::CPSetCallDivertingBase +// C++ constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPSetCallDivertingBase::CPSetCallDivertingBase( RMobilePhone& aPhone, CPsetCallDiverting* aDivert ) : + CActive ( EPriorityStandard ), + iPhone ( aPhone ), + iDivert( aDivert ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::CPSetCallDivertingBase"); + iFeatureManagerInitialized = EFalse; + __PHSLOGSTRING("[PHS]<-- CPSetCallDivertingBase::CPSetCallDivertingBase"); + } + +// ----------------------------------------------------------------------------- +// CPSetCallDivertingBase::ConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::ConstructL( MPsetDivertObserver& aObserver ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::ConstructL" ); + iLine = new ( ELeave ) RMobileLine; + + //Copy received information to member variable. + iObserver = &aObserver; + + CActiveScheduler::Add( this ); + + //Check which line is used, or if ALS is not active. + TInt usedLine = ESSSettingsAlsNotSupported; + + iSsSettings = new (ELeave) RSSSettings; + User::LeaveIfError( iSsSettings->Open() ); + TRAPD( err, iSsSettings->Register( ESSSettingsAls, *this ) ); + if ( err == KErrNone ) + { + iSsSettings->Get( ESSSettingsAls, usedLine ); + } + + iAls = static_cast ( usedLine ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::ConstructL: usedLine: %d", usedLine ); + + iRepository = CRepository::NewL( KCRUidCallForwarding ); + + // Sets up TLS, must be done before FeatureManager is used. + FeatureManager::InitializeLibL(); + iFeatureManagerInitialized = ETrue; + + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::ConstructL" ); + } + +// --------------------------------------------------------------------------- +// RunL +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::RunL() + { + // Empty implementation. + } + +// --------------------------------------------------------------------------- +// DoCancel +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::DoCancel() + { + // Empty implementation. + } + +// --------------------------------------------------------------------------- +// SetDivertingL +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::SetDivertingL( const TCallDivertSetting& /*aDivert*/, + TBasicServiceGroups /*aBsc*/ ) + { + //Empty implementation. + } + +// --------------------------------------------------------------------------- +// CancelCurrentRequest +// --------------------------------------------------------------------------- +// +TInt CPSetCallDivertingBase::CancelCurrentRequest() + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::CancelCurrentRequest" ); + // Set PSUI so that correct observer is used and hide requesting note. + // When interrupting a note, does not leave. + // This needs to be done first, since notes must be cleared from screen + // even though request is not active. + iObserver->SetEngineContact( iDivert ); + // Does not leave + TRAPD( err, iObserver->HandleCFRequestingL( EFalse, ETrue ) ); + + if ( !IsActive() || err != KErrNone ) + { + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::CancelCurrentRequest: KErrGeneral" ); + return KErrGeneral; + } + + if ( iCFStatusCheck ) + { + iCFStatusCheck = EFalse; + Cancel(); + } + + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::CancelCurrentRequest: KErrNone" ); + return KErrNone; + } + +// --------------------------------------------------------------------------- +// Sets new default number the the default numbers list, erases the oldest one. +// --------------------------------------------------------------------------- +// +TInt CPSetCallDivertingBase::SetNewDefaultNumberL( TDes& aNumber ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::SetNewDefaultNumberL" ); + TTelNumber oldFirst; + TTelNumber oldSecond; + + CDesC16ArrayFlat* defNumberArray = + new ( ELeave ) CDesC16ArrayFlat( KPSetDefaultNumberMax ); + CleanupStack::PushL( defNumberArray ); + + TInt defNumbers = GetNumbersFromSharedDataL( iAls, *defNumberArray ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::SetNewDefaultNumberL: defNumbers: %d", defNumbers); + + if ( defNumbers > 0 ) //at least one number was fetched + { + //save latest divert no. + oldFirst = defNumberArray->MdcaPoint( 0 ); + } + if ( defNumbers > 1 ) //at least two numbers were fetched + { + //save second latest divert no. + oldSecond = defNumberArray->MdcaPoint( 1 ); + } + CleanupStack::PopAndDestroy( defNumberArray ); + + if ( iAls != ESSSettingsAlsAlternate ) + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::SetNewDefaultNumberL: !ESSSettingsAlsAlternate" ); + switch ( defNumbers ) // cases flow through + { + case 3: + case 2://two default numbers + User::LeaveIfError( + SaveKey( KSettingsCFDefaultNumber3, oldSecond ) ); + case 1://one default number + User::LeaveIfError( + SaveKey( KSettingsCFDefaultNumber2, oldFirst ) ); + case 0://no default numbers + User::LeaveIfError( + SaveKey( KSettingsCFDefaultNumber1, aNumber ) ); + break; + } + } + else//aux line + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::SetNewDefaultNumberL: Aux line" ); + switch ( defNumbers ) // cases flow through + { + case 3: + case 2://two default numbers + User::LeaveIfError( + SaveKey( KSettingsCFDefaultNumberAls3, oldSecond ) ); + case 1://one default number + User::LeaveIfError( + SaveKey( KSettingsCFDefaultNumberAls2, oldFirst ) ); + case 0://no default numbers + User::LeaveIfError( + SaveKey( KSettingsCFDefaultNumberAls1, aNumber ) ); + break; + default: + User::Leave( KErrArgument ); + break; + } + } + + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::SetNewDefaultNumberL" ); + return KErrNone; //return value is not used + } + +// --------------------------------------------------------------------------- +// Saves a single value to central repository. Make sure that repository +// is open before calling this function. +// --------------------------------------------------------------------------- +// +TInt CPSetCallDivertingBase::SaveKey( + TUint32 aKeyId, + const TDesC& aKeyValue ) + { + TInt error = KErrUnknown; + + error = iRepository->Set( aKeyId, aKeyValue ); + + return error; + } + +// --------------------------------------------------------------------------- +// Reads used divert numbers (0-3) from shared data and fills array with them. +// --------------------------------------------------------------------------- +// +TInt CPSetCallDivertingBase::GetNumbersFromSharedDataL( TInt aType, + CDesC16ArrayFlat& aArray ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::GetNumbersFromSharedDataL" ); + + TInt amount = 0; + TTelNumber readValue; + aType = iAls; + + RArray keyArray( KPSetDefaultNumberMax ); + CleanupClosePushL( keyArray ); + //to simplify reading, append needed values to an array + if ( aType != ESSSettingsAlsAlternate ) + { + keyArray.AppendL( KSettingsCFDefaultNumber1 ); + keyArray.AppendL( KSettingsCFDefaultNumber2 ); + keyArray.AppendL( KSettingsCFDefaultNumber3 ); + } + else //auxiliary line + { + keyArray.AppendL( KSettingsCFDefaultNumberAls1 ); + keyArray.AppendL( KSettingsCFDefaultNumberAls2 ); + keyArray.AppendL( KSettingsCFDefaultNumberAls3 ); + } + + TInt i = KErrNone; + TInt loc = KErrNone; + while ( i == KErrNone && loc < KPSetDefaultNumberMax ) + { + i = iRepository->Get( keyArray.operator[]( loc ), readValue ); + if ( i == KErrNone ) + { + HBufC16* string = static_cast ( readValue.AllocLC() ); + if ( string->Length() > 0 ) + { + aArray.AppendL( *string ); + amount++; + } + CleanupStack::PopAndDestroy( string ); + } + loc++; + } + CleanupStack::PopAndDestroy(); // keyArray. + + __PHSLOGSTRING1("[PHS] <--CPSetCallDivertingBase::GetNumbersFromSharedDataL: amount: %d", amount ); + return amount; + } + +// --------------------------------------------------------------------------- +// Gets the timer value index related to "cfnry" from shared data +// In error cases, return default value (30). +// --------------------------------------------------------------------------- +// +TInt CPSetCallDivertingBase::GetTimerValueL() + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::GetTimerValueL" ); + + TInt timerValue = 0; + TInt error = KErrNone; + + if ( iAls == ESSSettingsAlsAlternate ) + { + error = iRepository->Get( KSettingsCFTimerValueAls, timerValue ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetTimerValueL: KSettingsCFTimerValueAls: %d", timerValue ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetTimerValueL: error: %d", error ); + } + else + { + error = iRepository->Get( KSettingsCFTimerValue, timerValue ); + + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetTimerValueL: KPsetCFTimerValue: %d", timerValue ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetTimerValueL: error: %d", error ); + } + + if ( error != KErrNone || !VerifyDelayTime( timerValue ) ) + { + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::GetTimerValueL: KPsetDefaultTimerValue" ); + return KPsetDefaultTimerValue; + } + else + { + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::GetTimerValueL: timerValue" ); + return timerValue; + } + } + +// --------------------------------------------------------------------------- +// Sets the default time for "divert when not answered" to .ini file +// --------------------------------------------------------------------------- +TInt CPSetCallDivertingBase::SetTimerValueL( const TInt& aValue ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::SetTimerValueL" ); + + TInt retValue = KErrNone; + + // If delay time is not divisable by five, return. + if ( !VerifyDelayTime( aValue ) ) + { + return KErrArgument; + } + + if ( iAls != ESSSettingsAlsAlternate ) + { + retValue = iRepository->Set( KSettingsCFTimerValue, aValue ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::SetTimerValueL: KPsetCFTimerValue: %d", aValue ); + } + else + { + retValue = iRepository->Set( KSettingsCFTimerValueAls, aValue ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::SetTimerValueL: KPsetCFTimerValueAls: %d", aValue ); + } + + __PHSLOGSTRING1("[PHS] <--CPSetCallDivertingBase::SetTimerValueL: retValue: %d", retValue ); + return retValue; + } + +// --------------------------------------------------------------------------- +// Verifies that delay time is divisible by five. +// --------------------------------------------------------------------------- +// +TBool CPSetCallDivertingBase::VerifyDelayTime( const TInt& aDelayTime ) + { + TReal res = 0; + Math::Mod( res, aDelayTime, KPsetDelayTimeDivider ); + return res == 0; + } + +// --------------------------------------------------------------------------- +// Swaps the most recently used number to first in the shared data file. +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::SwapDefaultNumberL( const TInt& aLocation ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::SwapDefaultNumberL" ); + + if ( aLocation == KPSetFirstDefNumber ) + { + return; //no need to reorganize, number is already first + } + else if ( + !( aLocation == KPSetSecondDefNumber || + aLocation == KPSetThirdDefNumber ) ) + { + User::Leave( KErrArgument ); + } + + CDesC16ArrayFlat* defNumbers = + new ( ELeave ) CDesC16ArrayFlat( KPSetDefaultNumberMax ); + CleanupStack::PushL( defNumbers ); + + GetNumbersFromSharedDataL( iAls, *defNumbers ); + + if ( iAls != ESSSettingsAlsAlternate ) + //EGetAlsLinePrimary or Not supported or Unknown + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::SwapDefaultNumberL: !ESSSettingsAlsAlternate" ); + switch( aLocation ) + { + case KPSetSecondDefNumber: + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumber2, + defNumbers->MdcaPoint(0) ) ); + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumber1, + defNumbers->MdcaPoint(1) ) ); + break; + case KPSetThirdDefNumber: + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumber2, + defNumbers->MdcaPoint(0) ) ); + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumber3, + defNumbers->MdcaPoint(1) ) ); + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumber1, + defNumbers->MdcaPoint(2) ) ); + break; + default: + break; + } + } + else //alternate line + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::SwapDefaultNumberL: ESSSettingsAlsAlternate" ); + switch( aLocation ) + { + case KPSetSecondDefNumber: + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumberAls1, + defNumbers->MdcaPoint(0) ) ); + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumberAls2, + defNumbers->MdcaPoint(1) ) ); + break; + case KPSetThirdDefNumber: + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumberAls2, + defNumbers->MdcaPoint(0) ) ); + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumberAls3, + defNumbers->MdcaPoint(1) ) ); + User::LeaveIfError( + SaveKey( + KSettingsCFDefaultNumberAls1, + defNumbers->MdcaPoint(2) ) ); + break; + default: + break; + } + } + CleanupStack::PopAndDestroy( defNumbers ); + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::SwapDefaultNumberL" ); + } + +// --------------------------------------------------------------------------- +// Request diverting status from network asynhronously. +// --------------------------------------------------------------------------- +void CPSetCallDivertingBase::GetDivertingStatusL( + const TServiceGroup aServiceGroup, + const TCallDivertingCondition aCondition, + TBasicServiceGroups aBsc ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::GetDivertingStatusL" ); + + if ( IsActive() ) + { + User::Leave( KErrInUse ); + } + + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetDivertingStatusL: aServiceGroup: %d", aServiceGroup ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetDivertingStatusL: aCondition: %d", aCondition ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetDivertingStatusL: aBsc: %d", aBsc ); + + iCFStatusCheck = ETrue; + + CPsetTelephony::CheckLineModeL( aServiceGroup, &iPhone, iLine ); + if ( !iLine->SubSessionHandle() ) + { + User::Leave( KErrBadHandle ); + } + + // in these cases basic service group will not be set + if ( !( aCondition == EDivertConditionAllCalls || + aCondition == EDivertConditionAllConditionalCases ) ) + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::GetDivertingStatusL: CancelAll should not come here" ); + ValidateBsc( aBsc ); + } + + iReason = PSetUtility::GetDivertReason( aCondition ); + + // Start to request for status. + if (iCfInterrogator) + { + delete iCfInterrogator; + iCfInterrogator = NULL; + } + iCfInterrogator = CRetrieveMobilePhoneCFList::NewL( iPhone ); + iCfInterrogator->Start( + iStatus, + iReason, + PSetUtility::ChangeToEtelInternal( aBsc ) ); + + StartRequestingL( EPSetGetDivertStatus ); + + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::GetDivertingStatusL" ); + } + +// --------------------------------------------------------------------------- +// Creates param list for NotifyDivertChange method. +// --------------------------------------------------------------------------- +// +TCallDivertNotifySetting CPSetCallDivertingBase::CreateDivertNotifySetting( + TUnconditionalCFStatus aCurrentDivert, TBool aDivertChanged, + TBool aVoiceMbxDivert, TInt aBasic ) + { + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase iVideoDivert = %d", iVideoDivert ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase iVoiceDivert = %d", iVoiceDivert ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase aVoiceMbxDivert = %d", aVoiceMbxDivert ); + + TCallDivertNotifySetting divertNotify; + divertNotify.Initialize(); + + divertNotify.iPreviousCfStatus = aCurrentDivert; + divertNotify.iCfActivated = aDivertChanged; + + divertNotify.iBasicServiceCode = aBasic; + + if ( aVoiceMbxDivert ) + { + divertNotify.iVmbxDivert = ETrue; + } + + return divertNotify; + } + +// --------------------------------------------------------------------------- +// Gets Als information +// --------------------------------------------------------------------------- +// +TSelectedLine CPSetCallDivertingBase::GetSAAls() + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::GetSAAls" ); + __PHSLOGSTRING2("[PHS] iAls: %d iBsc: %d", iAls, iBsc ); + TSelectedLine alsValue = ENotSupportedLine; + switch ( iAls ) + { + case ESSSettingsAlsNotSupported: + alsValue = ENotSupportedLine; + break; + case ESSSettingsAlsPrimary: + iChangeInfo.iServiceGroup == RMobilePhone::EAuxVoiceService + ? ( alsValue = EAuxiliaryLine ) + : ( alsValue = EPrimaryLine ); + break; + case ESSSettingsAlsAlternate: + alsValue = EAuxiliaryLine; + break; + default: + alsValue = ENotSupportedLine; + break; + } + + // If user checks/activates divert to line which is not selected currently than we have + // to change returned alsvalue accordinly, if this is not done divert icon status is updated to wrong status. + // Example case: Line 2 active user activates divert to line 1: **21*phonenumber*11#. + if ( iBsc == EAltTele && iAls == ESSSettingsAlsPrimary ) + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::GetSAAls - Line 2 divert activation/check from Line 1" ); + alsValue = EAuxiliaryLine; + } + else if ( iBsc == ETelephony && iAls == ESSSettingsAlsAlternate ) + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::GetSAAls - Line 1 divert activation/check from Line 2" ); + alsValue = EPrimaryLine; + } + + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::GetSAAls: alsValue: %d", alsValue ); + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::GetSAAls" ); + return alsValue; + } + +// --------------------------------------------------------------------------- +// Validates used bsc, if EUnknown, updates to real value +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::ValidateBsc( TBasicServiceGroups& aBsc ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::ValidateBsc" ); + if ( aBsc == EUnknown ) + // if bsc is unknown, update it + { + if ( iAls == ESSSettingsAlsAlternate ) + { + aBsc = EAltTele; + } + else + { + aBsc = ETelephony; + } + } + else + // If no specific line is indicated + { + if ( aBsc == EAllTeleAndBearer || + aBsc == EAllTele ) + { + // if ALS is used, use 89 bsc + if ( iAls == ESSSettingsAlsAlternate ) + { + aBsc = EAltTele; + } + } + } + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::ValidateBsc" ); + } + +// --------------------------------------------------------------------------- +// Starts requesting +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::StartRequestingL( const TInt& aRequest ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::StartRequestingL" ); + if ( aRequest != KPsetRequestAlreadySet ) + { + SetRequestStatus( static_cast ( aRequest ) ); + } + + SetActive(); + + iObserver->SetEngineContact( iDivert ); + + CleanupLeavePushL(); + iObserver->HandleCFRequestingL( ETrue, EFalse ); + CleanupStack::Pop(); // CleanupCancelPushL + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::StartRequestingL" ); + } + +// --------------------------------------------------------------------------- +// Inform request observer that request status has changed. +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::SetRequestStatus( TPSetDivertRequest aStatus ) + { + iCurrentReq = aStatus; + if ( iReqObserver ) + { + iReqObserver->RequestStatusChanged( aStatus ); + } + } + +// --------------------------------------------------------------------------- +// If divert activation/cancellation/etc. affects more than one bsc, +// inform PSUI about it. +// --------------------------------------------------------------------------- +TBool CPSetCallDivertingBase::IsMultiAffectingDivert( + const TCallDivertSetting& aDivert, TBasicServiceGroups aBsc ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::IsMultiAffectingDivert" ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::IsMultiAffectingDivert: aBsc = %d", aBsc ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::IsMultiAffectingDivert: aDivert.iCondition = %d", aDivert.iCondition ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::IsMultiAffectingDivert: aDivert.iStatus = %d", aDivert.iStatus ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::IsMultiAffectingDivert: aDivert.iServiceGroup = %d", aDivert.iServiceGroup ); + + if ( iReason == RMobilePhone::ECallForwardingAllCases || + iReason == RMobilePhone::ECallForwardingAllConditionalCases || + iReason == RMobilePhone::ECallForwardingNotReachable ) + { + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::IsMultiAffectingDivert1" ); + return ETrue; + } + if ( iReason == RMobilePhone::ECallForwardingUnconditional ) + { + //it is a MMI string + if ( ( aBsc != EUnknown && aBsc != ETelephony ) && aDivert.iServiceGroup == EServiceGroupVoice ) + { + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::IsMultiAffectingDivert2" ); + return ETrue; + } + } + + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::IsMultiAffectingDivert3" ); + return EFalse; + } + +// --------------------------------------------------------------------------- +// Push object into cleanupstack to catch leaving. +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::CleanupLeavePushL() + { + CleanupStack::PushL( TCleanupItem( DoHandleLeave, this ) ); + } + +// --------------------------------------------------------------------------- +// Object has caused a leave. +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::DoHandleLeave( TAny* aAny ) + { + REINTERPRET_CAST( CPSetCallDivertingBasicImpl*, aAny )->HandleLeave(); + } + +// --------------------------------------------------------------------------- +// Things to do when leave occurs. +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::HandleLeave() + { + CancelCurrentRequest(); + } + +// --------------------------------------------------------------------------- +// Inform the request observer that request has been completed. +// --------------------------------------------------------------------------- +// +void CPSetCallDivertingBase::RequestCompleted( const TInt& aError ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::RequestCompleted" ); + if ( aError != KErrNone ) + { + SetRequestStatus( static_cast (aError) ); + } + SetRequestStatus( EPSetNone ); + iVoiceDivert = EFalse; + + if ( iReqObserver ) + { + iReqObserver->RequestComplete(); + } + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::RequestCompleted" ); + } + +// --------------------------------------------------------------------------- +// Verifies whether the divert-to number is to voice mail box. +// --------------------------------------------------------------------------- +// +TBool CPSetCallDivertingBase::IsVMBXDivertL( TDesC& aTelNumber ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::IsVMBXDivertL" ); + + TBool result = EFalse; + + if ( FeatureManager::FeatureSupported ( KFeatureIdVmbxCallDivertIcon ) ) + { + RVmbxNumber vmbxConnection; + TTelNumber telNumber; + TInt retValue = OpenVmbxLC( telNumber, vmbxConnection ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::IsVMBXDivertL: telNumber = %S", &telNumber ); + __PHSLOGSTRING1("[PHS] CPSetCallDivertingBase::IsVMBXDivertL: retValue = %d", retValue ); + + CleanupStack::PopAndDestroy(); //vmbxConnection is closed when popped + if ( retValue == KErrNone ) //VMBX number found + { + + //Concatenate the existing number and add '*' to the beginning + TTelNumber tempStr; + tempStr.Zero(); + tempStr.Append( KPSetAsterisk ); + + //Match with seven characters + TInt matchChars = KPsetMatchingChars; + if ( telNumber.Length() < matchChars ) + { + matchChars = telNumber.Length(); + } + tempStr.Append( telNumber.Right( matchChars ) ); + + //Compare value with divert-to number + if ( aTelNumber.Match ( tempStr ) != KErrNotFound ) + { + __PHSLOGSTRING("[PHS] CPSetCallDivertingBase::IsVMBXDivertL: Match found" ); + result = ETrue; + } + } + } + __PHSLOGSTRING("[PHS] <--CPSetCallDivertingBase::IsVMBXDivertL" ); + return result; + } + +// --------------------------------------------------------------------------- +// Opens Vmbx. Leaves vmbx to the stack. +// --------------------------------------------------------------------------- +TInt CPSetCallDivertingBase::OpenVmbxLC( TDes& aTelNumber, RVmbxNumber& aVmbx ) + { + __PHSLOGSTRING("[PHS]--> CPSetCallDivertingBase::OpenVmbxLC" ); + User::LeaveIfError( aVmbx.Open( iPhone ) ); + CleanupClosePushL( aVmbx ); + __PHSLOGSTRING("[PHS]<-- CPSetCallDivertingBase::OpenVmbxLC" ); + return aVmbx.GetVmbxNumber( aTelNumber ); + } + +// --------------------------------------------------------------------------- +// If SsSettings notifies of settings change, copy new value to member variable. +// --------------------------------------------------------------------------- +void CPSetCallDivertingBase::PhoneSettingChanged( + TSSSettingsSetting aSetting, TInt aNewValue ) + { + __PHSLOGSTRING2("[PHS]--> CPSetCallDivertingBase::PhoneSettingChanged ESSSettingsAls: %d, aNewValue: %d", aSetting, aNewValue ); + if ( aSetting == ESSSettingsAls ) + { + iAls = static_cast (aNewValue); + } + __PHSLOGSTRING("[PHS]<-- CPSetCallDivertingBase::PhoneSettingChanged" ); + } + +// End of File