phonesrv_plat/call_information_api/tsrc/src/MT_CallInformation.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:15:03 +0100
branchRCL_3
changeset 20 987c9837762f
parent 19 7d48bed6ce0c
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201033 Kit: 201035

/*
* Copyright (c) 2009 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:
*
*/

#include "MT_CallInformation.h"

#ifdef __WINSCW__
#include "CPhoneEngineCreator.h"
#include "CPEMessageWaiter.h"
#endif

#include <EUnitMacros.h>
#include <EUnitDecorators.h>

#include <etelmm.h>

#include <mmtsy_names.h>
#include <MCall.h>
#include <ccallinfoiter.h>
#include <CPhCltEmergencyCall.h>
#include <MPhCltEmergencyCallObserver.h>
#include <CPhCltCommandHandler.h>

//Speaking clock number when calling from NTN network.
_LIT (KNumber, "99901");     
_LIT( KEmergencyNumber, "112" );
_LIT( KOtherNumber, "99999" );

class CDialer : public CActive, protected MPhCltEmergencyCallObserver
    {
public:
    
    static CDialer* NewL( RTelServer& aTelServer ) { 
        CDialer* self = CDialer::NewLC( aTelServer );
        CleanupStack::Pop( self );
        return self;
    }
    
    static CDialer* NewLC( RTelServer& aTelServer )
        {
        CDialer* self = new( ELeave )CDialer( aTelServer );
        CleanupStack::PushL( self );
        self->ConstructL();
        return self;
        }
    
    ~CDialer() {
        if( IsActive() )
            {
            WaitForRequest();
            }
        delete iEmergency;
        delete iCmdHandler;
        delete iWait;
        iCall.Close();
        }
    
    void Dial( const TDesC& aNumber ) {
        iCall.Dial( iStatus, aNumber );
        SetActive();
        }
    
    void Dial() {
        Dial( KNumber() );
        }
    
    void DialEmergency() {
        iEmergency->DialEmergencyCallL( KEmergencyNumber );
        }
    
    void Hangup() {
        iCall.HangUp(iStatus);
        SetActive();
        }
    
    void HangupEmergencyCall()
        {
        iCmdHandler->Chup( iStatus );
        SetActive();
        }
    
    void WaitForRequest() {
        if ( IsActive() || iEmergency->IsActive() )
            {
            iWait->Start();
            }
        }
    
    void WaitL( TInt aTimeoutInSeconds ) {
        RTimer timer;
        User::LeaveIfError( timer.CreateLocal() ); 
        CleanupClosePushL( timer );        
        timer.After( iStatus, aTimeoutInSeconds * 1000000 );
        SetActive();
        WaitForRequest();
        CleanupStack::PopAndDestroy( 1, &timer ); 
        }
    
protected:
    
    void RunL() {
        if( iWait->IsStarted() )
            {
            iWait->AsyncStop();
            }
    }
    
    void DoCancel() { 
         }
    
    void HandleEmergencyDialL( const TInt /*aStatus*/ ) {
        if ( iWait->IsStarted() )
            {
            iWait->AsyncStop();
            }
    }
private:
    
    void ConstructL() { 
        TBuf<100> name;
        name.Append( KMmTsyPhoneName );
        name.Append( _L("::") );
        name.Append( KMmTsyVoice1LineName );
        name.Append( _L("::") );
        TBuf<100> callName;
        User::LeaveIfError( iCall.OpenNewCall( iTelServer, name, callName  ) );
        iEmergency = CPhCltEmergencyCall::NewL( this );
        iCmdHandler = CPhCltCommandHandler::NewL();
        iWait = new( ELeave )CActiveSchedulerWait(); 
        }
    
    CDialer( RTelServer& aTelServer ) : CActive( EPriorityStandard ), iTelServer( aTelServer ) 
        { CActiveScheduler::Add( this ); }
    
private:
    RTelServer iTelServer;
    RMobileCall iCall;
    CActiveSchedulerWait* iWait;
    CPhCltEmergencyCall* iEmergency;
    CPhCltCommandHandler* iCmdHandler;
    };

// - Construction -----------------------------------------------------------

MT_CallInformation* MT_CallInformation::NewL()
    {
    MT_CallInformation* self = MT_CallInformation::NewLC();
    CleanupStack::Pop();
    return self;
    }

MT_CallInformation* MT_CallInformation::NewLC()
    {
    MT_CallInformation* self = new( ELeave ) MT_CallInformation();
    CleanupStack::PushL( self );
    self->ConstructL();
    return self;
    }

MT_CallInformation::~MT_CallInformation()
    {
#ifdef __WINSCW__
    delete iPECreator;
#endif    
    }

MT_CallInformation::MT_CallInformation()
    {
    }

void MT_CallInformation::ConstructL()
    {
#ifdef __WINSCW__
    iPECreator = CPhoneEngineCreator::NewL();    
#endif    
    CEUnitTestSuiteClass::ConstructL();
    }


void MT_CallInformation::CallInformationChanged()
    {
    if( iWait->IsStarted() )
        {
        iWait->AsyncStop();
        }
    }


