locationmgmt/networkgateway/src/netlocationchannel.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) 2006-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:
// Definition of network location channel component.
// 
//

/**
 @file
 @internalTechnology
 @released
*/

#include <e32base.h>
#include "lbsdevloggermacros.h"
#include "lbsprocessuiddefs.h"
#include "netlocationchannel.h"


//
// CNetworkLocationChannel
//

CNetworkLocationChannel::CNetworkLocationChannel(MNetworkLocationObserver& aObserver) : 
	CActive(EPriorityStandard),
	iObserver(aObserver)
	{
	CActiveScheduler::Add(this);
	}
	
CNetworkLocationChannel::~CNetworkLocationChannel()
	{
	Cancel();
	iFinalPositionUpdates.Close();
	iReferencePositionUpdates.Close();
	iLocationResponses.Close();
	iLocationRequests.Close();
	}

CNetworkLocationChannel* CNetworkLocationChannel::NewL(MNetworkLocationObserver& aObserver)
	{
	CNetworkLocationChannel* self = new (ELeave) CNetworkLocationChannel(aObserver);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(self);
	return self;
	}
		
void CNetworkLocationChannel::ConstructL()
	{	
	iLocationRequests.OpenL(RProcess().SecureId());
	iLocationResponses.OpenL(RProcess().SecureId());
	iReferencePositionUpdates.OpenL(RLbsNetworkPositionUpdates::ENetworkPositionReference);
	iFinalPositionUpdates.OpenL(RLbsNetworkPositionUpdates::ENetworkPositionFinal);
	NotifyNetworkLocationRequestUpdate();
	}
	
void CNetworkLocationChannel::RunL()
	{
	User::LeaveIfError(iStatus.Int());
	
	NotifyNetworkLocationRequestUpdate();
	TLbsNetLocMsgBase msg;
	iLocationRequests.GetNetworkLocationRequest(msg);
	iObserver.ProcessNetworkLocationMessage(msg);
	}
	
void CNetworkLocationChannel::DoCancel()
	{
	iLocationRequests.CancelNotifyNetworkLocationRequestUpdate();
	}
	
TInt CNetworkLocationChannel::RunError(TInt aError)
	{
	return aError;
	}

const TPositionInfoBase	& CNetworkLocationChannel::GetLastReferencePosition()
	{
	return iRefPosInfo;
	}

void CNetworkLocationChannel::SendNetworkLocationMessage(const TLbsNetLocMsgBase& aMessage)
	{
	iLocationResponses.SetNetworkLocationResponse(aMessage);
	}

void CNetworkLocationChannel::NotifyNetworkLocationRequestUpdate()
	{
	__ASSERT_DEBUG(!IsActive(), User::Invariant());	
	iLocationRequests.NotifyNetworkLocationRequestUpdate(iStatus);
	SetActive();
	}

