diff -r f742655b05bf -r d38647835c2e callcontinuity/vcchotrigger/src/vcchotrigger.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/callcontinuity/vcchotrigger/src/vcchotrigger.cpp Wed Sep 01 12:29:57 2010 +0100 @@ -0,0 +1,702 @@ +/* +* Copyright (c) 2007-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 the handover trigger +* +*/ + + + +#include + +#include +#include "vccuipsproperty.h" +#include "vcchotrigger.h" +#include "vccsignallevelhandler.h" +#include "vccwlansignallevelhandler.h" +#include "vccgsmsignallevelhandler.h" +#include "rubydebug.h" +#include "vcchopolicyreader.h" +#include "vcccchmonitor.h" +#include "vccengpsproperty.h" +#include "cvccperformer.h" + +// Min. signal strength. +static const TInt32 KStrengthMin = 110; + +// ======== MEMBER FUNCTIONS ======== + +// --------------------------------------------------------------------------- +// Symbian constructor +// --------------------------------------------------------------------------- +// +EXPORT_C CVccHoTrigger* CVccHoTrigger::NewL() + { + RUBY_DEBUG_BLOCKL( "CVccHoTrigger::NewL" ); + + CVccHoTrigger* self = new ( ELeave ) CVccHoTrigger(); + + CleanupStack::PushL( self ); + + self->ConstructL(); + + CleanupStack::Pop( self ); + + return self; + } + +// --------------------------------------------------------------------------- +// Destructor +// --------------------------------------------------------------------------- +// +CVccHoTrigger::~CVccHoTrigger() + { + RUBY_DEBUG0( "CVccHoTrigger::~CVccHoTrigger() - ENTER" ); + + delete iProperty; + delete iWlanSignalLevelHandler; + delete iGsmSignalLevelHandler; + delete iHoPolicyReader; + delete iCchMonitor; + delete iEngPsProperty; + + RUBY_DEBUG0( "CVccHoTrigger::~CVccHoTrigger() - EXIT" ); + } + +// ----------------------------------------------------------------------------- +// CVccHoTrigger::CVccHoTrigger() +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CVccHoTrigger::CVccHoTrigger() : //: CActive( EPriorityStandard ) + iGsmClass( ESignalClassUndefined ), + iWlanClass( ESignalClassUndefined ), + iManualHoDone( EFalse ), + iHoNotAllowed( EFalse ), + iHoAllowedIfCsOriginated( ETrue ) + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::CVccHoTrigger" ); + } +// --------------------------------------------------------------------------- +// 2nd phase constructor +// --------------------------------------------------------------------------- +// +void CVccHoTrigger::ConstructL() + { + RUBY_DEBUG_BLOCKL( "CVccHoTrigger::ConstructL" ); + + iProperty = CVccUiPsProperty::NewL(); + iHoPolicyReader = CVccHoPolicyReader::NewL(); + iHoPolicyReader->ReadSettingsL(); + + iEngPsProperty = CVccEngPsProperty::NewL(); + iPolicy = iHoPolicyReader->HoPolicy(); + TSignalLevelParams gsm = iHoPolicyReader->CsSignalLevelParams(); + TSignalLevelParams wlan = iHoPolicyReader->PsSignalLevelParams(); + + + iWlanSignalLevelHandler = + CVccWlanSignalLevelHandler::NewL( *this, wlan, *iEngPsProperty ); + + + iGsmSignalLevelHandler = + CVccGsmSignalLevelHandler::NewL( *this, gsm ); + + iHoAllowedIfCsOriginated = iPolicy.DtAllowedWhenCsOriginated(); + // Previous signal level class must be undefined + iPreviousGsmClass = ESignalClassUndefined; + iPreviousWlanClass = ESignalClassUndefined; + // In the beginning the VoIP service is not available. + // This will be changed when the cch monitor calls us + // when the service is available. + iCchServiceStatus = EServiceUnavailable; + + // CS network has signal level zero if the service is not + // available. + iCsSignalLevel = KStrengthMin; + + // We are not stared yet. + iStarted = EFalse; + + // Update P&S keys to tell if we can do ho or not. + UpdatePsKeysL(); + // Create the CCH monitor. We are the observer to be + // notified when the status changes. + iCchMonitor = CVccCchMonitor::NewL( *this ); + } + +// ----------------------------------------------------------------------------- +// Stop monitoring +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::Stop() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::Stop" ); + Stop( *iWhoStartedMe ); + } + +// ----------------------------------------------------------------------------- +// Stop monitoring +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::Stop( CVccPerformer& aStopper ) + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::Stop" ); + // If someone else that the one who started us tries + // to stop us, we do not allow it. + // There may be several performers that are in differnet state + // and in those state they do not need trigger and thus try + // to stop us. + if ( iWhoStartedMe == &aStopper ) + { + iWhoStartedMe = NULL; + iStarted = EFalse; + TRAP_IGNORE( UpdatePsKeysL() ); + TRAP_IGNORE( iProperty->NotifySubscriberL( EVccNoRequestOngoing ) ); + iWlanSignalLevelHandler->Stop(); + iGsmSignalLevelHandler->Stop(); + + iGsmClass = ESignalClassUndefined; + iWlanClass = ESignalClassUndefined; + + // Reset CS signal strength to min + iCsSignalLevel = KStrengthMin; + + // Disable (do not send notifications). + // The service is not actually disabled. + // It will be disabled (if needed) when the monitor + // is deleted. + iCchMonitor->DisableService(); + RUBY_DEBUG0( " -Trigger stopped"); + } + } + +// ----------------------------------------------------------------------------- +// Start monitoring +// We must not leave. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::Start( CVccPerformer& aWhoStartedMe, + TBool aCsOriginated ) + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::Start" ); + if( iHoAllowedIfCsOriginated == EFalse && aCsOriginated ) + { + RUBY_DEBUG0( "HO not allowed for CS originated calls" ); + + Stop(); + return; + } + //anyone can start, but only the last one who started can stop the trigger + iWhoStartedMe = &aWhoStartedMe; + if( !iStarted ) + { + + // Previous signal level class must be undefined + iPreviousGsmClass = ESignalClassUndefined; + iPreviousWlanClass = ESignalClassUndefined; + + // read signal high/low levels, timers etc. + TRAPD( err, iHoPolicyReader->ReadSettingsL() ); + RUBY_DEBUG1( "reading ho settings, err = %d", err ); + + if ( !err ) + { + TSignalLevelParams gsm = iHoPolicyReader->CsSignalLevelParams(); + TSignalLevelParams wlan = iHoPolicyReader->PsSignalLevelParams(); + iPolicy = iHoPolicyReader->HoPolicy(); + + iWlanSignalLevelHandler->SetParams( wlan ); + iGsmSignalLevelHandler->SetParams( gsm ); + + TRAPD( err_wlan, iWlanSignalLevelHandler->StartL() ); + RUBY_DEBUG1( "starting wlan signal level handler, err = %d", err_wlan ); + TRAPD( err_gsm, iGsmSignalLevelHandler->StartL() ); + RUBY_DEBUG1( "starting gsm signal level handler, err = %d", err_gsm ); + + if ( !err_wlan && !err_gsm ) + { + // Enable the VoIP service to be able to do VoIP calls. + TRAPD( err_cch, iCchMonitor->EnableServiceL() ); + RUBY_DEBUG1( "enabling service, err = %d", err_cch ); + + if ( !err_cch ) + { + // Everything was started ok + iStarted = ETrue; + } + } + else + { + // Stop the handlers just in case either one was started + iWlanSignalLevelHandler->Stop(); + iGsmSignalLevelHandler->Stop(); + } + } + + TRAP_IGNORE( UpdatePsKeysL() ); + } + } + +// ----------------------------------------------------------------------------- +// Set the domain type of the current call +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::SetCurrentDomainType( TCallDomainType aDomainType ) + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::SetCurrentDomainType" ); + iDomainType = aDomainType; + } + +// ----------------------------------------------------------------------------- +// Set the preferred domain type +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::SetPreferredDomainType( + TVccHoPolicyPreferredDomain aDomainType ) + { + RUBY_DEBUG1( "CVccHoTrigger::SetPreferredDomainType(%d)", aDomainType ); + iPolicy.SetPreferredDomain( aDomainType ); + } + +// ----------------------------------------------------------------------------- +// Set Immediate Domain Transfer on/off +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::SetImmediateDomainTransfer( TBool aImmediateDT ) + { + RUBY_DEBUG1( "CVccHoTrigger::SetImmediateDomainTransfer(%d)", aImmediateDT ); + iPolicy.SetDoImmediateHo( aImmediateDT ); + } + +// ----------------------------------------------------------------------------- +// Handles wlan signal change notifications +// ----------------------------------------------------------------------------- +// +void CVccHoTrigger::WlanSignalChanged( + TInt32 /*aSignalStrength*/, + TSignalStrengthClass aClass ) + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::WlanSignalChanged" ); + + //Store signal strength class to that we know later what is the strength + iWlanClass = aClass; + + RUBY_DEBUG1( " -iWlanClass=%x ", iWlanClass ); + RUBY_DEBUG1( " -iDomainType=%x ", iDomainType ); + RUBY_DEBUG1( " -iGsmClass=%x ", iGsmClass ); + RUBY_DEBUG1( " -DoImmediateHO=%x ", iPolicy.DoImmediateHo() ); + RUBY_DEBUG1( " -PreferredDomain=%x ", iPolicy.PreferredDomain() ); + RUBY_DEBUG1( " -iGsmClass=%x ", iGsmClass ); + RUBY_DEBUG1( " -DoHoInHeldWaitingCalls=%x ", iPolicy.DoHoInHeldWaitingCalls() ); + RUBY_DEBUG0( "0 = GOOD, 1 = WEAK, 2 = UNDEFINED" ); + + // If the previous class is the same as the new one + // - do nothing. + + if ( iPreviousWlanClass == iWlanClass ) + { + if (iWlanClass == ESignalClassWeak) + { + RUBY_DEBUG0( "Signal is still weak try again to do HO" ); + } + else + { + RUBY_DEBUG0( "No change in WLAN signal class -> return" ); + return; + } + } + else + { + iPreviousWlanClass = iWlanClass; + } + + TriggerHo(); + } + +// ----------------------------------------------------------------------------- +// Handles GSM singnal change notifications +// ----------------------------------------------------------------------------- +// +void CVccHoTrigger::GsmSignalChanged( + TInt32 aSignalStrength, + TSignalStrengthClass aClass ) + { + RUBY_DEBUG_BLOCK( "VccHoTrigger::GsmSignalChanged" ); + RUBY_DEBUG1( " -iCsSignalLevel=%d ", aSignalStrength ); + + //Store signal strength class to that we know later what is the strength + iGsmClass = aClass; + + // Save the signal strength as "status". + // Zero (0) means that the service is not available. + iCsSignalLevel = aSignalStrength; + + // Update P&S keys to tell if we can do ho or not. + // If the signal level has gone to zero, we are unable to + // do hondover. + + TVccHoStatus hoStatus( EVccHoStateUnknown ); + iEngPsProperty->GetCurrentHoStatus( hoStatus ); + + if( hoStatus != EVccCsToPsHoStarted || hoStatus != EVccCsToPsHoInprogress + || hoStatus != EVccPsToCsHoStarted || hoStatus != EVccPsToCsHoInprogress ) + { + RUBY_DEBUG0( "HO not in progress, updating keys" ); + TRAP_IGNORE( UpdatePsKeysL() ); + } + + RUBY_DEBUG1( " -iWlanClass=%x ", iWlanClass ); + RUBY_DEBUG1( " -iDomainType=%x ", iDomainType ); + RUBY_DEBUG1( " -iGsmClass=%x ", iGsmClass ); + RUBY_DEBUG1( " -DoImmediateHO=%x ", iPolicy.DoImmediateHo() ); + RUBY_DEBUG1( " -PreferredDomain=%x ", iPolicy.PreferredDomain() ); + RUBY_DEBUG1( " -DoHoInHeldWaitingCalls=%x ", iPolicy.DoHoInHeldWaitingCalls() ); + RUBY_DEBUG0( "0 = GOOD, 1 = WEAK, 2 = UNDEFINED" ); + + // If the previous class is the same as the new one + // - do nothing. + + if ( iPreviousGsmClass == iGsmClass && iWlanClass != ESignalClassWeak ) + { + RUBY_DEBUG0( "No change in GSM signal class -> return" ); + + return; + } + else + { + iPreviousGsmClass = iGsmClass; + } + + TriggerHo(); + } + +// ----------------------------------------------------------------------------- +// Handles CCH monitor notifications +// ----------------------------------------------------------------------------- +// +void CVccHoTrigger::CchServiceStatusChanged( TServiceStatus aStatus ) + { + RUBY_DEBUG_BLOCK( "VccHoTrigger::CchServiceStateChanged" ); + RUBY_DEBUG1( " -Service status = %d", aStatus ); + + // Save the status + iCchServiceStatus = aStatus; + + TRAP_IGNORE( UpdatePsKeysL() ); + TriggerHo(); + } + +// ----------------------------------------------------------------------------- +// Check if the CS or PS services are available or not +// ----------------------------------------------------------------------------- +// +TBool CVccHoTrigger::ServicesAvailable() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::AreServicesAvailable" ); + + TBool retVal( ETrue ); + + // If PS service (VoIP service) is unavailable or + // the CS service == 0 (i.e. signal level), + // we cannot do handover. + + if ( iCchServiceStatus == EServiceUnavailable || + iCsSignalLevel == KStrengthMin ) + { + RUBY_DEBUG0( " -VoIP/CS service(s) not available" ); + retVal = EFalse; + } + + return retVal; + } + +// ----------------------------------------------------------------------------- +// Update (write) service status state to P&S. +// ----------------------------------------------------------------------------- +// +void CVccHoTrigger::UpdatePsKeysL() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::UpdatePsKeysL" ); + + // If we are started and both services are available, + // handover can be done. + // Services available in CS means that we have + // signal strength != KStrengthMin (which is 110, returned + // from the CS signal level monitor). + + RUBY_DEBUG1( " -iStarted = %d", iStarted ); + RUBY_DEBUG1( " -iHoNotAllowed = %d", iHoNotAllowed ); + RUBY_DEBUG1( " -Service status = %d (0=unavailable, 1=available)", iCchServiceStatus ); + RUBY_DEBUG1( " -CS signal min level = 110, current level = %d", iCsSignalLevel ); + + if ( iStarted && + ( iCchServiceStatus == EServiceAvailable ) && + ( iCsSignalLevel != KStrengthMin ) && + ( !iHoNotAllowed ) ) + { + RUBY_DEBUG0( " -We are started and both services are available" ); + // Check HO direction restrictions + if ( ( iPolicy.AllowedDirection() & ECsToPsAllowed ) && + ( iPolicy.AllowedDirection() & EPsToCsAllowed ) ) + { + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + RUBY_DEBUG0( " -Services available and ho allowed to both \ + directions, also in multicall" ); + iEngPsProperty->NotifySubscriberL( EVccHoStateIdle, KErrNone ); + } + else + { + RUBY_DEBUG0( " -Services available and ho allowed to both \ + directions but not in multicall" ); + iEngPsProperty->NotifySubscriberL( EVccHoStateIdleIfSingleCall, KErrNone ); + } + } + else if ( !( iPolicy.AllowedDirection() & ECsToPsAllowed ) && + ( iPolicy.AllowedDirection() & EPsToCsAllowed ) ) + { + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + RUBY_DEBUG0( " -HO allowed only to CS" ); + iEngPsProperty->NotifySubscriberL( EVccCsToPsNotAllowed, KErrNone ); + } + else + { + RUBY_DEBUG0( " -HO allowed only to CS, in single call situation" ); + iEngPsProperty->NotifySubscriberL( EVccHoAllowedToCsIfSingleCall, KErrNone ); + } + } + else if ( !( iPolicy.AllowedDirection() & EPsToCsAllowed ) && + ( iPolicy.AllowedDirection() & ECsToPsAllowed ) ) + { + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + RUBY_DEBUG0( " -HO allowed only to PS" ); + iEngPsProperty->NotifySubscriberL( EVccPsToCsNotAllowed, KErrNone ); + } + else + { + RUBY_DEBUG0( " -HO allowed only to PS, in single call situation" ); + iEngPsProperty->NotifySubscriberL( EVccHoAllowedToPsIfSingleCall, KErrNone ); + } + } + } + else + { + RUBY_DEBUG0( " -We are stopped or services are unavailable:" ); + iEngPsProperty->NotifySubscriberL( EVccHoUnavailable, KErrNotReady ); + } + } + +// ----------------------------------------------------------------------------- +// If manual HO is done, no automatic should be made. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::ManualHoCallStarted() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::ManualHoCallStarted" ); + iManualHoDone = ETrue; + //notify Wlan Signal Level Handler so it can stop polling WLAN signal + iWlanSignalLevelHandler->SetManualHoDone( ETrue ); + } + +// ----------------------------------------------------------------------------- +// After manual HO call has been released automatic HOs can be made again. +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::ManualHoCallReleased() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::ManualHoCallReleased" ); + iManualHoDone = EFalse; + + iWlanSignalLevelHandler->SetManualHoDone( EFalse ); + } + +// ----------------------------------------------------------------------------- +// During conference HO is not allowed +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::HoNotAllowedL() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::HoNotAllowedL" ); + iHoNotAllowed = ETrue; + UpdatePsKeysL(); + } + +// ----------------------------------------------------------------------------- +// After conference HO is allowed again +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::HoAllowed() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::HoAllowed" ); + iHoNotAllowed = EFalse; + TRAP_IGNORE( UpdatePsKeysL() ); + } + +// ----------------------------------------------------------------------------- +// Read settings +// ----------------------------------------------------------------------------- +// +EXPORT_C void CVccHoTrigger::ReadHoAllowedWhenCsOriginatedSettingL() + { + iHoPolicyReader->ReadSettingsL(); + iPolicy = iHoPolicyReader->HoPolicy(); + iHoAllowedIfCsOriginated = iPolicy.DtAllowedWhenCsOriginated(); + } + +// ----------------------------------------------------------------------------- +// Initiate the actual ho when its ok +// ----------------------------------------------------------------------------- +// +void CVccHoTrigger::TriggerHo() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::TriggerHo" ); + + RUBY_DEBUG1("Current domain is: %d", iDomainType); + //Check if manual ho is already made during this call and the + //service availability. + if( iManualHoDone || !ServicesAvailable() || iHoNotAllowed ) + { + return; + } + + //If immediate ho is "ON" do it first and then return. + if( iPolicy.DoImmediateHo() ) + { + if ( DoImmediateHo() ) + { + RUBY_DEBUG0( "VccHoTrigger::TriggerHo - immediate HO was initiated" ); + return; + } + RUBY_DEBUG0( "VccHoTrigger::TriggerHo - no immediate HO" ); + } + + if ( ( iWlanClass == ESignalClassWeak || iCchServiceStatus == EServiceUnavailable )&& + iGsmClass == ESignalClassNormal && + ( iPolicy.AllowedDirection() & EPsToCsAllowed ) && iDomainType == ECallDomainTypePS ) + { + RUBY_DEBUG0( "VccHoTrigger::WlanSignalChanged - NotifySubscriberL" ); + + // First empty the key, so that director + // gets notified about all changes + + TRAP_IGNORE( iProperty->NotifySubscriberL( EVccNoRequestOngoing ) ); + // Check whether HO is allowed in multicall situation + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartPsToCsHoRequest ) ); + } + else + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartPsToCsHoRequestIfSingleCall ) ); + } + + } + + else if ( iGsmClass == ESignalClassWeak && + iWlanClass == ESignalClassNormal && + ( iPolicy.AllowedDirection() & ECsToPsAllowed )) + { + RUBY_DEBUG0( "VccHoTrigger::GsmSignalChanged - NotifySubscriberL" ); + + // First empty the key, so that director + // gets notified about all changes + + TRAP_IGNORE( iProperty->NotifySubscriberL( EVccNoRequestOngoing ) ); + // Check whether HO is allowed in multicall situation + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartCsToPsHoRequest ) ); + } + else + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartCsToPsHoRequestIfSingleCall ) ); + } + } + } + +// ----------------------------------------------------------------------------- +// Initiate immediate ho +// ----------------------------------------------------------------------------- +// +TBool CVccHoTrigger::DoImmediateHo() + { + RUBY_DEBUG_BLOCK( "CVccHoTrigger::DoImmediateHo" ); + TBool ret( EFalse ); + if( ( iPolicy.PreferredDomain() == ECsPreferred ) && + iGsmClass == ESignalClassNormal && + ( iPolicy.AllowedDirection() & EPsToCsAllowed ) ) + { + // Current call is PS, CS signal is ok, preferred domain is CS + // and immediate HO is requested -> HANDOVER to CS + + RUBY_DEBUG0( "VccHoTrigger::GsmSignalChanged - NotifySubscriberL ->\ + IMMEDIATE HO to CS" ); + + // First empty the key, so that director gets + // notified about all changes + + TRAP_IGNORE( iProperty->NotifySubscriberL( EVccNoRequestOngoing ) ); + + // Check whether HO is allowed in multicall situation + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartPsToCsHoRequest ) ); + ret = ETrue; + } + else + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartPsToCsHoRequestIfSingleCall ) ); + ret = ETrue; + } + } + + else if ( (iPolicy.PreferredDomain() == EPsPreferred) && + iWlanClass == ESignalClassNormal && iCchServiceStatus != EServiceUnavailable && + ( iPolicy.AllowedDirection() & ECsToPsAllowed ) && iDomainType != ECallDomainTypePS ) + { + // Current call is CS, PS signal is ok, preferred domain is PS and + // immediate HO is requested -> HANDOVER to PS + + RUBY_DEBUG0( "VccHoTrigger::WlanSignalChanged - NotifySubscriberL ->\ + IMMEDIATE HO to PS" ); + + // First empty the key, so that director gets + // notified about all changes + + TRAP_IGNORE( iProperty->NotifySubscriberL( EVccNoRequestOngoing ) ); + + // Check whether HO is allowed in multicall situation + if( iPolicy.DoHoInHeldWaitingCalls() ) + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartCsToPsHoRequest ) ); + ret = ETrue; + } + else + { + TRAP_IGNORE( iProperty->NotifySubscriberL( + EVccAutomaticStartCsToPsHoRequestIfSingleCall ) ); + ret = ETrue; + } + } + return ret; + }