// - Test methods -----------------------------------------------------------
void MT_CallInformation::SetupL(  )
    {
    EUNIT_PRINT( _L( "MT_CallInformation::SetupL in" ));
#ifdef __WINSCW__
    iMsgWaiter = CPEMessageWaiter::NewL();
    iPhoneModel = iPECreator->CreatePhoneEngineL( *iMsgWaiter );
    
    RProperty::Define( KPSUidNetworkInfo,
                       KNWRegistrationStatus,
                       RProperty::EInt );
        
    User::LeaveIfError( RProperty::Set( KPSUidNetworkInfo,
                        KNWRegistrationStatus,
                        ENWStatusRegisteredOnHomeNetwork ) ); 
    iMsgWaiter->WaitL(1);
#endif    
    User::LeaveIfError( iTelServer.Connect() );
    iCallInfos = CCallInformation::NewL();
    iCallInfos->NotifyCallInformationChanges( *this );
    iDialer = CDialer::NewL( iTelServer );
    iWait = new( ELeave )CActiveSchedulerWait();
    EUNIT_PRINT( _L( "MT_CallInformation::SetupL out" ));
    }
    

void MT_CallInformation::Teardown(  )
    {
    EUNIT_PRINT( _L( "MT_CallInformation::Teardown in" ));
    delete iWait;
    delete iCallInfos;
    delete iDialer;
    iTelServer.Close();
#ifdef __WINSCW__    
    delete iPhoneModel;
    iPhoneModel = NULL;
    delete iMsgWaiter;
    iMsgWaiter = NULL;    
#endif   
    EUNIT_PRINT( _L( "MT_CallInformation::Teardown out" ));
    }
    

void MT_CallInformation::TestNoCallsL(  )
    {
    CCallInfoIter& infos( iCallInfos->GetCallsL() );
    EUNIT_ASSERT_EQUALS( infos.Count(), 0 );    
    }

void MT_CallInformation::TestActiveCallL()
    {
    iDialer->Dial();
    // Wait for dial to complete, timing might be different in HW and emulator
    iDialer->WaitForRequest();   
    
    CCallInformation* callInfos = CCallInformation::NewL();
    CleanupStack::PushL( callInfos );
    
    TBool dataCecked (EFalse);
    while ( !dataCecked )
        {
        CCallInfoIter& infos( callInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 1 );
        
        if ( callInfos->IsCallInState( CCPCall::EStateConnected ) == ETrue )
            {
            CCPCall::TCallState state = call.CallState();
            EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateConnected );
            dataCecked = ETrue;
            }
        else
            {
            iDialer->WaitL( 1 );            
            }
        }
    
    CleanupStack::PopAndDestroy( callInfos );
    iDialer->Hangup();
    iDialer->WaitForRequest();
    
    }

void MT_CallInformation::TestSingleCallL()
    {
    iDialer->Dial();
    EUNIT_PRINT( _L( "MT_CallInformation: Dial returns" ));
    
    EUNIT_PRINT( _L( "MT_CallInformation: wait for EStateDialling" ));
    iWait->Start(); // Wait for state notification.    
    
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateDialling );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 1 );
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), EFalse );
    }
    EUNIT_PRINT( _L( "MT_CallInformation: wait for EStateConnecting" ));
    iWait->Start();    
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateConnecting );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 1 );
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), EFalse );
    }
    EUNIT_PRINT( _L( "MT_CallInformation: wait for EStateConnected" ));
    iWait->Start();    
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateConnected );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 1 );
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), EFalse );
    }
    if( iDialer->IsActive() )
        {
        // Wait for dial to complete
        iDialer->WaitForRequest();
        EUNIT_PRINT( _L( "MT_CallInformation: Dial completes" ));
        }
    
    iDialer->Hangup();
    EUNIT_PRINT( _L( "MT_CallInformation: Hangup returns" ));

    EUNIT_PRINT( _L( "MT_CallInformation: wait for EStateDisconnecting" ));
    iWait->Start();    
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateDisconnecting );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 1 );
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), EFalse );
    }
    EUNIT_PRINT( _L( "MT_CallInformation: wait for Idle" ));
    iWait->Start();    
        {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 0 );
        }
    if ( iDialer->IsActive() )
        {
        iDialer->WaitForRequest();
        EUNIT_PRINT( _L( "MT_CallInformation: Hangup completes" ));
        }
    }

void MT_CallInformation::TestEmergencyCallL()
    {
    iDialer->DialEmergency();
    iWait->Start(); // Wait for state notification.
    
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateDialling );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 0 ); 
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), ETrue );
    }
    iWait->Start();
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateConnecting );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 0 ); 
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), ETrue );
    }
    iWait->Start();
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateConnected );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 0 ); 
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), ETrue );
    }
    if( iDialer->IsActive() )
        {
        // Wait for dial to complete
        iDialer->WaitForRequest();
        }
    iDialer->HangupEmergencyCall();

    iWait->Start();
    {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 1 );
        const MCall& call( infos.Current() );
        EUNIT_ASSERT_EQUALS( call.CallState(), CCPCall::EStateDisconnecting );
        EUNIT_ASSERT_EQUALS( call.CallType(), CCPCall::ECallTypeCSVoice );
        EUNIT_ASSERT_EQUALS( call.CallIndex(), 1 );
        EUNIT_ASSERT_EQUALS( call.ServiceId(), 0 ); 
        EUNIT_ASSERT_EQUALS( call.IsEmergency(), ETrue );
    }
    iWait->Start();
        {
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        EUNIT_ASSERT_EQUALS( infos.Count(), 0 );
        }
    if ( iDialer->IsActive() )
        {
        iDialer->WaitForRequest();
        }
    }

