telephonyutils/etel3rdpartyapi/src/TelephonyFunctions.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 18 Aug 2010 10:57:47 +0300
changeset 62 8ef833fbf5aa
parent 0 3553901f7fa8
child 58 980b3d0c4069
permissions -rw-r--r--
Revision: 201033 Kit: 201033

/*
* Copyright (c) 2009 Sony Ericsson Mobile Communications AB
* 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:
* Sony Ericsson Mobile Communications AB - initial contribution.
* Nokia Corporation - additional changes.
* 
* Contributors:
* 
* Description:
* Code for CTelephonyFunctions class, used by CTelephony class.
*
*/


/**
 @file
*/

#include "TelephonyFunctions.h"
#include "TelephonyActPhone.h"
#include "TelephonyActSupplServices.h"
#include "TelephonyActLine.h"
#include "TelephonyActCall.h"
#include "TelephonyActNetwork.h"

#include <commsdattypesv1_1.h>
#include <cdblen.h>
#include <commsdat_partner.h>
using namespace CommsDat;

// construct/destruct

CTelephonyFunctions* CTelephonyFunctions::NewLC()
/**
Constructs a CTelephonyFunctions object.

A pointer to this object is left on the CleanupStack.

@leave	Leaves if no memory, or underlying Etel DLL returns error.
@return	Pointer to a newly created CTelephonyFunctions object connected to an RTelServer.
*/
	{
	CTelephonyFunctions* self=new (ELeave) CTelephonyFunctions();
	CleanupStack::PushL(self);
	self->ConstructL();
	return self;
	}

CTelephonyFunctions* CTelephonyFunctions::NewL()
/**
Constructs a CTelephonyFunctions object.

@leave	Leaves if no memory, or underlying Etel DLL returns error.
@return	pointer to a newly created CTelephonyFunctions object connected to an RTelServer.
*/
	{
	CTelephonyFunctions* self=NewLC();
	CleanupStack::Pop();
	return self;
	}

CTelephonyFunctions::~CTelephonyFunctions()
/**
Destructor
*/
	{

	CleanUp();

	if (iTelServerIsOpen)
		{
		iTelServer.Close();
		}

	iReqPendingTable.Close();
	iReqStatusTable.Close();
	iCallPool.Close();
	iCallPoolStatus.Close();
	iPhonePowerProperty.Close();
	}

