bearermanagement/S60MCPR/src/s60mpmrequests.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Mon, 15 Mar 2010 12:42:11 +0200
branchRCL_3
changeset 13 68f0c7cd80ec
parent 0 5a93021fdf25
child 50 6a30cdd10231
permissions -rw-r--r--
Revision: 201009 Kit: 201010

/*
* Copyright (c) 2008-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: Handling of the MPM interface.
 *
*/


/**
 @file s60mpmrequests.cpp
 Handling of the MPM interface.
 */

// Project includes
#include "s60mpmrequests.h"
#include "s60mcpr.h"
#include "s60mpmnotifications.h"

// Namespace
using namespace S60MCPRMPMOperations;

// ============================ MEMBER FUNCTIONS ===============================
// -----------------------------------------------------------------------------
// CMPMPolicyRequests::NewL
// -----------------------------------------------------------------------------
//
CMPMPolicyRequests* CMPMPolicyRequests::NewL( MMPMPolicyNotificationUser& aUser )
    {
    CMPMPolicyRequests* self = new ( ELeave ) CMPMPolicyRequests();
    CleanupStack::PushL( self );
    self->ConstructL( aUser );
    CleanupStack::Pop( self );
    return self;
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::PolicyNotification
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::PolicyNotification( TMpmNotification& aNotification )
    {
    if ( !iCommitedToDeleteItself )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::PolicyNotification() forwarding call tocalling MCPR", this )
        iPolicyNotificationsUser->PolicyNotification( aNotification );
        }
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::RequestDelete
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::RequestDelete()
    {
    iCommitedToDeleteItself = ETrue;
    // Either we have pending requests
    // (we always have at least notifications if we're connected.)
    //
    if ( iPolicyRequests.Count() > 0 )
        {
        S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::RequestDelete() %d pending requests,  IssueRequest", this, iPolicyRequests.Count() )
        IssueRequest();
        }
    // Or we are free to delete this.
    //
    else
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RequestDelete() IssueDeleteRequest", this )
        IssueDeleteRequest();
        }
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::CMPMPolicyRequests
// -----------------------------------------------------------------------------
//
CMPMPolicyRequests::CMPMPolicyRequests() :
                                    CActive( EPriorityStandard ),
                                    iCommitedToDeleteItself( EFalse ),
                                    iReconnectTimerRunning( EFalse ),
                                    iReconnectTimeout( KMPMInitialReconnectTimeout )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CMPMPolicyRequests()", this )
    CActiveScheduler::Add( this );
    iConnId = (TConnectionId)this;
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::~CMPMPolicyRequests
// -----------------------------------------------------------------------------
//
CMPMPolicyRequests::~CMPMPolicyRequests()
    {
    //LOG( ESockLog::Printf(KESockMetaConnectionTag, _L8("CMPMPolicyRequests<%x>::~CMPMPolicyRequests"), this ); )
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::~CMPMPolicyRequests()", this )

    __ASSERT_ALWAYS(!IsActive(), User::Panic(KS60MCprPanic, KPanicInvalidCActiveUsage));
    __ASSERT_DEBUG(iPolicyRequests.Count() == 0, User::Panic(KS60MCprPanic, KPanicInvalidCActiveUsage));

    // Clean up all objects in the list
    // Normally there shouldn't be any.
    TInt count = iPolicyRequests.Count();
    for (TInt i = 0; i < count; i++)
        {
        S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::~CMPMPolicyRequests() deleting request %d", 
                           this, (TInt)iPolicyRequests[i].iRequestType )
        // Delete prefs
        delete iPolicyRequests[i].iConnPref;
        delete iPolicyRequests[i].iPolicyPref;
        // PolicyRequest owns this class and can delete it.
        // MCPR must have cancelled its activity when this happens.
        delete iPolicyRequests[i].iUser;
        }

    // Reset the array.
    iPolicyRequests.Close();

    // Close the MPM handle 
    if ( iMpm.Connected() )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::~CMPMPolicyRequests() closing MPM session", this )
        iMpm.Close();
        }
    
    if ( iReconnectTimerRunning )
        {
        Cancel();
        iReconnectTimer.Close();
        }
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ConstructL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ConstructL( MMPMPolicyNotificationUser& aUser )
    {
    // Force MPMNotifications to go through CMPMPolicyRequests
    iPolicyNotificationsUser = &aUser;
    iPolicyNotifications = CMPMPolicyNotifications::NewL( *(MMPMPolicyNotificationUser*)this, 
                                                          iMpm );
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::ConstructL() using iPolicyNotifications<%x>", 
                       this, iPolicyNotifications )
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::IAPConnectionStartedL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::IAPConnectionStartedL( const TUint32 aIapId )
    {
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::IAPConnectionStartedL() IAP %d", this, aIapId )
    CreatePolicyRequestL( EPolicyRequestIAPConnectionStarted, aIapId );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::IAPConnectionStoppedL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::IAPConnectionStoppedL( const TUint32 aIapId )
    {
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::IAPConnectionStoppedL() IAP %d", this, aIapId )
    CreatePolicyRequestL( EPolicyRequestIAPConnectionStopped, aIapId );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationJoinsConnectionL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationJoinsConnectionL( const TUint32 aIapId )
    {
    // Can't use CreatePolicyRequest() here because this could
    // be the first call to MPM.

    PolicyRequest policydata = PolicyRequest();
    policydata.iRequestType = EPolicyRequestApplicationJoinsConnection;
    policydata.iConnId      = iConnId;
    policydata.iIapId       = aIapId;

    // Add request to array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationJoinsConnectionL() IAP %d", this, aIapId )
    
    // Submit it.
    IssueRequest();
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationLeavesConnectionL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationLeavesConnectionL( const TUint32 aIapId )
    {
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationLeavesConnectionL() IAP %d", this, aIapId )
    CreatePolicyRequestL( EPolicyRequestApplicationLeavesConnection, aIapId );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationLeavesConnectionL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationConnectionEndsL()
    {
    // This is only a notification. Thus, if the session doesn't exist, don't create one
    if ( !iMpm.Connected() )
        {
        return;
        }

    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationConnectionEndsL() IAP %d", this )
    
    PolicyRequest policydata = PolicyRequest();
    policydata.iRequestType  = EPolicyRequestApplicationConnectionEnds;
    policydata.iConnId       = iConnId;
//    policydata.iIapId               = aIapId;
    // Nothing to cleanup so it's ok to Leave in AppendL

    // Add request to array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    // Submit it.
    IssueRequest();
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::RegisterPreferredIAPNotificationL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::RegisterPreferredIAPNotificationL()
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RegisterPreferredIAPNotificationL()", this )

    PolicyRequest policydata = PolicyRequest();
    
    policydata.iRequestType  = EPolicyRequestRegisterPrefIAPNotif;
    policydata.iConnId       = iConnId;

    // Add request to array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    // Submit it.
    IssueRequest();
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::UnregisterPreferredIAPNotificationL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::UnregisterPreferredIAPNotificationL()
    {
    // Sanity check that we're still in business. 
    if ( !iMpm.Connected() )
        {
        return;
        }

    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::UnregisterPreferredIAPNotificationL()", this )

    PolicyRequest policydata = PolicyRequest();
    
    policydata.iRequestType  = EPolicyRequestUnregisterPrefIAPNotif;
    policydata.iConnId       = iConnId;

    // Add request to array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    // Submit it.
    IssueRequest();
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationIgnoredTheCarrierL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationIgnoredTheCarrierL( const TUint32 aIapId )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationIgnoredTheCarrierL()", this )
    CreatePolicyRequestL( EPolicyRequestApplicationIgnoredTheCarrier, aIapId );
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationMigratesToCarrierL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationMigratesToCarrierL( const TUint32 aIapId )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationMigratesToCarrierL()", this )
    CreatePolicyRequestL( EPolicyRequestApplicationMigratesToCarrier, aIapId );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationRejectedTheCarrierL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationRejectedTheCarrierL( const TUint32 aIapId )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationRejectedTheCarrierL()", this )
    CreatePolicyRequestL( EPolicyRequestApplicationRejectedTheCarrier, aIapId );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ApplicationAcceptedTheCarrierL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ApplicationAcceptedTheCarrierL( const TUint32 aIapId)
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ApplicationAcceptedTheCarrierL()", this )
    CreatePolicyRequestL( EPolicyRequestApplicationAcceptedTheCarrier, aIapId );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ChooseBestIAP
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ChooseBestIAPL( TConnPref*             aConnPref,
                                        const TUid&             aAppUid,
                                        TConnPref*              aPolicyPref,
                                        MMPMPolicyRequestsUser* aUser )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ChooseBestIAPL()", this )
    
    // Define policydata
    PolicyRequest policydata = PolicyRequest();
    policydata.iRequestType         = EPolicyRequestChooseBestIAP;
    policydata.iConnId              = iConnId;
    policydata.iAppUid              = aAppUid;

    // Heap allocated objects
    policydata.iConnPref            = aConnPref;
    policydata.iPolicyPref          = aPolicyPref;
    policydata.iUser                = aUser;

    // Nothing to cleanup so it's ok to Leave in AppendL
    // Heap allocated objects are on callers responsibility if we Leave.
    
    // Add it to the array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    IssueRequest();
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::CancelReselectBestIAP()
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::CancelReselectBestIAP()
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CancelReselectBestIAPL()", this )
    ASSERT( iPolicyRequests.Count() > 0 );
    CancelRequest( EMPMReselectBestIAP );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::CancelChooseBestIAPL()
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::CancelChooseBestIAPL()
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CancelChooseBestIAPL()", this )
    ASSERT( iPolicyRequests.Count() > 0 );
    CancelRequest( EMPMChooseBestIAP );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::CancelProcessError()
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::CancelProcessError()
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CancelProcessErrorL()", this )
    ASSERT( iPolicyRequests.Count() > 0 );
    CancelRequest( EMPMProcessError );
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ReselectIAPL()
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ReselectIAPL( TConnPref* aPolicyPref,
                                       MMPMPolicyRequestsUser* aUser )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::ReselectIAPL()", this )
    //Call MPM to get the list of potential IAPs for the connection
    //
    PolicyRequest policydata = PolicyRequest();

    policydata.iRequestType = EPolicyRequestReselectBestIAP;
    policydata.iConnId      = iConnId;
    policydata.iPolicyPref  = aPolicyPref;
    policydata.iUser        = aUser;

    // Add it to the array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    IssueRequest();
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::ProcessErrorL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::ProcessErrorL( TInt& anError,
                                        MMPMPolicyRequestsUser* aUser )
    {
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::ProcessErrorL() %d", this, anError )

    // insert into array of pending policy request
    PolicyRequest policydata = PolicyRequest();

    policydata.iRequestType = EPolicyRequestProcessError;
    policydata.iError       = anError;
    policydata.iConnId      = iConnId;
    policydata.iUser        = aUser;

    // Add it to the array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    IssueRequest();
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::IssueDeleteRequest
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::IssueDeleteRequest()
    {
    ASSERT( !IsActive() );
    // Always cancel & delete policynotifications.
    if ( iMpm.Connected() && iPolicyNotifications->IsActive() )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::IssueDeleteRequest() Asynch", this )
        iPolicyNotifications->CancelRequestAndDestroyD( &iStatus );
        iPolicyNotifications = NULL;
        SetActive();
        }
    else if ( iPolicyNotifications )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::IssueDeleteRequest() Immediate", this )
        iPolicyNotifications->CancelRequestAndDestroyD();
        iPolicyNotifications = NULL;
        delete this;
        }
    else
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::IssueDeleteRequest() Invalid state", this )
        }
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::IssueRequest
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::IssueRequest()
    {
    // If we have a pending request, back off.
    //
    if ( IsActive() || iPolicyRequests.Count() == 0 )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::IssueRequest() Unnecessary call, back off", this )
        return;
        }
    
    if ( !iMpm.Connected() )
        {
        PolicyRequest policydata = PolicyRequest();
        policydata.iRequestType  = EPolicyRequestConnect;
        // OK because default granularity is 8 and this is done when first request arrives.
        iPolicyRequests.Insert(policydata, 0);
        }

    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::IssueRequest() iRequestType %d", this, (TInt)iPolicyRequests[0].iRequestType )
    //
    // else we submit a new one.
    switch ( iPolicyRequests[0].iRequestType )
        {
        case EPolicyRequestConnect:
            {
            iMpm.Connect( iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestChooseBestIAP:
            {
            //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("\tcall MPM ChooseBestIAP")));
            iMpm.ChooseBestIAP( ( *iPolicyRequests[0].iConnPref ),
                                iPolicyRequests[0].iConnId,
                                iPolicyRequests[0].iAppUid,
                                ( *iPolicyRequests[0].iPolicyPref ),
                                iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestReselectBestIAP:
            {
            iMpm.ReselectBestIAP( iPolicyRequests[0].iConnId,
                                  ( *iPolicyRequests[0].iPolicyPref ),
                                  iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestIAPConnectionStarted:
            {
            iMpm.IAPConnectionStarted( iPolicyRequests[0].iIapId,
                                       iPolicyRequests[0].iConnId,
                                       iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestIAPConnectionStopped:
            {
            iMpm.IAPConnectionStopped( iPolicyRequests[0].iIapId,
                                       iPolicyRequests[0].iConnId,
                                       iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationJoinsConnection:
            {
            iMpm.ApplicationJoinsConnection( iPolicyRequests[0].iIapId,
                                             iPolicyRequests[0].iConnId,
                                             iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationLeavesConnection:
            {
            iMpm.ApplicationLeavesConnection( iPolicyRequests[0].iIapId,
                                              iPolicyRequests[0].iConnId,
                                              iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationConnectionEnds:
            {
            iMpm.ApplicationConnectionEnds( iPolicyRequests[0].iConnId,
                                            iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestRegisterPrefIAPNotif:
            {
            iMpm.RegisterPrefIAPNotif( iPolicyRequests[0].iConnId,
                                       iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestUnregisterPrefIAPNotif:
            {
            iMpm.UnregisterPrefIAPNotif( iPolicyRequests[0].iConnId,
                                         iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationIgnoredTheCarrier:
            {
            iMpm.ApplicationIgnoredTheCarrier( iPolicyRequests[0].iIapId,
                                               iPolicyRequests[0].iConnId,
                                               iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationMigratesToCarrier:
            {
            iMpm.ApplicationMigratesToCarrier( iPolicyRequests[0].iIapId,
                                               iPolicyRequests[0].iConnId,
                                               iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationRejectedTheCarrier:
            {
            iMpm.ApplicationRejectedTheCarrier( iPolicyRequests[0].iIapId,
                                                iPolicyRequests[0].iConnId,
                                                iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestApplicationAcceptedTheCarrier:
            {
            iMpm.ApplicationAcceptedTheCarrier( iPolicyRequests[0].iIapId,
                                                iPolicyRequests[0].iConnId,
                                                iStatus );
            SetActive();
            break;
            }
        case EPolicyRequestProcessError:
            {
            //LOG(ESockLog::Printf(KESockMetaConnectionTag, _L8("\tcall MPM ProcessError")));
            iMpm.ProcessError( iPolicyRequests[0].iError, 
                               iPolicyRequests[0].iConnId,
                               iPolicyRequests[0].iNeededAction, 
                               iStatus );
            SetActive();
            break;
            }
        default:
            {
#ifdef _DEBUG
            // In debug builds, panic
            _LIT( KPanicMsg, "CMPMPolicyRequests::IssueRequestL: Invalid case" );
            User::Panic( KPanicMsg, KErrNotSupported );
#endif
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CMPMPolicyRequests::RunL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::RunL()
    {
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::RunL() iStatus %d", this, iStatus.Int() )

    // At first, check if this is a timer activity
    if ( iReconnectTimerRunning )
        {
        // iMpm.Connect() failed at least once. Timeout has expired, try again.
#ifdef _DEBUG    
        TBool isConnected = iMpm.Connected();
        __ASSERT_DEBUG( !isConnected,  User::Panic( KS60MCprPanic, KErrGeneral ) );
#endif
        iReconnectTimerRunning = EFalse;
        iReconnectTimer.Close();
        iMpm.Connect( iStatus );
        SetActive();
        } 
    else if ( iPolicyRequests.Count() > 0 && !iCommitedToDeleteItself)
        {
        // there's a request waiting and is now completed
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RunL() Standard processing", this )
        PolicyRequest& policydata = iPolicyRequests[0];
        // Process the response
        //
        switch ( policydata.iRequestType )
            {
            case EPolicyRequestConnect:
                {
                if ( iStatus.Int() != KErrNone )
                    {
                    // MPM connection failed, set MPM connection required again.
                    iMpm.Close();
                    // Go to RunError
                    User::Leave( iStatus.Int() );
                    }
                else
                    {
                    // Otherwise MPM ok and start listening for notifications
                    iPolicyNotifications->Activate();
                    }
                break;
                }
            case EPolicyRequestProcessError:
            case EPolicyRequestChooseBestIAP:
            case EPolicyRequestReselectBestIAP:
                {
                if ( policydata.iUser )
                    {
                    // ChooseBest IAP is completed by iUser.
                    //
                    policydata.iStatus = iStatus.Int();
                    policydata.iUser->PolicyResponse( policydata );
                    }
                break;
                }
            // With these messages we ignore the result.
            case EPolicyRequestRegisterPrefIAPNotif:
            case EPolicyRequestUnregisterPrefIAPNotif:
            case EPolicyRequestApplicationIgnoredTheCarrier:
            case EPolicyRequestApplicationMigratesToCarrier:
            case EPolicyRequestApplicationRejectedTheCarrier:
            case EPolicyRequestApplicationAcceptedTheCarrier:
            case EPolicyRequestIAPConnectionStarted:
            case EPolicyRequestIAPConnectionStopped:
            case EPolicyRequestApplicationJoinsConnection:
            case EPolicyRequestApplicationLeavesConnection:
            case EPolicyRequestApplicationConnectionEnds:
                {
#ifdef _DEBUG                
                if ( iStatus.Int() != KErrNone )
                    {
                    S60MCPRLOGSTRING3( "S60MCPR::CMPMPolicyRequests<%x>::RunL() Request %d failed %d", 
                                       this, (TInt) policydata.iRequestType, iStatus.Int() )
                    }
#endif // _DEBUG
                break;
                }
            default:
                {
#ifdef _DEBUG
                // In debug builds, panic
                _LIT( KPanicMsg, "CMPMPolicyRequests::RunL: Invalid case" );
                User::Panic( KPanicMsg, KErrNotSupported );
#endif
                break;
                }
            }
        // Then cleanup
        //
        policydata.Cleanup();
        iPolicyRequests.Remove( 0 ); // remove request from the array
        // And if there are still pending request, cotinue with the next one
        //
        if ( iPolicyRequests.Count() > 0 )
             {
             IssueRequest();
             }
        }
    // We have pending requests but we have commited to delete itself
    // 
    else if ( iPolicyRequests.Count() > 0 && iCommitedToDeleteItself )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RunL() Processing pending requests before delete", this )
        // Submit pending requests to keep MPM in consistent state.
        // First cleanup the old one
        //
        iPolicyRequests[0].Cleanup();
        iPolicyRequests.Remove( 0 ); // remove request from the array
        // And if there are still pending request, cotinue with the next one
        //
        if ( iPolicyRequests.Count() > 0 )
            {
            IssueRequest();
            }
        // In this case we've processed everything and can close.
        //
        else
            {
            IssueDeleteRequest();
            }
        }
    else if ( iPolicyRequests.Count() == 0 && iCommitedToDeleteItself )
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RunL() About to delete itself", this )
        ASSERT( !iPolicyNotifications );
        delete this;
        }
    else
        {
        // INVALID STATE
#ifdef _DEBUG
        // In debug builds, panic
        _LIT( KPanicMsg, "CMPMPolicyRequests::RunL: Invalid state" );
        User::Panic( KPanicMsg, KErrNotSupported );
#endif
        // Even still, make sure we don't leak memory 
        //
        iPolicyNotifications->CancelRequestAndDestroyD();
        iPolicyNotifications = NULL;
        delete this;
        }
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::DoCancel
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::DoCancel()
    {
    _LIT( KPanicMsg, "CMPMPolicyRequests::DoCancel" );
    if ( iReconnectTimerRunning )
        {
        iReconnectTimer.Cancel();
        }
    else
        {
        // Not allowed! Cancel() may cause deadlock!
        User::Panic( KPanicMsg, KErrNotSupported );
        }
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::RunError
// -----------------------------------------------------------------------------
//
TInt CMPMPolicyRequests::RunError( TInt aError )
    {
    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RunError()", this )
    // Connect has failed, cleanup and deliver errors
    if ( aError != KErrServerBusy || iReconnectTimeout >= KMPMMaxReconnectTimeout )
        {
        TInt count = iPolicyRequests.Count();
        for ( TInt i = 0; i < count; i++ )
            {
            if ( iPolicyRequests[i].iUser )
                {
                S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::RunError() Sending error %d in PolicyResponse", this, aError )
                iPolicyRequests[i].iStatus = aError;
                iPolicyRequests[i].iUser->PolicyResponse( iPolicyRequests[i] );
                }
            
            // Delete prefs
            iPolicyRequests[i].Cleanup();
            }
        iPolicyRequests.Reset();
        }
    else
        {
        // KErrServerBusy received, try reconnecting after a brief pause
        iReconnectTimeout *= KMPMReconnectTimeoutMultiplier;
        TTimeIntervalMicroSeconds32 timeout( iReconnectTimeout );
        iReconnectTimer.CreateLocal();
        iReconnectTimer.After( iStatus, timeout );
        iReconnectTimerRunning = ETrue;
        SetActive();
        }

    return KErrNone;
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::CancelRequest
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::CancelRequest( TMpmAsynchCodes aRequestCode )
    {
    // Semantics of asynchronous cancellations:
    //
    // The biggest difference is that asynchronous cancellation will
    // cause RunL() -call for original request. Because of this the 
    // PolicyResponse() calls must be prevented.
    //
    // Asynch Cancellation cannot be queued along with the other requests.
    // Precondition for cancellation call to MPM is that there's an active request
    // and that request code matches to the given parameter.
    //
    // Cancellation of the unsent requests is simple. Just remove it from the queue.
    //
    // Asynchronous cancellation adds message to MPMServer's IPC queue but since we
    // queue all requests we can safely always call the SendCancelRequest()
    
    // If the cancelled request is the active one.
    //
    S60MCPRLOGSTRING2( "S60MCPR::CMPMPolicyRequests<%x>::CancelRequest() %d", this, (TInt)aRequestCode )
    if ( iPolicyRequests[0].iRequestType == aRequestCode )
        {
        // Cancel the query if active
        //
        if ( IsActive() )
            {
            S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CancelRequest() Cancelling active request", this )
#ifdef _DEBUG
            TInt ret = iMpm.SendCancelRequest( aRequestCode );
#else
            iMpm.SendCancelRequest( aRequestCode );
#endif
            __ASSERT_DEBUG( ret == KErrNone,  User::Panic( KS60MCprPanic, ret ) );
            // Prevent the callback.
            iPolicyRequests[0].Cancel();
            }
        // Completed or not started. Just remove the request.
        //
        else
            {
            S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CancelRequest() Cancelling non-active request", this )
            iPolicyRequests[0].Cleanup();
            // remove it.
            iPolicyRequests.Remove(0);
            }
        }
    // Else we need to find it from the queue
    //
    else 
        {
        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::CancelRequest() Cancelling pending request", this )
        TInt count = iPolicyRequests.Count();
        for (TInt i = 1; i < count; i++)
            {
            if ( iPolicyRequests[i].iRequestType == aRequestCode )
                {
                // Cancellable request found, clean it up
                iPolicyRequests[i].Cleanup();
                // remove it.
                iPolicyRequests.Remove(i);
                break; // first occurence is enough.
                }
            }
        }
    }


// -----------------------------------------------------------------------------
// CMPMPolicyRequests::CreatePolicyRequestL
// -----------------------------------------------------------------------------
//
void CMPMPolicyRequests::CreatePolicyRequestL( TPolicyServerOperations aRequestCode, 
                                               const TUint32& aIapId )
    {
    // Sanity check that we're still in business. 
    if ( !iMpm.Connected() )
        {
        return;
        }

    PolicyRequest policydata = PolicyRequest();
    
    policydata.iRequestType         = aRequestCode;
    policydata.iConnId              = iConnId;
    policydata.iIapId               = aIapId;

    // Add request to array of uncompleted requests
    iPolicyRequests.AppendL( policydata );

    // Submit it.
    IssueRequest();
    }

// End of file