javaextensions/location/position/src/cpositionerbase.cpp
branchRCL_3
changeset 14 04becd199f91
--- /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<KMaxNmeaSentenceLength> sentence8;
+                if (posInfo->GetValue(i, sentence8) == KErrNone)
+                {
+                    TBuf<KMaxNmeaSentenceLength> 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<jdouble>(pos.Latitude());
+    alatlon[1] = static_cast<jdouble>(pos.Longitude());
+    aAltHaccVacc[0] = static_cast<jfloat>(pos.Altitude());
+    aAltHaccVacc[1] = static_cast<jfloat>(pos.HorizontalAccuracy());
+    aAltHaccVacc[2] = static_cast<jfloat>(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<jfloat>(speed);
+        aSpeedCourse[1] = static_cast<jfloat>(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