/**
Cleans up any outstanding "Open" objects.
*/
void CTelephonyFunctions::CleanUp()
	{
	for ( TInt i=0;i<iReqPendingTable.Count(); i++)
		{
		if(iReqPendingTable[i]!=EFalse)
			{
			User::RequestComplete(iReqStatusTable[i], KErrCancel);
			}
		}

	iState = ECleaningUp;

	if(iGetPhoneId!=NULL)
		{
		delete iGetPhoneId;
		iGetPhoneId = NULL;
		}
	if(iGetSubscriberId!=NULL)
		{
		delete iGetSubscriberId;
		iGetSubscriberId = NULL;
		}
	if(iGetIndicator!=NULL)
		{
		delete iGetIndicator;
		iGetIndicator = NULL;
		}
	if(iGetBatteryInfo!=NULL)
		{
		delete iGetBatteryInfo;
		iGetBatteryInfo = NULL;
		}
	if(iGetSignalStrength!=NULL)
		{
		delete iGetSignalStrength;
		iGetSignalStrength = NULL;
		}
	if(iGetIccLockInfo!=NULL)
		{
		delete iGetIccLockInfo;
		iGetIccLockInfo = NULL;
		}
	if(iSendDTMFTones!=NULL)
		{
		delete iSendDTMFTones;
		iSendDTMFTones = NULL;
		}
	if(iDialNewCall!=NULL)
		{
		delete iDialNewCall;
		iDialNewCall = NULL;
		}
	if(iHold!=NULL)
		{
		delete iHold;
		iHold = NULL;
		}
	if(iResume!=NULL)
		{
		delete iResume;
		iResume = NULL;
		}
	if(iSwap!=NULL)
		{
		delete iSwap;
		iSwap = NULL;
		}
	if(iHangup!=NULL)
		{
		delete iHangup;
		iHangup = NULL;
		}
	if(iAnswerIncomingCall!=NULL)
		{
		delete iAnswerIncomingCall;
		iAnswerIncomingCall = NULL;
		}
	if(iGetNetworkRegistrationStatus!=NULL)
		{
		delete iGetNetworkRegistrationStatus;
		iGetNetworkRegistrationStatus = NULL;
		}
	if(iGetCurrentNetworkInfo!=NULL)
		{
		delete iGetCurrentNetworkInfo;
		iGetCurrentNetworkInfo = NULL;
		}
	if(iGetCurrentNetworkName!=NULL)
		{
		delete iGetCurrentNetworkName;
		iGetCurrentNetworkName = NULL;
		}
	if(iGetOperatorName!=NULL)
		{
		delete iGetOperatorName;
		iGetOperatorName = NULL;
		}
	if(iGetCFSupplementaryServiceStatus!=NULL)
		{
		delete iGetCFSupplementaryServiceStatus;
		iGetCFSupplementaryServiceStatus = NULL;
		}
	if(iGetCBSupplementaryServiceStatus!=NULL)
		{
		delete iGetCBSupplementaryServiceStatus;
		iGetCBSupplementaryServiceStatus = NULL;
		}
	if(iGetCWSupplementaryServiceStatus!=NULL)
		{
		delete iGetCWSupplementaryServiceStatus;
		iGetCWSupplementaryServiceStatus = NULL;
		}
	if(iGetIdentityServiceStatus!=NULL)
		{
		delete iGetIdentityServiceStatus;
		iGetIdentityServiceStatus = NULL;
		}
	if(iFlightModeChange!=NULL)
		{
		delete iFlightModeChange;
		iFlightModeChange = NULL;
		}
	if(iNotifyIndicator!=NULL)
		{
		delete iNotifyIndicator;
		iNotifyIndicator = NULL;
		}
	if(iNotifyBatteryInfo!=NULL)
		{
		delete iNotifyBatteryInfo;
		iNotifyBatteryInfo = NULL;
		}
	if(iNotifySignalStrength!=NULL)
		{
		delete iNotifySignalStrength;
		iNotifySignalStrength = NULL;
		}
	if(iNotifyIccLockInfo!=NULL)
		{
		delete iNotifyIccLockInfo;
		iNotifyIccLockInfo = NULL;
		}
	if(iNotifyNetworkRegStatus!=NULL)
		{
		delete iNotifyNetworkRegStatus;
		iNotifyNetworkRegStatus = NULL;
		}
	if(iNotifyCurrentNetworkInfo!=NULL)
		{
		delete iNotifyCurrentNetworkInfo;
		iNotifyCurrentNetworkInfo = NULL;
		}
	if(iNotifyOwnedCall1Status!=NULL)
		{
		delete iNotifyOwnedCall1Status;
		iNotifyOwnedCall1Status = NULL;
		}
	if(iNotifyOwnedCall2Status!=NULL)
		{
		delete iNotifyOwnedCall2Status;
		iNotifyOwnedCall2Status = NULL;
		}
	if(iNotifyOwnedCall1RemoteInfo!=NULL)
		{
		delete iNotifyOwnedCall1RemoteInfo;
		iNotifyOwnedCall1RemoteInfo = NULL;
		}
	if(iNotifyOwnedCall2RemoteInfo!=NULL)
		{
		delete iNotifyOwnedCall2RemoteInfo;
		iNotifyOwnedCall2RemoteInfo = NULL;
		}

	// Delete the internal active objects last
	if(iInternalNotifyVoiceLineStatus!=NULL)
		{
		delete iInternalNotifyVoiceLineStatus;
		iInternalNotifyVoiceLineStatus = NULL;
		}
	if (iInternalNotifyIncomingCall!=NULL)
		{
		delete iInternalNotifyIncomingCall;
		iInternalNotifyIncomingCall = NULL;
		}

	if(iCallIsOpen)
		{
		iCallIsOpen = EFalse;
		iCall.Close();
		}

	for(TInt k = 0; k < iCallPool.Count(); k++)
		{
		iCallPool[k].Close();
		}
		
	for(TInt k = 0; k < iCallPoolStatus.Count(); k++)
		{
		iCallPoolStatus[k] = EUnset;
		}

	if(iLineIsDataOpen)
		{
		iLineIsDataOpen = EFalse;
		iLineData.Close();
		}

	if(iLineIsVoiceOpen)
		{
		iLineIsVoiceOpen = EFalse;
		iLineVoice.Close();
		}

	if(iLineIsFaxOpen)
		{
		iLineIsFaxOpen = EFalse;
		iLineFax.Close();
		}

	if(iPhoneIsOpen)
		{
		iPhoneIsOpen = EFalse;
		iPhone.Close();
		}
	iState = EIdle;	// all cleaned up.
	}


CTelephonyFunctions::CTelephonyFunctions()
/**
First-phase constructor

private function which cannot Leave().
*/
: iState(EIdle),
  iReqStatusTable(EMaxNumberOperations),
  iReqPendingTable(EMaxNumberOperations),  
  iCallPool(CTelephony::EISVMaxNumOfCalls),
  iCallPoolStatus(CTelephony::EISVMaxNumOfCalls)
	{
	}


void CTelephonyFunctions::ConstructL()
/**
Second-phase constructor
*/
	{
#ifdef __WINS__
	// When bootstrapping C32 we have to avoid the PhBkSyncServer being started, since
  	// it needs a different CommDB
	_LIT(KPhbkSyncCMI, "phbsync.cmi");
	TInt err = StartC32WithCMISuppressions(KPhbkSyncCMI);		// Start Comms server if not already active.
	if( err!=KErrNone && err!=KErrAlreadyExists )
		{
		User::Leave(err);
		}

#endif
	User::LeaveIfError(iTelServer.Connect());
	iTelServerIsOpen = ETrue;
	User::LeaveIfError(iPhonePowerProperty.Attach(KUidSystemCategory, KUidPhonePwr.iUid));

	for( TInt i=0; i<EMaxNumberOperations; i++)
		{
		TRequestStatus dummy(KErrNone);
		iReqPendingTable.AppendL(EFalse);
		iReqStatusTable.AppendL(&dummy);
		}
	for( TInt j=0; j<CTelephony::EISVMaxNumOfCalls; j++)
		{
		RMobileCall aDummyCall;
		iCallPool.AppendL(aDummyCall);
		iCallPoolStatus.AppendL(EUnset);
		}

	__ASSERT_DEBUG(iState==EIdle, User::Invariant());

	InitialisePhoneL();
	}


