datasourcemodules/defaultpositioningmodule/src/EPos_CPosRequestController.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 02 Feb 2010 01:50:39 +0200
changeset 0 9cfd9a3ee49c
permissions -rw-r--r--
Revision: 201002 Kit: 201005

// Copyright (c) 2007-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:
//



// INCLUDE FILES
#include <ecom/ecom.h>

#include <lbscommon.h>
#include <lbspositioninfo.h>
#include <lbs/epos_cposmodules.h>
#include <lbs/epos_cposmoduleidlist.h>
#include <lbs/epos_cpositioner.h>
#include <lbssatellite.h>
#include "epos_mposmodulestatusmanager.h"

#include "EPos_CPosRequestController.h"
#include "epos_cposrequestor.h"
#include "epos_defaultproxycommon.h"
#include "epos_cpospsylisthandler.h"
#include "epos_cpospsyfixstatemanager.h"
#include "epos_cposconstmanager.h"
#include "epos_cposexternalgpsmonitor.h"
#include "epos_posgenericinfouser.h"


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

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

// C++ default constructor can NOT contain any code, that
// might leave.
//
CPosRequestController::CPosRequestController(
    CPosDefaultPositioner& aDefaultPositioner, 
    MPosModuleStatusManager& aModuleStatusManager)
    :
    iDefaultPositioner( aDefaultPositioner ),
    iModuleStatusManager( aModuleStatusManager ),
    iCurrentPsy( KErrNotFound )
    {
    }

// EPOC default constructor can leave.
void CPosRequestController::ConstructL(
        MPosModuleSettingsManager& aSettingsManager )
    {
    TRACESTRING( "CPosRequestController::ConstructL start... " )
    
    iPsyListHandler = CPosPsyListHandler::GetInstanceL();
    iPsyListHandler->SetModuleSettingsManagerL( 
        aSettingsManager );
    iPsyListHandler->AddListenerL( this );

    
    iPsyFixStateManager = CPosPsyFixStateManager::GetInstanceL();
    iPsyFixStateManager->AddListenerL( this );
    iConstManager = CPosConstManager::GetInstanceL();

    iExtGpsPsyMonitor = CPosExternalGpsMonitor::GetInstanceL( 
        iDefaultPositioner,
        iModuleStatusManager );

    //Construct cleanup timer
    iCleanupTimer = CPeriodic::NewL( CActive::EPriorityStandard );

    TRACESTRING( "CPosRequestController::ConstructL end " )
    
    }

// Two-phased constructor.
CPosRequestController* CPosRequestController::NewL(
    CPosDefaultPositioner& aDefaultPositioner,
    MPosModuleSettingsManager& aSettingsManager,
    MPosModuleStatusManager& aModuleStatusManager )
    {
    CPosRequestController* self = new (ELeave)
        CPosRequestController(
            aDefaultPositioner,
            aModuleStatusManager );

    CleanupStack::PushL(self);
    self->ConstructL( 
        aSettingsManager );
    CleanupStack::Pop(self);
    return self;
    }

// Destructor
CPosRequestController::~CPosRequestController()
    {
    TRACESTRING( "CPosRequestController::destructor start... " )
    
    if ( iPsyFixStateManager )
        {
        iPsyFixStateManager->RemoveListener( this );
        iPsyFixStateManager->ReleaseInstance();
        }
    
    if ( iPsyListHandler )
        {
        iPsyListHandler->RemoveListener( this );
        iPsyListHandler->ReleaseInstance();
        }
        
    if ( iConstManager )
        {
        iConstManager->ReleaseInstance();
        }
        
    if ( iExtGpsPsyMonitor )
        {
        iExtGpsPsyMonitor->ReleaseInstance(
            iDefaultPositioner );
        }

    // Close all requestors 
    iRequestorArray.ResetAndDestroy();
    iRequestorArray.Close();
    
    //Close PSY List
    iPsyList.Close();
    
    // Cleanup timer
    delete iCleanupTimer;

    TRACESTRING( "CPosRequestController::destructor end... " )

    }

