phoneclientserver/phoneserver/Src/CommandHandler/CommandHandler_NoAiw/CPhSrvComHandRequestManager.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) 2003-2004 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:  Command Handler Request Manager.
*
*/



// INCLUDES
#include "CPhSrvComHandRequestManager.h"
#include "CPhSrvComHandRequest.h"
#include "CPhSrvSubSessionBase.h"
#include "PhSrvUtils.h"
#include "CPhSrvServer.h"
#include "MPhSrvEmergencyNumberManager.h"


// CONSTANTS

// The size of the Notification manager storage.
const TInt KPhSrvComHandManagerPendingCallGranularity = 4;


// ============================ MEMBER FUNCTIONS ===============================

// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::CPhSrvComHandRequestManager
// 
// Constructor.
// -----------------------------------------------------------------------------
//
CPhSrvComHandRequestManager::CPhSrvComHandRequestManager( 
    CPhSrvServer& aServer )
:   iServer( aServer )
    {
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::~CPhSrvComHandRequestManager
// 
// Destructor.
// -----------------------------------------------------------------------------
//
CPhSrvComHandRequestManager::~CPhSrvComHandRequestManager()
    {
    if ( iOutstandingComHandRequests )
        {
        iOutstandingComHandRequests->ResetAndDestroy();
        iOutstandingComHandRequests->Close();

        delete iOutstandingComHandRequests;
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::ConstructL
// 
// Complete construction.
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::ConstructL()
    {
    iOutstandingComHandRequests = new ( ELeave ) RPointerArray< 
        CPhSrvComHandRequest >( KPhSrvComHandManagerPendingCallGranularity );

    CPhSrvComHandRequest* emergencyRequest = CPhSrvComHandRequest::NewL();
    CleanupStack::PushL( emergencyRequest );
    User::LeaveIfError( 
        iOutstandingComHandRequests->Append( emergencyRequest ) );
    CleanupStack::Pop(); // emergencyRequest
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::NegotiatorRequestL
// 
// Initiate a command handler request - called by the external command handler
// interface.
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::NegotiatorRequestL( 
    const RMessage2& aMessage, 
    const TPhCltComHandCommandParameters& aParams, 
    CPhSrvSubSessionBase& aSubSession )
    {
    // If we have no registered initiator then we can't perform the request.
    if ( !iComHandInitiator )
        {
        User::Leave( KErrNotReady );
        }

    // If the request is DTMF stop, it is handled as emergency request.
    TBool isDtmfCancel = 
        ( 
            ( aParams.iCommandHandlerCommand == EPhCltCommandVts ) &&
            ( aParams.iDtmfAction == EPhCltDtmfStop ) 
        );

    // If the request is dial and the number is emergencynumber, it is
    // handled as emergency request.
    TBool isEmergencyCall = 
        ( aParams.iCommandHandlerCommand == EPhCltCommandAtd );
    if( isEmergencyCall )
        {
        isEmergencyCall = iServer.EmergencyNumberManagerL().
        EmergencyNumberManagerIsEmergencyNumberL(
            ( TDes16& ) aParams.iDialData.iTelNumber, 
            EPhCltEmergencyNumberQueryModeNormal );
        }

    // Panic if this is not the only request from this subsession.
    if ( RequestAlreadyExists( aSubSession ) )
        {
        // Cancel all ongoing requests first.
        NegotiatorRequestCancel( aSubSession );

        PhoneServerUtils::PanicClient( 
            EPhoneServerPanicTooManyRequestsOngoing,
            aMessage );
        }

    // Normal request handling, request is ok.
    else
        {
        CPhSrvComHandRequest* temp = NULL;

        // Emergency request handling.
        if ( ( isDtmfCancel || isEmergencyCall ) && 
             ( *iOutstandingComHandRequests )[0]->SubSessionHandle() == 0 )
            {
            ( *iOutstandingComHandRequests )[0]->UpdateEmergencyRequest( 
                aMessage, 
                aParams,
                aSubSession.SubSessionUniqueHandle() );
            temp = ( *iOutstandingComHandRequests )[0];
            }
        else
            {
            // Create pending request
            CPhSrvComHandRequest* request = CPhSrvComHandRequest::NewLC( 
                aMessage, 
                aParams,
                aSubSession.SubSessionUniqueHandle() );

            User::LeaveIfError( 
                iOutstandingComHandRequests->Append( request ) );
            CleanupStack::Pop( request );
            temp = request;
            }

        // Now see if the command handler notifier (initiator) is ready 
        if ( iComHandInitiator->InitiatorIsReadyToPerformRequest() )
            {
            // Ask the call initiator to perform the request 
            // (basically completes the phone app engine's outstanding 
            // ComHand Notifier request).
            iComHandInitiator->InitiatorMakeAsynchronousComHandRequest( 
                aParams );

            iActiveRequest = temp;
            }
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::NegotiatorRequestCancel
// 
// Cancel a pending command handler request.
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::NegotiatorRequestCancel( 
    CPhSrvSubSessionBase& aSubSession )
    {
    // Obtain the subsessions handle
    const TInt handle = aSubSession.SubSessionUniqueHandle();

    // Now look for any pending requests that match.
    const TInt count = iOutstandingComHandRequests->Count();
    for( TInt i = 0; i < count; i++ )
        {
        CPhSrvComHandRequest* entry = ( *iOutstandingComHandRequests )[i];
        if ( entry->SubSessionHandle() == handle )
            {
            if ( entry == iActiveRequest )
                {
                // This request is active, so inform that it is deleted.
                iActiveRequest = NULL;
                }

            // Found matching entry, so cancel it and clean up
            if ( i == 0 ) // 0 stands for emergency request
                {
                entry->Cancel();
                entry->ClearEmergencyRequest();
                }
            else
                {
                iOutstandingComHandRequests->Remove( i );
                entry->Cancel();
                delete entry;
                }
            }
        }
    UpdateQueue();
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::SetNegotiatorReadyRequestL
// 
// Updates the negotiator so that it knows if the notifier
// session is able to perform the request.
// Does not leave.
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::SetNegotiatorReadyRequestL(
    MPhSrvComHandInitiator& aInitiator )
    {
    // There mustn't already be a command handler initiator, or the existing 
    // initiator must be the same as the new one (otherwise, panic).
    __ASSERT_ALWAYS( !iComHandInitiator || &aInitiator == iComHandInitiator, 
        PhoneServerUtils::Panic( 
        EPhoneServerPanicExistingComHandInitiatorFault ) );

    // Update our pointer
    iComHandInitiator = &aInitiator;

    UpdateQueue();
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::SetNegotiatorReadyRequestCancel
// 
// Indicates that the initiator is no longer available.
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::SetNegotiatorReadyRequestCancel( 
    MPhSrvComHandInitiator& aInitiator )
    {
    if ( iComHandInitiator && iComHandInitiator == &aInitiator )
        {
        iComHandInitiator = NULL;
        }
    }

// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::SetNegotiatorAttemptedRequestResponseValue
// 
// Handle a response from the phone app engine - this is the 
// result of attempting to perform a command handler request 
// (based upon a previous clients external command handler request).
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::SetNegotiatorAttemptedRequestResponseValue( 
    TPhCltPhoneResults aResult )
    {
    // Handle response event only if there is request that waits response.
    if ( iActiveRequest )
        {
        // Get the first item in the list - this is the oldest, and has the
        // details of the command handler request we had previously initiated.
        CPhSrvComHandRequest* head = NULL;
        if ( ( *iOutstandingComHandRequests )[0]->SubSessionHandle() != 0 )
            {
            head = ( *iOutstandingComHandRequests )[0];
            }
        else
            {
            head = ( *iOutstandingComHandRequests )[1];
            }
        // Complete the request so that the external command handler client 
        // knows the result of the request attempt
        head->InformOfComHandRequestAttemptResult( aResult );

        // Delete the pending request (now that it's been processed) and tidy
        // up
        if ( ( *iOutstandingComHandRequests )[0]->SubSessionHandle() != 0 )
            {
            ( *iOutstandingComHandRequests )[0]->ClearEmergencyRequest();
            }
        else
            {
            iOutstandingComHandRequests->Remove( 1 );
            delete head;
            }

        // Reset the iActiveRequest variable.
        iActiveRequest = NULL;
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::UpdateQueue
// 
// Update the request queue.
// -----------------------------------------------------------------------------
//
void CPhSrvComHandRequestManager::UpdateQueue()
    {
    // If we have no registered initiator then we do nothing here.
    if ( iComHandInitiator )
        {
        // If we have more than one item in the queue, then we
        // try and fire of the next item here.
        if ( iComHandInitiator->InitiatorIsReadyToPerformRequest() && 
            ( iOutstandingComHandRequests->Count() > 1 ||
            ( *iOutstandingComHandRequests )[0]->SubSessionHandle() != 0 ) )
            {
            // Get the request at the top of the list (head of the queue)
            CPhSrvComHandRequest* head = NULL;
            if ( ( *iOutstandingComHandRequests )[0]->SubSessionHandle() != 0 )
                {
                head = ( *iOutstandingComHandRequests )[0];
                }
            else
                {
                head = ( *iOutstandingComHandRequests )[1];
                }

            iComHandInitiator->InitiatorMakeAsynchronousComHandRequest(
                head->ComHandParameters() );

            iActiveRequest = head;
            }
        }
    }


// -----------------------------------------------------------------------------
// CPhSrvComHandRequestManager::RequestAlreadyExists
// 
// Check whether there already is request(s) for the subsession given as 
// parameter.
// -----------------------------------------------------------------------------
//
TBool CPhSrvComHandRequestManager::RequestAlreadyExists( 
    CPhSrvSubSessionBase& aSubSession )
    {
    TBool isThereRequest = EFalse;

    // Obtain the subsessions handle
    const TInt handle = aSubSession.SubSessionUniqueHandle();

    // Look for any pending requests that match the handle.
    const TInt count = iOutstandingComHandRequests->Count();
    TInt i = 0;
    for( i = 0; i < count; i++ )
        {
        CPhSrvComHandRequest* entry = 
            ( *iOutstandingComHandRequests )[i];
        if ( entry->SubSessionHandle() == handle )
            {
            isThereRequest = ETrue;
            }
        }
    return isThereRequest;
    }

// End of File