mmshplugins/mmshaoplugin/src/musvoipcallmonitor.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:12:07 +0300
branchRCL_3
changeset 22 73a1feb507fb
permissions -rw-r--r--
Revision: 201032 Kit: 201035

/*
* Copyright (c) 2005-2007 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:  Monitors the VOIP calls.
*
*/


#include <e32property.h>
#include <telephonydomainpskeys.h>

// Call Information API
#include <ccallinformation.h>

// SP Settings
#include <spdefinitions.h>
#include <spentry.h>
#include <spproperty.h>
#include <spsettings.h>

#include "musvoipcallmonitor.h"
#include "mussesseioninformationapi.h"
#include "muslogger.h"

const TUint KMusAoRemoteInfoMonitoringTimeout = 2000000; // 2 seconds
_LIT( KSipAt, "@" );

// -----------------------------------------------------------------------------
// Symbian two-phase constructor.
// -----------------------------------------------------------------------------
//
CMusVoipCallMonitor* CMusVoipCallMonitor::NewL( TName& aCallName, 
                                        MMusCallStateObserver& aCallStateObserver )
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::NewL" )
    CMusVoipCallMonitor* self = 
                new (ELeave) CMusVoipCallMonitor( aCallName, aCallStateObserver );
    CleanupStack::PushL( self );
    self->ConstructL( );
    CleanupStack::Pop( self );
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::NewL" )
    return self;
    }


// -----------------------------------------------------------------------------
// C++ destructor.
// -----------------------------------------------------------------------------
//
CMusVoipCallMonitor::~CMusVoipCallMonitor()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::~CMusVoipCallMonitor" )    
    
    ResetCallProviderName();
    
    StopRemoteInfoMonitoring();
    
    iPropertyEvent.Close();
    
    delete iGuardTimer;
    
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::~CMusVoipCallMonitor" )
    }


// -----------------------------------------------------------------------------
// C++ constructor.
// -----------------------------------------------------------------------------
//
CMusVoipCallMonitor::CMusVoipCallMonitor( TName& aCallName, 
                                        MMusCallStateObserver& aCallStateObserver ):
    CActive( CActive::EPriorityStandard ),
    iCallName ( aCallName ),
    iCallStateObserver ( aCallStateObserver ),
    iGuardTimerCallBack( GuardTimerExpired, this ) 
    {    
    CActiveScheduler::Add( this );
    
    iGuardTimerEntry.Set( iGuardTimerCallBack );
    }


// -----------------------------------------------------------------------------
// Symbian second-phase constructor.
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::ConstructL( )
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::ConstructL" ) 
    
    User::LeaveIfError( iPropertyEvent.Attach(
        KPSUidTelRemotePartyInformation,
        KTelCLINumber ) );
    
    iGuardTimer = CDeltaTimer::NewL( CActive::EPriorityStandard );
    
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::ConstructL" )
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::SetStateL( )
// Sets the call state property key.See mussesseioninformationapi.h
// Also sets the call information if call state is Connected.
// If call is connected but remote info cannot be found, information
// publishing is delayed until remote info comes available or monitoring
// for the info timeouts. In voip case, remote info should be basically
// always available, but in some cases it is not immediately available
// when call status changes to connected.
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::SetStateL(NMusSessionInformationApi::TMusCallEvent aVal)
    {    
    MUS_LOG1( "mus: [MUSAO]  -> CMusVoipCallMonitor::SetStateL, aVal %d", aVal )
    // set the call state only if the call count is one else it should be decided 
    // by conference monitor or line/tsy monitor.

    TBool delayStateChange( EFalse );
    if ( aVal == NMusSessionInformationApi::ECallConnected )
        {
        if ( !RemoteInfoExistsL() )
            {
            MonitorForRemoteInfoL();
            delayStateChange = ETrue;
            }
        }
    else
        {
        StopRemoteInfoMonitoring();
        }
    
    if ( delayStateChange )
        {
        MUS_LOG( "mus: [MUSAO]      state change delayed!" )   
        }
    else
        {
        ReportStateChangeL( aVal );
        }
    
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::SetStateL" )    
    }

///-----------------------------------------------------------------------------
// CMusVoipCallMonitor::SetCallInfoL( )
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::SetCallInfoL()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::SetCallInfoL")     
    
    // Set Call Provider Information
    TUint32 serviceId = CallServiceIdL();
    SetCallProviderInfoL( serviceId );

    HBufC* remoteUri = HBufC::NewLC( RProperty::KMaxPropertySize );
    TPtr rUri = remoteUri->Des();
    TInt err = RProperty::Get( KPSUidTelRemotePartyInformation,
                               KTelCLINumber,
                               rUri );
    
    if ( err == KErrNone && remoteUri->Des().Length() > 0 )
        {
        MUS_LOG_TDESC( "mus: [MUSAO] voip remote name: ", remoteUri->Des());
        
        // Add "sip:" prefix to remoteUri unless it already exists
        _LIT( KSipPrefix, "sip:" );
        TPtr prefix = remoteUri->Des().LeftTPtr( KSipPrefix().Length() );
        if ( prefix.Compare( KSipPrefix ) != 0 )
            {
            if ( remoteUri->Des().Length() + KSipPrefix().Length() >
                 remoteUri->Des().MaxLength() )
                {
                User::Leave( KErrOverflow );
                }
            remoteUri->Des().Insert( 0, KSipPrefix );
            }
        //if domain not present, add domain from voip profile (username)
        if ( remoteUri->Find( KSipAt ) == KErrNotFound )
            {
            rUri.Set( remoteUri->Des() );
            AddDomainFromOwnUsernameL( serviceId, rUri );
            MUS_LOG_TDESC ( "mus: [MUSAO] full voip remote name:", (*remoteUri) )
            }
        }
    else
        {
        remoteUri->Des().Zero();
        }

    User::LeaveIfError( RProperty::Set(
            NMusSessionInformationApi::KCategoryUid,
            NMusSessionInformationApi::KMusTelNumber, remoteUri->Des() ) );
    
    CleanupStack::PopAndDestroy(remoteUri);
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::SetCallInfoL" )  
    }