// ---------------------------------------------------------
// CPosRequestController::NotifyPositionUpdate
// ---------------------------------------------------------
//
void CPosRequestController::NotifyPositionUpdate(
    TPositionInfoBase& aPosInfo,
    TRequestStatus& aStatus)
    {
    TRACESTRING( "CPosRequestController::NotifyPositionUpdate start... " )

    //Default Proxy can't handle simultaneous location request.
    __ASSERT_DEBUG( 
        iPosRequestStatus == NULL, 
        DefaultProxyPanic( EDefaultProxyPanic_SimualtaneousLR ) );
    
    aStatus = KRequestPending;
    iPosRequestStatus = &aStatus;
    iPosInfo = &aPosInfo;
    
    //When location request received, clear cleanup timer
    iCleanupTimer->Cancel();
    
    TRAPD( err, StartPositionUpdateL() );
    if( err != KErrNone )
        {
        CompleteRequest(err);
        }

    TRACESTRING( "CPosRequestController::NotifyPositionUpdate end " )
    }

// ---------------------------------------------------------
// CPosRequestController::CancelNotifyPositionUpdate
// ---------------------------------------------------------
//
void CPosRequestController::CancelNotifyPositionUpdate(TInt aCancelReason)
    {
    TRACESTRING( "CPosRequestController::CancelNotifyPositionUpdate(TInt) start... " )

    //Cancel location request with error to all loaded requestor
    TInt loadedRequestorCount = iRequestorArray.Count();
    for ( TInt i = 0; i < loadedRequestorCount; i++ )
        {
        CancelRequest( i, aCancelReason );
        }
        
    CompleteRequest(KErrCancel);

    TRACESTRING( "CPosRequestController::CancelNotifyPositionUpdate(TInt) end " )
    }

// ---------------------------------------------------------
// CPosRequestController::CancelNotifyPositionUpdate
// ---------------------------------------------------------
//
void CPosRequestController::CancelNotifyPositionUpdate()
    {
    TRACESTRING( "CPosRequestController::CancelNotifyPositionUpdate start... " )

    // This is a real user cancel
    CancelNotifyPositionUpdate(KErrCancel);
    
    TRACESTRING( "CPosRequestController::CancelNotifyPositionUpdate end " )
    }

// ---------------------------------------------------------
// CPosRequestController::CancelRequest
// ---------------------------------------------------------
//
void CPosRequestController::CancelRequest( TInt aIndex, TInt aCancelReason )
    {
    TInt count = iRequestorArray.Count();
    if ( aIndex < count )
        {
        CPosRequestor* requestor = iRequestorArray[aIndex];
        if ( requestor->IsActive() )
            {
            //Notify external GPS PSY monitor that this PSY is not used.
            iExtGpsPsyMonitor->PsyNotUsed( requestor->ModuleId() );
            requestor->CancelWithReason(aCancelReason);
            }
        }
    }

// ---------------------------------------------------------
// CPosRequestController::CancelRequest
// ---------------------------------------------------------
//
void CPosRequestController::CancelRequest( TPositionModuleId aPsyId )
    {
    TInt count = iRequestorArray.Count();
    for ( TInt i = 0; i < count; i++ )
        {
        CPosRequestor* requestor = iRequestorArray[i];
        if ( requestor->ModuleId() == aPsyId && 
            requestor->IsActive() )
            {
            //Notify external GPS PSY monitor that this PSY is not used.
            iExtGpsPsyMonitor->PsyNotUsed( requestor->ModuleId() );
            requestor->Cancel();
            }
        }
    }

// ---------------------------------------------------------
// CPosRequestController::StartTrackingL
// ---------------------------------------------------------
//
void CPosRequestController::StartTracking(
    const TTimeIntervalMicroSeconds& /*aInterval*/)
    {
    //This function does nothing. Tracking will be started
    //to any specific PSY only if this PSY will be used by
    //Default Proxy. 

    TRACESTRING( "CPosRequestController::StartTracking" )

    }

// ---------------------------------------------------------
// CPosRequestController::StopTracking
// ---------------------------------------------------------
//
void CPosRequestController::StopTracking()
    {
    TRACESTRING( "CPosRequestController::StopTracking start..." )
    
    //Stop tracking to all loaded PSYs
    TInt loadedRequestorCount = iRequestorArray.Count();
    for ( TInt i = 0; i < loadedRequestorCount; i++ )
        {
        iRequestorArray[i]->StopTracking();
        }

    TRACESTRING( "CPosRequestController::StopTracking end" )

    }

