javaextensions/location/position/src/cpositionerbase.cpp
branchRCL_3
changeset 14 04becd199f91
equal deleted inserted replaced
13:f5050f1da672 14:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Base class for position request classes
       
    15  *
       
    16 */
       
    17 
       
    18 
       
    19 // INCLUDE FILES
       
    20 #include "cpositionerbase.h"
       
    21 #include "s60commonutils.h"
       
    22 #include "logger.h"
       
    23 
       
    24 using namespace java::location;
       
    25 
       
    26 // UNNAMED LOCAL NAMESPACE
       
    27 namespace
       
    28 {
       
    29 // Default size of the position info buffer if NMEA statements are supported
       
    30 // In fact, this is four times the standard buffer size
       
    31 const TInt KLocPositionGenericInfoNMEABufferSize = 0x1000; // Dec 4096
       
    32 
       
    33 // Default maximum number of fields if NMEA statements are supported
       
    34 // In fact, this is four times the default field count
       
    35 const TInt KLocPositionGenericInfoNMEAFieldCount = 0x0080; // Dec 128
       
    36 
       
    37 // Default buffer size increase. This is based on to BT GPS PSY standard
       
    38 // buffer which is the size of 5K. Usually 1K increase should be enough
       
    39 // since it is the standard size of HPositionGenericInfo when constructed
       
    40 const TInt KLocBufferSizeIncrease = 0x0400; // 1024
       
    41 
       
    42 // Default increase for accepted fields in position info buffer. This is based
       
    43 // on to MLFW default field count which is 32. The increse is synchronized
       
    44 // with the buffer size increase as these values are the same default values
       
    45 // which are used when HPositionGenericInfo is generated without parameters
       
    46 const TInt KLocFieldCountIncrease = 0x0020; // 32
       
    47 
       
    48 const TInt KNumFields = 17;
       
    49 const TUint16 positionField[KNumFields] =
       
    50     { EPositionFieldStreetExtension, EPositionFieldStreet,
       
    51       EPositionFieldPostalCode, EPositionFieldCity, EPositionFieldCounty,
       
    52       EPositionFieldState, EPositionFieldCountry, EPositionFieldCountryCode,
       
    53       EPositionFieldDistrict, EPositionFieldBuildingName,
       
    54       EPositionFieldBuildingFloor, EPositionFieldBuildingRoom,
       
    55       EPositionFieldBuildingZone, EPositionFieldCrossing1,
       
    56       EPositionFieldCrossing2, EPositionFieldMediaLinks,
       
    57       EPositionFieldBuildingTelephone
       
    58     };
       
    59 }
       
    60 
       
    61 // ============================ MEMBER FUNCTIONS ===============================
       
    62 
       
    63 // -----------------------------------------------------------------------------
       
    64 // CPositionerBase::CPositionerBase
       
    65 // C++ default constructor can NOT contain any code, that
       
    66 // might leave.
       
    67 // -----------------------------------------------------------------------------
       
    68 //
       
    69 CPositionerBase::CPositionerBase(LocationFunctionServer* aFunctionSource) :
       
    70         CActive(EPriorityNormal), mFunctionServer(aFunctionSource), iCapabilities(
       
    71             TPositionModuleInfo::ECapabilityNone)
       
    72 {
       
    73     CActiveScheduler::Add(this);
       
    74 }
       
    75 
       
    76 // -----------------------------------------------------------------------------
       
    77 // CPositionerBase::BaseConstructL
       
    78 // Symbian 2nd phase constructor can leave.
       
    79 // -----------------------------------------------------------------------------
       
    80 //
       
    81 void CPositionerBase::BaseConstructL(RPositionServer& aServer,
       
    82                                      TPositionModuleId aModuleId,
       
    83                                      TPositionModuleInfo::TCapabilities aCapabilities)
       
    84 {
       
    85     JELOG2(EJavaLocation);
       
    86 
       
    87     User::LeaveIfError(iPositioner.Open(aServer, aModuleId));
       
    88 
       
    89     _LIT(KService, "JavaVM");
       
    90     iPositioner.SetRequestor(CRequestor::ERequestorService,
       
    91                              CRequestor::EFormatApplication, KService);
       
    92 
       
    93     iCapabilities = aCapabilities;
       
    94 
       
    95     // By default, MLFW uses 1K buffer for location information. If the
       
    96     // PSY is capable of providing NMEA statements then the default buffer
       
    97     // runs out very quickly and the buffer size needs to adjusted. This may
       
    98     // cause delays when getting location fixes to Java-side. So if the
       
    99     // module supports NMEA statements then a larger buffer is created
       
   100     // by default. For example, BT GPS PSY receives all NMEA statements
       
   101     // that the module can provide so the default buffer size is not enough
       
   102     // Also the maximum number of fields needs to be changed in that case
       
   103 
       
   104     if (iCapabilities & TPositionModuleInfo::ECapabilityNmea)
       
   105     {
       
   106         iPositionInfo = CreatePositionInfoL(
       
   107                             KLocPositionGenericInfoNMEABufferSize,
       
   108                             KLocPositionGenericInfoNMEAFieldCount);
       
   109     }
       
   110     else
       
   111     {
       
   112         // Use default values defined in MLFW. Currently 1K for the buffer
       
   113         // size and the maximum number of 32 fields supported.
       
   114         iPositionInfo = CreatePositionInfoL(
       
   115                             KPositionGenericInfoDefaultBufferSize,
       
   116                             KPositionGenericInfoDefaultMaxFields);
       
   117     }
       
   118 }
       
   119 
       
   120 // -----------------------------------------------------------------------------
       
   121 // CPositionerBase::~CPositionerBase
       
   122 // -----------------------------------------------------------------------------
       
   123 //
       
   124 CPositionerBase::~CPositionerBase()
       
   125 {
       
   126     JELOG2(EJavaLocation);
       
   127     delete iPositionInfo;
       
   128     iPositioner.Close();
       
   129 }
       
   130 
       
   131 // -----------------------------------------------------------------------------
       
   132 // CPositionerBase::GetQualifiedCoordinates
       
   133 // (other items were commented in a header).
       
   134 // -----------------------------------------------------------------------------
       
   135 //
       
   136 void CPositionerBase::GetQualifiedCoordinates(CPositionerBase* aSelf,
       
   137         JNIEnv* aJni, jdouble* alatlon, jfloat* aAltHaccVacc,
       
   138         jlong* aTimestamp, jobjectArray aNmeaData)
       
   139 {
       
   140     JELOG2(EJavaLocation);
       
   141 
       
   142     HPositionGenericInfo* posInfo = aSelf->iPositionInfo;
       
   143 
       
   144     const TInt KMaxNmeaSentenceLength = 82;
       
   145     TUint8 numNmeaSentences(0);
       
   146     if (posInfo->GetValue(EPositionFieldNMEASentences, numNmeaSentences)
       
   147             == KErrNone)
       
   148     {
       
   149         HBufC* nmeaData = HBufC::New(KMaxNmeaSentenceLength * numNmeaSentences);
       
   150         if (nmeaData)
       
   151         {
       
   152             TPtr nmeaDataPtr = nmeaData->Des();
       
   153             TInt lastSentence = EPositionFieldNMEASentencesStart
       
   154                                 + numNmeaSentences;
       
   155             for (TUint16 i = EPositionFieldNMEASentencesStart; i < lastSentence; ++i)
       
   156             {
       
   157                 TBuf8<KMaxNmeaSentenceLength> sentence8;
       
   158                 if (posInfo->GetValue(i, sentence8) == KErrNone)
       
   159                 {
       
   160                     TBuf<KMaxNmeaSentenceLength> sentence;
       
   161                     sentence.Copy(sentence8);
       
   162                     nmeaDataPtr.Append(sentence);
       
   163                 }
       
   164             }
       
   165 
       
   166             jstring jstr = java::util::S60CommonUtils::NativeToJavaString(
       
   167                                *aJni, *nmeaData);
       
   168             aJni->SetObjectArrayElement(aNmeaData, 0, jstr);
       
   169 
       
   170             delete nmeaData;
       
   171         }
       
   172     }
       
   173 
       
   174     TPosition pos;
       
   175     posInfo->GetPosition(pos);
       
   176 
       
   177     alatlon[0] = static_cast<jdouble>(pos.Latitude());
       
   178     alatlon[1] = static_cast<jdouble>(pos.Longitude());
       
   179     aAltHaccVacc[0] = static_cast<jfloat>(pos.Altitude());
       
   180     aAltHaccVacc[1] = static_cast<jfloat>(pos.HorizontalAccuracy());
       
   181     aAltHaccVacc[2] = static_cast<jfloat>(pos.VerticalAccuracy());
       
   182 
       
   183     *aTimestamp = java::util::S60CommonUtils::TTimeToJavaTime(pos.Time());
       
   184 }
       
   185 
       
   186 // -----------------------------------------------------------------------------
       
   187 // CPositionerBase::GetSpeedAndCourse
       
   188 // (other items were commented in a header).
       
   189 // -----------------------------------------------------------------------------
       
   190 //
       
   191 TInt CPositionerBase::GetSpeedAndCourse(CPositionerBase* aSelf,
       
   192                                         jfloat* aSpeedCourse)
       
   193 {
       
   194     JELOG2(EJavaLocation);
       
   195     HPositionGenericInfo* posInfo = aSelf->iPositionInfo;
       
   196 
       
   197     if (posInfo->IsFieldAvailable(EPositionFieldHorizontalSpeed)
       
   198             && posInfo->IsFieldAvailable(EPositionFieldHeading))
       
   199     {
       
   200         TReal32 speed;
       
   201         TReal32 course;
       
   202         posInfo->GetValue(EPositionFieldHorizontalSpeed, speed);
       
   203         posInfo->GetValue(EPositionFieldHeading, course);
       
   204 
       
   205         aSpeedCourse[0] = static_cast<jfloat>(speed);
       
   206         aSpeedCourse[1] = static_cast<jfloat>(course);
       
   207         return KErrNone;
       
   208     }
       
   209 
       
   210     return KErrNotFound;
       
   211 }
       
   212 
       
   213 // -----------------------------------------------------------------------------
       
   214 // CPositionerBase::GetAddressInfo
       
   215 // (other items were commented in a header).
       
   216 // -----------------------------------------------------------------------------
       
   217 //
       
   218 TInt CPositionerBase::GetAddressInfo(CPositionerBase* aSelf, JNIEnv* aJni,
       
   219                                      jobjectArray aAddress)
       
   220 {
       
   221     JELOG2(EJavaLocation);
       
   222     HPositionGenericInfo* posInfo = aSelf->iPositionInfo;
       
   223     TInt availableFields(0);
       
   224     TPtrC ptr;
       
   225 
       
   226     for (TInt i = 0; i < (KNumFields - 2); ++i)
       
   227     {
       
   228         if (posInfo->GetValue(positionField[i], ptr) == KErrNone)
       
   229         {
       
   230             jstring jstr = java::util::S60CommonUtils::NativeToJavaString(
       
   231                                *aJni, ptr);
       
   232             aJni->SetObjectArrayElement(aAddress, i, jstr);
       
   233             aJni->DeleteLocalRef(jstr);
       
   234             availableFields |= 1 << i;
       
   235         }
       
   236     }
       
   237 
       
   238     TPtrC8 mediaLinkPtr;
       
   239     if (posInfo->GetValue(EPositionFieldMediaLinksStart, mediaLinkPtr)
       
   240             == KErrNone)
       
   241     {
       
   242         TInt numSlashFound(0);
       
   243         TInt length = mediaLinkPtr.Length();
       
   244         const TUint8* p = mediaLinkPtr.Ptr();
       
   245         while (numSlashFound < 2 && length--) // Find second slash
       
   246         {
       
   247             if (*p++ == '/')
       
   248             {
       
   249                 ++numSlashFound;
       
   250             }
       
   251         }
       
   252 
       
   253         if (length > 0)
       
   254         {
       
   255             HBufC* mediaLink = HBufC::New(length);
       
   256             if (mediaLink)
       
   257             {
       
   258                 mediaLink->Des().Copy(mediaLinkPtr.Right(length)); // Copy URL
       
   259                 jstring jstr = java::util::S60CommonUtils::NativeToJavaString(
       
   260                                    *aJni, *mediaLink);
       
   261                 aJni->SetObjectArrayElement(aAddress, KNumFields - 2, jstr);
       
   262                 aJni->DeleteLocalRef(jstr);
       
   263                 availableFields |= 1 << (KNumFields - 2);
       
   264                 delete mediaLink;
       
   265             }
       
   266         }
       
   267     }
       
   268 
       
   269     if (posInfo->GetValue(EPositionFieldBuildingTelephone, ptr) == KErrNone)
       
   270     {
       
   271         jstring jstr = java::util::S60CommonUtils::NativeToJavaString(*aJni,
       
   272                        ptr);
       
   273         aJni->SetObjectArrayElement(aAddress, KNumFields - 1, jstr);
       
   274         aJni->DeleteLocalRef(jstr);
       
   275         availableFields |= 1 << (KNumFields - 1);
       
   276     }
       
   277 
       
   278     return availableFields;
       
   279 }
       
   280 
       
   281 // -----------------------------------------------------------------------------
       
   282 // CPositionerBase::UpdatePosition
       
   283 // (other items were commented in a header).
       
   284 // -----------------------------------------------------------------------------
       
   285 //
       
   286 void CPositionerBase::UpdatePosition()
       
   287 {
       
   288     JELOG2(EJavaLocation);
       
   289 
       
   290     iPositioner.NotifyPositionUpdate(*iPositionInfo, iStatus);
       
   291     SetActive();
       
   292 }
       
   293 
       
   294 // -----------------------------------------------------------------------------
       
   295 // CPositionerBase::IncreaseBufferSizeL
       
   296 // (other items were commented in a header).
       
   297 // -----------------------------------------------------------------------------
       
   298 //
       
   299 void CPositionerBase::HandleBufferSizeErrorL(const TInt aError)
       
   300 {
       
   301     JELOG2(EJavaLocation);
       
   302 
       
   303     // Increase the size of the buffer by default value. This gets called
       
   304     // repeatedly if the buffer is not big enough for example if the positioning
       
   305     // module is able to handle multiple NMEA sentences as BT GPS PSY does
       
   306     TInt bufferSize = iPositionInfo->BufferSize();
       
   307     TInt numFields = iPositionInfo->MaxFields();
       
   308 
       
   309     // Check that what was the overflow situation
       
   310     switch (aError)
       
   311     {
       
   312     case KErrOverflow:
       
   313     {
       
   314         // There are not enough supported fields.
       
   315         numFields += KLocFieldCountIncrease;
       
   316         break;
       
   317     }
       
   318     case KErrPositionBufferOverflow:
       
   319     {
       
   320         // The buffer size was not enough as the positioner provided
       
   321         // more information than expected. Try to increase buffer size
       
   322         bufferSize += KLocBufferSizeIncrease;
       
   323         break;
       
   324     }
       
   325     default:
       
   326     {
       
   327         // Unkown buffer size error. Should newer get here because MLFW
       
   328         // does not return any other buffer overflow situations and
       
   329         // base classes should take care about other situations
       
   330         __ASSERT_DEBUG(EFalse, User::Invariant());
       
   331         break;
       
   332     }
       
   333     }
       
   334 
       
   335     // Create new buffer. Capabilities needs to be the same as in the original
       
   336     HPositionGenericInfo* newInfo = CreatePositionInfoL(bufferSize, numFields);
       
   337     delete iPositionInfo;
       
   338     iPositionInfo = newInfo;
       
   339 }
       
   340 
       
   341 // -----------------------------------------------------------------------------
       
   342 // CPositionerBase::CreatePositionInfoL
       
   343 // (other items were commented in a header).
       
   344 // -----------------------------------------------------------------------------
       
   345 //
       
   346 HPositionGenericInfo* CPositionerBase::CreatePositionInfoL(
       
   347     const TInt aBufferSize, const TInt aNumFields) const
       
   348 {
       
   349     JELOG2(EJavaLocation);
       
   350     HPositionGenericInfo* posInfo = HPositionGenericInfo::NewL(aBufferSize,
       
   351                                     aNumFields);
       
   352 
       
   353     // Request speed and direction if supported by the module
       
   354     if ((iCapabilities & TPositionModuleInfo::ECapabilitySpeed)
       
   355             && (iCapabilities & TPositionModuleInfo::ECapabilityDirection))
       
   356     {
       
   357         User::LeaveIfError(posInfo->SetRequestedField(
       
   358                                EPositionFieldHorizontalSpeed));
       
   359         User::LeaveIfError(posInfo->SetRequestedField(EPositionFieldHeading));
       
   360     }
       
   361     // Request NMEA statements if supported by the module
       
   362     if (iCapabilities & TPositionModuleInfo::ECapabilityNmea)
       
   363     {
       
   364         User::LeaveIfError(posInfo->SetRequestedField(
       
   365                                EPositionFieldNMEASentences));
       
   366     }
       
   367     if (iCapabilities & (TPositionModuleInfo::ECapabilityAddress
       
   368                          | TPositionModuleInfo::ECapabilityBuilding
       
   369                          | TPositionModuleInfo::ECapabilityMedia))
       
   370     {
       
   371         for (TInt i(0); i < KNumFields; i++)
       
   372         {
       
   373             User::LeaveIfError(posInfo->SetRequestedField(positionField[i]));
       
   374         }
       
   375     }
       
   376     return posInfo;
       
   377 }
       
   378 
       
   379 //  End of File