src/location/qgeopositioninfosource_s60.cpp
changeset 0 876b1a06bc25
equal deleted inserted replaced
-1:000000000000 0:876b1a06bc25
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QObject>
       
    43 #include <QDateTime>
       
    44 #include <limits.h>
       
    45 #include "qgeopositioninfosource_s60_p.h"
       
    46 #include "qgeopositioninfosource.h"
       
    47 #include "qmlbackendao_s60_p.h"
       
    48 
       
    49 
       
    50 QTM_BEGIN_NAMESPACE
       
    51 
       
    52 // constructor
       
    53 CQGeoPositionInfoSourceS60::CQGeoPositionInfoSourceS60(QObject* aParent) : QGeoPositionInfoSource(aParent),
       
    54         mCurrentModuleId(TUid::Null()),
       
    55         mReqModuleId(TUid::Null()),
       
    56         mDevStatusUpdateAO(NULL),
       
    57         mReqUpdateAO(NULL),
       
    58         mRegUpdateAO(NULL),
       
    59         mSupportedMethods(PositioningMethod(0)),
       
    60         mCurrentMethod(PositioningMethod(0)),
       
    61         mListSize(0),
       
    62         mStartUpdates(FALSE),
       
    63         mRegularUpdateTimedOut(FALSE),
       
    64         mModuleFlags(0)
       
    65 {
       
    66     memset(mList, 0 , MAX_SIZE * sizeof(CPosMethodInfo));
       
    67 }
       
    68 
       
    69 // destructor
       
    70 CQGeoPositionInfoSourceS60::~CQGeoPositionInfoSourceS60()
       
    71 {
       
    72     if (mReqUpdateAO)
       
    73         delete mReqUpdateAO;
       
    74 
       
    75     if (mRegUpdateAO)
       
    76         delete mRegUpdateAO;
       
    77 
       
    78     if (mDevStatusUpdateAO)
       
    79         delete mDevStatusUpdateAO;
       
    80 
       
    81 
       
    82 }
       
    83 
       
    84 // static function NewLC
       
    85 CQGeoPositionInfoSourceS60* CQGeoPositionInfoSourceS60::NewLC(QObject* aParent)
       
    86 {
       
    87     CQGeoPositionInfoSourceS60* self =
       
    88         new(ELeave) CQGeoPositionInfoSourceS60(aParent);
       
    89     CleanupStack::PushL(self);
       
    90     self->ConstructL();
       
    91     return self;
       
    92 }
       
    93 
       
    94 // static function NewL
       
    95 CQGeoPositionInfoSourceS60* CQGeoPositionInfoSourceS60::NewL(QObject * aParent)
       
    96 {
       
    97     CQGeoPositionInfoSourceS60* self = CQGeoPositionInfoSourceS60::NewLC(aParent);
       
    98     CleanupStack::Pop();
       
    99 
       
   100     //check if the second phase construction is successful
       
   101     if (!self->isValid()) {
       
   102         delete self;
       
   103         self = NULL;
       
   104     }
       
   105 
       
   106     return self;
       
   107 }
       
   108 
       
   109 // 2nd phase constructor
       
   110 void CQGeoPositionInfoSourceS60::ConstructL()
       
   111 {
       
   112     TInt error = mPositionServer.Connect();
       
   113 
       
   114     if (error == KErrNone) {
       
   115         CleanupClosePushL(mPositionServer);
       
   116 
       
   117         mDevStatusUpdateAO = CQMLBackendAO::NewL(this, DeviceStatus);
       
   118 
       
   119         if (mDevStatusUpdateAO == NULL) {
       
   120             CleanupStack::Pop(1);
       
   121 
       
   122             return;
       
   123         }
       
   124 
       
   125         //update the list array with the available method initially
       
   126         updateDeviceStatus();
       
   127         
       
   128         // Set the PreferredPositioningMethods based on Supported methods
       
   129         QGeoPositionInfoSource::setPreferredPositioningMethods( mSupportedMethods );
       
   130 
       
   131         //devStatusUpdateAO->NotifyDeviceStatus(mStatusEvent);
       
   132 
       
   133         CleanupStack::PushL(mDevStatusUpdateAO);
       
   134 
       
   135         if (mCurrentModuleId != TUid::Null())
       
   136             mRegUpdateAO = CQMLBackendAO::NewL(this, RegularUpdate, mCurrentModuleId);
       
   137 
       
   138         CleanupStack::Pop(2);
       
   139     }
       
   140 
       
   141 }
       
   142 
       
   143 QGeoPositionInfo CQGeoPositionInfoSourceS60::lastKnownPosition(bool aFromSatellitePositioningMethodsOnly) const
       
   144 {
       
   145 
       
   146     QGeoPositionInfo posUpdate;
       
   147     TPosition pos;
       
   148     TInt error = KErrNone;
       
   149     RPositioner iLastKnownpositioner;
       
   150     TRequestStatus status;
       
   151 
       
   152     error = iLastKnownpositioner.Open(*const_cast<RPositionServer*>(&mPositionServer));
       
   153     //request for lastknown position update and wait for the request to complete
       
   154     if (error == KErrNone) {
       
   155 
       
   156         TPositionInfo posInfo;
       
   157 
       
   158         iLastKnownpositioner.SetRequestor(CRequestor::ERequestorService ,
       
   159                                           CRequestor::EFormatApplication, _L("QTmobility_Location"));
       
   160 
       
   161 
       
   162         iLastKnownpositioner.GetLastKnownPosition(posInfo, status);
       
   163 
       
   164         User::WaitForRequest(status);
       
   165 
       
   166         error = status.Int();
       
   167 
       
   168         iLastKnownpositioner.Close();
       
   169 
       
   170         if ((error == KErrNone) || (error == KPositionPartialUpdate)) {
       
   171         
       
   172             TPositionModuleInfo modInfo;
       
   173             mPositionServer.GetModuleInfoById(posInfo.ModuleId(), modInfo);
       
   174             
       
   175             if(!aFromSatellitePositioningMethodsOnly || (aFromSatellitePositioningMethodsOnly && (modInfo.Capabilities() & TPositionModuleInfo::ECapabilitySatellite))){
       
   176                 QGeoCoordinate  coord;
       
   177 
       
   178                 posInfo.GetPosition(pos);
       
   179 
       
   180                 coord.setLatitude(pos.Latitude());
       
   181                 coord.setLongitude(pos.Longitude());
       
   182                 coord.setAltitude(pos.Altitude());
       
   183 
       
   184                 //store the QGeoCoordinate values
       
   185                 posUpdate.setCoordinate(coord);
       
   186 
       
   187                 TDateTime datetime = pos.Time().DateTime();
       
   188                 QDateTime dt(QDate(datetime.Year(), datetime.Month() + 1, datetime.Day() + 1),
       
   189                              QTime(datetime.Hour(), datetime.Minute(), datetime.Second(),
       
   190                                    datetime.MicroSecond() / 1000),
       
   191                             Qt::UTC);
       
   192 
       
   193                 //store the time stamp
       
   194                 posUpdate.setTimestamp(dt);
       
   195 
       
   196                 //store the horizontal accuracy
       
   197                 posUpdate.setAttribute(QGeoPositionInfo::HorizontalAccuracy, pos.HorizontalAccuracy());
       
   198 
       
   199                 //store the vertical accuracy
       
   200                 posUpdate.setAttribute(QGeoPositionInfo::VerticalAccuracy, pos.VerticalAccuracy());
       
   201 
       
   202             }
       
   203         }
       
   204     }
       
   205 
       
   206     return posUpdate;
       
   207 }
       
   208 
       
   209 //
       
   210 int CQGeoPositionInfoSourceS60::minimumUpdateInterval() const
       
   211 {
       
   212     if (mCurrentModuleId == TUid::Null())
       
   213         return 0;
       
   214 
       
   215     TInt i = checkModule(mCurrentModuleId);
       
   216     if (i != -1)
       
   217         return mList[i].mTimeToNextFix.Int64() / 1000;           //divide by 1000, to convert microsecond to milisecond
       
   218     return 0;
       
   219 }
       
   220 
       
   221 
       
   222 
       
   223 //private function : to derive the supported positioning methods
       
   224 void CQGeoPositionInfoSourceS60::updateAvailableTypes()
       
   225 {
       
   226     PositioningMethods types;
       
   227 
       
   228     for (TInt i = 0; i < mListSize ; i++) {
       
   229         //check only for the available module without any device errors
       
   230         if (mList[i].mIsAvailable &&
       
   231                 (mList[i].mStatus != TPositionModuleStatus::EDeviceUnknown) &&
       
   232                 (mList[i].mStatus != TPositionModuleStatus::EDeviceError)) {
       
   233             types |= mList[i].mPosMethod;
       
   234 
       
   235         }
       
   236 
       
   237         //if both SatellitePositioningMethods and NonSatellitePositioningMethods return
       
   238         if (types.testFlag(AllPositioningMethods))
       
   239             break;
       
   240     }
       
   241 
       
   242     //update the supported methods based on types value, derived from the above steps
       
   243     mSupportedMethods = types;
       
   244 }
       
   245 
       
   246 //private function : to retrieve the index of the supplied module id from the mList array
       
   247 TInt CQGeoPositionInfoSourceS60::checkModule(TPositionModuleId aId)const
       
   248 {
       
   249     TInt i;
       
   250     for (i = 0; i < mListSize; i++)
       
   251         if (mList[i].mUid == aId)
       
   252             return i;
       
   253     return -1;
       
   254 }
       
   255 
       
   256 //private function : get the index of the mList that supports the preferred method if
       
   257 //available,else returns the index of the default module
       
   258 TInt CQGeoPositionInfoSourceS60::getIndexPositionModule(TUint8 aBits, PositioningMethods aPosMethods) const
       
   259 {
       
   260     TInt index, error;
       
   261 
       
   262     TPositionModuleId modID;
       
   263 
       
   264     //get the default module Id, whose index is returned if the preferred methods are not
       
   265     //available
       
   266     error = mPositionServer.GetDefaultModuleId(modID);
       
   267 
       
   268     if (error != KErrNone)
       
   269         modID = TUid::Null();
       
   270 
       
   271     //index = -1 : no methods available in the mList that supports preferred methods
       
   272     index = -1;
       
   273 
       
   274 
       
   275     for (TInt i = 0; i < mListSize ; i++) {
       
   276         //check the module properties to select the preferred method,search should not
       
   277         //not select an unavailable method,error device or index matching aLastIndex
       
   278         if (mList[i].mIsAvailable && aPosMethods.testFlag(mList[i].mPosMethod)
       
   279                 && (mList[i].mStatus != TPositionModuleStatus::EDeviceUnknown)
       
   280                 && (mList[i].mStatus != TPositionModuleStatus::EDeviceError)
       
   281                 && (((aBits >> i) & 1))) {
       
   282             return i;
       
   283         }
       
   284 
       
   285         //store the index of the default module
       
   286         if ((modID == mList[i].mUid) && ((aBits >> i) & 1))
       
   287             index = i;
       
   288     }
       
   289 
       
   290 
       
   291     return index;
       
   292 }
       
   293 
       
   294 //private function : to get the index of the positioning method with time to first fix
       
   295 //lesser than timeout
       
   296 TInt CQGeoPositionInfoSourceS60::getMoreAccurateMethod(TInt aTimeout, TUint8 aBits)
       
   297 {
       
   298     TInt index = -1;
       
   299     double temp = -1.0;
       
   300     PositioningMethods posMethods;
       
   301     TTimeIntervalMicroSeconds microSeconds;
       
   302 
       
   303     posMethods = preferredPositioningMethods();
       
   304 
       
   305     //convert the timeout --> micro seconds
       
   306     microSeconds = aTimeout * 1000;
       
   307 
       
   308     for (TInt i = 0 ; i < mListSize; i++) {
       
   309         if (mList[i].mIsAvailable
       
   310                 //&& posMethods.testFlag(mList[i].mPosMethod)
       
   311                 && (mList[i].mStatus != TPositionModuleStatus::EDeviceUnknown)
       
   312                 && (mList[i].mStatus != TPositionModuleStatus::EDeviceError)
       
   313                 && (((aBits >> i) & 1))
       
   314                 && (mList[i].mTimeToFirstFix < microSeconds)) {
       
   315             if ((temp == -1.0) || (mList[i].mHorizontalAccuracy < temp)) {
       
   316                 index = i;
       
   317                 temp = mList[i].mHorizontalAccuracy;
       
   318             }
       
   319         }
       
   320     }
       
   321 
       
   322     if (index != -1) {
       
   323         return index;
       
   324     }
       
   325 
       
   326     bool minSet = false;
       
   327     microSeconds = 0;
       
   328 
       
   329     for (TInt i = 0 ; i < mListSize; i++) {
       
   330         if (mList[i].mIsAvailable
       
   331                 //&& posMethods.testFlag(mList[i].mPosMethod)
       
   332                 && (mList[i].mStatus != TPositionModuleStatus::EDeviceUnknown)
       
   333                 && (mList[i].mStatus != TPositionModuleStatus::EDeviceError)
       
   334                 && (((aBits >> i) & 1))) {
       
   335             if (!minSet || (mList[i].mTimeToFirstFix < microSeconds)) {
       
   336                 index = i;
       
   337                 minSet = true;
       
   338                 microSeconds = mList[i].mTimeToFirstFix;
       
   339             }
       
   340         }
       
   341     }
       
   342 
       
   343     return index;
       
   344 }
       
   345 
       
   346 //private function : to update the mList array
       
   347 void CQGeoPositionInfoSourceS60::updateStatus(TPositionModuleInfo aModInfo, TInt aStatus)
       
   348 {
       
   349 
       
   350     TInt i, index;
       
   351     TPositionModuleId id;
       
   352     PositioningMethod method;
       
   353     TBool available;
       
   354     TReal32 accuracy;
       
   355     TTimeIntervalMicroSeconds time_to_first_fix, time_to_next_fix;
       
   356     TPositionQuality quality;
       
   357     CQMLBackendAO *temp = NULL;
       
   358 
       
   359     //query for the following parameters
       
   360     id = aModInfo.ModuleId();
       
   361 
       
   362     //module with a satellite capability is assumed to be provided satellite based positioning
       
   363     //method
       
   364     method = (aModInfo.Capabilities() & TPositionModuleInfo::ECapabilitySatellite) ?
       
   365              SatellitePositioningMethods : NonSatellitePositioningMethods;
       
   366 
       
   367     //gets the device availability based on the user settings
       
   368     available = aModInfo.IsAvailable();
       
   369 
       
   370     //quality : holds the required metrics
       
   371     aModInfo.GetPositionQuality(quality);
       
   372 
       
   373     //Accuracy
       
   374     accuracy = quality.HorizontalAccuracy();
       
   375 
       
   376     //time taken for the first fix
       
   377     time_to_first_fix = quality.TimeToFirstFix();
       
   378 
       
   379     //time taken for the subsequent fix
       
   380     time_to_next_fix = quality.TimeToNextFix();
       
   381 
       
   382 
       
   383     if ((i = checkModule(id)) == -1) {
       
   384         //update the properties of the module
       
   385 
       
   386         //TPositionModuleId of the module
       
   387         mList[mListSize].mUid = id;
       
   388 
       
   389         //positioning method method type
       
   390         mList[mListSize].mPosMethod = method;
       
   391 
       
   392         //status of the device
       
   393         mList[mListSize].mStatus = aStatus;
       
   394 
       
   395         //availablility of the module
       
   396         mList[mListSize].mIsAvailable = available;
       
   397 
       
   398         //horizontal accuracy of the module
       
   399         mList[mListSize].mHorizontalAccuracy = accuracy;
       
   400 
       
   401         //time required to get the first fix
       
   402         mList[mListSize].mTimeToFirstFix = time_to_first_fix;
       
   403 
       
   404         //time required for subsequent fix
       
   405         mList[mListSize].mTimeToNextFix = time_to_next_fix;
       
   406 
       
   407         //count on the mList array size
       
   408         mListSize++;
       
   409         
       
   410         //update the supported source types based on the device status
       
   411         updateAvailableTypes();
       
   412         
       
   413         //store the correct method in use from the mCurrentModuleId retireved earlier
       
   414         if (id == mCurrentModuleId) {
       
   415             mCurrentMethod = method;
       
   416         }
       
   417     } else {
       
   418         //module's status has changed
       
   419         if (mList[i].mStatus != aStatus)
       
   420             mList[i].mStatus = aStatus;
       
   421 
       
   422         //module's availability has changed
       
   423         if (mList[i].mIsAvailable != available)
       
   424             mList[i].mIsAvailable = available;
       
   425 
       
   426         //module's horizontal accuracy has changed
       
   427         if (mList[i].mHorizontalAccuracy != accuracy)
       
   428             mList[i].mHorizontalAccuracy = accuracy;
       
   429 
       
   430         //module's time to first fix has changed
       
   431         if (mList[i].mTimeToFirstFix != time_to_first_fix)
       
   432             mList[i].mTimeToFirstFix = time_to_first_fix;
       
   433 
       
   434         //module's time to subsequent fix has changed
       
   435         if (mList[i].mTimeToNextFix != time_to_next_fix)
       
   436             mList[i].mTimeToFirstFix = time_to_next_fix;
       
   437         
       
   438         //update the supported source types based on the device status
       
   439         updateAvailableTypes();
       
   440 
       
   441         //if the mCurrentModuleId is NULL, try updating the reg update with the available
       
   442         //positioning method
       
   443         if (mCurrentModuleId == TUid::Null() && (available == TRUE) &&
       
   444                 (aStatus != TPositionModuleStatus::EDeviceUnknown) &&
       
   445                 (aStatus != TPositionModuleStatus::EDeviceError)) {
       
   446             TInt interval;
       
   447 
       
   448             interval = QGeoPositionInfoSource::updateInterval();
       
   449 
       
   450             TRAPD(ret, temp = CQMLBackendAO::NewL(this, RegularUpdate,
       
   451                                                   mList[i].mUid));
       
   452 
       
   453             if ((ret == KErrNone) && (temp != NULL)) {
       
   454                 temp->setUpdateInterval(interval);
       
   455 
       
   456                 if (mRegUpdateAO)
       
   457                     delete mRegUpdateAO;
       
   458                 mRegUpdateAO = temp;
       
   459 
       
   460                 //to be uncommented when startUpdates are done
       
   461 
       
   462                 if (mStartUpdates)
       
   463                     mRegUpdateAO->startUpdates();
       
   464 
       
   465                 mCurrentModuleId = mList[i].mUid;
       
   466 
       
   467                 mCurrentMethod = mList[i].mPosMethod;
       
   468 
       
   469             }
       
   470         }
       
   471 
       
   472         //check if the status of the currently used modules for regular update or
       
   473         //request update has changed
       
   474         if (((id == mCurrentModuleId) || (id == mReqModuleId)) &&
       
   475                 ((aStatus == TPositionModuleStatus::EDeviceUnknown) ||
       
   476                  (aStatus == TPositionModuleStatus::EDeviceError) ||
       
   477                  (available == FALSE))) {
       
   478             //if the change happened for regular update
       
   479             if (id == mCurrentModuleId) {
       
   480                 TInt interval;
       
   481 
       
   482                 TUint8 bits;
       
   483 
       
   484                 interval = QGeoPositionInfoSource::updateInterval();
       
   485 
       
   486                 if (mRegUpdateAO)
       
   487                     delete  mRegUpdateAO;
       
   488 
       
   489                 bits = mModuleFlags;
       
   490 
       
   491                 do {
       
   492                     //error = Get the index of the positioning module based on
       
   493                     //the preferred method if available , else get the default
       
   494                     //position module
       
   495                     index = getIndexPositionModule(bits);
       
   496 
       
   497                     if (index >= 0) {
       
   498                         TRAPD(ret, temp = CQMLBackendAO::NewL(this, RegularUpdate,
       
   499                                                               mList[index].mUid));
       
   500 
       
   501                         if ((ret == KErrNone) && (temp != NULL))
       
   502                             break;
       
   503 
       
   504                         bits = bits & (0XFF ^(1 << index));
       
   505                     }
       
   506                 } while (index >= 0);
       
   507 
       
   508 
       
   509                 if (temp != NULL) {
       
   510                     //successful in creating the subsession for the required
       
   511                     //method
       
   512                     mRegUpdateAO = temp;
       
   513 
       
   514                     mCurrentModuleId = mList[index].mUid;
       
   515                     mCurrentMethod = mList[index].mPosMethod;
       
   516 
       
   517                     mRegUpdateAO->setUpdateInterval(interval);
       
   518 
       
   519                     //to be uncommented when startUpdates are done
       
   520 
       
   521                     if (mStartUpdates)
       
   522                         mRegUpdateAO->startUpdates();
       
   523 
       
   524                 } else {
       
   525                     //no methods available,clean up the resources
       
   526                     mRegUpdateAO = NULL;
       
   527                     mCurrentModuleId = TUid::Null();
       
   528                     mCurrentMethod = PositioningMethod(0);
       
   529                     
       
   530                     emit updateTimeout();
       
   531                 }
       
   532 
       
   533             }
       
   534 
       
   535             //check if device status of the request update module changed
       
   536             if (id == mReqModuleId) {
       
   537                 if (mRegUpdateAO)
       
   538                     delete mReqUpdateAO;
       
   539                 mReqUpdateAO = NULL;
       
   540                 mReqModuleId = TUid::Null();
       
   541                 emit updateTimeout();
       
   542             }
       
   543 
       
   544         }
       
   545 
       
   546     }   //end else
       
   547 
       
   548 }
       
   549 
       
   550 
       
   551 // Notification methods from active object. Notifies device status changes
       
   552 void CQGeoPositionInfoSourceS60::updateDeviceStatus(void)
       
   553 {
       
   554     TPositionModuleStatus moduleStatus;
       
   555     TPositionModuleInfo moduleInfo;
       
   556     TInt error;
       
   557 
       
   558     //mListSize = 0 : called updateDeviceStatus() first time to initialise the array
       
   559     if (mListSize == 0) {
       
   560         TUint modCount;
       
   561 
       
   562         //count on the modules currently supported by the device
       
   563         mPositionServer.GetNumModules(modCount);
       
   564 
       
   565         //module ID of the default module
       
   566         error = mPositionServer.GetDefaultModuleId(mCurrentModuleId);
       
   567 
       
   568         if (error != KErrNone)
       
   569             mCurrentModuleId = TUid::Null();
       
   570 
       
   571         for (TUint i = 0; i < modCount; i++) {
       
   572             //get module information
       
   573             mPositionServer.GetModuleInfoByIndex(i, moduleInfo);
       
   574 
       
   575             //get module status
       
   576             mPositionServer.GetModuleStatus(moduleStatus, moduleInfo.ModuleId());
       
   577 
       
   578             //update the properties of the module in the mList array
       
   579             updateStatus(moduleInfo, moduleStatus.DeviceStatus());
       
   580 
       
   581             mModuleFlags |= (1 << i);
       
   582         }
       
   583     } else {
       
   584         //UpdateDeviceStatus() called after registering for NotifyModuleStatusEvent
       
   585 
       
   586         //get the module id from the status event
       
   587         TPositionModuleId id = mStatusEvent.ModuleId();
       
   588 
       
   589         //get module information
       
   590         mPositionServer.GetModuleInfoById(id, moduleInfo);
       
   591 
       
   592         //get current status of the module
       
   593         mStatusEvent.GetModuleStatus(moduleStatus);
       
   594 
       
   595         //update the properties of the module in the mList array
       
   596         updateStatus(moduleInfo, moduleStatus.DeviceStatus());
       
   597 
       
   598 
       
   599     }
       
   600 
       
   601     //register for next NotifyModuleStatusEvent
       
   602     mDevStatusUpdateAO->notifyDeviceStatus(mStatusEvent);
       
   603 
       
   604 }
       
   605 
       
   606 //
       
   607 void CQGeoPositionInfoSourceS60::TPositionInfo2QGeoPositionInfo(
       
   608     HPositionGenericInfo *aPosInfo1, QGeoPositionInfo& aPosInfo2)
       
   609 {
       
   610     TPosition pos;
       
   611     QGeoCoordinate  coord;
       
   612     float val;
       
   613 
       
   614     aPosInfo1->GetPosition(pos);
       
   615 
       
   616 
       
   617     coord.setLatitude(pos.Latitude());
       
   618     coord.setLongitude(pos.Longitude());
       
   619     coord.setAltitude(pos.Altitude());
       
   620 
       
   621     //store the QGeoCoordinate values
       
   622     aPosInfo2.setCoordinate(coord);
       
   623 
       
   624     TDateTime datetime = pos.Time().DateTime();
       
   625     QDateTime dt(QDate(datetime.Year() , datetime.Month() + 1, datetime.Day() + 1),
       
   626                  QTime(datetime.Hour() , datetime.Minute(), datetime.Second(),
       
   627                        datetime.MicroSecond() / 1000),
       
   628                 Qt::UTC);
       
   629 
       
   630     //store the time stamp
       
   631     aPosInfo2.setTimestamp(dt);
       
   632 
       
   633     //store the horizontal accuracy
       
   634     aPosInfo2.setAttribute(QGeoPositionInfo::HorizontalAccuracy, pos.HorizontalAccuracy());
       
   635 
       
   636     //store the vertical accuracy
       
   637     aPosInfo2.setAttribute(QGeoPositionInfo::VerticalAccuracy, pos.VerticalAccuracy());
       
   638 
       
   639     //check for the horizontal speed
       
   640     if (aPosInfo1->IsFieldAvailable(EPositionFieldHorizontalSpeed)) {
       
   641         aPosInfo1->GetValue(EPositionFieldHorizontalSpeed, val);
       
   642         aPosInfo2.setAttribute(QGeoPositionInfo::GroundSpeed, val);
       
   643     }
       
   644 
       
   645     //check for the vertcal speed
       
   646     if (aPosInfo1->IsFieldAvailable(EPositionFieldVerticalSpeed)) {
       
   647         aPosInfo1->GetValue(EPositionFieldVerticalSpeed, val);
       
   648         aPosInfo2.setAttribute(QGeoPositionInfo::VerticalSpeed, val);
       
   649     }
       
   650 
       
   651     //check for the magnetic variation
       
   652     if (aPosInfo1->IsFieldAvailable(EPositionFieldMagneticCourseError)) {
       
   653         aPosInfo1->GetValue(EPositionFieldMagneticCourseError, val);
       
   654         aPosInfo2.setAttribute(QGeoPositionInfo::MagneticVariation, val);
       
   655     }
       
   656 
       
   657     //check for the heading
       
   658     if (aPosInfo1->IsFieldAvailable(EPositionFieldHeading)) {
       
   659         aPosInfo1->GetValue(EPositionFieldHeading, val);
       
   660         aPosInfo2.setAttribute(QGeoPositionInfo::Direction, val);
       
   661     }
       
   662 }
       
   663 //
       
   664 void CQGeoPositionInfoSourceS60::updatePosition(HPositionGenericInfo *aPosInfo, int aError)
       
   665 {
       
   666     QGeoPositionInfo  posInfo;
       
   667 
       
   668     if (aError == KErrNone) {
       
   669         //fill posUpdate
       
   670         TPositionInfo2QGeoPositionInfo(aPosInfo, posInfo);
       
   671 
       
   672         mRegularUpdateTimedOut = false;
       
   673 
       
   674         //emit posUpdate
       
   675         emit positionUpdated(posInfo);
       
   676     } else if (aError == KErrTimedOut) {
       
   677         //request has timed out
       
   678         if (mStartUpdates) {
       
   679             if (!mRegularUpdateTimedOut) {
       
   680                 mRegularUpdateTimedOut = true;
       
   681                 emit updateTimeout();
       
   682             }
       
   683         } else {
       
   684             emit updateTimeout();
       
   685         }
       
   686     } else {
       
   687         //posiitoning module is unable to return any position information
       
   688         if (mStartUpdates) {
       
   689             if (!mRegularUpdateTimedOut) {
       
   690                 mRegularUpdateTimedOut = true;
       
   691                 emit updateTimeout();
       
   692             }
       
   693         } else {
       
   694             emit positionUpdated(posInfo);
       
   695         }
       
   696     }
       
   697 }
       
   698 
       
   699 // Returns the PositionServer handle
       
   700 RPositionServer& CQGeoPositionInfoSourceS60:: getPositionServer()
       
   701 {
       
   702     return mPositionServer;
       
   703 }
       
   704 
       
   705 
       
   706 // for request update
       
   707 void CQGeoPositionInfoSourceS60::requestUpdate(int aTimeout)
       
   708 {
       
   709     TInt index = -1;
       
   710     TUint8 bits;
       
   711 
       
   712     CQMLBackendAO *temp= NULL;
       
   713 
       
   714     //return if already a request update is pending
       
   715     if (mReqUpdateAO && mReqUpdateAO->isRequestPending())
       
   716         return;
       
   717 
       
   718     if (aTimeout < 0 || (aTimeout != 0 && aTimeout < minimumUpdateInterval())) {
       
   719         emit updateTimeout();
       
   720         return;
       
   721     }
       
   722 
       
   723     if (aTimeout == 0)
       
   724         aTimeout = 20000;
       
   725 
       
   726     bits = mModuleFlags;
       
   727 
       
   728     do  {
       
   729 
       
   730         //index of the more accurate method in the array
       
   731         index = getMoreAccurateMethod(aTimeout, bits);
       
   732 
       
   733         //no positioning method method available : emit updateTimeout
       
   734         if (index < 0) {
       
   735             emit updateTimeout();
       
   736             break;
       
   737         }
       
   738         //if the selected module for request update is same as the previous one reuse the request
       
   739         if (mList[index].mUid == mReqModuleId) {
       
   740             mReqUpdateAO->requestUpdate(aTimeout);
       
   741             return;
       
   742         }
       
   743 
       
   744         TRAPD(ret, temp = CQMLBackendAO::NewL(this, OnceUpdate, mList[index].mUid));
       
   745 
       
   746         if ((ret == KErrNone) && (temp != NULL)) {
       
   747             //delete the old reqest update
       
   748             if (mReqUpdateAO)
       
   749                 delete mReqUpdateAO;
       
   750 
       
   751             //set the requestAO to the newly created AO
       
   752             mReqUpdateAO = temp;
       
   753 
       
   754             //set the request module ID
       
   755             mReqModuleId = mList[index].mUid;
       
   756 
       
   757             //start the update
       
   758             mReqUpdateAO->requestUpdate(aTimeout);
       
   759 
       
   760             return;
       
   761         }
       
   762 
       
   763         bits = bits & (0XFF ^(1 << index));
       
   764 
       
   765     } while (index >= 0);
       
   766 
       
   767     //cleanup resources if the invalid requpdate is still stored
       
   768     if (mReqUpdateAO) {
       
   769         delete mReqUpdateAO;
       
   770         mReqUpdateAO = NULL;
       
   771         mReqModuleId = TUid::Null();
       
   772     }
       
   773 
       
   774 }
       
   775 
       
   776 // starts the regular updates
       
   777 void CQGeoPositionInfoSourceS60::startUpdates()
       
   778 {
       
   779     if (receivers(SIGNAL(positionUpdated(QGeoPositionInfo))) > 0 && !mStartUpdates)
       
   780         mRegUpdateAO->startUpdates();
       
   781     mRegularUpdateTimedOut = false;
       
   782     mStartUpdates = true;
       
   783 }
       
   784 
       
   785 // stops the regular updates
       
   786 void CQGeoPositionInfoSourceS60::stopUpdates()
       
   787 {
       
   788     mStartUpdates = false;
       
   789     mRegUpdateAO->cancelUpdate();
       
   790 }
       
   791 
       
   792 void CQGeoPositionInfoSourceS60::setPreferredPositioningMethods(PositioningMethods aMethods)
       
   793 {
       
   794     QGeoPositionInfoSource::setPreferredPositioningMethods(aMethods);
       
   795     
       
   796     PositioningMethods preferredMethod(PositioningMethods(0));
       
   797     TInt index = -1;
       
   798     // the poistioning methods are not supported
       
   799     // if the preferred positioning method is the current poistioning
       
   800 
       
   801     if (!(mSupportedMethods & aMethods) || (aMethods == PositioningMethods(AllPositioningMethods)) ||
       
   802             (aMethods == PositioningMethods(mCurrentMethod)))
       
   803 
       
   804         return;
       
   805 
       
   806     //TPositionModuleId moduleId = getPreferredPoistionModuleId(methods);
       
   807 
       
   808     //if(moduleId == TUid::Null())
       
   809     //return;
       
   810     CQMLBackendAO *temp = NULL;
       
   811     TUint8 bits;
       
   812     bits = mModuleFlags;
       
   813     do {
       
   814         //index = Get the index of the positioning module based on
       
   815         //the preferred method if available , else get the default
       
   816         //position module
       
   817         index = getIndexPositionModule(bits, aMethods);
       
   818 
       
   819         if (index == -1)
       
   820             return;
       
   821 
       
   822         if (index >= 0) {
       
   823 
       
   824             TRAPD(error, temp = CQMLBackendAO::NewL(this, RegularUpdate,
       
   825                                                     mList[index].mUid));
       
   826             if ((temp != NULL) && (error == KErrNone))
       
   827                 break;
       
   828 
       
   829             bits = bits & (0XFF ^(1 << index));
       
   830         }
       
   831     } while (index >= 0);
       
   832 
       
   833 
       
   834     if (temp != NULL) {
       
   835         // this is needed as the previous setupdateinterval value should not be lost
       
   836         int updateInterval = QGeoPositionInfoSource::updateInterval();
       
   837         if (mRegUpdateAO)
       
   838             delete mRegUpdateAO;
       
   839         mRegUpdateAO = temp;
       
   840         mCurrentModuleId = mList[index].mUid ;
       
   841 
       
   842         index = checkModule(mCurrentModuleId);
       
   843 
       
   844         mCurrentMethod = mList[index].mPosMethod ;
       
   845 
       
   846 
       
   847         if (updateInterval) {
       
   848             int value = mRegUpdateAO->setUpdateInterval(updateInterval);
       
   849             //as the poistioning module has changed
       
   850             //possibility of the minimumupdateinterval being changed
       
   851             if (value != updateInterval)
       
   852                 QGeoPositionInfoSource::setUpdateInterval(value);
       
   853 
       
   854         }
       
   855     }
       
   856 
       
   857 }
       
   858 
       
   859 void CQGeoPositionInfoSourceS60::setUpdateInterval(int aMilliSec)
       
   860 {
       
   861     if (mRegUpdateAO) {
       
   862         int interval = mRegUpdateAO->setUpdateInterval(aMilliSec);
       
   863         // as the above set value can be minimum value so
       
   864         // assigning to the base class data member
       
   865         QGeoPositionInfoSource::setUpdateInterval(interval);
       
   866     }
       
   867 }
       
   868 
       
   869 void CQGeoPositionInfoSourceS60::connectNotify(const char *aSignal)
       
   870 {
       
   871     // start update if it already connected
       
   872     if (mStartUpdates && mRegUpdateAO && QLatin1String(aSignal) == SIGNAL(positionUpdated(QGeoPositionInfo)))
       
   873         mRegUpdateAO->startUpdates();
       
   874 
       
   875 }
       
   876 
       
   877 void CQGeoPositionInfoSourceS60::disconnectNotify(const char *aSignal)
       
   878 {
       
   879     // Cancel updates if slot is disconnected for the positionUpdate() signal.
       
   880 
       
   881     if ((mRegUpdateAO) && (QLatin1String(aSignal) == SIGNAL(positionUpdated(QGeoPositionInfo))) && receivers(SIGNAL(positionUpdated(QGeoPositionInfo))) == 0)
       
   882         mRegUpdateAO->cancelUpdate();
       
   883 
       
   884 }
       
   885 
       
   886 QTM_END_NAMESPACE