// ---------------------------------------------------------
// CPosRequestController::StartPositionUpdateL
// ---------------------------------------------------------
//
void CPosRequestController::StartPositionUpdateL()
    {
    TRACESTRING( "CPosRequestController::StartPositionUpdateL start..." )

    //Rebuid PSY list if neccessary
    if ( !iPsyListValid )
        {
        iPsyListHandler->GetPsyListL( iPsyList );
        iPsyListValid = ETrue;
        }
        
    iFirstResult = KErrNotFound;    // as if no enabled psys found
    iCurrentPsy = KErrNotFound;     // start from first module
    TryNextPositioner();
    
    if ( !IsLocationRequestOnGoing() )
        {
        CompleteRequest( iFirstResult );
        }

    TRACESTRING( "CPosRequestController::StartPositionUpdateL end" )

    }


// ---------------------------------------------------------
// CPosRequestController::TryNextPositioner
// ---------------------------------------------------------
//
void CPosRequestController::TryNextPositioner()
{
    TRACESTRING( "CPosRequestController::TryNextPositioner start..." )

    // Find next enabled plugin we should try with
    TInt count = iPsyList.Count();
    while ( ++iCurrentPsy < count )
        {
        TPositionModuleId currentPsyId = iPsyList[iCurrentPsy];
        
        TRACESTRING2( "PSY: %x", currentPsyId )

        TUint32 classType = iPosInfo->PositionClassType();
        if ( !iPsyListHandler->IsClassSupported( 
            classType,
            currentPsyId ) )
            {
            //if the requested class is not supported, then we try next PSY
            //in the PSY list
            
            if ( iCurrentPsy == 0 )
                {
                //Error code fromt the first PSY
                iFirstResult = KErrArgument;
                }

            continue;
            }
            
        TRAPD( err, TryPositionerL( currentPsyId ) );
        
        TRACESTRING2( "Try PSY completion code = %d", err )

        if( err == KErrNone )
            {
            //Location request is made to currentPsy. Check the fix state of
            //current PSY, if current PSY can't give a fix, we load next PSY
            if ( iPsyFixStateManager->GetPsyFixState( currentPsyId ) 
                != CPosPsyFixStateManager::EPsyFixStateNo )
                {
                //break from here. Othsewise, try next PSY
                break;
                }
            }
        else
            {
            //In error case, we store the error code if needed and try next PSY
            if ( iCurrentPsy == 0 )
                {
                //Error code fromt the first PSY
                iFirstResult = err;
                }
            }
        }

    TRACESTRING( "CPosRequestController::TryNextPositioner end" )

}

// ---------------------------------------------------------
// CPosRequestController::TryPositionerL
// ---------------------------------------------------------
//
void CPosRequestController::TryPositionerL( TPositionModuleId aPsyId )
    {
    CPosRequestor* currentRequestor = NULL;
    
    
    //Check device status of the PSY. If it's in error status,
    //it will not be used at all.
    TPositionModuleStatus moduleStatus;
    iModuleStatusManager.GetModuleStatus( 
        aPsyId,
        moduleStatus );
    if ( moduleStatus.DeviceStatus() == TPositionModuleStatus::EDeviceError )
        {
        TRACESTRING2( "PSY %x device error", aPsyId )

        User::Leave( KErrGeneral );
        }
    
    //Find if the PSY is already loaded
    TInt requestorCount = iRequestorArray.Count();
    for ( TInt i = 0; i < requestorCount; i++ )
        {
        if ( iRequestorArray[i]->ModuleId() == aPsyId )
            {
            currentRequestor = iRequestorArray[i];
            break;
            }
        }
    
    if ( currentRequestor == NULL )
        {
        //PSY has not been loaded before, load it now
        TRACESTRING2( "Loading Positioner: %x", aPsyId )
        currentRequestor = 
            CPosRequestor::NewL(
                iDefaultPositioner,
                aPsyId,
                *this,
                *iPsyFixStateManager,
                iModuleStatusManager );
                
        CleanupStack::PushL( currentRequestor );
        
        //Notify fix state manager that a PSY is loaded
        iPsyFixStateManager->PsyLoadedL( aPsyId );
        
        //Add this requestor to requestor array
        User::LeaveIfError( iRequestorArray.Append( 
            currentRequestor ) );
        CleanupStack::Pop( currentRequestor );
        }
        
    //Start tracking if needed
    TTimeIntervalMicroSeconds interval = iDefaultPositioner.TrackingInterval();
    if (interval.Int64() != 0 )
        {
        currentRequestor->StartTrackingL( interval );
        }
    
    //Make location request to current positioner
    currentRequestor->MakeLocationRequestL( *iPosInfo );
    
    //Notify external GPS PSY monitor that a PSY is used
    iExtGpsPsyMonitor->PsyUsed( aPsyId );
    }