///-----------------------------------------------------------------------------
// CMusVoipCallMonitor::AddDomainFromOwnUsernameL( )
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::AddDomainFromOwnUsernameL( 
    TUint32 /*aServiceId*/, 
    TDes16& /*aUri*/ )
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::AddDomainFromOwnUsernameL")
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::AddDomainFromOwnUsernameL, NOT SUPPORTED")
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::AddDomainFromOwnUsernameL")
    }

///-----------------------------------------------------------------------------
// CMusVoipCallMonitor::CallServiceIdL( )
// -----------------------------------------------------------------------------
//
TUint32 CMusVoipCallMonitor::CallServiceIdL()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::CallServiceIdL")
    TUint32 serviceId( 0 );
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::CallServiceIdL, NOT SUPPORTED")
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::CallServiceIdL")
    return serviceId;
    }

///-----------------------------------------------------------------------------
// CMusVoipCallMonitor::SetCallProviderInfoL( )
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::SetCallProviderInfoL( TUint32 aServiceId )
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::SetCallProviderInfoL")
    CSPSettings* settings = CSPSettings::NewLC();    
    CSPEntry* entry = CSPEntry::NewLC();
    
    TInt errorCode = settings->FindEntryL( aServiceId, *entry );
    
    if ( errorCode == KErrNone && entry != NULL ) 
        {
        const TDesC& name = entry->GetServiceName();    
    
        MUS_LOG_TDESC ( "mus: [MUSAO]]  CallProviderName IS -->", name )
        User::LeaveIfError(RProperty::Set( 
                                        NMusSessionInformationApi::KCategoryUid,
                                        NMusSessionInformationApi::KMUSCallProvider,
                                        name));
        }
    
    CleanupStack::PopAndDestroy( entry );
    CleanupStack::PopAndDestroy( settings );
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::SetCallProviderInfoL" )  
    }


// -----------------------------------------------------------------------------
// Checks the aName is equal to this monitors name.
// @return ETrue if matches else EFalse
// -----------------------------------------------------------------------------
//
TBool CMusVoipCallMonitor::IsEqual(TName& aName)
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::IsEqual" )
    MUS_LOG_TDESC( "mus: [MUSAO]  -> aName : ", aName );
    MUS_LOG_TDESC( "mus: [MUSAO]  -> iCallName : ", iCallName );
    TBool val = EFalse ;    
    val = ( aName == iCallName );    
    MUS_LOG1( "mus: [MUSAO]  <- CMusCallMonitor::IsEqual = %d",val )
    return val;
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::RunL
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::RunL()
    {
    MUS_LOG( "mus: [MUSAO] -> CMusVoipCallMonitor::RunL" )
    
    if ( RemoteInfoExistsL() )
        {
        // Connected state reporting was delayed because not having
        // remote info, now it can be reported and monitoring is not needed anymore
        StopRemoteInfoMonitoring();
        ReportStateChangeL( NMusSessionInformationApi::ECallConnected  );
        }
    else
        {
        // resubscribe
        iPropertyEvent.Subscribe( iStatus );    
        SetActive();
        }

    MUS_LOG( "mus: [MUSAO] <- CMusVoipCallMonitor::RunL" )
    }


// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::DoCancel
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::DoCancel()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::DoCancel" )
    
    iPropertyEvent.Cancel();
    
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::DoCancel" )
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::RunError
// -----------------------------------------------------------------------------
//
TInt CMusVoipCallMonitor::RunError( TInt aError )
    {
    MUS_LOG1( "mus: [MUSAO]  -> CMusVoipCallMonitor::RunError = %d", aError )    
    if ( aError != KErrNoMemory )
        {
        aError = KErrNone;
        }
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::RunError" )
    return aError;    
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::RemoteInfoExistsL
// -----------------------------------------------------------------------------
//
TBool CMusVoipCallMonitor::RemoteInfoExistsL()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::RemoteInfoExistsL" )

    HBufC* remoteUri = HBufC::NewLC(RProperty::KMaxPropertySize);
    TPtr rUri = remoteUri->Des();
    
    TInt err = RProperty::Get( KPSUidTelRemotePartyInformation,
                                 KTelCLINumber,
                                 rUri );

    TBool remoteInfoExists( err == KErrNone && remoteUri->Des().Length() > 0 );
    CleanupStack::PopAndDestroy(remoteUri);
    
    MUS_LOG1( "mus: [MUSAO]  <- CMusVoipCallMonitor::RemoteInfoExistsL = %d", 
              remoteInfoExists )    

    return remoteInfoExists;
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::MonitorForRemoteInfoL
// Start monitoring remote info P&S key. Guard timer is started
// to prevent waiting for the infomation forever.
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::MonitorForRemoteInfoL()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::MonitorForRemoteInfoL" )
    
    if ( !IsActive() )
        {
        MUS_LOG( "mus: [MUSAO]      activate" )
        
        iGuardTimer->Remove( iGuardTimerEntry );
        TTimeIntervalMicroSeconds32 interval( KMusAoRemoteInfoMonitoringTimeout );
        iGuardTimer->Queue( interval, iGuardTimerEntry );
        
        iPropertyEvent.Subscribe( iStatus );    
        SetActive();
        }
    
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::MonitorForRemoteInfoL" )
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::MonitorForRemoteInfoL
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::StopRemoteInfoMonitoring()
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::StopRemoteInfoMonitoring" )
    
    if ( iGuardTimer )
        {
        iGuardTimer->Remove( iGuardTimerEntry );
        }
    
    Cancel();
    
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::StopRemoteInfoMonitoring" )
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::ReportStateChangeL
// -----------------------------------------------------------------------------
//
void CMusVoipCallMonitor::ReportStateChangeL( 
    NMusSessionInformationApi::TMusCallEvent aVal )
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::ReportStateChangeL" )
    
    TInt currentVal = 0;
    User::LeaveIfError(RProperty::Get( NMusSessionInformationApi::KCategoryUid,
                                       NMusSessionInformationApi::KMusCallEvent,
                                       currentVal));
    
    
    // Report only if the value changed else do not publish.
    if(currentVal != (TInt)aVal)
        {
        User::LeaveIfError(RProperty::Set( 
                                   NMusSessionInformationApi::KCategoryUid,
                                   NMusSessionInformationApi::KMusCallEvent,
                                   aVal ));    
        }        
    // When call is connected and the callcount is one, 
    // set the call informations.
    if( aVal==NMusSessionInformationApi::ECallConnected ) 
        {
        SetCallInfoL();
        }  
    
    iCallStateObserver.MusCallStateChanged();
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::ReportStateChangeL" )
    }

// -----------------------------------------------------------------------------
// CMusVoipCallMonitor::GuardTimerExpired
// If timer expired, it took too long to get remote party information via
// P&S monitoring. Because of monitoring, call connected was not yet informed,
// inform it now.
// -----------------------------------------------------------------------------
//
TInt CMusVoipCallMonitor::GuardTimerExpired( TAny* aPtr )
    {
    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::GuardTimerExpired" )
    if ( aPtr )
        {
        CMusVoipCallMonitor* self = reinterpret_cast<CMusVoipCallMonitor*>( aPtr );
        self->StopRemoteInfoMonitoring();
        TRAP_IGNORE( 
                self->ReportStateChangeL( NMusSessionInformationApi::ECallConnected ) )
        }
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::GuardTimerExpired" )
    
    return KErrNone;
    }

// --------------------------------------------------------------------------------
// CMusCallConferenceMonitor::IsDataReadyL()
// Checks if Data is ready VoIP Call.
// --------------------------------------------------------------------------------

TBool CMusVoipCallMonitor::IsDataReadyL()
    {
    //This function need to updated if some other P/S Key is published
    //to ensure correct behaviour.

    MUS_LOG( "mus: [MUSAO]  -> CMusVoipCallMonitor::IsDataReadyL" )

    // Ensure Provider Information is Availble.
    HBufC* providerInfo = HBufC::NewLC( RProperty::KMaxPropertySize );
    TPtr pInfo = providerInfo->Des();
    TInt err  = KErrNone;
    
    err = RProperty::Get( NMusSessionInformationApi::KCategoryUid,
                                NMusSessionInformationApi::KMUSCallProvider,
                                 pInfo );

    TBool providerInfoExisit ( err == KErrNone && providerInfo->Des().Length() > 0 );
    CleanupStack::PopAndDestroy( providerInfo );

    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::IsDataReadyL" )
    return !IsActive() && providerInfoExisit;
    }


// --------------------------------------------------------------------------------
// Reset the Call Provider Information. 
// --------------------------------------------------------------------------------

void CMusVoipCallMonitor::ResetCallProviderName( )
    {
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::ResetCallProviderName" )
    TInt errorCode = RProperty::Set( NMusSessionInformationApi::KCategoryUid,
                                 NMusSessionInformationApi::KMUSCallProvider,
                                 KNullDesC );

    // Error Code is just for debug only 
    MUS_LOG1( "mus: [MUSAO]  ErrorCode = %d", errorCode )
    MUS_LOG( "mus: [MUSAO]  <- CMusVoipCallMonitor::ResetCallProviderName" )
    }


// End of file