locationtriggering/ltstrategyengine/src/lbtcoordinatesupervisor.cpp
changeset 0 667063e416a2
child 7 19bff11d6c18
equal deleted inserted replaced
-1:000000000000 0:667063e416a2
       
     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:  Implementation of coordinate supervisor class
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <e32math.h>
       
    21 #include <e32const.h>
       
    22 #include <lbttriggerconditionarea.h>
       
    23 #include <lbtgeocircle.h>
       
    24 #include "lbtcelliddatabase.h"
       
    25 #include "lbtcellchangehandler.h"
       
    26 #include "lbtlogger.h"
       
    27 #include "lbtcoordinatesupervisor.h"
       
    28 #include "lbtstrategyengineobserver.h"
       
    29 #include "lbtpsychangelistner.h"
       
    30 
       
    31 // ==================== CONSTANTS ===================================
       
    32 
       
    33 /**
       
    34  * Constant used to adjust trigger radius to accomodate inaccuracy 
       
    35  * of position fixes
       
    36  */
       
    37 static const TReal32 KAccuracyMultiplier = 0.666667;
       
    38 
       
    39 /**
       
    40  * The cut off value of the ratio of radius to position accuracy. Over this 
       
    41  * value the radius of a trigger will not be expanded.
       
    42  */
       
    43 static const TReal32 KCofftOfHighEdgeLimit = 1.5;
       
    44 
       
    45 /**
       
    46  * Constant used in calculation of trigger hysteresis
       
    47  */
       
    48 static const TUint16 KTriggerRadiusCutoff = 500;
       
    49 
       
    50 /**
       
    51  *  Contant time use in calculation of speed
       
    52  */
       
    53 static const TReal32 constantTime = 20;
       
    54 
       
    55 /**
       
    56  * Defines the number of historic speed values that will be stored
       
    57  * and used for calculation of current speed
       
    58  */
       
    59 static const TUint16 maxObsValues = 10;
       
    60 
       
    61 /**
       
    62  * Minimum calculated speed. If this calculated speed drops below this value
       
    63  * then the below value is speed as the speed value 
       
    64  */
       
    65 static const TReal KMinProjSpeed = 20.0;
       
    66 
       
    67 static const TReal KMaxSpeedToUseMvmtDet = 5.0;
       
    68 /**
       
    69  * If the estimated sleep interval goes below this value then location request
       
    70  * will be issued immediately with the estimated interval as the time out value
       
    71  * for the location rquest
       
    72  */
       
    73 static const TInt KMinSleepInterval = 2;
       
    74 
       
    75 /**
       
    76  * Multiplier used for 10 power 3. Used for conversion of seconds to micro
       
    77  * seconds
       
    78  */
       
    79 static const TUint KMicroMultiplier = 1000000;
       
    80 
       
    81 /**
       
    82  * Number of seconds to sleep before making location request in cases where 
       
    83  * a location acquisition attempt fails to obtain a fix
       
    84  */
       
    85 static const TUint KSleepTimeOnLocAcqFailure = 10; // 10 seconds
       
    86 
       
    87 /**
       
    88  * Safe range of HA obtained from NPP
       
    89  */
       
    90 //static const TUint KNppSafeHA = 1500; // 1500 meters
       
    91 
       
    92 // ============================== MEMBER FUNCTIONS ============================================
       
    93 
       
    94 // -----------------------------------------------------------------------------
       
    95 // CLbtCoOrdinateSupervisor::NewL
       
    96 // CLbtCoOrdinateSupervisor instantiation method
       
    97 // -----------------------------------------------------------------------------
       
    98 //
       
    99 CLbtCoOrdinateSupervisor* CLbtCoOrdinateSupervisor::NewL( TAny* aConstructionParameters, 
       
   100                                                           CLbtTriggerView* aView,
       
   101                                                           MLbtStrategyEngineObsrvr* aObserver,
       
   102                                                           CLbtCellChangeHandler* aCellChangeHandler )
       
   103     {
       
   104     CLbtCoOrdinateSupervisor* self = new ( ELeave ) CLbtCoOrdinateSupervisor();
       
   105     CleanupStack::PushL( self );
       
   106     self->ConstructL( aConstructionParameters, aView,aObserver,aCellChangeHandler );
       
   107     CleanupStack::Pop();
       
   108     return self;    
       
   109     }
       
   110 
       
   111 
       
   112 // -----------------------------------------------------------------------------
       
   113 // CLbtCoOrdinateSupervisor::~CLbtCoOrdinateSupervisor
       
   114 // Default destructor
       
   115 // -----------------------------------------------------------------------------
       
   116 //
       
   117 CLbtCoOrdinateSupervisor::~CLbtCoOrdinateSupervisor()
       
   118     {
       
   119     // This is just done as a precautionary measure!
       
   120     StopSupervision();
       
   121     delete iLocationRequestor;
       
   122     delete iStatusManager;
       
   123     delete iTimer;
       
   124     delete iPsyChangeListner;
       
   125     delete iCellIdDatabase;
       
   126     iNObservedValues.Close();
       
   127     iNearestTriggers.Close();
       
   128     }	
       
   129 
       
   130 
       
   131 // -----------------------------------------------------------------------------
       
   132 // CLbtCoOrdinateSupervisor::StartSupervision
       
   133 // 
       
   134 // -----------------------------------------------------------------------------
       
   135 //
       
   136 void CLbtCoOrdinateSupervisor::StartSupervision()
       
   137     {
       
   138     FUNC_ENTER("CLbtCoOrdinateSupervisor::StartSupervision");
       
   139     iCellChangeHandler->SetObserver( this );    
       
   140     RequestTerminalPosition( iSettings.iLocationRequestTimeout );    
       
   141     }
       
   142 
       
   143     
       
   144 // -----------------------------------------------------------------------------
       
   145 // CLbtCoOrdinateSupervisor::StopSupervision
       
   146 // 
       
   147 // -----------------------------------------------------------------------------
       
   148 //
       
   149 void CLbtCoOrdinateSupervisor::StopSupervision()
       
   150     {
       
   151     FUNC_ENTER("CLbtCoOrdinateSupervisor::StopSupervision");
       
   152     iCellChangeHandler->Remove( this );
       
   153     Term(); 
       
   154     }
       
   155     
       
   156 
       
   157 // -----------------------------------------------------------------------------
       
   158 // CLbtCoOrdinateSupervisor::SettingsChanged
       
   159 // Handles notification of triggering settings change provided by server
       
   160 // -----------------------------------------------------------------------------
       
   161 //
       
   162 void CLbtCoOrdinateSupervisor::SettingsChanged()
       
   163     {    
       
   164     iEngObserver->RetrieveTriggeringSettings( iSettings );    
       
   165     }
       
   166 
       
   167 
       
   168 // -----------------------------------------------------------------------------
       
   169 // CLbtCoOrdinateSupervisor::Resume
       
   170 
       
   171 // -----------------------------------------------------------------------------
       
   172 //
       
   173 void CLbtCoOrdinateSupervisor::Resume()
       
   174     {
       
   175     FUNC_ENTER("CLbtCoOrdinateSupervisor::Resume");
       
   176     TInt err = KErrNone;
       
   177     iCellChangeHandler->SetObserver( this );    
       
   178 
       
   179     switch( iProjectedState )
       
   180             {
       
   181         case ELocationAcquisition:
       
   182             iProjectedState = EIdle;
       
   183             RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
   184             break;
       
   185 
       
   186         case ETriggerEvaluation:
       
   187             // Reset trigger iterator and start evaluation of all triggers in
       
   188             // view            
       
   189             iProjectedState = EIdle;
       
   190             err = ResetViewIterator();
       
   191             if( KErrNone != err )
       
   192                 {
       
   193                 return;
       
   194                 }
       
   195             iState = ETriggerEvaluation;
       
   196             SetEvent();
       
   197             break;
       
   198             
       
   199         case EUpdateIntervalEstimation:
       
   200 
       
   201             // Evaluate triggers that have undergone changes during the state
       
   202             // change. This is to determine any new nearest trigger
       
   203             iProjectedState = EIdle;
       
   204 
       
   205 
       
   206             iView->DetermineNearestTriggerChanges( &iNearestTriggers );
       
   207             if( iNearestTriggers.Count() == 0 )
       
   208                 {
       
   209                 // This means all known nearest triggers have been modified. 
       
   210                 // Reset iterator re-evaluate all triggers in the system. 
       
   211                 TInt err = ResetViewIterator();
       
   212                 if( KErrNone != err )
       
   213                     {
       
   214                     return;
       
   215                     }
       
   216                 
       
   217                 iState = ETriggerEvaluation;
       
   218                 SetEvent();
       
   219                 }
       
   220             else
       
   221                 {
       
   222                 // Evaluate only the modified triggers
       
   223                 TBool makeLocReq = EFalse;
       
   224                 TRAP( err, makeLocReq = EvaluateModifiedTriggersL() );
       
   225                 if( KErrNone == err )
       
   226                     {
       
   227                     if( makeLocReq )
       
   228                     	{
       
   229                     	// Location request is needed based on evaluating
       
   230             			// modified triggers
       
   231                     	RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
   232                     	return;
       
   233                     	}
       
   234                     // Switch to estimation of update interval
       
   235                     iState = EUpdateIntervalEstimation;
       
   236                     SetEvent();
       
   237                     }
       
   238                 else
       
   239                     {
       
   240                     Term();
       
   241                     }
       
   242                 }
       
   243             break;
       
   244 
       
   245         case ESleep:
       
   246             iProjectedState = EIdle;
       
   247             iState = ESleep;
       
   248             SetEvent();
       
   249             break;
       
   250             
       
   251         case EIdle:
       
   252             if( EIdle == iState && EIdle == iProjectedState
       
   253                            && iView->CoordTriggerCount() )
       
   254                 {
       
   255                 RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
   256                 }
       
   257             break;
       
   258             
       
   259         default:
       
   260             break;
       
   261             }
       
   262      }
       
   263 
       
   264 
       
   265 // -----------------------------------------------------------------------------
       
   266 // CLbtCoOrdinateSupervisor::Suspend
       
   267 // -----------------------------------------------------------------------------
       
   268 //
       
   269 void CLbtCoOrdinateSupervisor::Suspend()
       
   270     {
       
   271     FUNC_ENTER("CLbtCoOrdinateSupervisor::Suspend");
       
   272     iCellChangeHandler->Remove( this );
       
   273     switch( iState )
       
   274         {
       
   275     case ELocationAcquisition:
       
   276     	if( iLastLocationFixType == EProperFix )
       
   277     		{
       
   278     		iLocationRequestor->Cancel();
       
   279     		}
       
   280     	else
       
   281     		{
       
   282     		iLocationRequestor->CancelFixFromNpp();
       
   283     		}
       
   284     	
       
   285         iProjectedState = iState;
       
   286         iState = EIdle;
       
   287         break;
       
   288         
       
   289     case ETriggerEvaluation:
       
   290         iProjectedState = ETriggerEvaluation;
       
   291         iState = EIdle;
       
   292         break;
       
   293         
       
   294     case EUpdateIntervalEstimation:
       
   295         iProjectedState = EUpdateIntervalEstimation;
       
   296         iState = EIdle;
       
   297         break;
       
   298         
       
   299     case ESleep:
       
   300         iTimer->Cancel();
       
   301         iProjectedState = iState;
       
   302         iState = EIdle;
       
   303                 
       
   304     case EIdle:
       
   305         break;
       
   306         
       
   307     default:
       
   308         break;
       
   309         }
       
   310     
       
   311     Cancel();
       
   312     }
       
   313     
       
   314 
       
   315 // -----------------------------------------------------------------------------
       
   316 // CLbtCoOrdinateSupervisor::Reset
       
   317 // -----------------------------------------------------------------------------
       
   318 //
       
   319 void CLbtCoOrdinateSupervisor::Reset()
       
   320     {
       
   321     iState = iProjectedState = EIdle;
       
   322     iNearestTriggers.Reset();
       
   323     iLocReqCount = 0;
       
   324     TPositionInfo posInfo;
       
   325     iPosInfo = posInfo;
       
   326     iFixForFiringCloseTriggers = EFalse;
       
   327     }
       
   328 
       
   329 
       
   330 // -----------------------------------------------------------------------------
       
   331 // CLbtCoOrdinateSupervisor::GetPositionInfo
       
   332 // Processes the location information obtained from location requestor
       
   333 // -----------------------------------------------------------------------------
       
   334 //
       
   335 void CLbtCoOrdinateSupervisor::GetPositionInfoL()
       
   336     {
       
   337     FUNC_ENTER("CLbtCoOrdinateSupervisor::GetPositionInfo");
       
   338     
       
   339     // Update location acquisition status information
       
   340     
       
   341     if( !( (KErrNone == iStatus.Int()) ||
       
   342     	   (KPositionQualityLoss == iStatus.Int()) ) )
       
   343     	{
       
   344     	ERROR("Position Information with : %d",iStatus.Int());
       
   345     	iStatusManager->ReportLocationAcquisitionStatus( iStatus.Int() );
       
   346     	    	
       
   347     	// The following check determines if there was a problem using the 
       
   348     	// specified positioning technology to retrieve position information
       
   349     	if( KErrNotFound == iStatus.Int() &&
       
   350     	    iLastLocationFixType == EProperFix )
       
   351     	    {
       
   352     	    LOG("Specified PSY not found");
       
   353     	    iAcquisitionStatus = ELocationAcquisitionNoMethod;
       
   354     	    
       
   355     	    if( iPsyChangeListner == NULL )
       
   356     	        {
       
   357     	        iPsyChangeListner = CLbtPsyChangeListner::NewL( *this );
       
   358     	        }
       
   359     	    iPsyChangeListner->StartToListen( iModuleId );
       
   360     	    LOG1("Listen to PSY change:%x",iModuleId);
       
   361     	    TUid defaultID = { 0XFFFFFFFF };
       
   362     	    if( iLocationRequestor->GetPositionModuleId() != defaultID )
       
   363     	        {
       
   364     	        LOG("Use default proxy");
       
   365     	        // switch to using default positioning technology
       
   366     	        iModuleId = defaultID;
       
   367     	        RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix );   
       
   368     	        }
       
   369     	    }
       
   370     	else
       
   371     	    {
       
   372     	    LOG("Location acquisition failed");
       
   373     	    if( iFixForFiringCloseTriggers && 
       
   374     	        (KErrTimedOut == iStatus.Int())&&
       
   375     	        iLastLocationFixType == EProperFix )
       
   376     	        {
       
   377     	        LOG("Firing Close triggers");
       
   378                 FireClosestTriggers();                
       
   379                 RequestTerminalPosition(iSettings.iLocationRequestTimeout, EProperFix);
       
   380                 }
       
   381             else
       
   382                 {
       
   383                 if( iLastLocationFixType == EProperFix )
       
   384                     {
       
   385                     // Get fix from NPP PSY
       
   386                     LOG("Timed Out. Taking fix from NPP");
       
   387                     RequestTerminalPosition( iSettings.iLocationRequestTimeout, EFixFromNpp );
       
   388                     return;
       
   389                     
       
   390                     /*
       
   391                     iState = ESleep;
       
   392                     iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue );               
       
   393                     SetActive();
       
   394 
       
   395                     if( KErrAccessDenied == iStatus.Int() )
       
   396                         {
       
   397                         iAcquisitionStatus = ELocationAcquisitionPrivacyReject;
       
   398                         }
       
   399                     else 
       
   400                         {
       
   401                         iAcquisitionStatus = ELocationAcquisitionFailure;
       
   402                         }*/
       
   403                     }
       
   404                 else
       
   405                     {
       
   406                     LOG("Npp psy failed to provide fix. Sleep now");
       
   407                     iState = ESleep;
       
   408                     iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue );               
       
   409                     SetActive();
       
   410 
       
   411                     if( KErrAccessDenied == iStatus.Int() )
       
   412                         {
       
   413                         iAcquisitionStatus = ELocationAcquisitionPrivacyReject;
       
   414                         }
       
   415                     else 
       
   416                         {
       
   417                         iAcquisitionStatus = ELocationAcquisitionFailure;
       
   418                         }
       
   419                     }
       
   420                 }
       
   421     	    }
       
   422 
       
   423     	if( iFixForFiringCloseTriggers )
       
   424     	    {
       
   425     	    iFixForFiringCloseTriggers = EFalse;
       
   426     	    }
       
   427 
       
   428     	// Update supervision dynamic info to the strategy class
       
   429         TLbtStrategySupervisionDynamicInfo supervisionDynamicInfo;
       
   430         supervisionDynamicInfo.iDistanceToNearestTrigger = 0.0;
       
   431         supervisionDynamicInfo.iLatestAcquiredPosInfo = iPosInfo;
       
   432         supervisionDynamicInfo.iLocationAcquisitionStatus = iAcquisitionStatus;
       
   433         supervisionDynamicInfo.iNearestTriggerId = 0;
       
   434     
       
   435         iEngObserver->ReportTriggeringSupervisionStatus( supervisionDynamicInfo );    
       
   436     	return;
       
   437     	}
       
   438 
       
   439 	if( iStatus.Int() == KPositionQualityLoss )
       
   440 		{
       
   441 		// TODO: Remove this. Only for Debug
       
   442 		TPosition currentPosition;
       
   443 		iPosInfo.GetPosition( currentPosition );
       
   444 		LOG("Received KPositionQualityLoss");
       
   445 		LOG1("Lat:%f",currentPosition.Latitude());
       
   446 		LOG1("Long:%f",currentPosition.Longitude());
       
   447 		LOG1("HA:%f",currentPosition.HorizontalAccuracy());
       
   448 		}
       
   449     		
       
   450     iStatusManager->ReportLocationAcquisitionStatus( KErrNone );
       
   451     // The fix was taken to fire nearest triggers then reset the flag
       
   452     // to EFalse since the fix was successful and the nearest triggers will be
       
   453     // evaluated and will be fired
       
   454     if(iFixForFiringCloseTriggers)
       
   455         {
       
   456         iFixForFiringCloseTriggers = EFalse;
       
   457         }
       
   458     
       
   459     TPosition currentPosition, prevPosition;
       
   460     iPosInfo.GetPosition( currentPosition );
       
   461     iPrevPosInfo.GetPosition( prevPosition );
       
   462     
       
   463     if( Math::IsNaN( currentPosition.Latitude() ) || 
       
   464         Math::IsNaN( currentPosition.Longitude() ) )
       
   465     	{
       
   466     	LOG("ERROR:Lat/Long is Nan. Sleep now");
       
   467     	iState = ESleep;
       
   468         iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue );               
       
   469         SetActive();
       
   470 
       
   471         if( KErrAccessDenied == iStatus.Int() )
       
   472             {
       
   473             iAcquisitionStatus = ELocationAcquisitionPrivacyReject;
       
   474             }
       
   475         else 
       
   476             {
       
   477             iAcquisitionStatus = ELocationAcquisitionFailure;
       
   478             }
       
   479     	return;
       
   480     	}
       
   481     
       
   482     // Record the time at which we got the fix
       
   483     iLastFixTime.UniversalTime();
       
   484     
       
   485     // Take note of reference time that would be used during estimation of 
       
   486     // sleep interval
       
   487     iAcquisitionStatus = ELocationAcquisitionActive;
       
   488     
       
   489     iLocReqCount++;
       
   490     iLocationRequestor->GetModuleInfo( iPosInfo.ModuleId() );    
       
   491         
       
   492     if( iLocArea.iCellId && iLastCellRequestStatus == KErrNone )
       
   493         {
       
   494         LOG("Writing position to DB");
       
   495         LOG1("Cell Id = %d", iLocArea.iCellId );
       
   496         LOG1("LAC = %d", iLocArea.iLocationAreaCode );
       
   497         // Add current cell id position to cell-id database
       
   498         TInt countryCode,networkCode;
       
   499         
       
   500         TLex lex( iNwInfo.iCountryCode );
       
   501         lex.Val( countryCode );
       
   502         
       
   503         lex.Assign( iNwInfo.iNetworkId );
       
   504         lex.Val( networkCode );
       
   505         
       
   506         TPosition cellPosition;
       
   507         iPosInfo.GetPosition( cellPosition );
       
   508         if( iLastLocationFixType == EProperFix )
       
   509             {
       
   510             cellPosition.SetHorizontalAccuracy( 3000 );
       
   511             }
       
   512         
       
   513         iCellIdDatabase->InsertCidLocation( countryCode,
       
   514                                             networkCode,
       
   515                                             iLocArea.iLocationAreaCode,
       
   516                                             iLocArea.iCellId,
       
   517                                             cellPosition );
       
   518         }
       
   519     
       
   520     // Check if there is no movement from last location fix. If true then 
       
   521     // re-evaluate sleep interval
       
   522     TReal32 dist;
       
   523     currentPosition.Distance( prevPosition, dist );
       
   524     if( dist == 0 )
       
   525         {
       
   526         iState = EUpdateIntervalEstimation;
       
   527         SetEvent();
       
   528         }
       
   529     
       
   530     LOG1("Lat:%f",currentPosition.Latitude());
       
   531 	LOG1("Long:%f",currentPosition.Longitude());
       
   532 	LOG1("HA:%f",currentPosition.HorizontalAccuracy());
       
   533     
       
   534     // Switch to idle state as refresh is an async operation. Set projected 
       
   535     // state to trigger evaluation which will commence once the refresh 
       
   536     // operation is complete
       
   537     iState = ETriggerEvaluation;
       
   538     SetEvent();
       
   539 
       
   540     }
       
   541 
       
   542 
       
   543 // -----------------------------------------------------------------------------
       
   544 // CLbtCoOrdinateSupervisor::EvaluateTriggersL
       
   545 // Evaluates triggers based on the location information obtained 
       
   546 // -----------------------------------------------------------------------------
       
   547 //
       
   548 void CLbtCoOrdinateSupervisor::EvaluateTriggersL()
       
   549     {
       
   550     FUNC_ENTER("CLbtCoOrdinateSupervisor::EvaluateTriggersL");
       
   551     
       
   552     // Reset nearest trigger array
       
   553     iNearestTriggers.Reset();
       
   554     
       
   555     // TODO: In case of updates to trigger information do not change state
       
   556     //       else change state to EUpdateIntervalEstimation
       
   557     CLbtContainerTriggerEntry* conTrigger;
       
   558     
       
   559     // ResetViewIterator will switch state to Idle if there are no triggers in 
       
   560     // the system
       
   561     if( KErrNone != ResetViewIterator() )
       
   562         {
       
   563         return;
       
   564         }
       
   565 
       
   566     while( iViewIterator.NextL( conTrigger ) )
       
   567         {
       
   568         if( conTrigger )    
       
   569             {
       
   570             CLbtTriggerEntry* trigger = conTrigger->TriggerEntry();
       
   571             if( CLbtTriggerConditionBase::ETriggerConditionArea == 
       
   572                                                 trigger->GetCondition()->Type() )
       
   573                 {
       
   574                 // Area type trigger
       
   575                 CLbtTriggerConditionArea* triggerConArea = 
       
   576                                         static_cast< CLbtTriggerConditionArea* >
       
   577                                                 ( trigger->GetCondition() );
       
   578                    
       
   579                 switch( triggerConArea->TriggerArea()->Type() )
       
   580                     {
       
   581                 	// Circular area
       
   582                 	case CLbtGeoAreaBase::ECircle:
       
   583                 		{
       
   584                 		if( iLastLocationFixType == EProperFix )
       
   585                             {
       
   586                             EvalCircularTriggerL( conTrigger );
       
   587                             }
       
   588                         else if( iLastLocationFixType == EFixFromDb || iLastLocationFixType == EFixFromNpp )
       
   589                             {
       
   590                             if( EvalCircularTriggerBasedOnCellPositionL( conTrigger ) )
       
   591                                 {
       
   592                                 if( iLastLocationFixType == EFixFromNpp )
       
   593                                 	{
       
   594                                 	// Fix is taken from NPP only when Proper Fix fails. Now we should
       
   595                                 	// sleep for location acquisition failure time our period since there is no point
       
   596                                 	// in attempting another proper fix
       
   597                                 	iState = ESleep;
       
   598 				                    iTimer->Set( iStatus, KSleepTimeOnLocAcqFailure, ETrue );               
       
   599 				                    SetActive();
       
   600 
       
   601 				                    if( KErrAccessDenied == iStatus.Int() )
       
   602 				                        {
       
   603 				                        iAcquisitionStatus = ELocationAcquisitionPrivacyReject;
       
   604 				                        }
       
   605 				                    else 
       
   606 				                        {
       
   607 				                        iAcquisitionStatus = ELocationAcquisitionFailure;
       
   608 				                        }
       
   609                                 	}
       
   610                                 else
       
   611                                 	{
       
   612                                 	RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix );
       
   613                                 	}                                
       
   614                                 return;
       
   615                                 }
       
   616                             }                            
       
   617                     	break;
       
   618                 		}                    
       
   619                 	default:
       
   620                     	break;
       
   621                     }
       
   622                 }
       
   623             }
       
   624         }
       
   625         
       
   626     // Update supervision dynamic info to the strategy class
       
   627     TLbtStrategySupervisionDynamicInfo supervisionDynamicInfo;
       
   628     if( iNearestTriggers.Count() )
       
   629         {
       
   630         supervisionDynamicInfo.iDistanceToNearestTrigger = iNearestTriggers[0].distance;
       
   631         supervisionDynamicInfo.iNearestTriggerId = iNearestTriggers[0].id;
       
   632         }
       
   633     supervisionDynamicInfo.iLatestAcquiredPosInfo = iPosInfo;
       
   634     supervisionDynamicInfo.iLocationAcquisitionStatus = iAcquisitionStatus;
       
   635     
       
   636     
       
   637     iEngObserver->ReportTriggeringSupervisionStatus( supervisionDynamicInfo );
       
   638     
       
   639     iState = EUpdateIntervalEstimation;
       
   640     SetEvent();
       
   641     }
       
   642     
       
   643 
       
   644 // -----------------------------------------------------------------------------
       
   645 // CLbtCoOrdinateSupervisor::EvaluateTriggers
       
   646 // Evaluates triggers based on the location information obtained 
       
   647 // -----------------------------------------------------------------------------
       
   648 //
       
   649 TBool CLbtCoOrdinateSupervisor::EvaluateModifiedTriggersL()
       
   650     {
       
   651     FUNC_ENTER("CLbtCoOrdinateSupervisor::EvaluateModifiedTriggersL");
       
   652     
       
   653     // Retrieve modified trigger list from trigger view to be supervised
       
   654     RArray< TLbtTriggerId > modifiedTriggers;
       
   655     iView->GetModifiedTriggers( modifiedTriggers );
       
   656     CleanupClosePushL( modifiedTriggers );
       
   657     if( modifiedTriggers.Count() )
       
   658         {
       
   659         // TODO: Need to check for the deletion of
       
   660         // Create an iterator to parse through the modified trigger list
       
   661         CLbtTriggerView::TTriggerViewIter iter = iView->Begin( &modifiedTriggers, CLbtGeoAreaBase::ECircle );        
       
   662         
       
   663         CLbtContainerTriggerEntry* conTrigger;
       
   664         while( iter.NextL( conTrigger ) )
       
   665             {
       
   666             if( conTrigger )
       
   667                 {
       
   668                 CLbtTriggerEntry* trigger = conTrigger->TriggerEntry();
       
   669                 if( CLbtTriggerConditionBase::ETriggerConditionArea == 
       
   670                                                     trigger->GetCondition()->Type() )
       
   671                     {
       
   672                     // Area type trigger
       
   673                     CLbtTriggerConditionArea* triggerConArea = 
       
   674                                             static_cast< CLbtTriggerConditionArea* >
       
   675                                                     ( trigger->GetCondition() );
       
   676                        
       
   677                     switch( triggerConArea->TriggerArea()->Type() )
       
   678                         {
       
   679 	                    // Circular area
       
   680 	                    case CLbtGeoAreaBase::ECircle:
       
   681 	                        if( iLastLocationFixType == EProperFix )
       
   682 	                            {
       
   683 	                            EvalCircularTriggerL( conTrigger );
       
   684 	                            }
       
   685 	                        else if( iLastLocationFixType == EFixFromDb || iLastLocationFixType == EFixFromNpp )
       
   686 	                            {
       
   687 	                            if( EvalCircularTriggerBasedOnCellPositionL( conTrigger ) )
       
   688 	                                {
       
   689 	                                CleanupStack::PopAndDestroy();  // modifiedTriggers
       
   690 	                                return ETrue;
       
   691 	                                }
       
   692 	                            }
       
   693 	                        break; 
       
   694 	                        
       
   695 	                    // TODO: Cell ID triggers need to be handled
       
   696 	                    default:
       
   697 	                        break;
       
   698                         }
       
   699                     }
       
   700                 }
       
   701             }        
       
   702         }
       
   703         
       
   704     CleanupStack::PopAndDestroy();  // modifiedTriggers
       
   705     return EFalse;
       
   706     }
       
   707     
       
   708 
       
   709 // -----------------------------------------------------------------------------
       
   710 // CLbtCoOrdinateSupervisor::EvalCircularTrigger
       
   711 // Evaluates triggers with circular area definition
       
   712 // -----------------------------------------------------------------------------
       
   713 //
       
   714 void CLbtCoOrdinateSupervisor::EvalCircularTriggerL( 
       
   715                                           CLbtContainerTriggerEntry* aTrigger )
       
   716     {
       
   717     FUNC_ENTER("CLbtCoOrdinateSupervisor::EvalCircularTrigger");
       
   718     
       
   719     
       
   720     // Extract strategy data
       
   721     TStrategyData strategyData = aTrigger->StrategyData();                                          
       
   722     
       
   723     TInt remRearmTime = 0;
       
   724     TReal distanceToLatestLocation = 0.0;
       
   725     TBool hasRearmTimeExpired = ETrue;
       
   726     
       
   727     LOGSTRING("Trigger: \"%S\" ", &(aTrigger->TriggerEntry()->Name()));
       
   728         
       
   729     if( strategyData.iFireTime )
       
   730         {
       
   731         TTime triggerFiredTime( strategyData.iFireTime );
       
   732 
       
   733         TTime currentTime;
       
   734         currentTime.UniversalTime();
       
   735         
       
   736         TTimeIntervalSeconds interval;
       
   737         currentTime.SecondsFrom( triggerFiredTime, interval );
       
   738         
       
   739         remRearmTime = aTrigger->TriggerEntry()->TimeToRearm() - interval.Int();
       
   740         
       
   741         
       
   742         if( remRearmTime <= 0 )
       
   743             {
       
   744             remRearmTime = 0;
       
   745             strategyData.iFireTime = 0;
       
   746             }
       
   747         else
       
   748         	{
       
   749         	LOG("Rearm Time has not expired");
       
   750         	hasRearmTimeExpired = EFalse;
       
   751         	}
       
   752         }
       
   753         
       
   754     CLbtTriggerConditionArea* trgCondition = 
       
   755                               static_cast< CLbtTriggerConditionArea* >
       
   756                               ( ( aTrigger->TriggerEntry() )->GetCondition() );
       
   757     
       
   758     CLbtGeoCircle* circularArea = static_cast< CLbtGeoCircle* >
       
   759                                                ( trgCondition->TriggerArea() );
       
   760 
       
   761     // Calculate distance of trigger from current location
       
   762     TReal32 distanceToCenter;
       
   763     TPosition currentPosition;
       
   764     iPosInfo.GetPosition( currentPosition );
       
   765     TInt err = currentPosition.Distance( circularArea->Center(), 
       
   766                                          distanceToCenter );
       
   767     if( KErrNone != err )
       
   768         {
       
   769         ERROR("Error in calculating distance:%d",err);
       
   770         LOG1("Current Lat:%f",currentPosition.Latitude());
       
   771 	    LOG1("Current Long:%f",currentPosition.Longitude());   
       
   772 	    LOG1("Trigger Lat:%f",circularArea->Center().Latitude());   
       
   773 	    LOG1("Trigger Long:%f",circularArea->Center().Longitude());
       
   774         return;
       
   775         }
       
   776 
       
   777     // Determine trigger radius and hysteresis radius to be used for supervision
       
   778     // based on the accuracy of location fix
       
   779     TTriggerArea triggerArea;
       
   780     TReal positionAccuracy = currentPosition.HorizontalAccuracy();    
       
   781     triggerArea = EstimateTriggerRadii( circularArea->Radius(), 
       
   782                     aTrigger->ExtendedTriggerInfo()->HysteresisRadius(), 
       
   783                         positionAccuracy );
       
   784     
       
   785     // ENTRY Trigger
       
   786     // Determine current position of terminal relative to the trigger area and 
       
   787     // set trigger fire status accordingly
       
   788     if( CLbtTriggerConditionArea::EFireOnEnter == trgCondition->Direction() )
       
   789         {
       
   790         TLbtTriggerDataMask dataMask = 0;
       
   791         
       
   792         TReal tolerableRadius = CalculateTolerableRadius( triggerArea.triggerRadius );
       
   793         // Terminal is inside trigger area
       
   794         if( ( distanceToCenter < tolerableRadius ) && 
       
   795             ( ( distanceToCenter + positionAccuracy ) <= triggerArea.hysteresisRadius ) )
       
   796             {
       
   797             LOG("Inside triggerin area");
       
   798             // If trigger in active state then fire trigger and set state to
       
   799             // inactive. If trigger is inactive nothing is to be done other
       
   800             // than calculating its distance from the hysteresis boundary
       
   801             if( EActive == strategyData.iActivityStatus )
       
   802                 {
       
   803 				LOG("Active trigger");
       
   804                 // Check FireOnCreation flag here. If EFalse then dont 
       
   805                 // fire the trigger. Instead only change the activity
       
   806                 // status.
       
   807                 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() &&
       
   808                     hasRearmTimeExpired )
       
   809                     {
       
   810                     // Set trigger state to fired
       
   811                     aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue );
       
   812                     TLbtTriggerFireInfo triggerFireInfo;
       
   813                     TPositionInfo positionInfo;
       
   814                     triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id();
       
   815                     triggerFireInfo.iFiredPositionInfo = iPosInfo;
       
   816                     
       
   817                     aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo );
       
   818                     
       
   819                     // Time at which trigger fired
       
   820                     TTime triggerFiredTime;
       
   821                     triggerFiredTime.UniversalTime();
       
   822                     LOG("TRIGGER FIRED");
       
   823                     
       
   824                     strategyData.iFireTime = triggerFiredTime.Int64();
       
   825                     
       
   826                     remRearmTime = aTrigger->TriggerEntry()->TimeToRearm();
       
   827                     dataMask |= 
       
   828                     CLbtContainerTriggerEntry::EContainerAttributeIsFired | 
       
   829                     CLbtContainerTriggerEntry::EContainerAttributeFireInfo ;
       
   830                     }
       
   831                 
       
   832                 // Set trigger to inactive state                
       
   833                 strategyData.iActivityStatus = EInactive;
       
   834                 }
       
   835             
       
   836             // Calculate distance to current location and update trigger's 
       
   837             // dynamic info. This distance is (rH - D) where D is the distance 
       
   838             // between the two centers and rH is the radius of the hysteresis 
       
   839             // circle. Here the radius of hysteresis boundary is considered for 
       
   840             // distance calculation as this trigger would undergo a state 
       
   841             // change only when it crosses the hysteresis area
       
   842             distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter );
       
   843             }
       
   844             
       
   845         // Terminal is outside hysteresis area
       
   846         else if( distanceToCenter > ( triggerArea.hysteresisRadius + positionAccuracy ) )
       
   847             {
       
   848             if( EInactive == strategyData.iActivityStatus )
       
   849                 {
       
   850                 // Reset trigger state to valid
       
   851                 strategyData.iActivityStatus = EActive;     
       
   852                 LOG("Trigger activated");
       
   853                 }
       
   854                 
       
   855             // Calculate distance of trigger to current location and update
       
   856             // trigger's dynamic info. This distance is (D - rT) where D is 
       
   857             // the distance between two centers and rT is the radius of trigger. 
       
   858             // State change will occur only when the terminal moves beyond the
       
   859             // boundary of the trigger
       
   860             distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius );
       
   861             }
       
   862 
       
   863         // Terminal is inside hysteresis area. 
       
   864         else
       
   865             {
       
   866             // Trigger does not undergo any state change in this region. Theres 
       
   867             // only distance to be determined here
       
   868             if( EActive == strategyData.iActivityStatus )
       
   869                 {
       
   870                 // Terminal was outside hysteresis area earlier. Distance is
       
   871                 // therefore (D - rT)
       
   872                 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius );
       
   873                 }
       
   874             else
       
   875                 {
       
   876                 // Terminal was inside trigger area earlier. Distance is
       
   877                 // therefore (rH - D)
       
   878                 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter );
       
   879                 }
       
   880             }
       
   881         
       
   882         // Set FireOnCreation flag to ETrue here if its not already
       
   883         // ETrue. This is done to ensure that the trigger is fired 
       
   884         // in the subsequent iterations if the triggering conditions
       
   885         // are satisfied.
       
   886         if( !aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() )
       
   887             {
       
   888             aTrigger->ExtendedTriggerInfo()->SetTriggerFireOnCreation( ETrue );
       
   889             dataMask |= CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation;
       
   890             }
       
   891         
       
   892         if( dataMask )
       
   893             {
       
   894             iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, aTrigger, dataMask );            
       
   895             }
       
   896         }
       
   897         
       
   898     // EXIT Trigger
       
   899     else
       
   900         {
       
   901         TLbtTriggerDataMask dataMask = 0;
       
   902         // Retrieve boundary information of trigger
       
   903         TTriggerBoundary boundary = EUndefined;
       
   904         
       
   905         // Retrieve boundary information of trigger
       
   906         ( strategyData.iBoundaryCondition >= 0 && strategyData.iBoundaryCondition <= 2 )?boundary =
       
   907                                      TTriggerBoundary( strategyData.iBoundaryCondition ):boundary;
       
   908         
       
   909         TReal tolerableRadius = CalculateTolerableRadius( triggerArea.triggerRadius );                             
       
   910         
       
   911         // Terminal is inside trigger area
       
   912         if( ( distanceToCenter < tolerableRadius ) && 
       
   913             ( ( distanceToCenter + positionAccuracy ) <= triggerArea.hysteresisRadius ) )
       
   914             {
       
   915             // Check boundary condition to determine if the terminal has moved
       
   916             // inside the trigger area without having gone beyond the area of
       
   917             // hysteresis. In this case the trigger shall not be set as active
       
   918             if( EOutside != boundary && 
       
   919                     EInactive == strategyData.iActivityStatus )
       
   920                 {
       
   921                 // Set trigger state to active
       
   922                 strategyData.iActivityStatus = EActive;
       
   923                 }
       
   924             
       
   925             // Set boundary as Outside
       
   926             strategyData.iBoundaryCondition =  TInt( EOutside );
       
   927             
       
   928             if( EActive == strategyData.iActivityStatus )
       
   929                 {
       
   930                 // Set Distance to the border of trigger area. This distance is
       
   931                 // (rT - D).
       
   932                 distanceToLatestLocation = Abs( triggerArea.triggerRadius - distanceToCenter );
       
   933                 }
       
   934             else
       
   935                 {
       
   936                 // Set distance to border of hysteresis area. This distance is
       
   937                 // (rH - D) where rH is the radius of hysteresis and D is the 
       
   938                 // distance between the center of trigger and the center of 
       
   939                 // location
       
   940                 distanceToLatestLocation = Abs( triggerArea.hysteresisRadius - distanceToCenter );
       
   941                 }
       
   942             }
       
   943             
       
   944         // Terminal is outside hysteresis area  
       
   945         else if( ( distanceToCenter > triggerArea.hysteresisRadius )  &&
       
   946             ( distanceToCenter > ( triggerArea.triggerRadius + positionAccuracy ) ) )
       
   947             {
       
   948             if( EActive == strategyData.iActivityStatus  )
       
   949                 {
       
   950                 // Check FireOnCreation flag here. If EFalse then dont 
       
   951                 // fire the trigger. Instead only change the activity
       
   952                 // status.
       
   953                 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() &&
       
   954                     hasRearmTimeExpired )
       
   955                     {
       
   956                     // Set trigger state to fired
       
   957                     aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue );
       
   958                     
       
   959                     TLbtTriggerFireInfo triggerFireInfo;
       
   960                     TPositionInfo positionInfo;
       
   961                     triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id();
       
   962                     triggerFireInfo.iFiredPositionInfo = iPosInfo;
       
   963                     
       
   964                     aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo );
       
   965                     
       
   966                      // Time at which trigger fired
       
   967                     TTime triggerFiredTime;
       
   968                     triggerFiredTime.UniversalTime();
       
   969                     strategyData.iFireTime = triggerFiredTime.Int64();
       
   970                     LOG("TRIGGER FIRED");
       
   971                     remRearmTime = aTrigger->TriggerEntry()->TimeToRearm();             
       
   972                     dataMask |= 
       
   973                     CLbtContainerTriggerEntry::EContainerAttributeIsFired | 
       
   974                     CLbtContainerTriggerEntry::EContainerAttributeFireInfo;
       
   975                     }
       
   976                 
       
   977                 // Set the trigger state to inactive
       
   978                 strategyData.iActivityStatus = EInactive;
       
   979                 
       
   980                 }
       
   981 
       
   982             // Set boundary as Inside
       
   983             strategyData.iBoundaryCondition = TInt( EInside );
       
   984             
       
   985             // Calculate distance to border of trigger area. This distance
       
   986             // is (D - rT)
       
   987             distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius );
       
   988             }
       
   989         
       
   990         // Terminal is inside hysteresis area
       
   991         else
       
   992             {
       
   993             if( EOutside == boundary && EActive == strategyData.iActivityStatus )
       
   994                 {
       
   995                 // Check FireOnCreation flag here. If EFalse then dont 
       
   996                 // fire the trigger. Instead only change the activity
       
   997                 // status.
       
   998                 if( aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() )
       
   999                     {
       
  1000                     // Set trigger state to fired
       
  1001                     aTrigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue );
       
  1002                     TLbtTriggerFireInfo triggerFireInfo;
       
  1003                     TPositionInfo positionInfo;
       
  1004                     triggerFireInfo.iTriggerId = aTrigger->TriggerEntry()->Id();
       
  1005                     triggerFireInfo.iFiredPositionInfo = iPosInfo;
       
  1006                     
       
  1007                     aTrigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo );
       
  1008                     
       
  1009                      // Time at which trigger fired
       
  1010                     TTime triggerFiredTime;
       
  1011                     triggerFiredTime.UniversalTime();
       
  1012                     
       
  1013                     strategyData.iFireTime = triggerFiredTime.Int64();
       
  1014                     strategyData.iBoundaryCondition =  TInt( EOutside );
       
  1015                     
       
  1016                     remRearmTime = aTrigger->TriggerEntry()->TimeToRearm();             
       
  1017                     dataMask |= 
       
  1018                     CLbtContainerTriggerEntry::EContainerAttributeIsFired | 
       
  1019                     CLbtContainerTriggerEntry::EContainerAttributeFireInfo;
       
  1020                     }
       
  1021                 
       
  1022                 // Set the trigger state to inactive
       
  1023                 strategyData.iActivityStatus = EInactive;
       
  1024                 }
       
  1025 
       
  1026             if( EOutside != boundary )
       
  1027                 {
       
  1028                 // Set the trigger state to inactive. This is done here because
       
  1029                 // if a trigger was newly created (state is active) and it is
       
  1030                 // found to be within hysteresis area, then the activity status 
       
  1031                 // needs to be set to inactive to enable the trigger to be
       
  1032                 // handled appropriately when terminal moves inside trigger
       
  1033                 // area.
       
  1034                 strategyData.iActivityStatus = EInactive;
       
  1035                 // Calclulate distance to border of trigger area. This 
       
  1036                 // distance is (D - rT)
       
  1037                 distanceToLatestLocation = Abs( distanceToCenter - triggerArea.triggerRadius );
       
  1038                 }
       
  1039             else 
       
  1040                 {
       
  1041                 // Calculate distance to the boundary of hysteresis. This 
       
  1042                 // distance is (rH - D)
       
  1043                 distanceToLatestLocation = 
       
  1044                                Abs( triggerArea.hysteresisRadius - distanceToCenter );
       
  1045                 }
       
  1046             }
       
  1047         
       
  1048         // Set FireOnCreation flag to ETrue here if its not already
       
  1049         // ETrue. This is done to ensure that the trigger is fired 
       
  1050         // in the subsequent iterations if the triggering conditions
       
  1051         // are satisfied.
       
  1052         if( !aTrigger->ExtendedTriggerInfo()->IsTriggerFireOnCreation() )
       
  1053             {
       
  1054             aTrigger->ExtendedTriggerInfo()->SetTriggerFireOnCreation( ETrue );
       
  1055             dataMask |= CLbtContainerTriggerEntry::EContainerAttributeIsTriggerFireOnCreation;
       
  1056             }
       
  1057         
       
  1058         if( dataMask )    
       
  1059             {
       
  1060             iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, aTrigger, dataMask );
       
  1061             }
       
  1062         }
       
  1063     aTrigger->SetStrategyData( strategyData );    
       
  1064     UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation , remRearmTime );
       
  1065     LOG1("DistToTrig:%f",distanceToLatestLocation );
       
  1066     }
       
  1067 
       
  1068 
       
  1069 // -----------------------------------------------------------------------------
       
  1070 // CLbtCoOrdinateSupervisor::EvalCircularTriggerBasedOnCellPosition
       
  1071 // Evaluates triggers with circular area definition
       
  1072 // -----------------------------------------------------------------------------
       
  1073 //
       
  1074 TBool CLbtCoOrdinateSupervisor::EvalCircularTriggerBasedOnCellPositionL( 
       
  1075                                           CLbtContainerTriggerEntry* aTrigger )
       
  1076     {
       
  1077     TTime currentTime;
       
  1078     currentTime.UniversalTime();
       
  1079     
       
  1080     CLbtTriggerConditionArea* trgCondition = 
       
  1081                               static_cast< CLbtTriggerConditionArea* >
       
  1082                               ( ( aTrigger->TriggerEntry() )->GetCondition() );
       
  1083         
       
  1084     // Extract strategy data
       
  1085     TStrategyData strategyData = aTrigger->StrategyData();
       
  1086     
       
  1087     TInt remRearmTime = 0;
       
  1088     TReal distanceToLatestLocation = 0.0;
       
  1089        
       
  1090     if( strategyData.iFireTime )
       
  1091         {
       
  1092         TTime triggerFiredTime( strategyData.iFireTime );
       
  1093 
       
  1094         TTimeIntervalSeconds interval;
       
  1095         currentTime.SecondsFrom( triggerFiredTime, interval );
       
  1096     
       
  1097         remRearmTime = aTrigger->TriggerEntry()->TimeToRearm() - interval.Int();
       
  1098         
       
  1099         if( remRearmTime <= 0 )            
       
  1100             {
       
  1101             remRearmTime = 0;
       
  1102             strategyData.iFireTime = 0;
       
  1103             aTrigger->SetStrategyData( strategyData );
       
  1104             }
       
  1105         }
       
  1106             
       
  1107     
       
  1108     TPosition currentPosition;
       
  1109     iPosInfo.GetPosition( currentPosition );
       
  1110     TReal positionAccuracy = currentPosition.HorizontalAccuracy();    
       
  1111     
       
  1112     CLbtGeoCircle* circularArea = static_cast< CLbtGeoCircle* >
       
  1113                                            ( trgCondition->TriggerArea() );
       
  1114                                            
       
  1115     TReal32 distanceToCenter;
       
  1116     TInt err = currentPosition.Distance( circularArea->Center(), 
       
  1117                                                         distanceToCenter );
       
  1118     if( err!=KErrNone )
       
  1119         {
       
  1120         return ETrue;
       
  1121         }
       
  1122     
       
  1123     // If the trigger is entry type,we calculate distance to the hysterisis radius
       
  1124     if( CLbtTriggerConditionArea::EFireOnEnter == trgCondition->Direction() )
       
  1125         {
       
  1126         distanceToLatestLocation = distanceToCenter -
       
  1127                                          ( positionAccuracy+aTrigger->ExtendedTriggerInfo()->HysteresisRadius());
       
  1128                                          
       
  1129         if( distanceToLatestLocation < 0 && (remRearmTime == 0) )
       
  1130         	{
       
  1131         	// Request fix using any of the available psy
       
  1132         	LOG("Request Proper Fix");
       
  1133         	return ETrue;
       
  1134         	}
       
  1135 
       
  1136         // Activate the trigger if the trigger is outside Hysteresis area
       
  1137         if( EInactive == strategyData.iActivityStatus && distanceToLatestLocation > 0 )
       
  1138         	{
       
  1139 	   		// Activate the trigger
       
  1140     		strategyData.iActivityStatus = EActive;
       
  1141     		aTrigger->SetStrategyData( strategyData );
       
  1142     		LOG("Trigger activated based on NPP fix");
       
  1143         	}
       
  1144         UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation, remRearmTime );
       
  1145         }
       
  1146     // If the trigger is exit type,we calculate distance to the radius    
       
  1147     else if( CLbtTriggerConditionArea::EFireOnExit == trgCondition->Direction() )  
       
  1148         {
       
  1149         distanceToLatestLocation = distanceToCenter -
       
  1150                                      ( positionAccuracy+circularArea->Radius() );
       
  1151 
       
  1152         if( distanceToLatestLocation < 0 && (remRearmTime == 0) )
       
  1153         	{
       
  1154         	// Request fix using any of the available psy
       
  1155         	LOG("Request Proper Fix");
       
  1156         	return ETrue;
       
  1157         	}	                             
       
  1158         UpdateNearestTriggers( aTrigger->TriggerEntry()->Id(), distanceToLatestLocation,remRearmTime );                                                          
       
  1159         }
       
  1160     return EFalse;     
       
  1161     }
       
  1162 
       
  1163 // -----------------------------------------------------------------------------
       
  1164 // CLbtCoOrdinateSupervisor::EstimateSleepInterval
       
  1165 // Calculates the sleep interval
       
  1166 // -----------------------------------------------------------------------------
       
  1167 //
       
  1168 void CLbtCoOrdinateSupervisor::EstimateSleepInterval()
       
  1169     {
       
  1170     FUNC_ENTER("CLbtCoOrdinateSupervisor::EstimateSleepInterval");
       
  1171     
       
  1172     // TODO: Need to use GPS speed for observed speed values
       
  1173     TReal maxUserSpeed = iSettings.iMaximumUserSpeed;
       
  1174         
       
  1175     TReal actualEstimatedSpeed = KMinProjSpeed;
       
  1176     // Flag to determine if the nearest trigger is an inactive trigger
       
  1177     TBool nearestTriggerInactive = EFalse;
       
  1178     
       
  1179     // This is first time when there are no previously observed values
       
  1180     if( iLocReqCount == 1 )
       
  1181         {
       
  1182         // First iteration use the minimum update interval
       
  1183         if( iNearestTriggers.Count() )
       
  1184             {
       
  1185             iSleepInterval = iNearestTriggers[0].distance / maxUserSpeed;
       
  1186             }
       
  1187         else
       
  1188             {
       
  1189             iSleepInterval = iSettings.iMinimumLocationUpdateInterval;
       
  1190             }
       
  1191         }
       
  1192     else
       
  1193         {
       
  1194         iEstimatedUserSpeed = 0.0;
       
  1195         if( (iLastLocationFixType == EFixFromDb) || 
       
  1196             (iLastLocationFixType == EFixFromNpp) )
       
  1197             {
       
  1198             iEstimatedUserSpeed = (maxUserSpeed + KMinProjSpeed)/2;
       
  1199             }
       
  1200         else if( iLastLocationFixType == EProperFix )
       
  1201             {
       
  1202             // determine average speed from previous location request which is the
       
  1203             // observed speed
       
  1204             TPosition currentPosition, prevPosition;
       
  1205             iPosInfo.GetPosition( currentPosition );
       
  1206             iPrevPosInfo.GetPosition( prevPosition );
       
  1207             
       
  1208             TReal32 avgSpeed = 0.0;
       
  1209             
       
  1210             currentPosition.Speed( prevPosition, avgSpeed );
       
  1211             TObservedValues obsValue;
       
  1212             obsValue.speed = avgSpeed;
       
  1213             obsValue.time = currentPosition.Time();
       
  1214 
       
  1215             if( iNObservedValues.Count() == maxObsValues )
       
  1216                 {
       
  1217                 iNObservedValues.Remove( 0 );
       
  1218                 }
       
  1219             iNObservedValues.Append( obsValue );
       
  1220             
       
  1221             TReal num = 0.0;
       
  1222             TReal den = 0.0;
       
  1223             TReal obsSpeed = 0.0;
       
  1224             TReal obsTime = 0.0;
       
  1225             TTime currentTime;
       
  1226 
       
  1227             // Determine average of previously obtained observed speed, time values.
       
  1228             // Use the current time value obtained from the approximation of speed.
       
  1229             currentTime.UniversalTime();
       
  1230             
       
  1231             for( TInt i = 0; i < iNObservedValues.Count(); i++ )
       
  1232                 {
       
  1233                 obsSpeed = maxUserSpeed - ( iNObservedValues[i] ).speed;
       
  1234                 TTimeIntervalSeconds timediff; 
       
  1235                 currentTime.SecondsFrom( ( iNObservedValues[i] ).time, timediff );  
       
  1236                 obsTime = timediff.Int() / constantTime;
       
  1237                 TReal timeExp = 0.0;
       
  1238                 Math::Exp( timeExp, (-1 * obsTime ) );
       
  1239                 
       
  1240                 num += obsSpeed * timeExp * timeExp;
       
  1241                 den += timeExp;
       
  1242                 }
       
  1243         
       
  1244             iEstimatedUserSpeed = maxUserSpeed - ( num / den );
       
  1245             
       
  1246             if( Math::IsNaN(iEstimatedUserSpeed) )
       
  1247             	{
       
  1248             	iEstimatedUserSpeed = maxUserSpeed;
       
  1249             	}
       
  1250 
       
  1251             actualEstimatedSpeed = iEstimatedUserSpeed;
       
  1252             LOG1("Actual estimated speed:%f",actualEstimatedSpeed);
       
  1253             
       
  1254             if(iEstimatedUserSpeed < KMinProjSpeed)
       
  1255                 {
       
  1256                 iEstimatedUserSpeed = KMinProjSpeed;
       
  1257                 }
       
  1258             // There are some cases estimate user speed goes to infinty.    
       
  1259             else if( iEstimatedUserSpeed > maxUserSpeed )    
       
  1260                 {
       
  1261                 iEstimatedUserSpeed = maxUserSpeed;
       
  1262                 }
       
  1263             }
       
  1264         
       
  1265         /**
       
  1266          * Find the position of the nearest trigger which: -
       
  1267          *
       
  1268          * a) Is Active
       
  1269          * b) Its rearm time has expired
       
  1270          */
       
  1271         TInt position = -1;
       
  1272         for( TInt i=0;i<iNearestTriggers.Count();i++ )
       
  1273             {
       
  1274             iNearestTriggers[i].minTimeRequired = iNearestTriggers[i].distance / iEstimatedUserSpeed;
       
  1275                 
       
  1276             if( iNearestTriggers[i].remRearmTime == 0 )
       
  1277                 {
       
  1278                 // It is enough for us to know the approx time required to reach nearest trigger whose 
       
  1279                 // rearm time is not zero( nearest which is not fired )  
       
  1280                 position = i;
       
  1281                 break;
       
  1282                 }
       
  1283             }
       
  1284         
       
  1285         /**
       
  1286          * Determine the sleep interval considering the rearm time of all the fired triggers.
       
  1287          * Sleep interval should be min[max[rearm time,minimum time to reach trigger]]. Flag needed
       
  1288          * for determining if movement detection is needed. Movement detector will be used if
       
  1289          * position acquisition should be made to re-activate the trigger.
       
  1290          */        
       
  1291         iSleepInterval = 0;
       
  1292         TLbtTriggerId nearestTriggerId = 0;
       
  1293         
       
  1294         // Sleep interval should be min[max[rearm time,minimum time to reach trigger]]
       
  1295         if( position >= 0 )
       
  1296             {
       
  1297             for( TInt i=0;i<=position;i++ )
       
  1298                 {
       
  1299                 // Sleep interval for a trigger is the maximum of time to trigger and rearm time
       
  1300                 TInt maxSleepTimeForTrigger;
       
  1301                 if( iNearestTriggers[i].remRearmTime < iNearestTriggers[i].minTimeRequired )
       
  1302                     {
       
  1303                     maxSleepTimeForTrigger = iNearestTriggers[i].minTimeRequired;
       
  1304                     }
       
  1305                 else
       
  1306                     {
       
  1307                     maxSleepTimeForTrigger = iNearestTriggers[i].remRearmTime;
       
  1308                     }
       
  1309                 
       
  1310                 // Sleep interval for system is minimum sleep interval of all triggers    
       
  1311                 if( ( !iSleepInterval.Int() && maxSleepTimeForTrigger ) ||
       
  1312                       iSleepInterval.Int() > maxSleepTimeForTrigger )  
       
  1313                     {
       
  1314                     iSleepInterval = maxSleepTimeForTrigger;
       
  1315                     nearestTriggerId = iNearestTriggers[i].id;
       
  1316                     }
       
  1317                 }
       
  1318             }
       
  1319         // Case where all the triggers are waiting for rearm time to elapse
       
  1320         else
       
  1321             {
       
  1322             for( TInt i=0;i<iNearestTriggers.Count();i++ )
       
  1323                 {
       
  1324                 if( !iSleepInterval.Int() || 
       
  1325                     ( iSleepInterval.Int() > iNearestTriggers[i].remRearmTime ))
       
  1326                     {
       
  1327                     iSleepInterval = iNearestTriggers[i].remRearmTime;
       
  1328                     }
       
  1329                 }
       
  1330             }  
       
  1331             
       
  1332         LOG1("Estimated speed:%f",iEstimatedUserSpeed);
       
  1333         
       
  1334         
       
  1335         if( nearestTriggerId )
       
  1336             {
       
  1337             // Update the nearestTriggerInactive flag                        
       
  1338             CLbtContainerTriggerEntry* trigEntry = NULL;
       
  1339             TBool found = iView->GetTriggerByID( nearestTriggerId, trigEntry );
       
  1340             
       
  1341             if( found && (trigEntry != NULL) )
       
  1342                 {
       
  1343                 TStrategyData strategyData = trigEntry->StrategyData();
       
  1344                 
       
  1345                 if( strategyData.iActivityStatus == EInactive )
       
  1346                     {
       
  1347                     // Inside triggering area
       
  1348                     nearestTriggerInactive = ETrue;
       
  1349                     }
       
  1350                 else
       
  1351                     {
       
  1352                     // Outside triggering area
       
  1353                     nearestTriggerInactive = EFalse;
       
  1354                     }
       
  1355                 }
       
  1356             }
       
  1357         
       
  1358         // Reduce the time taken from last position fix
       
  1359         if( iLastLocationFixType == EProperFix )
       
  1360         	{
       
  1361         	TTime currentTime;
       
  1362     	    currentTime.UniversalTime();
       
  1363     	    TTimeIntervalSeconds seconds;
       
  1364     	    currentTime.SecondsFrom(iLastFixTime, seconds);
       
  1365     	    iProcessingInterval = seconds.Int();
       
  1366     	    iSleepInterval = iSleepInterval.Int() - iProcessingInterval;
       
  1367         	}
       
  1368         
       
  1369        // TODO: Check with Krishna on the commented code
       
  1370         // Check to determine if GPS method used for location information. If 
       
  1371         // true, then need to use the GPS tracking mode interval here 
       
  1372         /*if( iLocationRequestor->GPSUsed() )
       
  1373             {
       
  1374             if( ( iSleepInterval.Int() < 
       
  1375                     iSettings.iMinimumLocationUpdateInterval ) || 
       
  1376                     ( iSleepInterval.Int() - iSettings.iGpsTrackingModeInterval ) < 5 )
       
  1377                 {
       
  1378                 iSleepInterval = iSettings.iGpsTrackingModeInterval;
       
  1379                 }
       
  1380             }
       
  1381         else
       
  1382             // 
       
  1383             {
       
  1384             // If GPS not used check if sleep interval is less than minimum 
       
  1385             // update interval. If true then use minimum update interval
       
  1386             if( iSleepInterval.Int() < 
       
  1387                     iSettings.iMinimumLocationUpdateInterval )
       
  1388                 {
       
  1389                 iSleepInterval = iSettings.iMinimumLocationUpdateInterval;
       
  1390                 }
       
  1391             }*/
       
  1392         }   
       
  1393     
       
  1394     // If sleep interval is less than KMinSleepInterval and the UE is travelling in
       
  1395     // high speed then request terminal position immediately
       
  1396     if( !nearestTriggerInactive &&
       
  1397         ( iSleepInterval.Int() <= KMinSleepInterval ) &&
       
  1398         ( iLastLocationFixType == EProperFix ) )
       
  1399         {
       
  1400         LOG1("Requesting time out %d", iSleepInterval.Int());
       
  1401         iFixForFiringCloseTriggers = ETrue;
       
  1402         // Here we need fix with in the estimated time to reach trigger.Hence setting timeout value to 
       
  1403         // estimated sleep interval	
       
  1404         RequestTerminalPosition( (KMinSleepInterval * KMicroMultiplier),EProperFix );
       
  1405         return;
       
  1406         }
       
  1407     
       
  1408     iState = ESleep;
       
  1409     TBool useMvmtDet = ETrue;
       
  1410     if( iLastLocationFixType != EProperFix )
       
  1411     	{
       
  1412     	useMvmtDet = ETrue;
       
  1413     	}
       
  1414     else if( nearestTriggerInactive )
       
  1415     	{
       
  1416     	useMvmtDet = ETrue;
       
  1417     	}    
       
  1418     else if( iSleepInterval.Int() < 20 )
       
  1419     	{
       
  1420     	useMvmtDet = EFalse;
       
  1421     	}
       
  1422 	else if( actualEstimatedSpeed > KMaxSpeedToUseMvmtDet )
       
  1423     	{
       
  1424     	useMvmtDet = EFalse;
       
  1425     	}
       
  1426     LOG1("useMvmtDet = %d", useMvmtDet);
       
  1427     iTimer->Set( iStatus, iSleepInterval, useMvmtDet );
       
  1428     SetActive();
       
  1429     }
       
  1430 
       
  1431     
       
  1432 // -----------------------------------------------------------------------------
       
  1433 // CLbtCoOrdinateSupervisor::ProcessInterrupt
       
  1434 // Evaluates the cause of a timer interrupt and determines the necessary 
       
  1435 // actions to be performed
       
  1436 // -----------------------------------------------------------------------------
       
  1437 //
       
  1438 void CLbtCoOrdinateSupervisor::ProcessInterrupt()
       
  1439     {
       
  1440     FUNC_ENTER("CLbtCoOrdinateSupervisor::ProcessInterrupt");
       
  1441     
       
  1442     // This is when errors occur while acquiring terminal position
       
  1443     if( !iStatusManager->LocationAcqSuccess() )
       
  1444         {
       
  1445         // Check sleep interval and determine if sleep mode can continue else 
       
  1446         // retry acquiring terminal position. This happens when there are 
       
  1447         // changes to triggers in the sleep mode during which the sleep is 
       
  1448         // cancelled and trigger view is refreshed. Once the refresh operation
       
  1449         // is completed, this method is invoked.
       
  1450         TTimeIntervalSeconds interval;
       
  1451         if( iTimer->RemainingSleepInterval( interval ) )
       
  1452             {
       
  1453             iState = ESleep;
       
  1454             if( interval.Int() < 5 )
       
  1455                 {
       
  1456                 iTimer->ResetInterval( iStatus, interval,EFalse );
       
  1457                 }
       
  1458             else
       
  1459                 {
       
  1460                 iTimer->ResetInterval( iStatus, interval,ETrue );
       
  1461                 }
       
  1462             SetActive();
       
  1463             }
       
  1464         else
       
  1465             {
       
  1466             // If the last location acqusition has failed and the location information for the current cell
       
  1467             // is unavailable then request location from NPP PSY else request from DB itself
       
  1468             if( (iLastCellRequestStatus == KErrNone) && 
       
  1469                 iLocArea.iCellId )
       
  1470 		        {
       
  1471 		        // Cell information is available
       
  1472 		        if( !(KErrNone == GetCellIdPosition( iPosInfo ) ) )
       
  1473 		        	{
       
  1474 		        	RequestTerminalPosition( iSettings.iLocationRequestTimeout, EProperFix );
       
  1475 		        	}
       
  1476 		        else
       
  1477 		            {
       
  1478 		            RequestTerminalPosition( iSettings.iLocationRequestTimeout, EFixFromDb );
       
  1479 		            }
       
  1480             	}
       
  1481             else
       
  1482             	{
       
  1483             	// Current cell information un-available. Make proper fix
       
  1484             	RequestTerminalPosition( iSettings.iLocationRequestTimeout, EProperFix );
       
  1485             	}
       
  1486         	}
       
  1487         }
       
  1488 
       
  1489     
       
  1490     // This is when sleep mode is interrupted due to notifications from 
       
  1491     // container for addition/modification/deletion of triggers in the system
       
  1492     else if( iTimer->SleepIntervalInterrupted() )
       
  1493         {
       
  1494         TLbtTriggerId nearestTrigger = 0;
       
  1495         if( iNearestTriggers.Count() )
       
  1496             {
       
  1497             for( TInt i=0;i<iNearestTriggers.Count();i++ )
       
  1498                 {
       
  1499                 if( iNearestTriggers[i].remRearmTime == 0 )
       
  1500                     {
       
  1501                     nearestTrigger = iNearestTriggers[i].id;
       
  1502                     break;
       
  1503                     }
       
  1504                 }
       
  1505             }
       
  1506         iView->DetermineNearestTriggerChanges( &iNearestTriggers );
       
  1507         
       
  1508         if( iNearestTriggers.Count() == 0 )
       
  1509             {
       
  1510             // This means the nearest 5 triggers have been changed. Reset
       
  1511             // iterator re-evaluate all triggers in the system. 
       
  1512             if( KErrNone != ResetViewIterator() )
       
  1513                 {
       
  1514                 return;
       
  1515                 }
       
  1516             iState = ETriggerEvaluation;
       
  1517             SetEvent();
       
  1518             }
       
  1519         else
       
  1520             {
       
  1521             TBool makeLocReq = EFalse;
       
  1522             TRAPD( err, makeLocReq = EvaluateModifiedTriggersL( ) );
       
  1523             
       
  1524             if( KErrNone != err )
       
  1525             	{
       
  1526             	ERROR("EvaluateTriggersL leaving with %d", err);
       
  1527 	            Term();
       
  1528 	            return;            	
       
  1529             	}
       
  1530             
       
  1531             if( makeLocReq )
       
  1532             	{
       
  1533             	// Location request is needed based on evaluating
       
  1534             	// modified triggers
       
  1535             	RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
  1536             	return;
       
  1537             	}
       
  1538             
       
  1539             // Check if nearest trigger has changed
       
  1540             TLbtTriggerId nearestTriggerAfterEvaluation = 0;
       
  1541             if( iNearestTriggers.Count() )
       
  1542                 {
       
  1543                 for( TInt i=0;i<iNearestTriggers.Count();i++ )
       
  1544                     {
       
  1545                     if( iNearestTriggers[i].remRearmTime == 0 )
       
  1546                         {
       
  1547                         nearestTriggerAfterEvaluation = iNearestTriggers[i].id;
       
  1548                         break;
       
  1549                         }
       
  1550                     }
       
  1551                 }
       
  1552             // This is check is required when all triggers in the system has fired
       
  1553             // and new trigger has been added.
       
  1554             if( (nearestTriggerAfterEvaluation) && 
       
  1555                 (nearestTrigger != nearestTriggerAfterEvaluation) )                 
       
  1556                 {
       
  1557                 RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
  1558                 }            
       
  1559             else
       
  1560                 {
       
  1561                 // Check if there be any remaining sleep interval. If true, 
       
  1562                 // then switch to sleep mode for the remaining time period. 
       
  1563                 // Else switch to acquiring location information.
       
  1564                 TTimeIntervalSeconds remainingInterval;
       
  1565                 if( iTimer->RemainingSleepInterval( remainingInterval ) )
       
  1566                     {
       
  1567                     iState = ESleep;
       
  1568                     if( remainingInterval.Int() < 5 )
       
  1569                         {
       
  1570                         iTimer->ResetInterval( iStatus, remainingInterval,EFalse ); 
       
  1571                         }
       
  1572                     else
       
  1573                         {
       
  1574                         iTimer->ResetInterval( iStatus, remainingInterval,ETrue ); 
       
  1575                         }
       
  1576                     SetActive();
       
  1577                     }
       
  1578                 else
       
  1579                     {
       
  1580                     RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
  1581                     }
       
  1582                 }
       
  1583             }
       
  1584         }        
       
  1585     else if( KErrNone == iStatus.Int() || KErrAbort == iStatus.Int() )
       
  1586         {
       
  1587         // TODO: Check accuracy of movement monitor and 
       
  1588         //       if there was any detection made.
       
  1589         // For accuracy, pass the distance to nearest trigger as a reference 
       
  1590         // for movement detector plugin. If accuracy cannot be met then
       
  1591         // go ahead with acquiring current location else need to switch to
       
  1592         // movement detection mode.
       
  1593         RequestTerminalPosition( iSettings.iLocationRequestTimeout );
       
  1594         }
       
  1595     
       
  1596     // Error in timer operation
       
  1597     else
       
  1598         {
       
  1599         }
       
  1600 
       
  1601     }
       
  1602     
       
  1603 
       
  1604 // -----------------------------------------------------------------------------
       
  1605 // CLbtCoOrdinateSupervisor::RequestTerminalPosition
       
  1606 // Issues an asynchronous request to determine terminal's position
       
  1607 // -----------------------------------------------------------------------------
       
  1608 //
       
  1609 void CLbtCoOrdinateSupervisor::RequestTerminalPosition( TInt aLocationRequestTimeout,
       
  1610                                                         TLocationFixType aFixLocationFixType )
       
  1611     {
       
  1612     FUNC_ENTER("CLbtCoOrdinateSupervisor::RequestTerminalPosition");
       
  1613     iPrevPosInfo = iPosInfo;
       
  1614     LOG1("aFixLocationFixType = %d", aFixLocationFixType);
       
  1615     LOG1("Cell Id = %d", iLocArea.iCellId);
       
  1616 
       
  1617     if( (aFixLocationFixType == EFixFromDb) && 
       
  1618         (iLastCellRequestStatus == KErrNone) && 
       
  1619         iLocArea.iCellId )
       
  1620         {
       
  1621         LOG("Taking fix from DB");
       
  1622         TInt error = GetCellIdPosition( iPosInfo );
       
  1623         if( KErrNone ==  error)
       
  1624             {
       
  1625             LOG("Fix From DB");
       
  1626             TPosition position;
       
  1627             iPosInfo.GetPosition(position);
       
  1628             LOG1("Lat:%f", position.Latitude());
       
  1629 			LOG1("Long:%f", position.Longitude());
       
  1630 			LOG1("HA:%f", position.HorizontalAccuracy());
       
  1631             iLastLocationFixType = EFixFromDb;
       
  1632             iState = ETriggerEvaluation;
       
  1633             SetEvent();
       
  1634             return;
       
  1635             }
       
  1636         else
       
  1637         	{
       
  1638         	LOG1("Failed to get Fix From DB with %d", error);
       
  1639         	}
       
  1640         }
       
  1641     else if( aFixLocationFixType == EFixFromNpp )
       
  1642         {
       
  1643         iLastLocationFixType = EFixFromNpp;
       
  1644         iLocationRequestor->CurrentLocationFromNpp( iPosInfo, iStatus, 
       
  1645                                                     TTimeIntervalMicroSeconds( aLocationRequestTimeout ) );
       
  1646         iState = ELocationAcquisition;
       
  1647         SetActive();
       
  1648         return;
       
  1649         }
       
  1650 
       
  1651     iLastLocationFixType = EProperFix;
       
  1652     iLocationRequestor->CurrentLocation( iPosInfo, iStatus, 
       
  1653                                             iModuleId,
       
  1654                                             TTimeIntervalMicroSeconds( aLocationRequestTimeout ) );
       
  1655     iState = ELocationAcquisition;
       
  1656     SetActive();        
       
  1657     }
       
  1658 
       
  1659 
       
  1660 // -----------------------------------------------------------------------------
       
  1661 // CLbtCoOrdinateSupervisor::GetCellIdPosition
       
  1662 // Get the position corresponding to current cell id
       
  1663 // -----------------------------------------------------------------------------
       
  1664 //
       
  1665 TInt CLbtCoOrdinateSupervisor::GetCellIdPosition( TPositionInfo& aPositionInfo )
       
  1666     {
       
  1667     FUNC_ENTER("CLbtCoOrdinateSupervisor::GetCellIdPosition");
       
  1668     TInt countryCode,networkCode;
       
  1669     
       
  1670     TLex lex( iNwInfo.iCountryCode );
       
  1671     lex.Val( countryCode );
       
  1672     
       
  1673     lex.Assign( iNwInfo.iNetworkId );
       
  1674     lex.Val( networkCode );
       
  1675     
       
  1676     TPosition position;
       
  1677     TInt error = iCellIdDatabase->GetLocationForCid( countryCode,networkCode,iLocArea.iLocationAreaCode,
       
  1678                                                      iLocArea.iCellId,position );
       
  1679     if( error == KErrNone )
       
  1680         {
       
  1681         aPositionInfo.SetPosition( position );
       
  1682         }
       
  1683     return error;    
       
  1684     }
       
  1685 
       
  1686 
       
  1687 // -----------------------------------------------------------------------------
       
  1688 // CLbtCoOrdinateSupervisor::UpdateNearestTriggers
       
  1689 // Updates the record of nearest triggers
       
  1690 // -----------------------------------------------------------------------------
       
  1691 //
       
  1692 void CLbtCoOrdinateSupervisor::UpdateNearestTriggers( TLbtTriggerId aID, TReal aDistance , TInt aRemRearmTime )
       
  1693     {
       
  1694     FUNC_ENTER("CLbtCoOrdinateSupervisor::UpdateNearestTriggers");
       
  1695     TNearestTrigger nTrigger;
       
  1696     nTrigger.distance = aDistance;
       
  1697     nTrigger.id = aID;
       
  1698     nTrigger.remRearmTime = aRemRearmTime;
       
  1699     
       
  1700     TLinearOrder< TNearestTrigger > byDistance( CompareByDistance );
       
  1701     iNearestTriggers.InsertInOrderAllowRepeats( nTrigger, byDistance );
       
  1702     }
       
  1703 
       
  1704 
       
  1705 // -----------------------------------------------------------------------------
       
  1706 // CLbtCoOrdinateSupervisor::EstimateTriggerRadii
       
  1707 // Calculcates the trigger radius and the radius of the hysteresis circle
       
  1708 // -----------------------------------------------------------------------------
       
  1709 //
       
  1710 CLbtCoOrdinateSupervisor::TTriggerArea CLbtCoOrdinateSupervisor::EstimateTriggerRadii( 
       
  1711                          TReal aTriggerRadius, TReal aHysteresisRadius,
       
  1712                          TReal aPositionAccuracy )
       
  1713     {
       
  1714     TTriggerArea trgArea;
       
  1715     TReal ratioOfCircularAreas =  aPositionAccuracy / aTriggerRadius;
       
  1716     
       
  1717     if(  ratioOfCircularAreas >= KCofftOfHighEdgeLimit )
       
  1718         {
       
  1719         trgArea.triggerRadius = aTriggerRadius;
       
  1720         trgArea.hysteresisRadius = aHysteresisRadius;
       
  1721         }
       
  1722     else
       
  1723         {
       
  1724         // Update radiusOfTrigger and radiusOfHysteresis accordingly
       
  1725         trgArea.triggerRadius = aTriggerRadius +( KAccuracyMultiplier * aPositionAccuracy );
       
  1726         trgArea.hysteresisRadius = Hysteresis( trgArea.triggerRadius );        
       
  1727         }
       
  1728         
       
  1729     return trgArea;
       
  1730     }
       
  1731 
       
  1732 
       
  1733 // -----------------------------------------------------------------------------
       
  1734 // CLbtCoOrdinateSupervisor::Hysteresis
       
  1735 // Calculates the hysteresis radius 
       
  1736 // -----------------------------------------------------------------------------
       
  1737 //
       
  1738 TReal CLbtCoOrdinateSupervisor::Hysteresis( TReal aTriggerRadius )
       
  1739     {
       
  1740     TReal hysteresis;
       
  1741     if( aTriggerRadius > KTriggerRadiusCutoff )
       
  1742         {
       
  1743         TReal logRadius;				
       
  1744         Math::Ln( logRadius, aTriggerRadius / 10 );
       
  1745         hysteresis = aTriggerRadius / logRadius;        
       
  1746         }
       
  1747     else
       
  1748         {
       
  1749         hysteresis = aTriggerRadius / 4;
       
  1750         }
       
  1751     
       
  1752     return hysteresis + aTriggerRadius;
       
  1753     }
       
  1754 
       
  1755 
       
  1756 // -----------------------------------------------------------------------------
       
  1757 // CLbtCoOrdinateSupervisor::DetermineNearestDistances
       
  1758 // Algorithm to determine the shortest distance
       
  1759 // -----------------------------------------------------------------------------
       
  1760 //
       
  1761 TInt CLbtCoOrdinateSupervisor::CompareByDistance( const TNearestTrigger& src,
       
  1762         const TNearestTrigger& dst )
       
  1763     {
       
  1764     if( src.distance > dst.distance )
       
  1765         {
       
  1766         return 1;
       
  1767         }
       
  1768     else if( src.distance < dst.distance )
       
  1769         {
       
  1770         return -1;
       
  1771         }
       
  1772     return 0;
       
  1773     }
       
  1774    
       
  1775 
       
  1776 // -----------------------------------------------------------------------------
       
  1777 // CLbtCoOrdinateSupervisor::CompareByID
       
  1778 // Determine equality of nearest triggers by id
       
  1779 // -----------------------------------------------------------------------------
       
  1780 //
       
  1781 TBool CLbtCoOrdinateSupervisor::CompareByID( const TNearestTrigger& src,
       
  1782         const TNearestTrigger& dst )
       
  1783     {
       
  1784     if( src.id > dst.id )
       
  1785         {
       
  1786         return ETrue;
       
  1787         }
       
  1788     return EFalse;
       
  1789     }
       
  1790 
       
  1791 
       
  1792 // -----------------------------------------------------------------------------
       
  1793 // CLbtCoOrdinateSupervisor::ResetViewIterator
       
  1794 // Resets trigger view iterator.
       
  1795 // -----------------------------------------------------------------------------
       
  1796 //
       
  1797 TInt CLbtCoOrdinateSupervisor::ResetViewIterator()
       
  1798     {
       
  1799     FUNC_ENTER("CLbtCoOrdinateSupervisor::ResetViewIterator");
       
  1800     TInt err = iViewIterator.Reset();
       
  1801     if( KErrNone != err )
       
  1802         {
       
  1803         if( KErrNotFound == err )
       
  1804             {
       
  1805             
       
  1806             // determine update interval
       
  1807             iState = iProjectedState = EIdle;
       
  1808             }
       
  1809         else
       
  1810             {
       
  1811             Term();
       
  1812             // TODO: Server needs to be notified about termination of supervision 
       
  1813             }
       
  1814         return err;
       
  1815         }
       
  1816         
       
  1817     return KErrNone;
       
  1818     }
       
  1819 
       
  1820 
       
  1821 // -----------------------------------------------------------------------------
       
  1822 // CLbtCoOrdinateSupervisor::RunL
       
  1823 // Inherited from CActive - called when the request issued is completed.
       
  1824 // -----------------------------------------------------------------------------
       
  1825 //
       
  1826 void CLbtCoOrdinateSupervisor::RunL()
       
  1827     {
       
  1828     FUNC_ENTER("CLbtCoOrdinateSupervisor::RunL");
       
  1829     switch ( iState )
       
  1830         {
       
  1831         case ELocationAcquisition:
       
  1832             GetPositionInfoL();
       
  1833             break;
       
  1834 
       
  1835         case ETriggerEvaluation:
       
  1836             EvaluateTriggersL();
       
  1837             break;
       
  1838             
       
  1839         case EUpdateIntervalEstimation:
       
  1840             EstimateSleepInterval();
       
  1841             break;
       
  1842 
       
  1843         case ESleep:
       
  1844         	LOG("Wakeup");
       
  1845             ProcessInterrupt();
       
  1846             break;
       
  1847         
       
  1848         default:
       
  1849             break;
       
  1850         }
       
  1851     }
       
  1852 
       
  1853 
       
  1854 // -----------------------------------------------------------------------------
       
  1855 // CLbtCoOrdinateSupervisor::DoCancel
       
  1856 // Inherited from CActive - called to cancel outanding events.
       
  1857 // -----------------------------------------------------------------------------
       
  1858 //
       
  1859 void CLbtCoOrdinateSupervisor::DoCancel()
       
  1860     {
       
  1861     FUNC_ENTER("CLbtCoOrdinateSupervisor::DoCancel");
       
  1862     iFixForFiringCloseTriggers = EFalse;
       
  1863     }
       
  1864 
       
  1865 
       
  1866 // -----------------------------------------------------------------------------
       
  1867 // CLbtCoOrdinateSupervisor::RunError
       
  1868 // Handles the event of leave from the request completion event handler RunL()
       
  1869 // -----------------------------------------------------------------------------
       
  1870 //
       
  1871 TInt CLbtCoOrdinateSupervisor::RunError( TInt /*aError*/ ) 
       
  1872     {
       
  1873     FUNC_ENTER("CLbtCoOrdinateSupervisor::RunError");
       
  1874     Term();
       
  1875     return KErrNone;
       
  1876     }
       
  1877 
       
  1878 
       
  1879 // -----------------------------------------------------------------------------
       
  1880 // CLbtCoOrdinateSupervisor::CLbtCoOrdinateSupervisor
       
  1881 // C++ default constructor.
       
  1882 // -----------------------------------------------------------------------------
       
  1883 //
       
  1884 CLbtCoOrdinateSupervisor::CLbtCoOrdinateSupervisor() : 
       
  1885                 CActive( EPriorityHigh )
       
  1886     {
       
  1887     CActiveScheduler::Add( this );
       
  1888     }
       
  1889 
       
  1890     
       
  1891 // -----------------------------------------------------------------------------
       
  1892 // CLbtCoOrdinateSupervisor::ConstructL
       
  1893 // Symbian 2nd phase constructor.
       
  1894 // -----------------------------------------------------------------------------
       
  1895 //
       
  1896 void CLbtCoOrdinateSupervisor::ConstructL( TAny* /*aConstructionParameters*/,
       
  1897                                            CLbtTriggerView* aView,
       
  1898                                            MLbtStrategyEngineObsrvr* aObserver,
       
  1899                                            CLbtCellChangeHandler* aCellChangeHandler )
       
  1900     {
       
  1901 	iEngObserver = aObserver;
       
  1902 	iState = iProjectedState = EIdle;
       
  1903 	iEngObserver->RetrieveTriggeringSettings( iSettings );
       
  1904 	iCellChangeHandler = aCellChangeHandler;
       
  1905   
       
  1906     iModuleId = iSettings.iPositioningTechnology;
       
  1907     
       
  1908 	iLocationRequestor = CLbtLocationRequestor::NewL();
       
  1909 	
       
  1910 	iStatusManager = CLbtStatusManager::NewL();
       
  1911 	iTimer = CLbtStrategyTimer::NewL();
       
  1912 	iView = aView;	
       
  1913 	
       
  1914 	iViewIterator = iView->BeginL( CLbtGeoAreaBase::ECircle );
       
  1915 	iCellIdDatabase = CLbtCellIdDatabase::NewL();
       
  1916 	iLastCellRequestStatus = KErrUnknown;
       
  1917 	iLastLocationFixType = EFixUnknown;
       
  1918 	iPsyChangeListner = NULL;
       
  1919 	iFixForFiringCloseTriggers = EFalse;
       
  1920     }
       
  1921     
       
  1922 
       
  1923 // -----------------------------------------------------------------------------
       
  1924 // CLbtCoOrdinateSupervisor::SetEvent
       
  1925 // Completes the iRequestStatus with KErrNone.
       
  1926 // -----------------------------------------------------------------------------
       
  1927 //
       
  1928 void CLbtCoOrdinateSupervisor::SetEvent()
       
  1929     {
       
  1930     if ( !IsActive() )
       
  1931     	{
       
  1932     	TRequestStatus* lStatus = &iStatus;
       
  1933     	User::RequestComplete( lStatus, KErrNone );
       
  1934         SetActive();
       
  1935     	}    
       
  1936     }
       
  1937 
       
  1938 
       
  1939 // -----------------------------------------------------------------------------
       
  1940 // CLbtCoOrdinateSupervisor::Term
       
  1941 // 
       
  1942 // -----------------------------------------------------------------------------
       
  1943 //
       
  1944 void CLbtCoOrdinateSupervisor::Term()
       
  1945     {
       
  1946     FUNC_ENTER("CLbtCoOrdinateSupervisor::Term");
       
  1947     
       
  1948     iSupervisionInitiated = EFalse;
       
  1949             
       
  1950     iView->Cancel();
       
  1951     switch( iState )
       
  1952         {
       
  1953     case ELocationAcquisition:
       
  1954         if( iLastLocationFixType == EProperFix )
       
  1955     		{
       
  1956     		iLocationRequestor->Cancel();
       
  1957     		}
       
  1958     	else
       
  1959     		{
       
  1960     		iLocationRequestor->CancelFixFromNpp();
       
  1961     		}
       
  1962         break;
       
  1963         
       
  1964     case ESleep:
       
  1965         iTimer->Cancel();
       
  1966         break;
       
  1967     
       
  1968     default:
       
  1969         Cancel();
       
  1970         break;
       
  1971         }
       
  1972         
       
  1973     iState = iProjectedState = EIdle;
       
  1974     iLastLocationFixType = EFixUnknown;
       
  1975     iFixForFiringCloseTriggers = EFalse;
       
  1976     }
       
  1977 
       
  1978 // -----------------------------------------------------------------------------
       
  1979 // CLbtCoOrdinateSupervisor::FireClosestTriggers
       
  1980 // 
       
  1981 // -----------------------------------------------------------------------------
       
  1982 //
       
  1983 void CLbtCoOrdinateSupervisor::FireClosestTriggers()
       
  1984 	{
       
  1985 	FUNC_ENTER("CLbtCoOrdinateSupervisor::FireClosestTriggers");
       
  1986 	LOG1("NT Count = %d", iNearestTriggers.Count());
       
  1987 	for( TInt i=0;i<iNearestTriggers.Count();i++ )
       
  1988 		{
       
  1989 		if(iNearestTriggers[i].remRearmTime != 0)
       
  1990 		    {
       
  1991 		    continue;
       
  1992 		    }
       
  1993 
       
  1994 		TInt timeToTrigger = (iNearestTriggers[i].distance / iEstimatedUserSpeed);		
       
  1995 
       
  1996         TInt estimatedInterval = timeToTrigger - iProcessingInterval;
       
  1997 
       
  1998 		LOG1("estimatedInterval = %d", estimatedInterval);
       
  1999 
       
  2000 		if( estimatedInterval <= KMinSleepInterval )
       
  2001 			{
       
  2002 			LOG("NEED TO FIRE");
       
  2003 			CLbtContainerTriggerEntry* trigger;
       
  2004 			if( iView->GetTriggerByID( iNearestTriggers[i].id,trigger ) )
       
  2005 				{
       
  2006 				LOGSTRING("Trigger: \"%S\" ", &(trigger->TriggerEntry()->Name()));
       
  2007 				// check the activity status
       
  2008 				TStrategyData strategyData = trigger->StrategyData();   
       
  2009 				if( strategyData.iActivityStatus == EActive )
       
  2010 				    {
       
  2011 				    // Fire the trigger
       
  2012                     TLbtTriggerDataMask dataMask = 0;
       
  2013                     
       
  2014                     // Set trigger state to fired
       
  2015                     trigger->ExtendedTriggerInfo()->SetTriggerFiredState( ETrue );
       
  2016                     TLbtTriggerFireInfo triggerFireInfo;
       
  2017                     TPositionInfo positionInfo;
       
  2018                     triggerFireInfo.iTriggerId = trigger->TriggerEntry()->Id();
       
  2019                     triggerFireInfo.iFiredPositionInfo = iPrevPosInfo;
       
  2020                     
       
  2021                     trigger->ExtendedTriggerInfo()->SetFiredInfo( triggerFireInfo );
       
  2022                     
       
  2023                     // Time at which trigger fired
       
  2024                     TTime triggerFiredTime;
       
  2025                     triggerFiredTime.UniversalTime();
       
  2026                     LOG("NEAREST TRIGGER FIRED");
       
  2027                     
       
  2028                     strategyData.iFireTime = triggerFiredTime.Int64();
       
  2029                     // Set trigger to inactive state
       
  2030                     strategyData.iActivityStatus = EInactive;
       
  2031                     
       
  2032                     dataMask |= 
       
  2033                     CLbtContainerTriggerEntry::EContainerAttributeIsFired | 
       
  2034                     CLbtContainerTriggerEntry::EContainerAttributeFireInfo ;
       
  2035                     
       
  2036                     iView->UpdateTriggerInfo( CLbtGeoAreaBase::ECircle,iPosInfo, trigger, dataMask );
       
  2037                     trigger->SetStrategyData( strategyData );
       
  2038 				    }
       
  2039                 }
       
  2040             else
       
  2041                 {
       
  2042                 LOG("TRIGGER NOT FOUND ??");
       
  2043                 }
       
  2044 			}
       
  2045 		else
       
  2046 			{
       
  2047 			LOG("ELSE");
       
  2048 			// Since the array is in the ascending order of distance( which is directly proportional to time ),
       
  2049 			// we can need not search rest of the array.	
       
  2050 			break;
       
  2051 			}					
       
  2052 		}
       
  2053 	}
       
  2054 
       
  2055 // -----------------------------------------------------------------------------
       
  2056 // CLbtCoOrdinateSupervisor::CalculateTolerableRadius
       
  2057 // 
       
  2058 // -----------------------------------------------------------------------------
       
  2059 //
       
  2060 TReal CLbtCoOrdinateSupervisor::CalculateTolerableRadius( TReal aRadius )
       
  2061     {
       
  2062     // Tolerance can be calculated using the straight line equation. Slope of straight line is 0.07 and 
       
  2063     // intercept is 22.2
       
  2064     TReal tolerableInaccuracy = ( 0.07 * aRadius ) + 22.2;
       
  2065     return ( tolerableInaccuracy + aRadius );
       
  2066     }
       
  2067 
       
  2068 // -----------------------------------------------------------------------------
       
  2069 // CLbtCoOrdinateSupervisor::HandleCellChangeEvent
       
  2070 // 
       
  2071 // -----------------------------------------------------------------------------
       
  2072 //
       
  2073 void CLbtCoOrdinateSupervisor::HandleCellChangeEvent(
       
  2074             const TInt aStatus,
       
  2075             const RMobilePhone::TMobilePhoneNetworkInfoV1& aNwInfo,
       
  2076             const RMobilePhone::TMobilePhoneLocationAreaV1& aLocArea)
       
  2077     {
       
  2078     FUNC_ENTER("CLbtCoOrdinateSupervisor::HandleCellChangeEvent");
       
  2079     if( KErrNone == aStatus )
       
  2080 	    {
       
  2081 	    // validate network info
       
  2082 		if (aNwInfo.iMode == RMobilePhone::ENetworkModeGsm ||
       
  2083             aNwInfo.iMode == RMobilePhone::ENetworkModeWcdma)
       
  2084             {
       
  2085             TLex lex( aNwInfo.iCountryCode );
       
  2086             TInt countryCode,networkCode;
       
  2087             lex.Val( countryCode );
       
  2088             if( countryCode )
       
  2089                 {
       
  2090                 lex.Assign( aNwInfo.iNetworkId );
       
  2091                 lex.Val( networkCode );
       
  2092                 if( networkCode )
       
  2093                     {
       
  2094                     if( aLocArea.iLocationAreaCode && aLocArea.iCellId )
       
  2095                         {
       
  2096                         iLastCellRequestStatus = KErrNone;
       
  2097                         iNwInfo = aNwInfo;
       
  2098 		                iLocArea = aLocArea;
       
  2099 		                }
       
  2100                     }
       
  2101                 }
       
  2102             }
       
  2103 		}
       
  2104 	else 
       
  2105 	    {
       
  2106 	    iLastCellRequestStatus = aStatus;
       
  2107 	    }	
       
  2108     }
       
  2109 
       
  2110 // -----------------------------------------------------------------------------
       
  2111 // CLbtCoOrdinateSupervisor::HandlePsyChangeEvent
       
  2112 // 
       
  2113 // -----------------------------------------------------------------------------
       
  2114 //
       
  2115 void CLbtCoOrdinateSupervisor::HandlePsyChangeEvent( TPositionModuleId aModuleId  )
       
  2116     {
       
  2117     LOG("CLbtCoOrdinateSupervisor::HandlePsyChangeEvent");
       
  2118     if( aModuleId == iSettings.iPositioningTechnology )
       
  2119         {
       
  2120         LOG("aModuleId == iSettings.iPositioningTechnology");
       
  2121         iModuleId = aModuleId;
       
  2122         delete iPsyChangeListner;
       
  2123         iPsyChangeListner = NULL;        
       
  2124         }
       
  2125     else
       
  2126         {
       
  2127         LOG("aModuleId != iSettings.iPositioningTechnology");
       
  2128         // We will use defualt proxy
       
  2129         iModuleId = TUid::Uid(0xFFFFFFFF);
       
  2130         iPsyChangeListner->StartToListen( iSettings.iPositioningTechnology );
       
  2131         }
       
  2132     
       
  2133     // If coordinate supervisor AO is not active,request terminal position    
       
  2134     if( !IsActive() )
       
  2135         {
       
  2136         RequestTerminalPosition( iSettings.iLocationRequestTimeout,EProperFix );
       
  2137         }    
       
  2138     }
       
  2139 // end of file