// ---------------------------------------------------------
// CPosRequestController::LocationRequestCompleted
// ---------------------------------------------------------
//
void CPosRequestController::LocationRequestCompleted( 
            TPositionModuleId aModuleId,
            TInt aErr,
            const TPositionInfoBase& aPosInfo,
            TBool aIsPosInfoUpToDate )
    {
    TRACESTRING( "CPosRequestController::LocationRequestCompleted start..." )
    TRACESTRING2( "PSY: %x", aModuleId )
    TRACESTRING2( "Err: %d", aErr )
    TRACESTRING2( "Is PosInfo Updated: %d", aIsPosInfoUpToDate )

    //Notify the external GPS PSY monitor that a PSY in not used
    iExtGpsPsyMonitor->PsyNotUsed( aModuleId );

    TInt err = aErr;
    if ( aErr == KPositionPartialUpdate && IsLocationRequestOnGoingOnNetworkPsy() )
        {
        //Partial update is returned when Network PSY is used.
        //partial update is not forwarded to system. Instead, location
        //request is made to the loaded PSY again.
        TInt ignore;
        TRAP( ignore, TryPositionerL( aModuleId ) );
        }
    else if ( aErr == KErrNone || 
        aErr == KErrPositionBufferOverflow ||
        aErr == KPositionPartialUpdate  )
        {
        //Location request succeed or
        //buffer over flow is returned from a PSY or
        //partial update is returned when only GPS PSY is used
        
        //Copy request info, and complete LR
        if ( aIsPosInfoUpToDate )
            {
            __ASSERT_DEBUG( 
                aPosInfo.PositionClassSize() == iPosInfo->PositionClassSize(),
                DefaultProxyPanic( EDefaultProxyPanic_PosInfoSizeMismatch ) );
            
            Mem::Copy( iPosInfo, &aPosInfo, iPosInfo->PositionClassSize() );
            }
        else
            {
            TInt cpErr = CopyPosInfoClass( aPosInfo , *iPosInfo );
            if ( cpErr != KErrNone && err == KErrNone )
                {
                err = cpErr;
                }
            }
        
        if ( iPosInfo->ModuleId() != aModuleId )
            {
            err = KErrGeneral;
            }
            
        CompleteRequest( err );
        }
    else
        {
        if ( aModuleId == iPsyList[0] )
            {
            //Store the result from first PSY
            iFirstResult = aErr;
            
            //Store module ID of first positioner
            iPosInfo->SetModuleId( aModuleId );
            }
        }
        
    //This will cause the state change notification and generate fallback 
    //if it's a error case.
    iPsyFixStateManager->SetPsyFixState( aModuleId, aErr );
    
    if ( !IsLocationRequestOnGoing() )
        {
        CompleteRequest( iFirstResult );
        }

    TRACESTRING( "CPosRequestController::LocationRequestCompleted end" )
    }

// ---------------------------------------------------------
// CPosRequestController::IsLocationRequestOnGoing
// ---------------------------------------------------------
//
TBool CPosRequestController::IsLocationRequestOnGoing() const
    {
    TInt count = iRequestorArray.Count();
    for ( TInt i=0; i < count; i++ )
        {
        const CPosRequestor& requestor = *(iRequestorArray[i]);
        if ( requestor.IsActive() )
            {
            return ETrue;
            }
        }
    return EFalse;
    }

// ---------------------------------------------------------
// CPosRequestController::IsLocationRequestOnGoingOnNetworkPsy
// ---------------------------------------------------------
//
TBool CPosRequestController::IsLocationRequestOnGoingOnNetworkPsy() const
    {
    TInt count = iRequestorArray.Count();
    for ( TInt i=0; i < count; i++ )
        {
        const CPosRequestor& requestor = *(iRequestorArray[i]);
        if ( requestor.IsActive() && 
            iPsyListHandler->IsModuleNetworkBased(
                requestor.ModuleId() ) )
            {
            return ETrue;
            }
        }
    return EFalse;
    }