/* Store the latest position to be sent in from the network.

The network can send two types of position:
1) A 'reference' position - this is sent in before each location request.
   it is usually a fairly inaccurate position, e.g. the area of error
   can be as large as the size of one cell.
2) A 'final' position - this is sent at the end of a location request, before
   the final 'session complete' closes the request. It represents a position 
   returned from the network and may be more accurate than the position
   the terminal sent to the network in reply to the original location request.
   
Both types of location are published on an internal interface so that
other LBS components can access them.
*/
void CNetworkLocationChannel::SetNetworkPosition(const TLbsNetSessionIdInt& aSessionId, const TPositionInfoBase& aPosition)
	{
	// Check that aPosition is a valid TPositionInfoBase type
	TUint32 type = aPosition.PositionClassType();
	if (((type & EPositionInfoUnknownClass) != EPositionInfoUnknownClass)
	    && ((type & EPositionInfoClass) != EPositionInfoClass)
	    && ((type & EPositionCourseInfoClass) != EPositionCourseInfoClass)
	    && ((type & EPositionSatelliteInfoClass) != EPositionSatelliteInfoClass)
	    && ((type & EPositionExtendedSatelliteInfoClass) != EPositionExtendedSatelliteInfoClass))
		{
		// If the aPosition is not a supported positionInfo type, ignore it.
		// (Panic in debug builds)
		__ASSERT_DEBUG(EFalse, User::Panic(_L("LbsNetGateway"), 1));
		return;
		}
	
	// Treat the position as a reference position or final position based
	// on the technology type.
	switch (aPosition.PositionMode())
		{
		case TPositionModuleInfo::ETechnologyNetwork:
			{
			SetReferenceNetworkPosition(aSessionId, aPosition);
			break;
			}
 		case (TPositionModuleInfo::ETechnologyTerminal):
 			 // this will only happen if PM / AGPS module not setting the  'assisted' bit as they should
 			 __ASSERT_DEBUG(EFalse, User::Panic(_L("LbsNetGateway"), 1));
 			 // drop through				
		case (TPositionModuleInfo::ETechnologyNetwork 
			  | TPositionModuleInfo::ETechnologyAssisted):
		case (TPositionModuleInfo::ETechnologyTerminal 
			  | TPositionModuleInfo::ETechnologyAssisted):
			{
			SetFinalNetworkPosition(aSessionId, aPosition);
			break;
			}
		default:
			{
			// Default to treating network positions as a reference position
			SetReferenceNetworkPosition(aSessionId, aPosition);
			break;	
			}
		}
	}

void CNetworkLocationChannel::SetReferenceNetworkPosition(const TLbsNetSessionIdInt& aSessionId, const TPositionInfoBase& aLocation)
	{
	// Store the most recent reference position, so that it can be
	// read when sending a location request to the NRH.

	// The TPositionInfoBase is just the base class, so we need to copy over 
	// the data from the actual concrete class type.
	__ASSERT_DEBUG(aLocation.PositionClassSize() <= sizeof(TPositionExtendedSatelliteInfo), User::Invariant());
	Mem::Copy(&iRefPosInfo, &aLocation, aLocation.PositionClassSize());	
	
	// Broadcast the reference position to the other LBS components.
	TTime actualTime;
	actualTime.UniversalTime();
	iReferencePositionUpdates.SetPositionInfo(aSessionId, KErrNone, aLocation, actualTime);
	}

void CNetworkLocationChannel::SetFinalNetworkPosition(const TLbsNetSessionIdInt& aSessionId, const TPositionInfoBase& aLocation)
	{
	// Set the moduleID based on the PositionMode() of the position info
	// Make a copy so we don't change the posInfo that is owned by the protocol module.
	__ASSERT_DEBUG(iFinalPosInfo.PositionClassSize() >= aLocation.PositionClassSize(), 
				   User::Invariant());
	Mem::Copy(&iFinalPosInfo, &aLocation, aLocation.PositionClassSize());
	switch (iFinalPosInfo.PositionMode())
		{
		case (TPositionModuleInfo::ETechnologyTerminal
			  | TPositionModuleInfo::ETechnologyAssisted):
			{
			iFinalPosInfo.SetModuleId(KLbsGpsLocManagerUid);
			break;
			}
		case (TPositionModuleInfo::ETechnologyNetwork
			  | TPositionModuleInfo::ETechnologyAssisted):
			{
			iFinalPosInfo.SetModuleId(KLbsNetLocManagerUid);
			break;
			}
		default:
			{
			LBSLOG_WARN2(ELogP3, "Unrecognised PositionMode() for a Final Network Position (%d), ignoring update", iFinalPosInfo.PositionMode());
			break;
			}
		}
	
	// Broadcast the final position to the other LBS components.
	TTime actualTime;
	actualTime.UniversalTime();
	iFinalPositionUpdates.SetPositionInfo(aSessionId, KErrNone, iFinalPosInfo, actualTime);
	}