void MT_CallInformation::TestMultiCallL()
    {
    EUNIT_PRINT( _L( "MT_CallInformation: TestMultiCallL" ));
    iDialer->Dial();
    iDialer->WaitForRequest(); // Waits call to go connected state
    
    CDialer* otherDialer = CDialer::NewLC( iTelServer );
    otherDialer->Dial( KNumber );
    
    while ( iCallInfos->IsCallInState( CCPCall::EStateHold ) != ETrue &&
            iCallInfos->IsCallInState( CCPCall::EStateConnected ) != ETrue )
        {
        iWait->Start(); // Wait for state notifications
        CCallInfoIter& infos( iCallInfos->GetCallsL() );
        
        if( infos.Count() == 2 )
            {
            const MCall& call_1( infos.Current() );
            infos.Next();
            const MCall& call_2( infos.Current() );
         
            EUNIT_ASSERT_EQUALS( call_1.CallIndex(), 1 );
            EUNIT_ASSERT_EQUALS( call_2.CallIndex(), 2 );
            }
        }
    EUNIT_PRINT( _L( "MT_CallInformation: held and connected call exist" ));
    
    
    if ( otherDialer->IsActive() )
        {
        otherDialer->WaitForRequest();
        }
    iDialer->Hangup();
    iDialer->WaitForRequest();
    otherDialer->Hangup();
    otherDialer->WaitForRequest();
    CleanupStack::PopAndDestroy( otherDialer );
    }


void MT_CallInformation::TwoCallsExistL()
    {
    EUNIT_PRINT( _L( "MT_CallInformation: TwoCallsExistL" ));
    iDialer->Dial();
    iDialer->WaitForRequest(); // Waits call to go connected state
        
    CDialer* otherDialer = CDialer::NewLC( iTelServer );
    otherDialer->Dial( KNumber );  
    
    TBool TwoCallsExist = EFalse;
    while ( !TwoCallsExist )
        {
        iWait->Start(); // Wait for state notifications            
        CCallInfoIter& infos( iCallInfos->GetCallsL() );        
            
        TInt callIndex(1);                
        for( infos.First(); !infos.IsDone(); infos.Next() )
            {
            const MCall& call( infos.Current() );
            EUNIT_ASSERT_EQUALS( call.CallIndex(), callIndex );
            EUNIT_PRINT( _L( "MT_CallInformation: CallIndex()" ));
            callIndex++;
            if ( infos.Count() == 2 )
                {
                EUNIT_PRINT( _L( "MT_CallInformation: Count()" ));
                TwoCallsExist = ETrue;
                }
            }    
        }
    EUNIT_PRINT( _L( "MT_CallInformation: TwoCallsExist == ETrue" ));
        
    if ( otherDialer->IsActive() )
        {
        otherDialer->WaitForRequest();
        }
    iDialer->Hangup();
    iDialer->WaitForRequest();
    otherDialer->Hangup();
    otherDialer->WaitForRequest();
    CleanupStack::PopAndDestroy( otherDialer );    
    }

    

// - EUnit test table -------------------------------------------------------

EUNIT_BEGIN_TEST_TABLE(
    MT_CallInformation,
    "API tests for Call information api",
    "MODULE" )

EUNIT_TEST(
    "No calls",
    "CCallInformation",
    "GetCallsL",
    "FUNCTIONALITY",
    SetupL, TestNoCallsL, Teardown)
    
EUNIT_TEST(
    "Constructing API when call available",
    "CCallInformation",
    "GetCallsL",
    "FUNCTIONALITY",
    SetupL, TestActiveCallL, Teardown)
    
EUNIT_TEST(
    "Single call states",
    "CCallInformation",
    "GetCallsL",
    "FUNCTIONALITY",
    SetupL, TestSingleCallL, Teardown)
    
/* testing emergency call should be done only in special lab    
EUNIT_TEST(
    "Emergency call states",
    "CCallInformation",
    "GetCallsL",
    "FUNCTIONALITY",
    SetupL, TestEmergencyCallL, Teardown)
*/
    
EUNIT_TEST(
    "Multicall states",
    "CCallInformation",
    "GetCallsL",
    "FUNCTIONALITY",
    SetupL, TestMultiCallL, Teardown)
    
EUNIT_TEST(
    "Two calls exist",
    "CCallInformation",
    "GetCallsL",
    "FUNCTIONALITY",
    SetupL, TwoCallsExistL, Teardown)    

EUNIT_END_TEST_TABLE