// ---------------------------------------------------------
// CPosRequestController::PsyFixStateChanged
// ---------------------------------------------------------
//
void CPosRequestController::PsyFixStateChanged( 
            TPositionModuleId aModuleId,
            CPosPsyFixStateManager::TPsyFixState aFixState )
    {
    TRACESTRING( "CPosRequestController::PsyFixStateChanged start..." )
    TRACESTRING2( "PSY: %x", aModuleId )
    TRACESTRING2( "Fix state: %d", aFixState )

    //If there is location request on going and
    //current can't give a fix, we try next PSY
    if( iPosRequestStatus && iCurrentPsy<iPsyList.Count() )
        {
        if ( aFixState == CPosPsyFixStateManager::EPsyFixStateNo &&
            iPsyList[iCurrentPsy] == aModuleId )
            {
            TryNextPositioner();
            }
        }

    TRACESTRING( "CPosRequestController::PsyFixStateChanged end" )
    }

// ---------------------------------------------------------
// CPosRequestController::CompleteRequest
// ---------------------------------------------------------
//
void CPosRequestController::CompleteRequest(TInt aCompleteCode)
    {
    TRACESTRING( "CPosRequestController::CompleteRequest start..." )
    TRACESTRING2( "Completion code: %d", aCompleteCode )
    TRACESTRING2( "Module Id: %x", iPosInfo->ModuleId() )

    if (iPosRequestStatus)
        {
        User::RequestComplete(iPosRequestStatus, aCompleteCode);
        iPosRequestStatus = NULL;
        
        //Clear all location request if this is not 
        //a partial update
        if ( aCompleteCode != KPositionPartialUpdate )
            {
            ClearLocationRequests();
            }
            
        //If there is still location request ongoing to other PSYs,
        //start cleanup timer
        TInt count = iRequestorArray.Count();
        for ( TInt i = 0; i < count; i++ )
            {
            if ( iRequestorArray[i]->IsActive() )
                {
                
                if ( !iCleanupTimer->IsActive() )
                    {
                    iCleanupTimer->Start(
                        iConstManager->GetCleanupTimeoutValue().Int64(),
                        iConstManager->GetCleanupTimeoutValue().Int64(),
                        TCallBack( CleanupTimeoutCallback, this )
                        );
                    }
                }
            }
        }
    TRACESTRING( "CPosRequestController::CompleteRequest end" )
    }

// ---------------------------------------------------------
// CPosRequestController::ClearLocationRequests
// ---------------------------------------------------------
//
void CPosRequestController::ClearLocationRequests()
    {
    TInt count = iRequestorArray.Count();
    for ( TInt i = 0; i < count; i++ )
        {
        CancelRequest( i, KErrCancel);
        }
    }

// ---------------------------------------------------------
// CPosRequestController::PsyListChanged
// ---------------------------------------------------------
//
void CPosRequestController::PsyListChanged( 
            const TPosPsyListChangeEvent& aEvent )
    {
    TRACESTRING( "CPosRequestController::PsyListChanged start..." )
    TRACESTRING2( "Event type: %d", aEvent.iType )
    TRACESTRING2( "PSY: %x", aEvent.iPsyId )
    
    switch ( aEvent.iType )
        {
        case EPosPsyListChangeEventPsyDeleted:
            {
            //Cancel location request to this PSY
            CancelRequest( aEvent.iPsyId );
                    
            if ( iCurrentPsy >= 0 && iCurrentPsy < iPsyList.Count() )
                {
                //If there is location request on going
                if ( aEvent.iPsyId == iPsyList[iCurrentPsy] )
                    {
                    //fallback to next PSY
                    TryNextPositioner();
                    }
                }
            //Delete this PSY from the list
            TInt index = iPsyList.Find( aEvent.iPsyId );
            if ( index != KErrNotFound )
                {
                iPsyList.Remove( index );
                }
                
            //Unload this PSY
            UnloadRequestor( aEvent.iPsyId );
            }
            break;
        case EPosPsyListChangeEventListRebuild:
        default:
            //Rebuild the list
            iPsyListValid = EFalse;
            break;
        }

    TRACESTRING( "CPosRequestController::PsyListChanged end" )
    }


// ---------------------------------------------------------
// CPosRequestController::GetRequestor
// ---------------------------------------------------------
//
CPosRequestor* CPosRequestController::GetRequestor(
            TPositionModuleId aPsyId )
    {
    TInt count = iRequestorArray.Count();
    for ( TInt i = 0; i < count; i++ )
        {
        if ( iRequestorArray[i]->ModuleId() == aPsyId )
            {
            return iRequestorArray[i];
            }
        }
    return NULL;
    }

