datasourcemodules/defaultpositioningmodule/src/epos_cpospsyfixstatemanager.cpp
author Pat Downey <patd@symbian.org>
Wed, 01 Sep 2010 12:35:25 +0100
branchRCL_3
changeset 55 c92d4f3c47c5
parent 54 0c2046328c85
child 65 a796fdeeb33c
permissions -rw-r--r--
Revert incorrect RCL_3 drop: Revision: 201027 Kit: 201035

// 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 "epos_cpospsyfixstatemanager.h"
#include "epos_cpospsylisthandler.h"
#include "epos_cpossingletonmanager.h"
#include "epos_cposfixstatetimer.h"
#include "epos_defaultproxycommon.h"
#include "epos_cposconstmanager.h"
#include "epos_mpospsyfixstatelistener.h"

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

// C++ default constructor can NOT contain any code, that
// might leave.
//
CPosPsyFixStateManager::CPosPsyFixStateManager()
    {
    }

// EPOC default constructor can leave.
void CPosPsyFixStateManager::ConstructL()
    {
    TRACESTRING( "CPosPsyFixStateManager::ConstructL start... " )

    iConstManager = CPosConstManager::GetInstanceL();

    TRACESTRING( "CPosPsyFixStateManager::ConstructL end " )

    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::GetInstanceL
// ---------------------------------------------------------
//
CPosPsyFixStateManager* CPosPsyFixStateManager::GetInstanceL()
    {
    CPosPsyFixStateManager* self = reinterpret_cast < CPosPsyFixStateManager* > 
        ( CPosSingletonManager::GetObject( 
            EPosSigletonObjectIdPsyFixStateManager ) );
        
    if ( !self )
        {
        //Construct a new object and store it to CPosSingletonManager
        self = new ( ELeave ) CPosPsyFixStateManager;
        CleanupStack::PushL(self);
        self->ConstructL();
        CPosSingletonManager::SetObjectL(
            self,
            EPosSigletonObjectIdPsyFixStateManager );
        CleanupStack::Pop(self);
        }
        
    self->iRefCount++;
    
    return self;
    }

// Destructor
CPosPsyFixStateManager::~CPosPsyFixStateManager()
    {
    TRACESTRING( "CPosPsyFixStateManager::destructor start... " )

    if ( iConstManager )
        {
        iConstManager->ReleaseInstance();
        }
        
    //Clear fix state timer
    TInt count = iPsyStateArray.Count();
    for ( TInt i=0; i<count; i++)
        {
        delete iPsyStateArray[i].iTimer;
        }
        
    iPsyStateArray.Close();
    iListenerArray.Close();

    TRACESTRING( "CPosPsyFixStateManager::destructor end... " )
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::ReleaseInstance
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::ReleaseInstance()
    {
    iRefCount--;
    if ( iRefCount == 0 )
        {
        //We shall delete the instance
        CPosSingletonManager::ReleaseObject(
            EPosSigletonObjectIdPsyFixStateManager );
        }
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::AddListenerL
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::AddListenerL( MPosPsyFixStateListener* aListener )
    {
    User::LeaveIfError( iListenerArray.Append( aListener ) );
    }
        
// ---------------------------------------------------------
// CPosPsyFixStateManager::RemoveListener
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::RemoveListener( MPosPsyFixStateListener* aListener )
    {
    TInt count = iListenerArray.Count();
    for ( TInt i=count -1; i>=0; i-- )
        {
        if( iListenerArray[i] == aListener )
            {
            iListenerArray.Remove( i );
            }
        }
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::PsyLoadedL
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::PsyLoadedL(
            TPositionModuleId aPsyId )
    {
    TRACESTRING( "CPosPsyFixStateManager::PsyLoadedL" )
    TRACESTRING2( "PSY: %x", aPsyId )    
    if ( PsyIndex( aPsyId ) == KErrNotFound )
        {
        //If PSY is not in the PSY state array, add PSY to 
        //the array and set the fix state as unkown.
        CPosFixStateTimer* timer = CPosFixStateTimer::NewL(
            aPsyId, 
            *this );
        CleanupStack::PushL( timer );
        
        TPsyAndFixState fixAndState;
        fixAndState.iPsyId = aPsyId;
        fixAndState.iPsyState = EPsyFixStateUnknown;
        fixAndState.iLocationRequestCount = 0;
        fixAndState.iTimer = timer;
        iPsyStateArray.AppendL( fixAndState ) ;           
        CleanupStack::Pop( timer );
        }
    }
        
// ---------------------------------------------------------
// CPosPsyFixStateManager::GetPsyFixState
// ---------------------------------------------------------
//
CPosPsyFixStateManager::TPsyFixState CPosPsyFixStateManager::GetPsyFixState(
            TPositionModuleId aPsyId )
    {
    TInt index = PsyIndex( aPsyId );
    if ( index != KErrNotFound )
        {
        return iPsyStateArray[index].iPsyState;
        }
        
    //If PSY has not been loaded before, return fix state
    //as unknown.
    return EPsyFixStateUnknown;
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::PsyUsed
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::PsyUsed( 
        TPositionModuleId aPsyId,
        TPositionModuleStatus::TDeviceStatus aPreviousDeviceStatus )
    {
    TRACESTRING( "CPosPsyFixStateManager::PsyUsed" )
    TRACESTRING2( "PSY: %x", aPsyId )
    TRACESTRING2( "Device status: %d", aPreviousDeviceStatus)

    TInt index = PsyIndex( aPsyId );
    __ASSERT_DEBUG( index != KErrNotFound,
        DefaultProxyPanic( EDefaultProxyPanic_PsyNotFoundInStateManager ) );
    
    if( index != KErrNotFound )
        {
        TPsyAndFixState& fixState = iPsyStateArray[index];
        //If PSY has not been used before, then start timeshift timer
        if( fixState.iLocationRequestCount == 0 )
            {
            StartTimeshiftTimer( fixState, aPreviousDeviceStatus );
            }
            
        //Cancel unknown timer
        fixState.iTimer->CancelUnknownTimer();
            
        fixState.iLocationRequestCount++;
        }
    }


// ---------------------------------------------------------
// CPosPsyFixStateManager::SetPsyFixState
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::SetPsyFixState( 
            TPositionModuleId aPsyId, 
            TInt aLRErr  )
    {
    TRACESTRING( "CPosPsyFixStateManager::SetPsyFixState" )
    TRACESTRING2( "PSY: %x", aPsyId )
    TRACESTRING2( "Err: %d", aLRErr )

    TInt index = PsyIndex( aPsyId );
    if ( index != KErrNotFound )
        {
        TPsyAndFixState& fixState = iPsyStateArray[index];

        TPsyFixState previousFixState = fixState.iPsyState;
             
        switch ( aLRErr )
            {
            case KErrNone:
                //Location request completed successfully.
                //Stop timeshift timer
                fixState.iPsyState = EPsyFixStateYes;
                fixState.iTimer->CancelTimeshiftTimer();
                break;
            case KPositionPartialUpdate:
            case KErrPositionBufferOverflow:
            case KErrCancel:
                //State not changed.
                //Leave timeshift timer running
                break;
            default:
                //Stop timeshift timer
                fixState.iPsyState = EPsyFixStateNo;
                fixState.iTimer->CancelTimeshiftTimer();
                break;
            }

        //Notify liseners
        NotifyListener( aPsyId, previousFixState );
        

        //If the decrease the LR count for this PSY
        if( fixState.iLocationRequestCount > 0 )
            {
            fixState.iLocationRequestCount--;

            //Check if the PSY is not used anymore
            if ( fixState.iLocationRequestCount == 0 )
                {
                //if the PSY is not used anymore, start
                //unknown timer
                fixState.iTimer->StartUnknownTimer(
                    iConstManager->GetUnusedTimeoutValue() );
                }
            }
                
        }
    //If the PSY has not been loaded, we don't do anything.
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::SetExtGpsPsyFixState
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::SetExtGpsPsyFixState(
            TPositionModuleId aPsyId, 
            TInt aLRErr )
    {
    TRACESTRING( "CPosPsyFixStateManager::SetExtGpsPsyFixState" )
    TRACESTRING2( "PSY: %x", aPsyId )
    TRACESTRING2( "Err: %d", aLRErr )

    TInt index = PsyIndex( aPsyId );
    if ( index != KErrNotFound )
        {
        if ( aLRErr == KErrNone )
            {
            TPsyFixState previousFixState = iPsyStateArray[index].iPsyState;
            iPsyStateArray[index].iPsyState = EPsyFixStateYes;
            NotifyListener( aPsyId, previousFixState );
            }
        //otherwise the state will not be changed.
        }
    }

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

    TInt index = PsyIndex( aPsyId );
    if ( index != KErrNotFound )
        {
        TPsyFixState previousFixState = iPsyStateArray[index].iPsyState;

        iPsyStateArray[index].iPsyState = EPsyFixStateNo;
        
        TRACESTRING2( "PSY fix sate: %d", 
            iPsyStateArray[index].iPsyState );
            
        //Notify listner that PSY fix state is changed
        NotifyListener( aPsyId, previousFixState );
        }
    }
            
// ---------------------------------------------------------
// CPosPsyFixStateManager::UnknownTimerTimeout
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::UnknownTimerTimeout(
            TPositionModuleId aPsyId )
    {
    TRACESTRING( "CPosPsyFixStateManager::UnknownTimerTimeout" )
    TRACESTRING2( "PSY: %x", aPsyId )

    TInt index = PsyIndex( aPsyId );
    if ( index != KErrNotFound )
        {
        TPsyFixState previousFixState = iPsyStateArray[index].iPsyState;
        
        //Cancel timeshift timer
        iPsyStateArray[index].iTimer->CancelTimeshiftTimer();

        iPsyStateArray[index].iPsyState = EPsyFixStateUnknown;
        
        TRACESTRING2( "PSY fix sate: %d", 
            iPsyStateArray[index].iPsyState );
            
        //Notify listner that PSY fix state is changed
        NotifyListener( aPsyId, previousFixState );
        }
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::PsyIndex
// ---------------------------------------------------------
//
TInt CPosPsyFixStateManager::PsyIndex(
            TPositionModuleId aPsyId )
    {
    TInt count = iPsyStateArray.Count();
    for ( TInt i = 0; i < count; i++ )
        {
        if ( iPsyStateArray[i].iPsyId == aPsyId )
            {
            return i;
            }
        }
    return KErrNotFound;
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::StartTimeshiftTimer
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::StartTimeshiftTimer(
            TPsyAndFixState& aFixState,
            TPositionModuleStatus::TDeviceStatus aPreviousDeviceStatus )
    {
    TTimeIntervalMicroSeconds ttff;
    TTimeIntervalMicroSeconds ttnf;
    CPosPsyListHandler* listHandler = NULL;
    TInt ignore = KErrNone;
    TRAP( ignore, listHandler = 
            CPosPsyListHandler::GetInstanceL() );
                
    __ASSERT_DEBUG( listHandler != NULL,  
        DefaultProxyPanic( 
            EDefaultProxyPanic_GlobalObjectNotConstructed ) );
        
    listHandler->GetTtffAndTtnf(
        aFixState.iPsyId,
        ttff,
        ttnf );
            
    listHandler->ReleaseInstance();
    //Start timeshift timer
    aFixState.iTimer->StartTimeshiftTimer(
        iConstManager->GetTimeshiftValue(
            ttff,
            ttnf,
            aPreviousDeviceStatus ) );
    }

// ---------------------------------------------------------
// CPosPsyFixStateManager::NotifyListener
// ---------------------------------------------------------
//
void CPosPsyFixStateManager::NotifyListener(
            TPositionModuleId aPsyId,
            TPsyFixState aPreviousFixState )
    {
    TInt index = PsyIndex( aPsyId );
    if ( index != KErrNotFound )
        {
        TPsyFixState newState = iPsyStateArray[index].iPsyState;
        if ( newState != aPreviousFixState )
            {
            TInt count = iListenerArray.Count();
            for ( TInt i = count-1; i >= 0; i-- )
                {
                iListenerArray[i]->PsyFixStateChanged(
                    aPsyId,
                    newState );
                }
            }
        }
    }

//  End of File