bearermanagement/S60MCPR/src/s60mpmrequests.cpp
changeset 0 5a93021fdf25
child 13 68f0c7cd80ec
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bearermanagement/S60MCPR/src/s60mpmrequests.cpp	Thu Dec 17 08:55:21 2009 +0200
@@ -0,0 +1,889 @@
+/*
+* 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 )
+    {
+    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();
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// 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()
+    {
+    //__ASSERT_ALWAYS(IsActive() || iPolicyRequests.Count() > 0,User::Panic(KNetMCprPanic, KPanicInvalidCActiveUsage));
+
+    // 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() )
+
+    // If there's a request waiting and is now completed
+    //
+    if ( iPolicyRequests.Count() > 0 && !iCommitedToDeleteItself)
+        {
+        S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RunL() Standard processing", this )
+        PolicyRequest& policydata = iPolicyRequests[0];
+        // Process the response
+        //
+        switch ( policydata.iRequestType )
+            {
+            case EPolicyRequestConnect:
+                {
+                if ( iStatus.Int() != KErrNone )
+                    {
+                    //-jl- MPM connection failed, set MPM connection required again.
+                    iMpm.Close();
+                    //-jl- 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()
+    {
+    // Not allowed! Cancel() may cause deadlock!
+    _LIT( KPanicMsg, "CMPMPolicyRequests::DoCancel" );
+    User::Panic( KPanicMsg, KErrNotSupported );
+    }
+
+
+// -----------------------------------------------------------------------------
+// CMPMPolicyRequests::RunError
+// -----------------------------------------------------------------------------
+//
+TInt CMPMPolicyRequests::RunError( TInt aError )
+    {
+    S60MCPRLOGSTRING1( "S60MCPR::CMPMPolicyRequests<%x>::RunError()", this )
+    // Connect has failed, cleanup and deliver errors
+    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();
+
+    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