// ---------------------------------------------------------
// CPosRequestController::UnloadRequestor
// ---------------------------------------------------------
//
void CPosRequestController::UnloadRequestor( TPositionModuleId aPsyId )
    {
    TRACESTRING( "CPosRequestController::UnloadRequestor" )
    TRACESTRING2( "PSY: %x", aPsyId )

    TInt count = iRequestorArray.Count();
    for ( TInt i = count-1; i >= 0; i-- )
        {
        if ( iRequestorArray[i]->ModuleId() == aPsyId )
            {
            delete iRequestorArray[i];
            iRequestorArray.Remove( i );
            }
        }
    }

// ---------------------------------------------------------
// CPosRequestController::CopyPosInfoClass
// ---------------------------------------------------------
//
TInt CPosRequestController::CopyPosInfoClass(
            const TPositionInfoBase& aSrc,
            TPositionInfoBase& aDst )
    {
    TInt err = KErrNone;
    
    TUint32 srcClasses = aSrc.PositionClassType();
    TUint32 dstClasses = aDst.PositionClassType();
    
    //Handle TPositionInfoBase
    aDst.SetModuleId( aSrc.ModuleId() );
    aDst.SetUpdateType( aSrc.UpdateType() );
    
    //Handle TPositionInfo
    if ( ( srcClasses & EPositionInfoClass ) &&
        ( dstClasses & EPositionInfoClass ) )
        {
        TPosition pos;
        static_cast < const TPositionInfo& > ( aSrc ).GetPosition( pos );
        static_cast < TPositionInfo& > ( aDst ).SetPosition( pos );
        }
        
    //Handle TPositionCourseInfo
    if ( ( srcClasses & EPositionCourseInfoClass ) &&
        ( dstClasses & EPositionCourseInfoClass ) )
        {
        TCourse course;
        static_cast < const TPositionCourseInfo& > ( aSrc ).GetCourse( course );
        static_cast < TPositionCourseInfo& > ( aDst ).SetCourse( course );
        }
        
    //Handle TPositionSatelliteInfo
    if ( ( srcClasses & EPositionSatelliteInfoClass ) &&
        ( dstClasses & EPositionSatelliteInfoClass ) )
        {
        const TPositionSatelliteInfo& srcSat = 
            static_cast < const TPositionSatelliteInfo& > ( aSrc );
        TPositionSatelliteInfo& dstSat = 
            static_cast < TPositionSatelliteInfo& > ( aDst );

        dstSat.SetSatelliteTime( srcSat.SatelliteTime() );
        dstSat.SetHorizontalDoP( srcSat.HorizontalDoP() );
        dstSat.SetTimeDoP( srcSat.TimeDoP() );
        dstSat.SetVerticalDoP( srcSat.VerticalDoP() );
        
        dstSat.ClearSatellitesInView();
        TInt numSatData = srcSat.NumSatellitesInView();
        
        for ( TInt i = 0; i < numSatData; i++ )
            {
            TSatelliteData satData;
            srcSat.GetSatelliteData( i, satData );
            err = dstSat.AppendSatelliteData( satData );
            if ( err != KErrNone )
                {
                return KErrNone;
                }
            }
        }
        
    //Handle HPositionGenericInfo
    if ( ( srcClasses & EPositionGenericInfoClass ) &&
        ( dstClasses & EPositionGenericInfoClass ) )
        {
        const HPositionGenericInfo& srcGen = 
            static_cast < const HPositionGenericInfo& > ( aSrc );
        HPositionGenericInfo& dstGen = 
            static_cast < HPositionGenericInfo& > ( aDst );
        
        err = PosGenericInfoUser::CopyHGenericInfo( srcGen, dstGen );
        }
    
    return err;
    }

// ---------------------------------------------------------
// CPosRequestController::CleanupTimeoutCallback
// ---------------------------------------------------------
//
TInt CPosRequestController::CleanupTimeoutCallback( TAny* aAny )
    {
    reinterpret_cast< CPosRequestController* > ( aAny ) ->
        CleanupTimeout();
    return KErrNone;
    }
        
// ---------------------------------------------------------
// CPosRequestController::CleanupTimeout
// ---------------------------------------------------------
//
void CPosRequestController::CleanupTimeout()
    {
    //Cleanup all outstanding location requests
    ClearLocationRequests();
    iCleanupTimer->Cancel();
    }

// End of file