void CTelephonyFunctions::GetCommDbTSYnameL(TDes& aTsyName)
	{
#ifdef SYMBIAN_NON_SEAMLESS_NETWORK_BEARER_MOBILITY
	CMDBSession* db = CMDBSession::NewL(KCDVersion1_2);
#else
	CMDBSession* db = CMDBSession::NewL(KCDVersion1_1);
#endif
	CleanupStack::PushL(db);

	CMDBField<TDesC>* globalSettingField = new(ELeave) CMDBField<TDesC>(KCDTIdBearerAvailabilityCheckTSY);
	CleanupStack::PushL(globalSettingField);
	globalSettingField->SetRecordId(1);
	globalSettingField->SetMaxLengthL(KMaxTextLength);
	globalSettingField->LoadL(*db);
	aTsyName = *globalSettingField;
	CleanupStack::PopAndDestroy(globalSettingField);

	CleanupStack::PopAndDestroy(db);
	}


void CTelephonyFunctions::InitialisePhoneL()
/**
Finds the first data-Line and Open()'s the Phone and Line.

@leave	Leaves if underlying ETEL.DLL returns error,
or if we can't find a suitable Phone/Line or can't open it.
*/
	{
	TBuf<KCommsDbSvrMaxFieldLength> tsyName;
	GetCommDbTSYnameL(tsyName);

	User::LeaveIfError(iTelServer.LoadPhoneModule(tsyName));

	TInt numPhones;
	User::LeaveIfError(iTelServer.EnumeratePhones(numPhones));

	TInt phoneIndx;
	TInt ret = KErrHardwareNotAvailable;

	RPhone::TLineInfo lineInfo;
	for(phoneIndx=0; phoneIndx<numPhones; phoneIndx++)
		{
		RTelServer::TPhoneInfo tInfo;
		ret = iTelServer.GetPhoneInfo(phoneIndx, tInfo);
		if(ret != KErrNone)
			{
			continue;
			}
		
		ret = iPhone.Open(iTelServer, tInfo.iName);	
		if(ret != KErrNone)
			{
			continue;
			}

		iPhoneIsOpen = ETrue;

		RPhone::TStatus status;
		User::LeaveIfError(iPhone.GetStatus(status));
		if(status.iModemDetected!=RPhone::EDetectedPresent)
			{
			ret = iPhone.Initialise();
			if(ret != KErrNone)
				{
				iPhone.Close();
				iPhoneIsOpen = EFalse;
				continue;
				}
			}

		TInt lines;
		ret = iPhone.EnumerateLines(lines);
		if(ret != KErrNone)
			{
			iPhone.Close();
			iPhoneIsOpen = EFalse;
			continue;
			}

		if(lines<1)
			{
			ret = KErrEtelWrongModemType;
			iPhone.Close();
			iPhoneIsOpen = EFalse;
			continue;
			}

		TInt lineIndx;
		TBool lineVoiceFound=EFalse, lineFaxFound=EFalse, lineDataFound=EFalse;
		for(lineIndx=0; lineIndx<lines; lineIndx++)
			{
			if(iPhone.GetLineInfo(lineIndx, lineInfo) != KErrNone)
				{
				continue;
				}

			if((lineInfo.iLineCapsFlags & RLine::KCapsVoice)&&(!lineVoiceFound))
				{
				User::LeaveIfError(iLineVoice.Open(iPhone, lineInfo.iName));
				iLineIsVoiceOpen = ETrue;
				lineVoiceFound = ETrue;
				iLineVoiceName.Copy(lineInfo.iName);
				continue;
				}
			else if((lineInfo.iLineCapsFlags & RLine::KCapsData)&&(!lineDataFound))
				{
				User::LeaveIfError(iLineData.Open(iPhone, lineInfo.iName));
				iLineIsDataOpen = ETrue;
				lineDataFound = ETrue;
				continue;
				}
			else if((lineInfo.iLineCapsFlags & RLine::KCapsFax)&&(!lineFaxFound))
				{
				User::LeaveIfError(iLineFax.Open(iPhone, lineInfo.iName));
				iLineIsFaxOpen = ETrue;
				lineFaxFound = ETrue;
				continue;
				}

			}

		if(!iLineIsVoiceOpen)
			{
			ret = KErrEtelWrongModemType;
			iPhone.Close();
			iPhoneIsOpen = EFalse;
			continue;
			}

		//get TSY version
		TBool result;
		iTsyVersion = KETelExtMultimodeV3;
		User::LeaveIfError(iTelServer.IsSupportedByModule(tsyName, iTsyVersion, result));
		if(!result)
			{
			iTsyVersion = KETelExtMultimodeV2;
			User::LeaveIfError(iTelServer.IsSupportedByModule(tsyName, iTsyVersion, result));
			if(!result)
				{
				iTsyVersion = KETelExtMultimodeV1;
				User::LeaveIfError(iTelServer.IsSupportedByModule(tsyName, iTsyVersion, result));
				if(!result)
					{
					iTsyVersion = KNoMultimodeTsy;
					}
				}
			}

		//
		// A CTelephonyFunctions object is always listening for a change
		// in the line status and for an incoming call.
		// The iInternalNotifyVoiceLineStatus and iInternalNotifyIncoming
		// call objects persist throughout this object's lifetime.
		// Create the internal active objects and post the first request.
		//
		iInternalNotifyIncomingCall=CNotifyIncomingCallAct::NewL(this);
		iInternalNotifyIncomingCall->NotifyIncomingCall();
		iInternalNotifyVoiceLineStatus=CNotifyLineStatusAct::NewL(this, CTelephonyFunctions::ENotifyVoiceLineStatus, *iInternalNotifyIncomingCall);
		iInternalNotifyVoiceLineStatus->NotifyLineStatus(NULL);

		//
		// We have found a valid phone to use...
		//
		break;
		}

	//
	// ret will be KErrNone if a valid phone was found...
	//
	User::LeaveIfError(ret);
	}

