diff -r f5050f1da672 -r 04becd199f91 javaextensions/location/position/src/cpositionerbase.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaextensions/location/position/src/cpositionerbase.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,379 @@ +/* +* Copyright (c) 2008 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: Base class for position request classes + * +*/ + + +// INCLUDE FILES +#include "cpositionerbase.h" +#include "s60commonutils.h" +#include "logger.h" + +using namespace java::location; + +// UNNAMED LOCAL NAMESPACE +namespace +{ +// Default size of the position info buffer if NMEA statements are supported +// In fact, this is four times the standard buffer size +const TInt KLocPositionGenericInfoNMEABufferSize = 0x1000; // Dec 4096 + +// Default maximum number of fields if NMEA statements are supported +// In fact, this is four times the default field count +const TInt KLocPositionGenericInfoNMEAFieldCount = 0x0080; // Dec 128 + +// Default buffer size increase. This is based on to BT GPS PSY standard +// buffer which is the size of 5K. Usually 1K increase should be enough +// since it is the standard size of HPositionGenericInfo when constructed +const TInt KLocBufferSizeIncrease = 0x0400; // 1024 + +// Default increase for accepted fields in position info buffer. This is based +// on to MLFW default field count which is 32. The increse is synchronized +// with the buffer size increase as these values are the same default values +// which are used when HPositionGenericInfo is generated without parameters +const TInt KLocFieldCountIncrease = 0x0020; // 32 + +const TInt KNumFields = 17; +const TUint16 positionField[KNumFields] = + { EPositionFieldStreetExtension, EPositionFieldStreet, + EPositionFieldPostalCode, EPositionFieldCity, EPositionFieldCounty, + EPositionFieldState, EPositionFieldCountry, EPositionFieldCountryCode, + EPositionFieldDistrict, EPositionFieldBuildingName, + EPositionFieldBuildingFloor, EPositionFieldBuildingRoom, + EPositionFieldBuildingZone, EPositionFieldCrossing1, + EPositionFieldCrossing2, EPositionFieldMediaLinks, + EPositionFieldBuildingTelephone + }; +} + +// ============================ MEMBER FUNCTIONS =============================== + +// ----------------------------------------------------------------------------- +// CPositionerBase::CPositionerBase +// C++ default constructor can NOT contain any code, that +// might leave. +// ----------------------------------------------------------------------------- +// +CPositionerBase::CPositionerBase(LocationFunctionServer* aFunctionSource) : + CActive(EPriorityNormal), mFunctionServer(aFunctionSource), iCapabilities( + TPositionModuleInfo::ECapabilityNone) +{ + CActiveScheduler::Add(this); +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::BaseConstructL +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CPositionerBase::BaseConstructL(RPositionServer& aServer, + TPositionModuleId aModuleId, + TPositionModuleInfo::TCapabilities aCapabilities) +{ + JELOG2(EJavaLocation); + + User::LeaveIfError(iPositioner.Open(aServer, aModuleId)); + + _LIT(KService, "JavaVM"); + iPositioner.SetRequestor(CRequestor::ERequestorService, + CRequestor::EFormatApplication, KService); + + iCapabilities = aCapabilities; + + // By default, MLFW uses 1K buffer for location information. If the + // PSY is capable of providing NMEA statements then the default buffer + // runs out very quickly and the buffer size needs to adjusted. This may + // cause delays when getting location fixes to Java-side. So if the + // module supports NMEA statements then a larger buffer is created + // by default. For example, BT GPS PSY receives all NMEA statements + // that the module can provide so the default buffer size is not enough + // Also the maximum number of fields needs to be changed in that case + + if (iCapabilities & TPositionModuleInfo::ECapabilityNmea) + { + iPositionInfo = CreatePositionInfoL( + KLocPositionGenericInfoNMEABufferSize, + KLocPositionGenericInfoNMEAFieldCount); + } + else + { + // Use default values defined in MLFW. Currently 1K for the buffer + // size and the maximum number of 32 fields supported. + iPositionInfo = CreatePositionInfoL( + KPositionGenericInfoDefaultBufferSize, + KPositionGenericInfoDefaultMaxFields); + } +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::~CPositionerBase +// ----------------------------------------------------------------------------- +// +CPositionerBase::~CPositionerBase() +{ + JELOG2(EJavaLocation); + delete iPositionInfo; + iPositioner.Close(); +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::GetQualifiedCoordinates +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPositionerBase::GetQualifiedCoordinates(CPositionerBase* aSelf, + JNIEnv* aJni, jdouble* alatlon, jfloat* aAltHaccVacc, + jlong* aTimestamp, jobjectArray aNmeaData) +{ + JELOG2(EJavaLocation); + + HPositionGenericInfo* posInfo = aSelf->iPositionInfo; + + const TInt KMaxNmeaSentenceLength = 82; + TUint8 numNmeaSentences(0); + if (posInfo->GetValue(EPositionFieldNMEASentences, numNmeaSentences) + == KErrNone) + { + HBufC* nmeaData = HBufC::New(KMaxNmeaSentenceLength * numNmeaSentences); + if (nmeaData) + { + TPtr nmeaDataPtr = nmeaData->Des(); + TInt lastSentence = EPositionFieldNMEASentencesStart + + numNmeaSentences; + for (TUint16 i = EPositionFieldNMEASentencesStart; i < lastSentence; ++i) + { + TBuf8 sentence8; + if (posInfo->GetValue(i, sentence8) == KErrNone) + { + TBuf sentence; + sentence.Copy(sentence8); + nmeaDataPtr.Append(sentence); + } + } + + jstring jstr = java::util::S60CommonUtils::NativeToJavaString( + *aJni, *nmeaData); + aJni->SetObjectArrayElement(aNmeaData, 0, jstr); + + delete nmeaData; + } + } + + TPosition pos; + posInfo->GetPosition(pos); + + alatlon[0] = static_cast(pos.Latitude()); + alatlon[1] = static_cast(pos.Longitude()); + aAltHaccVacc[0] = static_cast(pos.Altitude()); + aAltHaccVacc[1] = static_cast(pos.HorizontalAccuracy()); + aAltHaccVacc[2] = static_cast(pos.VerticalAccuracy()); + + *aTimestamp = java::util::S60CommonUtils::TTimeToJavaTime(pos.Time()); +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::GetSpeedAndCourse +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPositionerBase::GetSpeedAndCourse(CPositionerBase* aSelf, + jfloat* aSpeedCourse) +{ + JELOG2(EJavaLocation); + HPositionGenericInfo* posInfo = aSelf->iPositionInfo; + + if (posInfo->IsFieldAvailable(EPositionFieldHorizontalSpeed) + && posInfo->IsFieldAvailable(EPositionFieldHeading)) + { + TReal32 speed; + TReal32 course; + posInfo->GetValue(EPositionFieldHorizontalSpeed, speed); + posInfo->GetValue(EPositionFieldHeading, course); + + aSpeedCourse[0] = static_cast(speed); + aSpeedCourse[1] = static_cast(course); + return KErrNone; + } + + return KErrNotFound; +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::GetAddressInfo +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +TInt CPositionerBase::GetAddressInfo(CPositionerBase* aSelf, JNIEnv* aJni, + jobjectArray aAddress) +{ + JELOG2(EJavaLocation); + HPositionGenericInfo* posInfo = aSelf->iPositionInfo; + TInt availableFields(0); + TPtrC ptr; + + for (TInt i = 0; i < (KNumFields - 2); ++i) + { + if (posInfo->GetValue(positionField[i], ptr) == KErrNone) + { + jstring jstr = java::util::S60CommonUtils::NativeToJavaString( + *aJni, ptr); + aJni->SetObjectArrayElement(aAddress, i, jstr); + aJni->DeleteLocalRef(jstr); + availableFields |= 1 << i; + } + } + + TPtrC8 mediaLinkPtr; + if (posInfo->GetValue(EPositionFieldMediaLinksStart, mediaLinkPtr) + == KErrNone) + { + TInt numSlashFound(0); + TInt length = mediaLinkPtr.Length(); + const TUint8* p = mediaLinkPtr.Ptr(); + while (numSlashFound < 2 && length--) // Find second slash + { + if (*p++ == '/') + { + ++numSlashFound; + } + } + + if (length > 0) + { + HBufC* mediaLink = HBufC::New(length); + if (mediaLink) + { + mediaLink->Des().Copy(mediaLinkPtr.Right(length)); // Copy URL + jstring jstr = java::util::S60CommonUtils::NativeToJavaString( + *aJni, *mediaLink); + aJni->SetObjectArrayElement(aAddress, KNumFields - 2, jstr); + aJni->DeleteLocalRef(jstr); + availableFields |= 1 << (KNumFields - 2); + delete mediaLink; + } + } + } + + if (posInfo->GetValue(EPositionFieldBuildingTelephone, ptr) == KErrNone) + { + jstring jstr = java::util::S60CommonUtils::NativeToJavaString(*aJni, + ptr); + aJni->SetObjectArrayElement(aAddress, KNumFields - 1, jstr); + aJni->DeleteLocalRef(jstr); + availableFields |= 1 << (KNumFields - 1); + } + + return availableFields; +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::UpdatePosition +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPositionerBase::UpdatePosition() +{ + JELOG2(EJavaLocation); + + iPositioner.NotifyPositionUpdate(*iPositionInfo, iStatus); + SetActive(); +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::IncreaseBufferSizeL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +void CPositionerBase::HandleBufferSizeErrorL(const TInt aError) +{ + JELOG2(EJavaLocation); + + // Increase the size of the buffer by default value. This gets called + // repeatedly if the buffer is not big enough for example if the positioning + // module is able to handle multiple NMEA sentences as BT GPS PSY does + TInt bufferSize = iPositionInfo->BufferSize(); + TInt numFields = iPositionInfo->MaxFields(); + + // Check that what was the overflow situation + switch (aError) + { + case KErrOverflow: + { + // There are not enough supported fields. + numFields += KLocFieldCountIncrease; + break; + } + case KErrPositionBufferOverflow: + { + // The buffer size was not enough as the positioner provided + // more information than expected. Try to increase buffer size + bufferSize += KLocBufferSizeIncrease; + break; + } + default: + { + // Unkown buffer size error. Should newer get here because MLFW + // does not return any other buffer overflow situations and + // base classes should take care about other situations + __ASSERT_DEBUG(EFalse, User::Invariant()); + break; + } + } + + // Create new buffer. Capabilities needs to be the same as in the original + HPositionGenericInfo* newInfo = CreatePositionInfoL(bufferSize, numFields); + delete iPositionInfo; + iPositionInfo = newInfo; +} + +// ----------------------------------------------------------------------------- +// CPositionerBase::CreatePositionInfoL +// (other items were commented in a header). +// ----------------------------------------------------------------------------- +// +HPositionGenericInfo* CPositionerBase::CreatePositionInfoL( + const TInt aBufferSize, const TInt aNumFields) const +{ + JELOG2(EJavaLocation); + HPositionGenericInfo* posInfo = HPositionGenericInfo::NewL(aBufferSize, + aNumFields); + + // Request speed and direction if supported by the module + if ((iCapabilities & TPositionModuleInfo::ECapabilitySpeed) + && (iCapabilities & TPositionModuleInfo::ECapabilityDirection)) + { + User::LeaveIfError(posInfo->SetRequestedField( + EPositionFieldHorizontalSpeed)); + User::LeaveIfError(posInfo->SetRequestedField(EPositionFieldHeading)); + } + // Request NMEA statements if supported by the module + if (iCapabilities & TPositionModuleInfo::ECapabilityNmea) + { + User::LeaveIfError(posInfo->SetRequestedField( + EPositionFieldNMEASentences)); + } + if (iCapabilities & (TPositionModuleInfo::ECapabilityAddress + | TPositionModuleInfo::ECapabilityBuilding + | TPositionModuleInfo::ECapabilityMedia)) + { + for (TInt i(0); i < KNumFields; i++) + { + User::LeaveIfError(posInfo->SetRequestedField(positionField[i])); + } + } + return posInfo; +} + +// End of File