cellular/telephonysettings/src/PSetCallDivertingBase.cpp
changeset 0 ff3b6d0fd310
child 3 a4a774cb6ea7
child 12 ae8abd0db65c
--- /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 <badesca.h>
+#include <etelmm.h>           
+#include <e32math.h>
+#include <vmnumber.h>
+#include <e32svr.h>
+#include <featmgr.h>
+#include <centralrepository.h>
+#include <SettingsInternalCRKeys.h>
+
+#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 <TSSSettingsAlsValue> ( 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<TUint32> 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 <HBufC16*> ( 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 <TPSetDivertRequest> ( 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 <TPSetDivertRequest> (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 <TSSSettingsAlsValue> (aNewValue);
+        }
+    __PHSLOGSTRING("[PHS]<-- CPSetCallDivertingBase::PhoneSettingChanged" );
+    }
+
+// End of File