locationsystemui/locationsysui/posindicator/posindicatorhelperserver/src/posindicatorlocationrequestor.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 31 Aug 2010 15:37:04 +0300
branchRCL_3
changeset 44 2b4ea9893b66
permissions -rw-r--r--
Revision: 201033 Kit: 201035

/*
* Copyright (c) 2010 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: Implementation of location requestor class.
*
*/

#include "posindicatorlocationrequestor.h"
#include "posindicatorserverconst.h"
#include "posindicatorlogger.h"

#include <epos_poslandmarkserialization.h>
#include <ecom.h>

_LIT( KServer,"PositionIndicatorServer" );
static const TInt KMaxUpdateAge = 10;
static const TInt KUpdateTimeOut = 5000000;

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::NewL
// -----------------------------------------------------------------------------
CPosIndicatorLocationRequestor* CPosIndicatorLocationRequestor::NewL()
    {
    FUNC("CPosIndicatorLocationRequestor::NewL");
    CPosIndicatorLocationRequestor* self = new ( ELeave ) 
                                        CPosIndicatorLocationRequestor;
    CleanupStack::PushL( self );
    self->ConstructL();
    CleanupStack::Pop();
    return self;
    }
    

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::~CPosIndicatorLocationRequestor
// -----------------------------------------------------------------------------
CPosIndicatorLocationRequestor::~CPosIndicatorLocationRequestor()
    {
    FUNC("CPosIndicatorLocationRequestor::~CPosIndicatorLocationRequestor");
    
    // Cancel the current operation.
    Cancel();
    
    iPositionRequestQueue.Close();
    iAddressRequestQueue.Close();
    iPositioner.Close();
    iPosServer.Close();    
    delete iReverseGeoCodeInterface;
    iReverseGeoCodeInterface = NULL;
    delete iLandmark;
    iLandmark = NULL;
    delete iLandmarkPackage;
    iLandmarkPackage = NULL;
    // Release all landmark resources
    ReleaseLandmarkResources();
    
    // Release all ECOM resources
    REComSession::FinalClose();	
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::CPosIndicatorLocationRequestor
// -----------------------------------------------------------------------------
CPosIndicatorLocationRequestor::CPosIndicatorLocationRequestor():CActive( 
                                                              EPriorityStandard )
    {
    FUNC("CPosIndicatorLocationRequestor::CPosIndicatorLocationRequestor");
    CActiveScheduler::Add( this );
    }
 
// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::ConstructL
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::ConstructL()
    {
    FUNC("CPosIndicatorLocationRequestor::ConstructL");
    iOperation = ENone;
    
    User::LeaveIfError( iPosServer.Connect() );
    
    TInt error = iPositioner.Open( iPosServer );
    
    User::LeaveIfError( iPositioner.SetRequestor( 
                        CRequestor::ERequestorService,
                        CRequestor::EFormatApplication,
                        KServer ) );

    TPositionUpdateOptions updateops;
    updateops.SetUpdateTimeOut(TTimeIntervalMicroSeconds(KUpdateTimeOut));
    User::LeaveIfError( iPositioner.SetUpdateOptions( updateops ));
 
    iReverseGeoCodeInterface = CPosReverseGeocodeInterface::NewL( *this );
    
    iLandmark = CPosLandmark::NewL();
    
    iLandmarkPackage = NULL;
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::GetCurrentPosition
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::GetCurrentPosition( const RMessage2&
                                                         aMessage )
    { 
    FUNC("CPosIndicatorLocationRequestor::GetCurrentPosition");
    // If location fix is already available and this is waiting for address info,
    // reply the message with the fix available
    if( iOperation == ECurrentAddress )
        {
        FUNC("iOperation == ECurrentAddress");
        TPckg<TPositionSatelliteInfo> posSatPckg( iPositionInfo );
        TInt error = aMessage.Write( KParamCurrentPosition,posSatPckg );
        aMessage.Complete( error );
        }
    else 
        {
        FUNC("iOperation != ECurrentAddress");
        // Store client's message
        iPositionRequestQueue.Append( aMessage );   
        // If the requestor is idle without doing any operation, request
        // current location.
        if( iOperation == ENone )
            {
            FUNC("iOperation == ENone");
            iOperation = ELastKnownPosition;
            
            // Last known position.
            iPositioner.GetLastKnownPosition( iLastKnownInfo,iStatus );
            SetActive();
            }
        }
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::GetCurrentAddressInfoSizeL
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::GetCurrentAddressInfoSizeL( const RMessage2& 
                                                                 aMessage )
    {
    FUNC("CPosIndicatorLocationRequestor::GetCurrentAddressInfoSizeL");
    // Store client's message
    iAddressRequestQueue.Append( aMessage );
    
    // If the requestor is idle without doing any operation, request
    // address information.
    if( iOperation == ENone )
        {
        iOperation = ECurrentAddress;
        // Clear previous landmark information.
        iLandmark->RemoveLandmarkAttributes( CPosLandmark::EAllAttributes );
        TPosition position;
        iPositionInfo.GetPosition( position );
        iLandmark->SetPositionL( position );
        iReverseGeoCodeInterface->GetAddressByCoordinateL( *iLandmark );
        }
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::GetCurrentAddressInfoL
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::GetCurrentAddressInfoL( const RMessage2& 
                                                             aMessage )
    {
    FUNC("CPosIndicatorLocationRequestor::GetCurrentAddressInfoL");
    TInt error = aMessage.Write( KParamCurrentAddress,*iLandmarkPackage );
    aMessage.Complete( error );
    }


// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::RunL
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::RunL()
    {
    FUNC("CPosIndicatorLocationRequestor::RunL");
    LOG("Error Status : ", iStatus.Int());
    switch( iOperation )
        {
        case ELastKnownPosition:
            {
                // Check the time stamp of the last fix, if the fix is 10 sec
                // old, request for the new fix.
                TPosition position;
                iLastKnownInfo.GetPosition( position );
                TTime timeOfFix = position.Time();
                TTime currentTime;
                currentTime.HomeTime();
                timeOfFix += TTimeIntervalSeconds( KMaxUpdateAge );
                if( iStatus.Int() == KErrNone && timeOfFix < currentTime && 
                	!(Math::IsNaN( position.Latitude() ) || Math::IsNaN( position.Longitude() ) ) )
                    {
                    // Set the last knowm position to position info to send it to
                    // client.
                    iPositionInfo.SetPosition( position );
                    }
                else
                    {
                    iOperation = ECurrentPosition;
                 
                    // Request current position.
                    iPositioner.NotifyPositionUpdate( iPositionInfo,iStatus );
                    SetActive();
                    return;
                    }
            	}
        case ECurrentPosition:
            {
            // Reset operation id
            iOperation = ENone;
            // Pack the satellite position information 
            TPckg<TPositionSatelliteInfo> posSatPckg( iPositionInfo );
            TInt count = iPositionRequestQueue.Count();
            for( TInt i=0;i<count;++i )
                {
                TInt error = iStatus.Int();
                if( error == KErrNone )
                    {
                    error = iPositionRequestQueue[i].Write( KParamCurrentPosition,posSatPckg );
                    }
                iPositionRequestQueue[i].Complete( error );
                }
            // All the messages in the position request queue are completed. Hence reset the list.
            iPositionRequestQueue.Reset();
            break;
            }
        case ECurrentAddress:
            {
            FUNC("ECurrentAddress");
            // Reset operation id
            iOperation = ENone;
            // Pack landmarks information
            delete iLandmarkPackage;
			iLandmarkPackage = NULL;
            iLandmarkPackage = PosLandmarkSerialization::PackL( *iLandmark );
            TInt count = iAddressRequestQueue.Count();
            for( TInt i=0;i<count;i++ )
                {
                TInt error = iStatus.Int();
                if( error == KErrNone )
                    {
                    TPckg<TInt> size( iLandmarkPackage->Size() );
                    error = iAddressRequestQueue[i].Write( KParamCurrentAddressSize,size );
                    }
                iAddressRequestQueue[i].Complete( error );
                }
            // All the messages in the address request queue are completed. Hence reset the list.
            iAddressRequestQueue.Reset();
            break;
            }

        default:
            {
            FUNC("- CPosIndicatorLocationRequestor::RunL default case");
            break;
            }
        }
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::CancelRequest
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::CancelRequest( const RMessage2& aMessage )
    {
    // Iterate through the outstanding request and check whether there are 
    // outstanding request from the subsession from which cancel call is 
    // received.
    RMessage2 outStandingMessage;
    TBool outStandingFlag = EFalse;
    TInt count = iPositionRequestQueue.Count();
    for( TInt i=0;i<count;++i )
        {
        if( iPositionRequestQueue[i].SecureId() == aMessage.SecureId() &&
            iPositionRequestQueue[i].Int3() == aMessage.Int3() )
            {
            outStandingMessage = iPositionRequestQueue[i];
            iPositionRequestQueue.Remove(i);
            outStandingFlag = ETrue;
            break;
            }
        }
    
    // If the outstanding request is not found in the position request queue,
    // search address request queue.
    if( !outStandingFlag )
        {   
        count = iAddressRequestQueue.Count();
        for( TInt i=0;i<count;++i )
            {
            if( iAddressRequestQueue[i].SecureId() == aMessage.SecureId() &&
                iAddressRequestQueue[i].Int3() == aMessage.Int3() )
                {
                outStandingMessage = iAddressRequestQueue[i];
                iAddressRequestQueue.Remove(i);
                outStandingFlag = ETrue;
                break;
                }
            }
        }
    
    // If the both position and address request queue are zero, cancel outstanding request
    if( !iAddressRequestQueue.Count() &&
        !iPositionRequestQueue.Count() )
        {
        Cancel();
        }
    if( outStandingFlag )
        {
        outStandingMessage.Complete( KErrCancel );
        }
    // Complete cancel request.
    aMessage.Complete( KErrNone );
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::DoCancel
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::DoCancel()
    {
    FUNC("CPosIndicatorLocationRequestor::DoCancel");
    switch( iOperation )
        {
        case ELastKnownPosition:
            {
            iPositioner.CancelRequest( RPositionerSubSessionBase::EReqGetLastKnownPosition );
            break;
            }
        case ECurrentPosition:
            {
            iPositioner.CancelRequest( RPositionerSubSessionBase::EReqNotifyPositionUpdate );
            break;
            }    
        case ECurrentAddress:    
            {
            iReverseGeoCodeInterface->Cancel();
            break;
            }
        default:
            break;
        }
    }

// -----------------------------------------------------------------------------
// CPosIndicatorLocationRequestor::ReverseGeocodeComplete
// -----------------------------------------------------------------------------
void CPosIndicatorLocationRequestor::ReverseGeocodeComplete( TInt aErrorcode )
    {
    FUNC("CPosIndicatorLocationRequestor::ReverseGeocodeComplete");
    // Here we self complete our active to release the control from this 
    // call back method.
    iStatus = KRequestPending;
    SetActive();
    TRequestStatus* statusPtr = &iStatus;
    User::RequestComplete( statusPtr,aErrorcode );
    }

// End of file.