Remote Call Termination Tutorial

This tutorial describes how to detect when a caller at the remote end of the connection has terminated a call with the telephony API for applications.

CTelephony represents the status of your calls with a CTelephony::TCallStatus Possible status values include Idle, Ringing, On-Hold.

  • When a call status changes from

    CTelephony::EStatusConnected to CTelephony::EStatusIdle then the call has terminated.
  • When a call status changes from

    CTelephony::EStatusHold to CTelephony::EStatusIdle then the call has terminated.

The method starts an asynchonous operation that completes when the calls's status changes. At this point, the call's new status is written into the CTelephony::TCallStatusV1Pckg.


  1. create a new instance of CTelephony.

  2. use CTelephony::NotifyChange() to detect changes in the voice line status. Pass a CTelephony::EOwnedCall1StatusChange to detect a change in call 1, and pass it CTelephony::EOwnedCall2StatusChange for call 2. Also pass an empty CTelephony::TCallStatusV1Pckg.

  3. pass the enumeration CTelephony::EOwnedCall1StatusChangeCancel to cancel the request for call1 notification and CTelephony::EOwnedCall2StatusChangeCancel for call2 notification.

Remote call termination example

#include <e32base.h>
#include <Etel3rdParty.h>

class CClientApp : public CActive
    { 

private:
    CTelephony* iTelephony;
    CTelephony::TCallId iCallId;
                CTelephony::TCallStatusV1 iCallStatusV1;
                CTelephony::TCallStatusV1Pckg iCallStatusV1Pckg;
    CTelephony::TNotificationEvent iEvent;

public:
    CClientApp(CTelephony* aTelephony, CTelephony::TCallId aCallId);
    TInt SomeFunction();

private:
    /*
       These are the pure virtual methods from CActive that  
       MUST be implemented by all active objects
       */
    void RunL();
    void DoCancel();
   };

CClientApp::CClientApp(CTelephony* aTelephony, CTelephony::TCallId aCallId)
    : CActive(EPriorityStandard),
      iTelephony(aTelephony),
      iCallId(aCallId),
      iCallStatusV1Pckg(iCallStatusV1)
    {
    //default constructor
    }

TInt CClientApp::SomeFunction()
    {
    switch(iCallId)
       {
       case CTelephony::EISVCall1:
          iEvent = CTelephony::EOwnedCall1StatusChange;
          break;

       case CTelephony::EISVCall2:
          iEvent = CTelephony::EOwnedCall2StatusChange;
          break;

       default:
          // We have not been given a valid call ID, so return an error
          return KErrArgument;
       }

    iTelephony->NotifyChange(iStatus, iEvent, iCallStatusV1Pckg);
    SetActive();
    return KErrNone;
    }

void CClientApp::RunL()
    {
    if(iStatus==KErrNone)
       {
       // The status of the call has changed.
       if(iCallStatusV1.iStatus == CTelephony::EStatusIdle)
          {
          // The call has been terminated.
          }
       else
          {
          // The call has not yet been terminated, so request notification again
          iTelephony->NotifyChange(iStatus, iEvent, iCallStatusV1Pckg);
          SetActive();
          }
       }
    }

void CClientApp::DoCancel()
    {
    CTelephony::TCancellationRequest cancelRequest;
    if(iCallId == CTelephony::EISVCall1)
       {
       cancelRequest = CTelephony::EOwnedCall1StatusChangeCancel;
       }
    else // iCallId == CTelephony::EISVCall2
       {
       cancelRequest = CTelephony::EOwnedCall2StatusChangeCancel;
       }
    iTelephony->CancelAsync(cancelRequest);
    }