bearermanagement/mpm/src/mpmconnmonreqs.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 13 Oct 2010 14:59:48 +0300
branchRCL_3
changeset 69 cf1b3ddbe9a1
parent 62 bb1f80fb7db2
permissions -rw-r--r--
Revision: 201039 Kit: 201041

/*
* Copyright (c) 2005-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: MPM ConnMon request handling
*
*/

/**
@file mpmconnmonreqs.cpp
Mobility Policy Manager ConnMon request handling.
*/

// INCLUDE FILES
#include "mpmconnmonreqs.h"
#include "mpmlogger.h"
#include "mpmserversession.h"
#include "mpmiapselection.h"

// ============================= LOCAL FUNCTIONS ===============================

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

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::NewL
// -----------------------------------------------------------------------------
//
CMPMConnMonReqs* CMPMConnMonReqs::NewL(CMPMConnMonEvents& aParent,
                                       RConnectionMonitor& aConnMon,
                                       TUint aConnId, 
                                       CMPMServerSession* aSession )
    {
    CMPMConnMonReqs* self = new (ELeave) CMPMConnMonReqs(
                                aParent, aConnMon, aConnId, aSession );
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop(self);
    return self;
    }


// -----------------------------------------------------------------------------
// CMPMConnMonReqs::CMPMConnMonReqs
// -----------------------------------------------------------------------------
//
CMPMConnMonReqs::CMPMConnMonReqs(CMPMConnMonEvents& aParent,
                                 RConnectionMonitor& aConnMon,
                                 TUint aConnId, 
                                 CMPMServerSession* aSession )
    : CActive(CActive::EPriorityStandard), 
      iParent(aParent), 
      iConnMon(aConnMon), 
      iConnId(aConnId), 
      iSession(aSession), 
      iWlanScanCallback( EWlanScanCallbackNone ), 
      iConnectionCount( 0 )
    {
    }