/**
Cancel the outstanding async request.
*/
TInt CTelephonyFunctions::CancelAsync(CTelephony::TCancellationRequest aCancel)
	{
	switch(aCancel)
		{
		case CTelephony::EGetPhoneIdCancel:
			if((iGetPhoneId==NULL)||
				(IsRequestPending(EGetPhoneId)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetPhoneId;
				iGetPhoneId=NULL;
				}
			break;
		case CTelephony::EGetSubscriberIdCancel:
			if((iGetSubscriberId==NULL)||
				(IsRequestPending(EGetSubscriberId)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetSubscriberId;
				iGetSubscriberId=NULL;
				}
			break;
		case CTelephony::EGetIndicatorCancel:
			if((iGetIndicator==NULL)||
				(IsRequestPending(EGetIndicator)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetIndicator;
				iGetIndicator=NULL;
				}
			break;
		case CTelephony::EGetBatteryInfoCancel:
			if((iGetBatteryInfo==NULL)||
				(IsRequestPending(EGetBatteryInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetBatteryInfo;
				iGetBatteryInfo=NULL;
				}
			break;
		case CTelephony::EGetSignalStrengthCancel:
			if((iGetSignalStrength==NULL)||
				(IsRequestPending(EGetSignalStrength)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetSignalStrength;
				iGetSignalStrength=NULL;
				}
			break;
		case CTelephony::EGetLockInfoCancel:
			if((iGetIccLockInfo==NULL)||
				(IsRequestPending(EGetIccLockInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetIccLockInfo;
				iGetIccLockInfo=NULL;
				}
			break;
		case CTelephony::ESendDTMFTonesCancel:
			if((iSendDTMFTones==NULL)||
				(IsRequestPending(ESendDTMFTones)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iSendDTMFTones;
				iSendDTMFTones=NULL;
				}
			break;
		case CTelephony::EDialNewCallCancel:
			if((iDialNewCall==NULL)||
				(IsRequestPending(EDialNewCall)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iDialNewCall;
				iDialNewCall=NULL;
				}
			break;
		case CTelephony::EHoldCancel:
			if((iHold==NULL)||
				(IsRequestPending(EHold)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iHold;
				iHold=NULL;
				}
			break;
		case CTelephony::EResumeCancel:
			if((iResume==NULL)||
				(IsRequestPending(EResume)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iResume;
				iResume=NULL;
				}
			break;
		case CTelephony::ESwapCancel:
			if((iSwap==NULL)||
				(IsRequestPending(ESwap)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iSwap;
				iSwap=NULL;
				}
			break;
		case CTelephony::EHangupCancel:
			if((iHangup==NULL)||
				(IsRequestPending(EHangup)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iHangup;
				iHangup=NULL;
				}
			break;
		case CTelephony::EAnswerIncomingCallCancel:
			if((iAnswerIncomingCall==NULL)||
				(IsRequestPending(EAnswerIncomingCall)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iAnswerIncomingCall;
				iAnswerIncomingCall=NULL;
				}
			break;
		case CTelephony::EGetNetworkRegistrationStatusCancel:
			if((iGetNetworkRegistrationStatus==NULL)||
				(IsRequestPending(EGetNetworkRegistrationStatus)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetNetworkRegistrationStatus;
				iGetNetworkRegistrationStatus=NULL;
				}
			break;
		case CTelephony::EGetCurrentNetworkInfoCancel:
			if((iGetCurrentNetworkInfo==NULL)||
				(IsRequestPending(EGetCurrentNetworkInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetCurrentNetworkInfo;
				iGetCurrentNetworkInfo=NULL;
				}
			break;
		case CTelephony::EGetCurrentNetworkNameCancel:
			if((iGetCurrentNetworkName==NULL)||
				(IsRequestPending(EGetCurrentNetworkName)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetCurrentNetworkName;
				iGetCurrentNetworkName=NULL;
				}
			break;
		case CTelephony::EGetOperatorNameCancel:
			if((iGetOperatorName==NULL)||
				(IsRequestPending(EGetOperatorName)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetOperatorName;
				iGetOperatorName=NULL;
				}
			break;
		case CTelephony::EGetCallForwardingStatusCancel:
			if((iGetCFSupplementaryServiceStatus==NULL)||
				(IsRequestPending(EGetCFSupplServicesStatus)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetCFSupplementaryServiceStatus;
				iGetCFSupplementaryServiceStatus=NULL;
				}
			break;
		case CTelephony::EGetCallBarringStatusCancel:
			if((iGetCBSupplementaryServiceStatus==NULL)||
				(IsRequestPending(EGetCBSupplServicesStatus)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetCBSupplementaryServiceStatus;
				iGetCBSupplementaryServiceStatus=NULL;
				}
			break;
		case CTelephony::EGetCallWaitingStatusCancel:
			if((iGetCWSupplementaryServiceStatus==NULL)||
				(IsRequestPending(EGetCWSupplServicesStatus)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetCWSupplementaryServiceStatus;
				iGetCWSupplementaryServiceStatus=NULL;
				}
			break;
		case CTelephony::EGetIdentityServiceStatusCancel:
			if((iGetIdentityServiceStatus==NULL)||
				(IsRequestPending(EGetIdentityServiceStatus)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iGetIdentityServiceStatus;
				iGetIdentityServiceStatus=NULL;
				}
			break;
		case CTelephony::EFlightModeChangeCancel:
			if((iFlightModeChange==NULL)||
				(IsRequestPending(EFlightModeChange)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iFlightModeChange;
				iFlightModeChange=NULL;
				}
			break;
		case CTelephony::EIndicatorChangeCancel:
			if((iNotifyIndicator==NULL)||
				(IsRequestPending(ENotifyIndicator)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyIndicator;
				iNotifyIndicator=NULL;
				}
			break;
		case CTelephony::EBatteryInfoChangeCancel:
			if((iNotifyBatteryInfo==NULL)||
				(IsRequestPending(ENotifyBatteryInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyBatteryInfo;
				iNotifyBatteryInfo=NULL;
				}
			break;
		case CTelephony::ESignalStrengthChangeCancel:
			if((iNotifySignalStrength==NULL)||
				(IsRequestPending(ENotifySignalStrength)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifySignalStrength;
				iNotifySignalStrength=NULL;
				}
			break;
		case CTelephony::EPin1LockInfoChangeCancel:
			if((iNotifyIccLockInfo==NULL)||
				(IsRequestPending(ENotifyPin1LockInfo)==EFalse))
				{
				return KErrTelephonyOutOfSequence;
				}
			else if (IsRequestPending(ENotifyPin2LockInfo))
				{
				CompleteRequest(ENotifyPin1LockInfo,KErrCancel);
				}
			else
				{
				delete iNotifyIccLockInfo;
				iNotifyIccLockInfo=NULL;
				}

			break;
		case CTelephony::EPin2LockInfoChangeCancel:
			if((iNotifyIccLockInfo==NULL)||
				(IsRequestPending(ENotifyPin2LockInfo)==EFalse))
				{
				return KErrTelephonyOutOfSequence;
				}
			else if (IsRequestPending(ENotifyPin1LockInfo))
				{
				CompleteRequest(ENotifyPin2LockInfo,KErrCancel);
				}
			else
				{
				delete iNotifyIccLockInfo;
				iNotifyIccLockInfo=NULL;
				}
			break;
		case CTelephony::ENetworkRegistrationStatusChangeCancel:
			if((iNotifyNetworkRegStatus==NULL)||
				(IsRequestPending(ENotifyNetworkRegistrationStatus)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyNetworkRegStatus;
				iNotifyNetworkRegStatus=NULL;
				}
			break;
		case CTelephony::ECurrentNetworkInfoChangeCancel:
			if((iNotifyCurrentNetworkInfo==NULL)||
				(IsRequestPending(ENotifyCurrentNetworkInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyCurrentNetworkInfo;
				iNotifyCurrentNetworkInfo=NULL;
				}
			break;
		case CTelephony::EOwnedCall1StatusChangeCancel:
			if((iNotifyOwnedCall1Status==NULL)||
				(IsRequestPending(ENotifyOwnedCall1Status)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyOwnedCall1Status;
				iNotifyOwnedCall1Status=NULL;
				}
			break;
		case CTelephony::EOwnedCall2StatusChangeCancel:
			if((iNotifyOwnedCall2Status==NULL)||
				(IsRequestPending(ENotifyOwnedCall2Status)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyOwnedCall2Status;
				iNotifyOwnedCall2Status=NULL;
				}
			break;
		case CTelephony::EVoiceLineStatusChangeCancel:
			if (IsRequestPending(ENotifyVoiceLineStatus)==EFalse)
				{
				return KErrTelephonyOutOfSequence;
				}
			else
				{
				// Notifies the iInternalNotifyVoiceLineStatus active
				// object that the client is no longer interested
				// in being notified of line status changes.
				// The AO will then complete the request back to the
				// client with a status of KErrCancel.
				// The AO will still continue to monitor for line
				// status changes but now the result will not be
				// returned to the client.
				if (iInternalNotifyVoiceLineStatus)
					iInternalNotifyVoiceLineStatus->CancelFromClient();
				}
			break;
		case CTelephony::EFaxLineStatusChangeCancel:
			return KErrNotSupported;
		case CTelephony::EDataLineStatusChangeCancel:
			return KErrNotSupported;
		case CTelephony::EOwnedCall1RemotePartyInfoChangeCancel:
			if((iNotifyOwnedCall1RemoteInfo==NULL)||
				(IsRequestPending(ENotifyOwnedCall1RemoteInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyOwnedCall1RemoteInfo;
				iNotifyOwnedCall1RemoteInfo=NULL;
				}
			break;
		case CTelephony::EOwnedCall2RemotePartyInfoChangeCancel:
			if((iNotifyOwnedCall2RemoteInfo==NULL)||
				(IsRequestPending(ENotifyOwnedCall2RemoteInfo)==EFalse))
				return KErrTelephonyOutOfSequence;
			else
				{
				delete iNotifyOwnedCall2RemoteInfo;
				iNotifyOwnedCall2RemoteInfo=NULL;
				}
			break;
		default:
			return KErrNotSupported;
		}

	return KErrNone;
	}

/**
Send a notification request.

@param aRequestStatus The request status to be returned when an event
                      occurs for client notification.
@param aEvent The notification event the caller is requesting.
@param aDes Packaged data returned by the TSY when an event for notification occurs.
*/
TInt CTelephonyFunctions::NotifyChangeL(TRequestStatus& aRequestStatus,
             const CTelephony::TNotificationEvent& aEvent, TDes8& aDes)
	{
	TInt err;
	switch(aEvent)
		{
		case CTelephony::EFlightModeChange:
			err = NotifyFlightModeL(aRequestStatus, aDes);
			break;

		case CTelephony::EOwnedCall1RemotePartyInfoChange:
			err = NotifyOwnedCall1RemotePartyInfoL(aRequestStatus, aDes);
			break;

		case CTelephony::EOwnedCall2RemotePartyInfoChange:
			err = NotifyOwnedCall2RemotePartyInfoL(aRequestStatus, aDes);
			break;

		case CTelephony::EVoiceLineStatusChange:
			err = NotifyVoiceLineStatusL(aRequestStatus, aDes);
			break;

		case CTelephony::EFaxLineStatusChange:
			err = KErrNotSupported;
			break;

		case CTelephony::EDataLineStatusChange:
			err = KErrNotSupported;
			break;

		case CTelephony::EOwnedCall1StatusChange:
			err = NotifyOwnedCall1StatusL(aRequestStatus, aDes);
			break;

		case CTelephony::EOwnedCall2StatusChange:
			err = NotifyOwnedCall2StatusL(aRequestStatus, aDes);
			break;

		case CTelephony::EIndicatorChange:
			err = NotifyIndicatorL(aRequestStatus, aDes);
			break;

		case CTelephony::EPin1LockInfoChange:
		case CTelephony::EPin2LockInfoChange:
			err = NotifyPinLockInfoL(aRequestStatus, aEvent, aDes);
			break;

		case CTelephony::EBatteryInfoChange:
			err = NotifyBatteryInfoL(aRequestStatus, aDes);
			break;

		case CTelephony::ESignalStrengthChange:
			err = NotifySignalStrengthL(aRequestStatus, aDes);
			break;

		case CTelephony::ENetworkRegistrationStatusChange:
			err = NotifyNetworkRegistrationStatusL(aRequestStatus, aDes);
			break;

		case CTelephony::ECurrentNetworkInfoChange:
			err = NotifyCurrentNetworkInfoL(aRequestStatus, aDes);
			break;
		default:
			err = KErrArgument;
		}
	return err;
	}

TInt CTelephonyFunctions::NotifyFlightModeL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a Flight mode notification request
*/
	{
	if (IsRequestPending(EFlightModeChange)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::EFlightModeChange, ETrue);
		}

	if(iFlightModeChange==NULL)
		{
		iFlightModeChange=CFlightModeChangeAct::NewL(this);
		}
	iReqStatusTable[EFlightModeChange] = &aRequestStatus;

	iFlightModeChange->FlightModeChangeL(aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyOwnedCall1RemotePartyInfoL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a remote party info call 1 notification request
*/
	{
	if (IsRequestPending(ENotifyOwnedCall1RemoteInfo)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall1RemoteInfo, ETrue);
		}

	if(iCallPoolStatus[CTelephony::EISVCall1]==EUnset)
		{
		return KErrAccessDenied;
		}

	if(iNotifyOwnedCall1RemoteInfo==NULL)
		{
		iNotifyOwnedCall1RemoteInfo=CNotifyRemotePartyInfoAct::NewL(this, CTelephonyFunctions::ENotifyOwnedCall1RemoteInfo);
		}

	iReqStatusTable[ENotifyOwnedCall1RemoteInfo] = &aRequestStatus;

	iNotifyOwnedCall1RemoteInfo->NotifyRemotePartyInfo(aDes, CTelephony::EISVCall1);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyOwnedCall2RemotePartyInfoL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post aremote party info call 2 notification request
*/
	{
	if (IsRequestPending(ENotifyOwnedCall2RemoteInfo)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall2RemoteInfo, ETrue);
		}

	if(iCallPoolStatus[CTelephony::EISVCall2]==EUnset)
		{
		return KErrAccessDenied;
		}

	if(iNotifyOwnedCall2RemoteInfo==NULL)
		{
		iNotifyOwnedCall2RemoteInfo=CNotifyRemotePartyInfoAct::NewL(this, CTelephonyFunctions::ENotifyOwnedCall2RemoteInfo);
		}

	iReqStatusTable[ENotifyOwnedCall2RemoteInfo] = &aRequestStatus;

	iNotifyOwnedCall2RemoteInfo->NotifyRemotePartyInfo(aDes, CTelephony::EISVCall2);
	return KErrNone;
	}

/**
Post a voice line status notification request.

@param aRequestStatus The request status.
@param aDes Package containing TCallStatus which will store the resulting line status.
*/
TInt CTelephonyFunctions::NotifyVoiceLineStatusL(TRequestStatus& aRequestStatus, TDes8& aDes)
	{
	if (IsRequestPending(ENotifyVoiceLineStatus)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyVoiceLineStatus, ETrue);
		}
	iReqStatusTable[ENotifyVoiceLineStatus] = &aRequestStatus;

	iInternalNotifyVoiceLineStatus->NotifyLineStatus(&aDes);

	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyOwnedCall1StatusL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a call 1 status change notification request
*/
	{
	if (IsRequestPending(ENotifyOwnedCall1Status)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall1Status, ETrue);
		}
	if(iCallPoolStatus[CTelephony::EISVCall1]==EUnset)
		{
		return KErrAccessDenied;
		}

	if(iNotifyOwnedCall1Status==NULL)
		{
		iNotifyOwnedCall1Status=CNotifyCallStatusAct::NewL(this, CTelephonyFunctions::ENotifyOwnedCall1Status);
		}

	iReqStatusTable[ENotifyOwnedCall1Status] = &aRequestStatus;

	iNotifyOwnedCall1Status->NotifyCallStatus(aDes, CTelephony::EISVCall1);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyOwnedCall2StatusL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a call 2 status change notification request
*/
	{
	if (IsRequestPending(ENotifyOwnedCall2Status)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall2Status, ETrue);
		}
	if(iCallPoolStatus[CTelephony::EISVCall2]==EUnset)
		{
		return KErrAccessDenied;
		}

	if(iNotifyOwnedCall2Status==NULL)
		{
		iNotifyOwnedCall2Status=CNotifyCallStatusAct::NewL(this, CTelephonyFunctions::ENotifyOwnedCall2Status);
		}

	iReqStatusTable[ENotifyOwnedCall2Status] = &aRequestStatus;

	iNotifyOwnedCall2Status->NotifyCallStatus(aDes, CTelephony::EISVCall2);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyIndicatorL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a indicator notification request
*/
	{
	if (IsRequestPending(ENotifyIndicator)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyIndicator, ETrue);
		}

	if(iNotifyIndicator==NULL)
		{
		iNotifyIndicator=CNotifyIndicatorAct::NewL(this);
		}

	iReqStatusTable[ENotifyIndicator] = &aRequestStatus;

	iNotifyIndicator->NotifyIndicator(aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyPinLockInfoL(TRequestStatus& aRequestStatus, const CTelephony::TNotificationEvent& aEvent, TDes8& aDes)
/**
Post a pin lock change  notification request
*/
	{
	CTelephony::TIccLock lock;
	if(aEvent == CTelephony::EPin1LockInfoChange)
		{
		lock = CTelephony::ELockPin1;
		if (IsRequestPending(ENotifyPin1LockInfo))
			{
			return KErrInUse;
			}
		}
	else if(aEvent == CTelephony::EPin2LockInfoChange)
		{
		lock = CTelephony::ELockPin2;
		if (IsRequestPending(ENotifyPin2LockInfo))
			{
			return KErrInUse;
			}
		}
	else
		{
		return KErrNotSupported;
		}

	if(iNotifyIccLockInfo==NULL)
		{
		iNotifyIccLockInfo=CNotifyIccLockInfoAct::NewL(this);
		}

	if (lock == CTelephony::ELockPin1)
		{
		SetRequestPending(CTelephonyFunctions::ENotifyPin1LockInfo, ETrue);
		iReqStatusTable[ENotifyPin1LockInfo] = &aRequestStatus;
		}
	else if (lock == CTelephony::ELockPin2)
		{
		SetRequestPending(CTelephonyFunctions::ENotifyPin2LockInfo, ETrue);
		iReqStatusTable[ENotifyPin2LockInfo] = &aRequestStatus;
		}

	iNotifyIccLockInfo->NotifyIccLockInfo(lock, aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyBatteryInfoL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a battery info change notification request
*/
	{
	if (IsRequestPending(ENotifyBatteryInfo)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyBatteryInfo, ETrue);
		}

	if(iNotifyBatteryInfo==NULL)
		{
		iNotifyBatteryInfo=CNotifyBatteryInfoAct::NewL(this);
		}
	iReqStatusTable[ENotifyBatteryInfo] = &aRequestStatus;

	iNotifyBatteryInfo->NotifyBatteryInfo(aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifySignalStrengthL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a signal strength change notification request
*/
	{
	if (IsRequestPending(ENotifySignalStrength)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifySignalStrength, ETrue);
		}

	if(iNotifySignalStrength==NULL)
		{
		iNotifySignalStrength=CNotifySignalStrengthAct::NewL(this);
		}

	iReqStatusTable[ENotifySignalStrength] = &aRequestStatus;

	iNotifySignalStrength->NotifySignalStrength(aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyNetworkRegistrationStatusL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a network registration change notification request
*/
	{
	if (IsRequestPending(ENotifyNetworkRegistrationStatus)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyNetworkRegistrationStatus, ETrue);
		}

	if(iNotifyNetworkRegStatus==NULL)
		{
		iNotifyNetworkRegStatus=CNotifyNetworkRegistrationStatusAct::NewL(this);
		}
	iReqStatusTable[ENotifyNetworkRegistrationStatus] = &aRequestStatus;

	iNotifyNetworkRegStatus->NotifyNetworkRegistrationStatus(aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::NotifyCurrentNetworkInfoL(TRequestStatus& aRequestStatus, TDes8& aDes)
/**
Post a current network info change notification request
*/
	{
	if (IsRequestPending(ENotifyCurrentNetworkInfo)!=EFalse)
		{
		return KErrInUse;
		}
	else
		{
		SetRequestPending(CTelephonyFunctions::ENotifyCurrentNetworkInfo, ETrue);
		}

	if(iNotifyCurrentNetworkInfo==NULL)
		{
		iNotifyCurrentNetworkInfo=CNotifyCurrentNetworkInfoAct::NewL(this);
		}
	iReqStatusTable[CTelephonyFunctions::ENotifyCurrentNetworkInfo] = &aRequestStatus;

	iNotifyCurrentNetworkInfo->NotifyCurrentNetworkInfo(aDes);
	return KErrNone;
	}

TInt CTelephonyFunctions::GetISVCall(CTelephony::TCallId& aCallId)
/**
Return an available call ID.
Also, continue looping though other call objects for opportunity to close them if they have become idle.
*/
	{
	RMobileCall::TMobileCallStatus callStatus;
	//get first free call object
	TInt err;
	TInt ret = KErrNotFound;
	TInt foundACallId = EFalse;
	for(int k=0;k<CTelephony::EISVMaxNumOfCalls;k++)
		{
		if(iCallPoolStatus[k]!=EUnset)
			{
			err = Call((CTelephony::TCallId)k)->GetMobileCallStatus(callStatus);
			if(err==KErrNone && callStatus==RMobileCall::EStatusIdle)
				{
				if(!foundACallId)
					{
					aCallId=(CTelephony::TCallId)k;
					foundACallId = ETrue;
					ret = KErrNone;
					}
				else
					{
					CloseAndReset((CTelephony::TCallId)k);
					}
				}
			}
		else
			{
			if(!foundACallId)
				{
				aCallId=(CTelephony::TCallId)k;
				foundACallId = ETrue;
				ret = KErrNone;
				}
			}
		}
	return ret;
	}

TBool CTelephonyFunctions::IsFlightModeOn()
/**
Get Flight mode from SA
*/
	{
	TInt newPhonePowerState;
	if (iPhonePowerProperty.Get(newPhonePowerState) != KErrNone)
		newPhonePowerState = ESAPhoneOff;
	if(newPhonePowerState==ESAPhoneOn)
		{
		return EFalse;
		}
	else
		{
		return ETrue;
		}
	}

void CTelephonyFunctions::CloseAndReset(const CTelephony::TCallId aCallId)
/**
Closes the open call object and resets its pool status back to Unset
*/
	{
	//must close all outstanding notifiers invoked from this call session prior to closing the session.
	if( aCallId ==  CTelephony::EISVCall1)
		{
		if(IsRequestPending(ENotifyOwnedCall1RemoteInfo))
			{
			CancelAsync(CTelephony::EOwnedCall1RemotePartyInfoChangeCancel);
			}

		if(IsRequestPending(ENotifyOwnedCall1Status))
			{
			CancelAsync(CTelephony::EOwnedCall1StatusChangeCancel);
			}
		}
	else if(aCallId ==  CTelephony::EISVCall2)
		{
		if(IsRequestPending(ENotifyOwnedCall2RemoteInfo))
			{
			CancelAsync(CTelephony::EOwnedCall2RemotePartyInfoChangeCancel);
			}

		if(IsRequestPending(ENotifyOwnedCall2Status))
			{
			CancelAsync(CTelephony::EOwnedCall2StatusChangeCancel);
			}
		}

	//close the call session
	Call(aCallId)->Close();
	iCallPoolStatus[aCallId] = EUnset;
	}

void CTelephonyFunctions::ResetPendingNotifyRequest(CTelephony::TNotificationEvent aEvent)
/**
Reset the pending notify request flag
*/
	{
	switch(aEvent)
		{
		case CTelephony::EFlightModeChange:
			SetRequestPending(CTelephonyFunctions::EFlightModeChange, EFalse);
			break;
		case CTelephony::EOwnedCall1RemotePartyInfoChange:
			SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall1RemoteInfo, EFalse);
			break;
		case CTelephony::EOwnedCall2RemotePartyInfoChange:
			SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall2RemoteInfo, EFalse);
			break;
		case CTelephony::EVoiceLineStatusChange:
			SetRequestPending(CTelephonyFunctions::ENotifyVoiceLineStatus, EFalse);
			break;
		case CTelephony::EOwnedCall1StatusChange:
			SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall1Status, EFalse);
			break;
		case CTelephony::EOwnedCall2StatusChange:
			SetRequestPending(CTelephonyFunctions::ENotifyOwnedCall2Status, EFalse);
			break;
		case CTelephony::EIndicatorChange:
			SetRequestPending(CTelephonyFunctions::ENotifyIndicator, EFalse);
			break;
		case CTelephony::EPin1LockInfoChange:
			SetRequestPending(CTelephonyFunctions::ENotifyPin1LockInfo, EFalse);
			break;
		case CTelephony::EPin2LockInfoChange:
			SetRequestPending(CTelephonyFunctions::ENotifyPin2LockInfo, EFalse);
			break;
		case CTelephony::EBatteryInfoChange:
			SetRequestPending(CTelephonyFunctions::ENotifyBatteryInfo, EFalse);
			break;
		case CTelephony::ESignalStrengthChange:
			SetRequestPending(CTelephonyFunctions::ENotifySignalStrength, EFalse);
			break;
		case CTelephony::ENetworkRegistrationStatusChange:
			SetRequestPending(CTelephonyFunctions::ENotifyNetworkRegistrationStatus, EFalse);
			break;
		case CTelephony::ECurrentNetworkInfoChange:
			SetRequestPending(CTelephonyFunctions::ENotifyCurrentNetworkInfo, EFalse);
			break;
		default:
			break;
		}
	}

/**
Completes the request back to the client that requested it.

@param aOperation The operation that has been completed.
@param aCompleteCode The error code to be returned to the client.
*/
void CTelephonyFunctions::CompleteRequest(TOperations aOperation, TInt aCompleteCode)
	{
	if(IsRequestPending(aOperation))
		{
		User::RequestComplete(*GetRequestStatus(aOperation), aCompleteCode);
		SetRequestPending(aOperation, EFalse);
		}

	}

CAsyncRequestBaseAct::CAsyncRequestBaseAct()
	: CActive(CActive::EPriorityStandard)
	{} //NOP

CAsyncRequestBaseAct::~CAsyncRequestBaseAct()
	{} //NOP

void CAsyncRequestBaseAct::RunL()
/**
Service Completed request.

@leave	Leaves if System error.
*/
	{
	Complete();
	}