diff -r 000000000000 -r c53acadfccc6 locationmanager/locationtrail/src/clocationrecord.cpp --- /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 +#include +#include + +#include "rlocationtrail.h" +#include "clocationrecord.h" +#include "cnetworkinfo.h" +#include "locationmanagerdebug.h" +#include "locationtraildefs.h" +#include "locationtrailpskeys.h" +#include "mdeconstants.h" +#include + + +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 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 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(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(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