--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/locationmanager/locationtrail/src/clocationrecord.cpp Mon Jan 18 20:34:07 2010 +0200
@@ -0,0 +1,1120 @@
+/*
+* 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: A class for recording and storing locations.
+*
+*/
+
+#include <e32cmn.h>
+#include <LbsErrors.h>
+#include <LbsSatellite.h>
+
+#include "rlocationtrail.h"
+#include "clocationrecord.h"
+#include "cnetworkinfo.h"
+#include "locationmanagerdebug.h"
+#include "locationtraildefs.h"
+#include "locationtrailpskeys.h"
+#include "mdeconstants.h"
+#include <centralrepository.h>
+
+
+using namespace MdeConstants;
+
+// --------------------------------------------------------------------------
+// CLocationRecord::NewL
+// --------------------------------------------------------------------------
+//
+EXPORT_C CLocationRecord* CLocationRecord::NewL()
+ {
+ CLocationRecord* self = new (ELeave) CLocationRecord();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::CLocationRecord
+// --------------------------------------------------------------------------
+//
+CLocationRecord::CLocationRecord()
+ : iNetworkInfoTimer( NULL ),
+ iState( RLocationTrail::ETrailStopped ),
+ iTrailCaptureSetting( RLocationTrail::ECaptureAll ),
+ iLocationCounter( 0 ),
+ iRequestCurrentLoc( EFalse ),
+ iTrailStarted( EFalse ),
+ iLastGPSFixState( EFalse ),
+ iLastLocationId( 0 )
+ {
+ iMaxTrailSize = KMaxTrailLength / KUpdateInterval;
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::ConstructL
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::ConstructL()
+ {
+ const TInt KMillion = 1000000;
+ TInt err = iProperty.Define( KPSUidLocationTrail, KLocationTrailState, RProperty::EInt );
+ if ( err != KErrNone && err != KErrAlreadyExists )
+ {
+ User::Leave( err );
+ }
+ User::LeaveIfError( iProperty.Set( KPSUidLocationTrail,
+ KLocationTrailState, (TInt) RLocationTrail::ETrailStopped ) );
+
+ iNetworkInfo = CNetworkInfo::NewL( this );
+ iPositionInfo = CPositionInfo::NewL( this );
+ iRemapper = CLocationRemappingAO::NewL();
+ iNetworkInfoTimer = CPeriodic::NewL( CActive::EPriorityStandard );
+
+ TInt interval( 0 );
+ TRAP(err, ReadCenRepValueL(KIntervalKey, interval));
+ LOG1("CLocationManagerServer::ConstructL, cenrep interval value:%d", interval);
+
+ if (interval == 0)
+ {
+ LOG1("CLocationManagerServer::ConstructL, cenrep interval err:%d", err);
+ iInterval = KUpdateInterval;
+ }
+ else
+ {
+ iInterval = interval * KMillion;
+ }
+
+ TInt trailLength( 0 );
+ TRAP(err, ReadCenRepValueL(KTrailLengthKey, trailLength));
+ LOG1("CLocationManagerServer::ConstructL, cenrep trail length value:%d", trailLength);
+
+ if ( err != KErrNone )
+ {
+ LOG1("CLocationManagerServer::ConstructL, cenrep trail length err:%d", err);
+ iBufferSize = KMaxTrailLength / iInterval;
+ }
+ else
+ {
+ iBufferSize = trailLength * KMillion / iInterval;
+ }
+
+ TRAP(err, ReadCenRepValueL(KLocationDeltaKey, iLocationDelta));
+ LOG1("CLocationManagerServer::ConstructL, location delta value:%d", iLocationDelta);
+
+ if (iLocationDelta == 0)
+ {
+ LOG1("CLocationManagerServer::ConstructL, location delta err:%d", err);
+ iLocationDelta = KLocationDelta;
+ }
+
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::~CLocationRecord
+// --------------------------------------------------------------------------
+//
+CLocationRecord::~CLocationRecord()
+ {
+ Stop();
+ iProperty.Delete( KPSUidLocationTrail, KLocationTrailState );
+ iProperty.Close();
+ iTrail.Close();
+
+ delete iNetworkInfo;
+ delete iPositionInfo;
+ delete iNetworkInfoTimer;
+ if (iRemapper)
+ {
+ iRemapper->StopRemapping();
+ delete iRemapper;
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::CurrentState
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::LocationTrailState( TLocTrailState& aState )
+ {
+ aState = iState;
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::StartL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::StartL( RLocationTrail::TTrailCaptureSetting aCaptureSetting )
+ {
+ LOG( "CLocationRecord::StartL(), begin" );
+ iTrailCaptureSetting = aCaptureSetting;
+ if ( aCaptureSetting == RLocationTrail::ECaptureAll && !iPositionInfo->IsActive() )
+ {
+ iPositionInfo->StartL( aCaptureSetting, iInterval );
+ }
+ else if ( aCaptureSetting == RLocationTrail::ECaptureNetworkInfo )
+ {
+ // Update and store network info in location trail immediately.
+ // Timer will trigger the update again later.
+ UpdateNetworkInfo( this );
+
+ if ( iNetworkInfoTimer && iNetworkInfoTimer->IsActive() )
+ {
+ iNetworkInfoTimer->Cancel();
+ }
+
+ StartTimerL();
+ }
+
+ iLastLocationId = 0;
+
+ SetCurrentState( RLocationTrail::ETrailStarting );
+
+ iTrailStarted = ETrue;
+ LOG( "CLocationRecord::StartL(), end" );
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::Stop
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::Stop()
+ {
+ LOG( "CLocationRecord::StopL(), begin" );
+ iPositionInfo->Stop();
+ iTrailStarted = EFalse;
+
+ if ( iNetworkInfoTimer && iNetworkInfoTimer->IsActive() )
+ {
+ iNetworkInfoTimer->Cancel();
+ }
+
+ if ( iRemapper )
+ {
+ iRemapper->ResetQueue();
+ }
+ SetCurrentState( RLocationTrail::ETrailStopped );
+ LOG( "CLocationRecord::StopL(), end" );
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::SetStateToStop
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::SetStateToStopping()
+ {
+ SetCurrentState( RLocationTrail::ETrailStopping );
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::GetLocationByTimeL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::GetLocationByTimeL( const TTime aTime,
+ TLocationData& aLocationData,
+ TLocTrailState& aState )
+ {
+ LOG( "CLocationRecord::GetLocationByTimeL(), begin" );
+ TInt posFound( EFalse );
+
+#ifdef _DEBUG
+ _LIT( KDateTimeFormat, "%Y/%M/%D %H:%T:%S" );
+ const TInt DateTimeStrMaxLength = 20;
+ LOG1( "CLocationRecord::GetLocationByTimeL - aTime: %Ld", aTime.Int64() );
+ TBuf<DateTimeStrMaxLength> str1;
+ aTime.FormatL( str1, KDateTimeFormat );
+ LOG1( "CLocationRecord::GetLocationByTimeL - aTime: %S", &str1 );
+#endif
+
+ TTimeIntervalSeconds interval;
+ TTimeIntervalSeconds nextInterval;
+ for ( TInt i(iTrail.Count()-1) ; i >= 0 && !posFound ; i-- )
+ {
+ TInt err = iTrail[i].iTimeStamp.SecondsFrom( aTime, interval );
+
+ TInt timeDiff = Abs( interval.Int() );
+
+#ifdef _DEBUG
+ LOG1( "CLocationRecord::GetLocationByTimeL - Trail timestamp: %Ld", iTrail[i].iTimeStamp.Int64() );
+ TBuf<DateTimeStrMaxLength> str;
+ iTrail[i].iTimeStamp.FormatL( str, KDateTimeFormat );
+ LOG1( "CLocationRecord::GetLocationByTimeL - Trail timestamp: %S", &str );
+ LOG1( "CLocationRecord::GetLocationByTimeL - timeDiff: %d", timeDiff );
+#endif
+
+ if ( err == KErrNone && timeDiff <= KIntervalSeconds )
+ {
+ // The nearest time is in iTrail[i] or in iTrail[i-1].
+ if ( i > 0 )
+ {
+ iTrail[i-1].iTimeStamp.SecondsFrom( aTime, nextInterval );
+
+ TInt nextDiff = Abs( nextInterval.Int() );
+
+ if ( nextDiff < timeDiff )
+ {
+ aLocationData = iTrail[i-1].iLocationData;
+ aState = iTrail[i-1].iTrailState;
+ }
+ else
+ {
+ aLocationData = iTrail[i].iLocationData;
+ aState = iTrail[i].iTrailState;
+ }
+ }
+ else
+ {
+ aLocationData = iTrail[i].iLocationData;
+ aState = iTrail[i].iTrailState;
+ }
+ posFound = ETrue;
+ }
+ }
+ if ( !posFound )
+ {
+ User::Leave( KErrNotFound );
+ }
+ LOG( "CLocationRecord::GetLocationByTimeL(), end" );
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::RequestLocationL
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::RequestLocationL()
+ {
+ iRequestCurrentLoc = ETrue;
+ if ( iTrailCaptureSetting != RLocationTrail::ECaptureNetworkInfo &&
+ !iPositionInfo->IsActive() )
+ {
+ iPositionInfo->StartL( iTrailCaptureSetting, iInterval );
+ }
+ else if ( iTrailCaptureSetting == RLocationTrail::ECaptureNetworkInfo )
+ {
+ TPositionSatelliteInfo posInfo;
+ CTelephony::TNetworkInfoV1 network = CTelephony::TNetworkInfoV1();
+ GetNetworkInfo( network );
+ iObserver->CurrentLocation( posInfo, network, KErrNone );
+ iRequestCurrentLoc = EFalse;
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::CancelLocationRequest
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::CancelLocationRequest()
+ {
+ iRequestCurrentLoc = EFalse;
+ if ( !iTrailStarted )
+ {
+ iPositionInfo->Stop();
+ }
+ }
+
+
+// --------------------------------------------------------------------------
+// CLocationRecord::GetNetworkInfo
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::GetNetworkInfo( CTelephony::TNetworkInfoV1& aNetworkInfo )
+ {
+ LOG("CLocationRecord::GetNetworkInfo");
+
+ aNetworkInfo = iNetwork;
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::SetObserver
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::SetObserver( MLocationTrailObserver* aObserver)
+ {
+ iObserver = aObserver;
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::SetAddObserver
+// --------------------------------------------------------------------------
+//
+EXPORT_C void CLocationRecord::SetAddObserver( MLocationAddObserver* aObserver)
+ {
+ iAddObserver = aObserver;
+ }
+
+// --------------------------------------------------------------------------
+// From MNetworkInfoObserver.
+// CLocationRecord::Position
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::Position( const TPositionInfo& aPositionInfo,
+ const TInt aError )
+ {
+ const TPositionSatelliteInfo& positionSatelliteInfo =
+ static_cast<const TPositionSatelliteInfo&>(aPositionInfo);
+
+ if ( iRequestCurrentLoc )
+ {
+ HandleLocationRequest( positionSatelliteInfo, aError );
+ }
+ if( iState == RLocationTrail::ETrailStopped )
+ {
+ LOG("CLocationRecord::Position - trail stopped");
+ return;
+ }
+
+ if ( !iTrailStarted )
+ {
+ iPositionInfo->NextPosition();
+ return;
+ }
+ switch ( aError )
+ {
+ case KPositionPartialUpdate: // fall through
+ case KPositionQualityLoss:
+ {
+ // Location is stored, even if it may not be valid.
+ StoreLocation( positionSatelliteInfo );
+ LOG("CLocationRecord::Position - partial update");
+ if ( iState != RLocationTrail::EWaitingGPSData &&
+ iState != RLocationTrail::ETrailStopping )
+ {
+ SetCurrentState( RLocationTrail::EWaitingGPSData );
+ LOG("CLocationRecord::Position trail waiting for gps");
+ }
+ break;
+ }
+ case KErrNone:
+ {
+ StoreLocation( positionSatelliteInfo );
+ LOG("CLocationRecord::Position - good GPS coordinates");
+ if ( iState != RLocationTrail::ETrailStarted )
+ {
+ if ( iRemapper )
+ {
+ LOG("CLocationRecord::Position start remapping");
+ iLastLocationId = 0;
+ TBool createLocation = iRemapper->CheckQueue();
+ if( createLocation )
+ {
+ TRAP_IGNORE(
+ TItemId locationId = DoCreateLocationL( iNewItem.iLocationData );
+ iRemapper->UpdateRelationsL( locationId );
+ )
+ }
+ iRemapper->StartRemappingObjects( iNewItem.iLocationData );
+ }
+ if ( iState != RLocationTrail::ETrailStopping )
+ {
+ SetCurrentState( RLocationTrail::ETrailStarted );
+ LOG("CLocationRecord::Position trail started");
+ }
+ }
+ break;
+ }
+ default:
+ {
+ StoreLocation( positionSatelliteInfo );
+ LOG1("CLocationRecord::Position - searching GPS, aError %d", aError );
+ if ( iState != RLocationTrail::ESearchingGPS &&
+ iState != RLocationTrail::ETrailStopping )
+ {
+ SetCurrentState( RLocationTrail::ESearchingGPS );
+ LOG("CLocationRecord::Position trail searching gps");
+ }
+ break;
+ }
+ }
+ TBool fixState = CheckGPSFix( positionSatelliteInfo );
+ LOG1( "CLocationRecord::Position fixState %d", fixState );
+ LOG1( "CLocationRecord::Position iLastGPSFixState %d", iLastGPSFixState );
+
+ if ( iObserver && iLastGPSFixState != fixState )
+ {
+ LOG("CLocationRecord::Position quality changed");
+ iObserver->GPSSignalQualityChanged( positionSatelliteInfo );
+ }
+
+ iLastGPSFixState = fixState;
+
+ iPositionInfo->NextPosition();
+ }
+
+TBool CLocationRecord::CheckGPSFix( const TPositionSatelliteInfo& aSatelliteInfo )
+ {
+ TPosition position;
+ aSatelliteInfo.GetPosition( position );
+ LOG1( "CLocationRecord::CheckGPSFix latitude %f", position.Latitude() );
+ LOG1( "CLocationRecord::CheckGPSFix longitude %f", position.Longitude() );
+ TBool ret = ( Math::IsNaN(position.Latitude()) || Math::IsNaN(position.Longitude()) )
+ ? EFalse : ETrue;
+ return ret;
+ }
+
+// --------------------------------------------------------------------------
+// From MPositionerObserver.
+// CLocationRecord::NetworkInfo
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::NetworkInfo( const CTelephony::TNetworkInfoV1 &aNetworkInfo,
+ const TInt aError )
+ {
+ LOG("CLocationRecord::NetworkInfo");
+ if ( aError == KErrNone )
+ {
+ LOG("CLocationRecord::NetworkInfo - KErrNone");
+ iNetwork = aNetworkInfo;
+ if (iNetwork.iAccess == CTelephony::ENetworkAccessUtran)
+ {
+ iNetwork.iLocationAreaCode = 0;
+ }
+ if ( iState == RLocationTrail::ETrailStarting && iTrailStarted )
+ {
+ SetCurrentState( RLocationTrail::ETrailStarted );
+ }
+ }
+ else
+ {
+ LOG1("CLocationRecord::NetworkInfo - %d", aError );
+ iNetwork = CTelephony::TNetworkInfoV1();
+ iNetwork.iAreaKnown = EFalse;
+ iNetwork.iAccess = CTelephony::ENetworkAccessUnknown;
+ iNetwork.iCellId = 0;
+ iNetwork.iLocationAreaCode = 0;
+ iNetwork.iCountryCode.Zero();
+ iNetwork.iNetworkId.Zero();
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::StoreLocationL
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::StoreLocation( const TPositionSatelliteInfo& aSatelliteInfo )
+ {
+ aSatelliteInfo.GetPosition( iNewItem.iLocationData.iPosition );
+ aSatelliteInfo.GetCourse( iNewItem.iLocationData.iCourse );
+ iNewItem.iLocationData.iSatellites = aSatelliteInfo.NumSatellitesUsed();
+ iNewItem.iLocationData.iQuality = aSatelliteInfo.HorizontalDoP();
+
+ // Network info
+ GetNetworkInfo( iNewItem.iLocationData.iNetworkInfo );
+ // Get Universal time
+ iNewItem.iTimeStamp.UniversalTime();
+ iNewItem.iTrailState = iState;
+
+ TInt error = iTrail.Append( iNewItem );
+
+ // If appending an item to the trail fails because of OOM, remove oldest trail items
+ // until the new item fits or there's only one item left in the trail.
+ while ( error == KErrNoMemory && iTrail.Count() > 1 )
+ {
+ LOG("CLocationRecord::StoreLocation - Out of memory! Shortening trail!");
+ iTrail.Remove( 0 );
+ error = iTrail.Append( iNewItem );
+ }
+
+ if ( iTrail.Count() > iMaxTrailSize )
+ {
+ iTrail.Remove( 0 );
+ }
+
+ if( iAddObserver )
+ {
+ iAddObserver->LocationAdded( iNewItem, aSatelliteInfo );
+ }
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::SetCurrentState
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::SetCurrentState( TLocTrailState aState )
+ {
+ LOG1( "CLocationRecord::SetCurrentState(), begin, state:%d", aState );
+ iState = aState;
+ iProperty.Set( KPSUidLocationTrail, KLocationTrailState, (TInt) aState );
+ if ( iObserver )
+ {
+ iObserver->LocationTrailStateChange();
+ }
+ LOG( "CLocationRecord::SetCurrentState(), end" );
+ }
+
+// --------------------------------------------------------------------------
+// CLocationRecord::HandleLocationRequest
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::HandleLocationRequest( const TPositionSatelliteInfo& aSatelliteInfo,
+ const TInt aError )
+ {
+ CTelephony::TNetworkInfoV1 network = CTelephony::TNetworkInfoV1();
+ if ( aError == KErrNone )
+ {
+ GetNetworkInfo( network );
+ iObserver->CurrentLocation( aSatelliteInfo, network, aError );
+ iRequestCurrentLoc = EFalse;
+ if ( !iTrailStarted )
+ {
+ iPositionInfo->Stop();
+ }
+ }
+ else
+ {
+ iLocationCounter++;
+ if ( iLocationCounter > KCurrentLocTimeoutCount )
+ {
+ iObserver->CurrentLocation( aSatelliteInfo, network, KErrTimedOut );
+ iRequestCurrentLoc = EFalse;
+ iLocationCounter = 0;
+ if ( !iTrailStarted )
+ {
+ iPositionInfo->Stop();
+ }
+ }
+ }
+ }
+
+TInt CLocationRecord::UpdateNetworkInfo( TAny* aAny )
+ {
+ TPositionSatelliteInfo nullPositionInfo;
+ CLocationRecord* self = STATIC_CAST( CLocationRecord*, aAny );
+ self->StoreLocation( nullPositionInfo );
+ return KErrNone;
+ }
+
+
+EXPORT_C void CLocationRecord::CreateLocationObjectL( const TLocationData& aLocationData,
+ const TUint& aObjectId )
+ {
+ TItemId locationId = DoCreateLocationL( aLocationData );
+ CreateRelationL( aObjectId, locationId );
+ }
+
+
+EXPORT_C void CLocationRecord::LocationSnapshotL( const TUint& aObjectId )
+ {
+ LOG("CLocationRecord::LocationSnapshotL");
+
+ TBool previousMatch = EFalse;
+ CMdENamespaceDef& namespaceDef = iMdeSession->GetDefaultNamespaceDefL();
+
+ // get locationdata from trail with object time
+ TTime timestamp = GetMdeObjectTimeL( aObjectId );
+ TLocationData locationData;
+ TLocTrailState state;
+ GetLocationByTimeL( timestamp, locationData, state );
+
+ iObjectId = aObjectId;
+ iLocationData = locationData;
+
+ // capture only network data
+ if ( iTrailCaptureSetting == RLocationTrail::ECaptureNetworkInfo )
+ {
+ CTelephony::TNetworkInfoV1* net = &locationData.iNetworkInfo;
+
+ if ( net->iCellId == 0 &&
+ net->iLocationAreaCode == 0 &&
+ net->iCountryCode.Length() == 0 &&
+ net->iNetworkId.Length() == 0 )
+ {
+ // nothing to do
+ LOG("CLocationRecord::LocationSnapshotL - no network info available");
+ }
+ else if ( iLastLocationId != 0 )
+ {
+ CTelephony::TNetworkInfoV1* lastnet = &iLastLocation.iNetworkInfo;
+
+ // compare to previous network info
+ TItemId locationId = iLastLocationId;
+ if ( lastnet->iCellId != net->iCellId ||
+ lastnet->iLocationAreaCode != net->iLocationAreaCode ||
+ lastnet->iCountryCode != net->iCountryCode ||
+ lastnet->iNetworkId != net->iNetworkId )
+ {
+ LOG("CLocationRecord::LocationSnapshotL - network info changed");
+ locationId = DoCreateLocationL( locationData );
+ }
+ CreateRelationL( aObjectId, locationId );
+ }
+ else
+ {
+ // new location
+ TItemId locationId = DoCreateLocationL( locationData );
+ CreateRelationL( aObjectId, locationId );
+ }
+ return;
+ }
+
+ // coordinates empty (will be remapped)
+ if ( Math::IsNaN( locationData.iPosition.Latitude() ) &&
+ Math::IsNaN( locationData.iPosition.Longitude() ))
+ {
+ TRemapItem remapItem;
+ remapItem.iObjectId = aObjectId;
+ remapItem.iTime = timestamp;
+
+ CTelephony::TNetworkInfoV1* net = &locationData.iNetworkInfo;
+
+ // no network info (offline mode + no GPS fix)
+ if ( net->iCellId == 0 &&
+ net->iLocationAreaCode == 0 &&
+ net->iCountryCode.Length() == 0 &&
+ net->iNetworkId.Length() == 0 )
+ {
+ LOG("CLocationRecord::LocationSnapshotL - empty remap item created");
+ }
+ // check match for last created locationobject
+ else if ( iLastLocationId != 0 )
+ {
+ TItemId locationId;
+ CTelephony::TNetworkInfoV1* lastnet = &iLastLocation.iNetworkInfo;
+
+ // networkinfo changed from last location
+ if ( lastnet->iCellId != net->iCellId ||
+ lastnet->iLocationAreaCode != net->iLocationAreaCode ||
+ lastnet->iCountryCode != net->iCountryCode ||
+ lastnet->iNetworkId != net->iNetworkId )
+ {
+ LOG("CLocationRecord::LocationSnapshotL - remap with new network info");
+ locationId = DoCreateLocationL( locationData );
+ }
+ else
+ {
+ LOG("CLocationRecord::LocationSnapshotL - remap with previous network info");
+ locationId = iLastLocationId;
+ }
+ TItemId relationId = CreateRelationL( aObjectId, locationId );
+ remapItem.iLocationId = locationId;
+ remapItem.iRelationId = relationId;
+ }
+ else
+ {
+ // new location with only network data
+ TItemId locationId = DoCreateLocationL( locationData );
+ TItemId relationId = CreateRelationL( aObjectId, locationId );
+ remapItem.iLocationId = locationId;
+ remapItem.iRelationId = relationId;
+ }
+ iRemapper->Append( remapItem );
+ return;
+ }
+
+ // valid coordinates found
+ if ( iLastLocationId != 0 )
+ {
+ CTelephony::TNetworkInfoV1* net = &locationData.iNetworkInfo;
+ CTelephony::TNetworkInfoV1* lastnet = &iLastLocation.iNetworkInfo;
+
+ // first check if networkinfo matches last created location
+ if ( lastnet->iCellId == net->iCellId &&
+ lastnet->iLocationAreaCode == net->iLocationAreaCode &&
+ lastnet->iCountryCode == net->iCountryCode &&
+ lastnet->iNetworkId == net->iNetworkId )
+ {
+ LOG("CLocationRecord::LocationSnapshotL - network info matches");
+
+ // if both locations have valid coordinates, calculate distance between points
+ if ( !Math::IsNaN( iLastLocation.iPosition.Latitude() ) &&
+ !Math::IsNaN( iLastLocation.iPosition.Longitude() ) &&
+ !Math::IsNaN( locationData.iPosition.Latitude() ) &&
+ !Math::IsNaN( locationData.iPosition.Longitude() ))
+ {
+ TReal32 distance;
+ TInt err = locationData.iPosition.Distance(iLastLocation.iPosition, distance);
+
+ if ( distance < iLocationDelta )
+ {
+ LOG("CLocationRecord::LocationSnapshotL - location close to the previous one");
+ previousMatch = ETrue;
+ CreateRelationL( aObjectId, iLastLocationId );
+ LOG("CLocationRecord::CreateLocationObjectL - last location matched");
+ }
+ }
+ }
+ }
+
+ // last location did not match, find existing one from DB
+ if( !previousMatch )
+ {
+ LOG("CLocationRecord::LocationSnapshotL - query location");
+ const TReal64 KMeterInDegrees = 0.000009;
+ const TReal64 KPi = 3.14159265358979;
+ const TReal32 K180Degrees = 180.0;
+
+ TReal64 latitude = locationData.iPosition.Latitude();
+ TReal64 longitude = locationData.iPosition.Longitude();
+ // calculate distance in degrees
+ TReal64 cosine;
+ Math::Cos(cosine, locationData.iPosition.Latitude() * KPi / K180Degrees );
+ TReal64 latDelta = iLocationDelta * KMeterInDegrees;
+ TReal64 lonDelta = latDelta * cosine;
+
+ CMdEObjectDef& locationObjectDef = namespaceDef.GetObjectDefL( Location::KLocationObject );
+
+ CMdEPropertyDef& latitudeDef = locationObjectDef.GetPropertyDefL(
+ Location::KLatitudeProperty );
+ CMdEPropertyDef& longitudeDef = locationObjectDef.GetPropertyDefL(
+ Location::KLongitudeProperty );
+ CMdEPropertyDef& cellIdDef = locationObjectDef.GetPropertyDefL(
+ Location::KCellIdProperty );
+ CMdEPropertyDef& locationCodeDef = locationObjectDef.GetPropertyDefL(
+ Location::KLocationAreaCodeProperty );
+ CMdEPropertyDef& countryCodeDef = locationObjectDef.GetPropertyDefL(
+ Location::KCountryCodeProperty );
+ CMdEPropertyDef& networkCodeDef = locationObjectDef.GetPropertyDefL(
+ Location::KNetworkCodeProperty );
+
+ iLocationQuery = iMdeSession->NewObjectQueryL( namespaceDef, locationObjectDef, this );
+ CMdELogicCondition& cond = iLocationQuery->Conditions();
+ cond.SetOperator( ELogicConditionOperatorAnd );
+
+ LOG1( "CLocationRecord::LocationSnapshotL latitude: %f", latitude);
+ LOG1( "CLocationRecord::LocationSnapshotL latdelta: %f", latDelta);
+ LOG1( "CLocationRecord::LocationSnapshotL longitude: %f", longitude);
+ LOG1( "CLocationRecord::LocationSnapshotL londelta: %f", lonDelta);
+
+ cond.AddPropertyConditionL( latitudeDef,
+ TMdERealBetween( latitude - latDelta, latitude + latDelta ));
+ cond.AddPropertyConditionL( longitudeDef,
+ TMdERealBetween( longitude - lonDelta, longitude + lonDelta ));
+ cond.AddPropertyConditionL( cellIdDef,
+ TMdEUintEqual( locationData.iNetworkInfo.iCellId) );
+ cond.AddPropertyConditionL( locationCodeDef,
+ TMdEUintEqual( locationData.iNetworkInfo.iLocationAreaCode) );
+ cond.AddPropertyConditionL( countryCodeDef, ETextPropertyConditionCompareEquals,
+ locationData.iNetworkInfo.iCountryCode );
+ cond.AddPropertyConditionL( networkCodeDef, ETextPropertyConditionCompareEquals,
+ locationData.iNetworkInfo.iNetworkId );
+
+ iLocationQuery->FindL();
+ }
+ }
+
+
+TItemId CLocationRecord::DoCreateLocationL( const TLocationData& aLocationData )
+ {
+ LOG("CLocationRecord::DoCreateLocationL - start");
+ TItemId locationObjectId;
+
+ CMdENamespaceDef& namespaceDef = iMdeSession->GetDefaultNamespaceDefL();
+
+ CMdEObjectDef& locationObjectDef = namespaceDef.GetObjectDefL( Location::KLocationObject );
+
+ // required object properties
+ CMdEPropertyDef& creationDef = locationObjectDef.GetPropertyDefL(
+ Object::KCreationDateProperty );
+ CMdEPropertyDef& modifiedDef = locationObjectDef.GetPropertyDefL(
+ Object::KLastModifiedDateProperty );
+ CMdEPropertyDef& sizeDef = locationObjectDef.GetPropertyDefL(
+ Object::KSizeProperty );
+ CMdEPropertyDef& itemTypeDef = locationObjectDef.GetPropertyDefL(
+ Object::KItemTypeProperty );
+ CMdEPropertyDef& offSetDef = locationObjectDef.GetPropertyDefL(
+ Object::KTimeOffsetProperty );
+
+ // location related properties
+ CMdEPropertyDef& cellIdDef = locationObjectDef.GetPropertyDefL(
+ Location::KCellIdProperty );
+ CMdEPropertyDef& latitudeDef = locationObjectDef.GetPropertyDefL(
+ Location::KLatitudeProperty );
+ CMdEPropertyDef& longitudeDef = locationObjectDef.GetPropertyDefL(
+ Location::KLongitudeProperty );
+ CMdEPropertyDef& altitudeDef = locationObjectDef.GetPropertyDefL(
+ Location::KAltitudeProperty );
+
+ CMdEPropertyDef& directionDef = locationObjectDef.GetPropertyDefL(
+ Location::KDirectionProperty );
+ CMdEPropertyDef& speedDef = locationObjectDef.GetPropertyDefL(
+ Location::KSpeedProperty );
+ CMdEPropertyDef& locationCodeDef = locationObjectDef.GetPropertyDefL(
+ Location::KLocationAreaCodeProperty );
+ CMdEPropertyDef& countryCodeDef = locationObjectDef.GetPropertyDefL(
+ Location::KCountryCodeProperty );
+ CMdEPropertyDef& networkCodeDef = locationObjectDef.GetPropertyDefL(
+ Location::KNetworkCodeProperty );
+ CMdEPropertyDef& qualityDef = locationObjectDef.GetPropertyDefL(
+ Location::KQualityProperty );
+
+ // location object
+ CMdEObject* locationObject = NULL;
+
+ locationObject = iMdeSession->NewObjectL( locationObjectDef, Object::KAutomaticUri );
+ CleanupStack::PushL( locationObject );
+
+ TTime timestamp( 0 );
+ timestamp.UniversalTime();
+
+ TTimeIntervalSeconds timeOffset = User::UTCOffset();
+ TTime localTime = timestamp + timeOffset;
+
+ // required object properties
+ locationObject->AddTimePropertyL( creationDef, localTime );
+ locationObject->AddTimePropertyL( modifiedDef, timestamp );
+ locationObject->AddUint32PropertyL( sizeDef, 0 ); // always zero size for location objects
+ locationObject->AddTextPropertyL( itemTypeDef, Location::KLocationItemType );
+ locationObject->AddInt16PropertyL( offSetDef, timeOffset.Int() / 60 );
+
+ LOG1( "CLocationRecord::DoCreateLocationL - location created with stamp: %Ld", timestamp.Int64() );
+
+ // location related properties
+ if ( !Math::IsNaN( aLocationData.iPosition.Latitude() ) &&
+ !Math::IsNaN( aLocationData.iPosition.Longitude() ))
+ {
+ locationObject->AddReal64PropertyL( latitudeDef, aLocationData.iPosition.Latitude() );
+ locationObject->AddReal64PropertyL( longitudeDef, aLocationData.iPosition.Longitude() );
+ }
+ if ( !Math::IsNaN( aLocationData.iPosition.Altitude() ) )
+ {
+ locationObject->AddReal64PropertyL( altitudeDef, aLocationData.iPosition.Altitude() );
+ }
+ if ( !Math::IsNaN( aLocationData.iCourse.Course() ) )
+ {
+ locationObject->AddReal32PropertyL( directionDef, aLocationData.iCourse.Course() );
+ }
+ if ( !Math::IsNaN( aLocationData.iCourse.Speed() ) )
+ {
+ locationObject->AddReal32PropertyL( speedDef, aLocationData.iCourse.Speed() );
+ }
+ if ( !Math::IsNaN( aLocationData.iQuality ) )
+ {
+ locationObject->AddReal32PropertyL( qualityDef, aLocationData.iQuality );
+ }
+
+ // network related properties
+ if ( aLocationData.iNetworkInfo.iAreaKnown )
+ {
+ if ( aLocationData.iNetworkInfo.iAccess != CTelephony::ENetworkAccessUnknown )
+ {
+ locationObject->AddUint32PropertyL( cellIdDef, aLocationData.iNetworkInfo.iCellId );
+
+ }
+ if ( aLocationData.iNetworkInfo.iLocationAreaCode != 0 &&
+ aLocationData.iNetworkInfo.iAccess != CTelephony::ENetworkAccessUnknown )
+ {
+ locationObject->AddUint32PropertyL( locationCodeDef,
+ aLocationData.iNetworkInfo.iLocationAreaCode );
+
+ }
+ if ( aLocationData.iNetworkInfo.iCountryCode.Length() > 0 )
+ {
+ locationObject->AddTextPropertyL( countryCodeDef,
+ aLocationData.iNetworkInfo.iCountryCode );
+
+ }
+ if ( aLocationData.iNetworkInfo.iNetworkId.Length() > 0 )
+ {
+ locationObject->AddTextPropertyL(networkCodeDef, aLocationData.iNetworkInfo.iNetworkId);
+
+ }
+ }
+
+ // Add the location object to the database.
+ locationObjectId = iMdeSession->AddObjectL( *locationObject );
+
+ iLastLocationId = locationObjectId;
+ iLastLocation = aLocationData;
+
+ CleanupStack::PopAndDestroy( locationObject );
+
+ LOG("CLocationRecord::DoCreateLocationL - end");
+
+ return locationObjectId;
+ }
+
+
+TItemId CLocationRecord::CreateRelationL( const TUint& aObjectId, const TUint& aLocationId )
+ {
+ LOG("CLocationRecord::CreateRelationL - start");
+ CMdENamespaceDef& namespaceDef = iMdeSession->GetDefaultNamespaceDefL();
+
+ // "contains" relation definition
+ CMdERelationDef& containsRelDef = namespaceDef.GetRelationDefL(
+ Relations::KContainsLocation );
+
+ CMdERelation* relationObject = iMdeSession->NewRelationLC( containsRelDef,
+ aObjectId, aLocationId, 0 );
+ if ( !relationObject )
+ {
+ User::Leave( KErrBadHandle );
+ }
+ TItemId relationId = iMdeSession->AddRelationL( *relationObject );
+
+ CleanupStack::PopAndDestroy( relationObject );
+ LOG("CLocationRecord::CreateRelationL - end");
+
+ return relationId;
+ }
+
+// --------------------------------------------------------------------------
+// CLocationManagerServer::ReadCenRepValueL
+// --------------------------------------------------------------------------
+//
+void CLocationRecord::ReadCenRepValueL(TInt aKey, TInt& aValue)
+ {
+ LOG( "CLocationRecord::::ReadCenRepValueL(), begin" );
+ CRepository* repository;
+ repository = CRepository::NewLC( KRepositoryUid );
+ User::LeaveIfError(repository->Get( aKey, aValue));
+ CleanupStack::PopAndDestroy(repository);
+ LOG( "CLocationRecord::::ReadCenRepValueL(), end" );
+ }
+
+void CLocationRecord::HandleQueryNewResults(CMdEQuery& /*aQuery*/, TInt /*aFirstNewItemIndex*/,
+ TInt /*aNewItemCount*/)
+ {
+ }
+
+void CLocationRecord::HandleQueryCompleted(CMdEQuery& aQuery, TInt aError)
+ {
+ LOG("CLocationRecord::HandleQueryCompleted - start");
+ const TInt count = aQuery.Count();
+ LOG1("CLocationRecord::HandleQueryCompleted count: %d", count);
+
+ CMdENamespaceDef* namespaceDef = NULL;
+
+ TRAP_IGNORE( namespaceDef = &iMdeSession->GetDefaultNamespaceDefL() );
+ if ( namespaceDef )
+ {
+ CMdEObjectDef* locationObjectDef = NULL;
+
+ TRAP_IGNORE( locationObjectDef = &namespaceDef->GetObjectDefL( Location::KLocationObject ) );
+ if ( locationObjectDef )
+ {
+ CMdEPropertyDef* latitudeDef = NULL;
+ CMdEPropertyDef* longitudeDef = NULL;
+ CMdEPropertyDef* altitudeDef = NULL;
+
+ TRAP_IGNORE(
+ latitudeDef = &locationObjectDef->GetPropertyDefL(
+ Location::KLatitudeProperty );
+ longitudeDef = &locationObjectDef->GetPropertyDefL(
+ Location::KLongitudeProperty );
+ altitudeDef = &locationObjectDef->GetPropertyDefL(
+ Location::KAltitudeProperty );
+ );
+
+ if( latitudeDef && longitudeDef && altitudeDef )
+ {
+ TBool created = EFalse;
+ for ( TInt i = 0; i < count; i++ )
+ {
+ LOG1("CLocationRecord::HandleQueryCompleted check item: %d", i);
+ CMdEItem& item = aQuery.ResultItem(i);
+ CMdEObject& locationObject = static_cast<CMdEObject&>(item);
+
+ CMdEProperty* latProp = NULL;
+ CMdEProperty* lonProp = NULL;
+ CMdEProperty* altProp = NULL;
+
+ locationObject.Property( *latitudeDef, latProp, 0 );
+ locationObject.Property( *longitudeDef, lonProp, 0 );
+ locationObject.Property( *altitudeDef, altProp, 0 );
+
+ if ( latProp && lonProp )
+ {
+ TReal32 distance;
+ TCoordinate newCoords;
+ if ( altProp )
+ {
+ TRAP_IGNORE( newCoords = TCoordinate( latProp->Real64ValueL(), lonProp->Real64ValueL(), (TReal32)altProp->Real64ValueL() ) );
+ }
+ else
+ {
+ TRAP_IGNORE( newCoords = TCoordinate( latProp->Real64ValueL(), lonProp->Real64ValueL() ) );
+ }
+
+ const TInt err = iLocationData.iPosition.Distance(newCoords, distance);
+
+ if ( distance < iLocationDelta )
+ {
+ LOG("CLocationRecord::HandleQueryCompleted - match found in db");
+ TRAPD( err, CreateRelationL( iObjectId, locationObject.Id() ) );
+ if( err == KErrNone)
+ {
+ created = ETrue;
+ i = count;
+ }
+ else
+ {
+ aError = err;
+ }
+ }
+ }
+ }
+
+ if ( !created && aError == KErrNone )
+ {
+ LOG("CLocationRecord::HandleQueryCompleted - no match found in db, create new");
+ TInt locationId( 0 );
+ TRAPD( err, locationId = DoCreateLocationL( iLocationData ) );
+ LOG1("CLocationRecord::HandleQueryCompleted - DoCreateLocationL err: %d", err);
+ if( err == KErrNone )
+ {
+ TRAP( err, CreateRelationL( iObjectId, locationId ));
+ LOG1("CLocationRecord::HandleQueryCompleted - CreateRelationL err: %d", err);
+ }
+ }
+ }
+ }
+ }
+
+ LOG("CLocationRecord::HandleQueryCompleted - end");
+ }
+
+EXPORT_C void CLocationRecord::SetMdeSession( CMdESession* aSession )
+ {
+ iMdeSession = aSession;
+ TRAPD(err, iRemapper->InitialiseL( aSession ));
+ if( err != KErrNone )
+ {
+ delete iRemapper;
+ iRemapper = NULL;
+ }
+ }
+
+void CLocationRecord::StartTimerL()
+ {
+ LOG("CLocationRecord::StartTimerL");
+
+ if( !iNetworkInfoTimer->IsActive() )
+ {
+ iNetworkInfoTimer->Start( iInterval, iInterval, TCallBack( UpdateNetworkInfo, this ) );
+ }
+ }
+
+TTime CLocationRecord::GetMdeObjectTimeL( TItemId aObjectId )
+ {
+ CMdENamespaceDef& namespaceDef = iMdeSession->GetDefaultNamespaceDefL();
+
+ CMdEObjectDef& objectDef = namespaceDef.GetObjectDefL( Object::KBaseObject );
+ CMdEPropertyDef& timeDef = objectDef.GetPropertyDefL( Object::KLastModifiedDateProperty );
+
+ CMdEObject* object = NULL;
+ CMdEProperty* property = NULL;
+
+ object = iMdeSession->GetObjectL( aObjectId );
+ object->Property( timeDef, property, 0 );
+ if ( !property )
+ {
+ User::Leave( KErrNotFound );
+ }
+ return property->TimeValueL();
+ }
+
+EXPORT_C TBool CLocationRecord::RemappingNeeded()
+ {
+ return iRemapper->ItemsInQueue();
+ }
+
+// End of file