// -----------------------------------------------------------------------------
// CMPMConnMonReqs::~CMPMConnMonReqs
// -----------------------------------------------------------------------------
//
CMPMConnMonReqs::~CMPMConnMonReqs()
    {
    MPMLOGSTRING( "CMPMConnMonReqs::~CMPMConnMonReqs" )
    Cancel();
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::ConstructL
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::ConstructL()
    {
    MPMLOGSTRING( "CMPMConnMonReqs::ConstructL" )
    CActiveScheduler::Add(this);
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::AvailableIapsSync
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::AvailableIapsSync()
    {
    MPMLOGSTRING( "CMPMConnMonReqs::AvailableIapsSync" )
    iNextState = EGetIapAvailState;
    iLastCancelCode = EConnMonGetPckgAttribute;
    iConnMon.GetPckgAttribute( EBearerIdAll, 0, KIapAvailability,
                               iIapBuf, iStatus);
    SetActive();
    
    // Since CodeScanner does not recognise method IsStarted(), 
    // it claims that here is a problem:
    // 
    // Problem: Active object called without checking 
    // whether it is active or cancelling it first.
    // 
    if ( !iActiveSchedulerWait.IsStarted() )
        {
        iActiveSchedulerWait.Start();
        }
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::RefreshAvailableIAPs
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::RefreshAvailableIAPs( TWlanScanCallback aCallback, 
                                            TInt aForceRefreshIntervalSeconds )
    {
    MPMLOGSTRING2( "CMPMConnMonReqs::RefreshAvailableIAPs callback %d", aCallback )
    // set the type of callback to determine afterwards which function to call
    iWlanScanCallback = aCallback;
    iNextState      = EScanWLANNetworksState;   // Default value
    iLastCancelCode = EConnMonGetPckgAttribute;

    TTime time;
    time.UniversalTime();
    TTimeIntervalSeconds interval( 0 );
    
    TInt ret( KErrNone );
        
    // Calculate the elapsed time.
    ret = time.SecondsFrom( iParent.GetIAPRefreshTime(), interval );
    if ( ret != KErrNone )
        {
        MPMLOGSTRING2( "CMPMConnMonReqs::RefreshAvailableIAPs interval error %d ", ret )
        // problem with interval, force iapavailability.
        interval = 0;
        aForceRefreshIntervalSeconds = 0;
        }
    // Default behavior is to query KIapAvailability from ConnMon always
    // or if the availability information has aged at least aForceRefreshIntervalSeconds
    //
    if ( aForceRefreshIntervalSeconds == 0 || 
       ( interval.Int() >= aForceRefreshIntervalSeconds ) )
        {
        // Discard availability notifications from Connection Monitor 
        // until MPM initiated WLAN scan request has completed.
        // 
        iParent.EnableDiscarding();

        MPMLOGSTRING2( "CMPMConnMonReqs::RefreshAvailableIAPs interval %d, executing scan", 
            interval.Int() )
        iConnMon.GetPckgAttribute( EBearerIdAll, 0, KIapAvailability,
                                   iIapBuf, iStatus );
        SetActive();
        }
    // With consecutive calls we allow MPM to use cached value.
    //
    else
        {
        MPMLOGSTRING2( "CMPMConnMonReqs::RefreshAvailableIAPs interval %d, using cached value",
            interval.Int() )

        // iIapBuf is empty, thus we need a new state.
        iNextState = EScanWLANNetworksStateCached;
        TRequestStatus* statusPtr;
        statusPtr = &iStatus;
        // We can just complete the request.
        SetActive();
        User::RequestComplete( statusPtr, KErrNone );
        }
    }


// -----------------------------------------------------------------------------
// CMPMConnMonReqs::CompareConnIds
// -----------------------------------------------------------------------------
//
TBool CMPMConnMonReqs::CompareConnIds( const CMPMConnMonReqs& aReq1,
                                       const CMPMConnMonReqs& aReq2 )
    {
    if ( aReq1.iConnId == aReq2.iConnId )
        {
        return ETrue;
        }
    else
        {
        return EFalse;
        }
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::MyCancel()
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::MyCancel()
    {
    // Handle cancellation here.
    MPMLOGSTRING( "CMPMConnMonReqs::MyCancel()" )
    ASSERT( iNextState != EGetIapAvailState && iNextState != EObsolete );
    // Allow the availability update when the connmon request completes.
    iNextState = EObsolete;
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::ErrorCallbackL()
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::ErrorCallbackL( TInt aStatus )
    {
    switch ( iNextState )
        {
        case EGetIapAvailState:
        case EGetConnectionCountState: 
            {
            MPMLOGSTRING( "CMPMConnMonReqs::ErrorCallbackL: EGetIapAvailState failed" )
            if ( iActiveSchedulerWait.IsStarted() )
                {
                iActiveSchedulerWait.AsyncStop();
                }
            break;
            }
        case EScanWLANNetworksState:
        case EScanWLANNetworksStateCached:
            {
            MPMLOGSTRING( "CMPMConnMonReqs::ErrorCallbackL: EScanWLANNetworksState failed" )
            ASSERT( iSession );

            // Disable discarding availability notifications from Connection Monitor.
            // 
            iParent.DisableDiscarding(); 

            // check which callback function to use and continue
            // handling the request if possible.
            // 
            if( iWlanScanCallback == EWlanScanCallbackChooseIap )
                {
                iSession->IapSelectionL()->ChooseIapWLANScanCompletedL( aStatus );
                }
            else if( iWlanScanCallback == EWlanScanCallbackProcessErr )
                {
                iSession->ProcessErrorWlanScanCompletedL();
                }
            else if( iWlanScanCallback == EWlanScanCallbackCarrierRejected )
                {
                // No fresh IAP info available but try to select new IAP
                // based on whatever existing info there is
                // 
                iSession->CompleteCarrierRejected();
                }
            else if( iWlanScanCallback == EWlanScanCallbackSortSnap )
                {
                // SortSnap was called with old availability information.
                iSession->CompleteServerSortSNAP();
                }
            else
                {
                MPMLOGSTRING(
                    "CMPMConnMonReqs::ErrorCallbackL: iWlanScanCallback EWlanScanCallbackNone" )
                }
            // reset callback type
            //
            iWlanScanCallback = EWlanScanCallbackNone;
            break;
            }
        case EObsolete:
            MPMLOGSTRING( "CMPMConnMonReqs::ErrorCallbackL: EObsolete" )
            break;
        }
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::RunL
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::RunL()
    {
    MPMLOGSTRING( "CMPMConnMonReqs::RunL" )
    if ( iStatus != KErrNone )
        {
        // Nok
        MPMLOGSTRING2( "CMPMConnMonReqs::RunL: \
ConnMon request completed with error code = %i", iStatus.Int() )

        // Does nothing if state is obsolete.
        ErrorCallbackL( iStatus.Int() );

        // RemoveReqPtr is safe if "this" doesn't exist
        iParent.RemoveReqPtr( this );
        delete this;
        }
    else
        {
        // Ok
        switch (iNextState)
            {
            case EGetIapAvailState:
                {
                MPMLOGSTRING( "CMPMConnMonReqs::RunL: EGetIapAvailState" )
                iParent.SetAvailableIAPs( iIapBuf() );

                if ( iActiveSchedulerWait.IsStarted() )
                    {
                    iActiveSchedulerWait.AsyncStop();
                    }

                iNextState      = EGetConnectionCountState;
                iLastCancelCode = EConnMonGetConnectionCount;
                iConnMon.GetConnectionCount( iConnectionCount, iStatus );
                SetActive();
                break;
                }
            case EGetConnectionCountState: 
                {
                MPMLOGSTRING( "CMPMConnMonReqs::RunL: EGetConnectionCountState" )
                MPMLOGSTRING2( "CMPMConnMonReqs::RunL: Connection Count: %i", 
                    iConnectionCount )
                iParent.SetConnectionCounter( iConnectionCount );
                iParent.RemoveReqPtr( this );
                delete this;
                break;
                }
            case EScanWLANNetworksState:
            case EScanWLANNetworksStateCached:
                {
                MPMLOGSTRING( "CMPMConnMonReqs::RunL: EScanWLANNetworksState and EScanWLANNetworksStateCached" )
                ASSERT( iSession );

                if ( iNextState == EScanWLANNetworksState )
                    {
                    MPMLOGSTRING( "CMPMConnMonReqs::RunL: EScanWLANNetworksState fresh data available from ConnMon" )
                    iParent.SetAvailableIAPs( iIapBuf() );

                    // Disable discarding availability notifications from Connection Monitor.
                    // 
                    iParent.DisableDiscarding(); 

                    // Generate event only if we got new iaps from ConnMon.
                    // 
                    if ( iWlanScanCallback == EWlanScanCallbackGenerateEvent )
                        {
                        MPMLOGSTRING( "CMPMConnMonReqs::RunL: iWlanScanCallback EWlanScanCallbackGenerateEvent" )
                        // Generate event only if not 
                        //
                        iParent.IapAvailabilityChange( EConnMon );
                        }

                    if ( iParent.AvailabilityNotificationDiscarded() )
                        {
                        MPMLOGSTRING( "CMPMConnMonReqs::RunL: AvailabilityNotificationDiscarded, roaming logic triggered" )
                        iParent.IapAvailabilityChange( EConnMonEvent );
                        }
                    }
                // check which callback function to use
                // 
                if( iWlanScanCallback == EWlanScanCallbackChooseIap )
                    {
                    iSession->IapSelectionL()->ChooseIapWLANScanCompletedL( iStatus.Int() );
                    }
                else if( iWlanScanCallback == EWlanScanCallbackProcessErr )
                    {
                    iSession->ProcessErrorWlanScanCompletedL();
                    }
                else if( iWlanScanCallback == EWlanScanCallbackCarrierRejected )
                    {
                    iSession->CompleteCarrierRejected();
                    }
                else if( iWlanScanCallback == EWlanScanCallbackSortSnap )
                    {
                    iSession->CompleteServerSortSNAP();
                    }
                else
                    {
                    MPMLOGSTRING(
                    "CMPMConnMonReqs::RunL: iWlanScanCallback default processing" )
                    }
                // reset callback type
                //
                iWlanScanCallback = EWlanScanCallbackNone;
                
                iParent.RemoveReqPtr( this );
                delete this;
                break;
                }
            case EObsolete:
                iParent.SetAvailableIAPs( iIapBuf() );
                delete this;
                break;
            default:
                {
                MPMLOGSTRING( "CMPMConnMonReqs::RunL: default" )
                PanicServer( KErrNotSupported );
                break;
                }
            }
        }
    }


// -----------------------------------------------------------------------------
// CMPMConnMonReqs::RunError
// -----------------------------------------------------------------------------
//

TInt CMPMConnMonReqs::RunError( TInt aError )
    {
    MPMLOGSTRING2( "CMPMConnMonReqs::RunError: RunL made a leave with error = %i", aError )

    // Disable discarding availability notifications from Connection Monitor.
    // 
    iParent.DisableDiscarding(); 

    // check which callback function was used when leave occurred
    // 
    if( iWlanScanCallback == EWlanScanCallbackChooseIap )
        {
        ASSERT( iSession );
        iSession->ChooseIapComplete( aError, NULL );
        }
    else if( iWlanScanCallback == EWlanScanCallbackProcessErr )
        {
        TBMNeededAction neededAction( EPropagateError );
        ASSERT( iSession );
        iSession->ProcessErrorComplete( KErrNone, &aError, &neededAction );
        }
    else
        {
        MPMLOGSTRING(
        "CMPMConnMonReqs::RunError: iWlanScanCallback EWlanScanCallbackNone" )
        }

    // We are done
    iParent.RemoveReqPtr( this );
    delete this;

    // Return KErrNone to prevent panic 
    return KErrNone;
    }

// -----------------------------------------------------------------------------
// CMPMConnMonReqs::DoCancel
// -----------------------------------------------------------------------------
//
void CMPMConnMonReqs::DoCancel()
    {
    MPMLOGSTRING( "CMPMConnMonReqs::DoCancel" )

    // Disable discarding availability notifications from Connection Monitor.
    // 
    iParent.DisableDiscarding(); 

    iConnMon.CancelAsyncRequest( iLastCancelCode );
    
    if ( iActiveSchedulerWait.IsStarted() )
        {
        iActiveSchedulerWait.AsyncStop();
        }
    }

//  End of File