networkprotocolmodules/networkprotocolmodule/LbsProtocolModule/src/cnetlocstatemachine.cpp
changeset 0 9cfd9a3ee49c
equal deleted inserted replaced
-1:000000000000 0:9cfd9a3ee49c
       
     1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // This file provides the implementation of the class for
       
    15 // the NETLOC protocol state machine.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalTechnology
       
    22  @released
       
    23 */
       
    24 
       
    25 #include "cnetlocstatemachine.h"
       
    26 #include "cnetlocstatehandler.h"
       
    27 #include "lbsdevloggermacros.h"
       
    28 
       
    29 /** KNetLocReqIssuedTimerEvent
       
    30 Identity of timer for when Network Based Location request issued to network
       
    31 */
       
    32 const TInt KNetLocReqIssuedTimerEvent = 0x800;
       
    33 
       
    34 /** KNetLocReqIssuedTimerDurationInSec
       
    35 Timer duration for when Network Based Location request issued to network
       
    36 */
       
    37 const TInt KNetLocReqIssuedTimerDurationInSec = 20;
       
    38 
       
    39 /** KLocRespTimerEvent
       
    40 Identity of timer for when location response expected by network
       
    41 */
       
    42 const TInt KLocRespTimerEvent = 0x900;
       
    43 
       
    44 /** KLocRespTimerDurationInSec
       
    45 Timer duration for when location response expected by network
       
    46 */
       
    47 const TInt KLocRespTimerDurationInSec = 64;
       
    48 
       
    49 /** KMaxQueueEntry
       
    50 Maximum entries in this state machine request queue.
       
    51 */
       
    52 const TInt KMaxQueueEntry = 5;
       
    53 
       
    54 
       
    55 /** Static constructor.
       
    56 @param aObserver Reference to state machine observer.
       
    57 @return A new instance of the CNetLocStateMachine class
       
    58 */  
       
    59 CNetLocStateMachine* CNetLocStateMachine::NewL(MStateMachineObserver& aObserver)
       
    60 	{
       
    61 	CNetLocStateMachine* self = new (ELeave) CNetLocStateMachine(aObserver);
       
    62 	CleanupStack::PushL(self);
       
    63 	self->ConstructL();
       
    64 	CleanupStack::Pop(self);
       
    65 	return self;
       
    66 	}
       
    67 
       
    68 
       
    69 /** Standard constructor.
       
    70 @param aObserver Reference to state machine observer.
       
    71 */  
       
    72 CNetLocStateMachine::CNetLocStateMachine(MStateMachineObserver& aObserver)
       
    73 : CStateMachineBase(aObserver)
       
    74 	{
       
    75 	iLocReqType = MLbsNetworkProtocolObserver::EServiceNetworkLocation;
       
    76 	}
       
    77 
       
    78 
       
    79 /** Standard destructor.
       
    80 */  
       
    81 CNetLocStateMachine::~CNetLocStateMachine()
       
    82 	{
       
    83 	delete iLocRespTimer;
       
    84 	delete iNetLocReqIssuedTimer;
       
    85 	}
       
    86 
       
    87 
       
    88 /** Private second-stage constructor.
       
    89 */  
       
    90 void CNetLocStateMachine::ConstructL()
       
    91 	{
       
    92 	CActiveScheduler::Add(this);
       
    93 
       
    94 	// Create state handler
       
    95 	iStateHandler = CNetLocStateHandler::NewL(*this);
       
    96 
       
    97 	// Create timers used during Network Based Location protocol procedure
       
    98 	iNetLocReqIssuedTimer = CLbsCallbackTimer::NewL(*this);
       
    99 	iLocRespTimer = CLbsCallbackTimer::NewL(*this);
       
   100 	iAssistDataTimer = CLbsCallbackTimer::NewL(*this);
       
   101 
       
   102 	// Create request queue
       
   103 	iQueue = CStateQueue::NewL(KMaxQueueEntry);
       
   104 	}
       
   105 
       
   106 
       
   107 /** Retrieve current Network Based Location state
       
   108 @return TNetLocState Current Network Based Location state
       
   109 */
       
   110 CNetLocStateMachine::TNetLocState CNetLocStateMachine::CurrentState()
       
   111 	{
       
   112 	return iCurrentState;
       
   113 	}
       
   114 
       
   115 	
       
   116 /** Start Network Based Location request timer
       
   117 The state handler calls this when it has issued an Network Based Location request
       
   118 to the network and it requires a response before the timer expires.
       
   119 */
       
   120 void CNetLocStateMachine::StartNetLocReqTimer()
       
   121 	{
       
   122 	if(iNetLocReqIssuedTimer->IsActive())
       
   123 		{
       
   124 		iNetLocReqIssuedTimer->Cancel();
       
   125 		}
       
   126 	iNetLocReqIssuedTimer->EventAfter(TTimeIntervalSeconds(KNetLocReqIssuedTimerDurationInSec), KNetLocReqIssuedTimerEvent);
       
   127 	}
       
   128 
       
   129 	
       
   130 /** Start location response timer
       
   131 The state handler calls this when it has sent a location request
       
   132 to the client and requires a response before the timer expires.
       
   133 */
       
   134 void CNetLocStateMachine::StartLocRespTimer()
       
   135 	{
       
   136 	if(iLocRespTimer->IsActive())
       
   137 		{
       
   138 		iLocRespTimer->Cancel();
       
   139 		}
       
   140 	iLocRespTimer->EventAfter(TTimeIntervalSeconds(KLocRespTimerDurationInSec), KLocRespTimerEvent);
       
   141 	}
       
   142 
       
   143 
       
   144 /** Initialise internal state attributes.
       
   145 This is used when new Network Based Location procedure commences.
       
   146 */
       
   147 void CNetLocStateMachine::InitialiseProcedure()
       
   148 	{
       
   149 	// Initialise state machine
       
   150 	InitialiseMachineBase();
       
   151 
       
   152 	ASSERT(iStateHandler != NULL);
       
   153 	iStateHandler->Initialise();
       
   154 	}
       
   155 	
       
   156 
       
   157 /** Prepare state transition.
       
   158 */  
       
   159 void CNetLocStateMachine::PreStateTransition()
       
   160 	{
       
   161 	}
       
   162 	
       
   163 
       
   164 /** State transition.
       
   165 This method determines the next state to be adopted by the state machine.
       
   166 */  
       
   167 void CNetLocStateMachine::StateTransition()
       
   168 	{
       
   169 	if (CancelPending())
       
   170 		{
       
   171 		LBSLOG(ELogP2, "CNetLocStateMachine::StateTransition() ---> EStateCancelling \n");
       
   172 		SetMachineAsCancelling();
       
   173 		iCurrentState = EStateCancelling;
       
   174 		}
       
   175 	else
       
   176 		{
       
   177 		// Set new state		
       
   178 		switch (iCurrentState)
       
   179 			{
       
   180 		case EStateNull:
       
   181 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateNull ---> EStateClientReqRecvd\n");
       
   182 			iCurrentState = EStateClientReqRecvd;
       
   183 			break;
       
   184 			
       
   185 		case EStateClientReqRecvd:
       
   186 			LBSLOG(ELogP2, "CNetLocStateMachine: ---> EStateNetSessStarted\n");
       
   187 			iCurrentState = EStateNetSessStarted;
       
   188 			break;
       
   189 			
       
   190 		case EStateNetSessStarted:
       
   191 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateNetSessStarted ---> EStateMeasureDataRecvd\n");
       
   192 			iCurrentState = EStateMeasureDataRecvd;
       
   193 			break;
       
   194 			
       
   195 		case EStateMeasureDataRecvd:
       
   196 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateMeasureDataRecvd ---> EStateNetBasedLocSent\n");
       
   197 			iCurrentState = EStateNetBasedLocSent;
       
   198 			break;
       
   199 			
       
   200 		case EStateNetBasedLocSent:
       
   201 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateNetBasedLocSent ---> EStateLocReqByNet\n");
       
   202 			iIsMeasureControlHandled = ETrue;
       
   203 			iCurrentState = EStateLocReqByNet;
       
   204 			break;
       
   205 			
       
   206 		case EStateLocReqByNet:
       
   207 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateLocReqByNet ---> EStateLocRespRecvd\n");
       
   208 			iCurrentState = EStateLocRespRecvd;
       
   209 			break;
       
   210 			
       
   211 		case EStateLocRespRecvd:
       
   212 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateLocRespRecvd ---> EStateLocSentToNet\n");
       
   213 			iCurrentState = EStateLocSentToNet;
       
   214 			break;
       
   215 			
       
   216 		case EStateLocSentToNet:
       
   217 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateLocSentToNet ---> EStateNetSessToClose\n");
       
   218 			iCurrentState = EStateNetSessToClose;
       
   219 			break;
       
   220 			
       
   221 		case EStateNetSessToClose:
       
   222 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateNetSessToClose ---> EStateClientSessToClose\n");
       
   223 			iCurrentState = EStateClientSessToClose;
       
   224 			break;
       
   225 			
       
   226 		case EStateClientSessToClose:
       
   227 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateClientSessToClose ---> EStateSessionsClosed\n");
       
   228 			iCurrentState = EStateSessionsClosed;
       
   229 			break;
       
   230 			
       
   231 		case EStateSessionsClosed:
       
   232 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateSessionsClosed --> Procedure has completed\n");
       
   233 			// Procedure has completed
       
   234 			CompleteProcedure();
       
   235 			break;
       
   236 			
       
   237 		case EStateCancelling:
       
   238 			LBSLOG(ELogP2, "CNetLocStateMachine: EStateCancelling ---> EStateNetSessToClose\n");
       
   239 			iCurrentState = EStateNetSessToClose;
       
   240 			break;
       
   241 
       
   242 		default:
       
   243 			User::Panic(KProtocolModulePanic, EProtocolModuleNetLocState);
       
   244 			break;
       
   245 			};
       
   246 		}
       
   247 
       
   248 	}
       
   249 	
       
   250 
       
   251 /** Complete the procedure.
       
   252 */  
       
   253 void CNetLocStateMachine::CompleteProcedure()
       
   254 	{
       
   255 	LBSLOG(ELogP2, "CNetLocStateMachine::CompleteProcedure\n");
       
   256 	iCurrentState = EStateNull;
       
   257 	// Complete state machine
       
   258 	CompleteMachineBase();
       
   259 	}
       
   260 
       
   261 
       
   262 /** Complete a state transition.
       
   263 This is called by the base class when a state transition has
       
   264 concluded and it provides an opportunity for the state machine 
       
   265 to perform actions required immediately after this transition.
       
   266 
       
   267 The method can also initiate a further change of state. This is
       
   268 relevant when the state machine is required to perform an autonomous
       
   269 transition from one state to another e.g. this occurs when several
       
   270 interactions are required arising from a single external trigger.
       
   271 */  
       
   272 void CNetLocStateMachine::PostStateTransition()
       
   273 	{
       
   274 	// Some states are transitory i.e. they require
       
   275 	// an automatic transition to the next state
       
   276 	if ( CancelPending() ||
       
   277 		 (EStateClientReqRecvd		== iCurrentState) ||
       
   278 	 	 (EStateMeasureDataRecvd	== iCurrentState) ||
       
   279 	 	 (EStateNetBasedLocSent		== iCurrentState) ||
       
   280 	 	 (EStateLocRespRecvd		== iCurrentState) ||
       
   281 	 	 (EStateLocSentToNet		== iCurrentState) ||
       
   282 	 	 (EStateNetSessToClose		== iCurrentState) ||
       
   283 	 	 (EStateClientSessToClose	== iCurrentState) ||
       
   284 	 	 (EStateSessionsClosed		== iCurrentState) ||
       
   285 	 	 (EStateCancelling			== iCurrentState)
       
   286 	   )
       
   287 		{
       
   288 		// Perform a state transition
       
   289 		PerformStateTransition();
       
   290 		}
       
   291 	}
       
   292 
       
   293 
       
   294 /** Do actions required for a queued request.
       
   295 This currently only initiates another state change but it 
       
   296 has the scope for further actions to be carried out according
       
   297 to the nature of a queued request.
       
   298 */
       
   299 void CNetLocStateMachine::DoQueuedRequest(TInt aRequest)
       
   300 	{
       
   301 	LBSLOG(ELogP2, "CNetLocStateMachine::DoQueuedRequest\n");
       
   302 	switch (aRequest)
       
   303 		{
       
   304 	case EQueueLocResponse:
       
   305 	case EQueueMeasurementControl:
       
   306 	case EQueueNetworkResult:
       
   307 		// Perform a state transition
       
   308 		PerformStateTransition();
       
   309 		break;
       
   310 
       
   311 	default:
       
   312 		User::Panic(KProtocolModulePanic, EProtocolModuleQueueRequestId);
       
   313 		break;
       
   314 		};
       
   315 
       
   316 	}
       
   317 
       
   318 
       
   319 /** Cancel the active procedure
       
   320 */  
       
   321 void CNetLocStateMachine::CancelProcedure()
       
   322 	{
       
   323 	LBSLOG(ELogP2, "CNetLocStateMachine::CancelProcedure()\n");
       
   324 	// Kill all timers
       
   325 	iNetLocReqIssuedTimer->Cancel();
       
   326 	iLocRespTimer->Cancel();
       
   327 	iAssistDataTimer->Cancel();
       
   328 	}
       
   329 
       
   330 
       
   331 /** Timer expired callback.
       
   332 This is called by a CStateTimer object when the timer
       
   333 has expired - the event is identified by aEvent parameter.
       
   334 @param aTimerId The timer event identifier.
       
   335 */
       
   336 void CNetLocStateMachine::OnTimerEventL(TInt aTimerId)
       
   337 	{
       
   338 	
       
   339 	// Perform relevant action for the expired timer
       
   340 	switch (aTimerId)
       
   341 		{
       
   342 
       
   343 	// Network Based Location request timer
       
   344 	case KNetLocReqIssuedTimerEvent:
       
   345 		LBSLOG(ELogP2, "CNetLocStateMachine::OnTimerEventL(KNetLocReqIssuedTimerEvent)\n");
       
   346 		// Inform protocol manager
       
   347 		Observer().MeasurementControlTimeout();
       
   348 		break;
       
   349 
       
   350 	// Additional assistance data timer
       
   351 	case KAssistDataTimerEvent:
       
   352 		LBSLOG(ELogP2, "CNetLocStateMachine::OnTimerEventL(KAssistDataTimerEvent)\n");
       
   353 		// Ensure assistance data action is performed upon cancellation
       
   354 		iAssistanceDataActionRequired = ETrue;
       
   355 		iLocRespReason = KErrTimedOut;
       
   356 		// Inform protocol manager
       
   357 		Observer().MeasurementControlTimeout();
       
   358 		break;
       
   359 
       
   360 	// Location response timer
       
   361 	case KLocRespTimerEvent:
       
   362 		LBSLOG(ELogP2, "CNetLocStateMachine::OnTimerEventL(KLocRespTimerEvent)\n");
       
   363 		iLocRespReason = KErrTimedOut;
       
   364 		CancelMachine(ECancelClientTimeout);
       
   365 		break;
       
   366 
       
   367 	// Ignore unknown timer events
       
   368 	default:
       
   369 		break;
       
   370 
       
   371 		};
       
   372 
       
   373 	}
       
   374 
       
   375 
       
   376 /** Timer callback error handler.
       
   377 This is called if the timer expiry callback leaves.
       
   378 @see CNetLocStateMachine::OnTimerEventL()
       
   379 @param aTimerId The timer event identifier.
       
   380 @param aError Error value.
       
   381 */
       
   382 TInt CNetLocStateMachine::OnTimerError(TInt /*aTimerId*/, TInt aError)
       
   383 	{
       
   384 	LBSLOG(ELogP2, "CNetLocStateMachine::OnTimerError()\n");
       
   385 	return aError;
       
   386 	}
       
   387 
       
   388 
       
   389 /** Handle Measurement Control timeout
       
   390 */
       
   391 void CNetLocStateMachine::MeasurementControlTimeout()
       
   392 	{
       
   393 	LBSLOG(ELogP2, "CNetLocStateMachine::MeasurementControlTimeout()\n");
       
   394 	// Cancel procedure
       
   395 	CancelMachine(ECancelNetworkTimeout, KErrTimedOut);
       
   396 	}
       
   397 
       
   398 
       
   399 /** Handle LBS request for Network Based Location
       
   400 @param aSessionId Session ID provided by LBS 
       
   401 */
       
   402 void CNetLocStateMachine::NetLocReq(const TLbsNetSessionId& aSessionId)
       
   403 	{
       
   404 	LBSLOG2(ELogP2, "CNetLocStateMachine::NetLocReq() SessionId %d\n", aSessionId.SessionNum());
       
   405 	// Store the supplied ID information
       
   406 	SessionId(aSessionId);
       
   407 
       
   408 	// Initialise the new procedure
       
   409 	InitialiseProcedure();
       
   410 
       
   411 	// Perform a state transition
       
   412 	PerformStateTransition();
       
   413 	}
       
   414 
       
   415 
       
   416 /** Queue an LBS request for Network Based Location
       
   417 @param aSessionId Session ID provided by LBS 
       
   418 */
       
   419 void CNetLocStateMachine::QueueNetLocReq(const TLbsNetSessionId& aSessionId)
       
   420 	{
       
   421 	LBSLOG(ELogP2, "CNetLocStateMachine::QueueNetLocReq()\n");
       
   422 
       
   423 	QueueSessionId(aSessionId);
       
   424 
       
   425 	CStateMachineBase::SetMachineAsQueued();
       
   426 	}
       
   427 
       
   428 
       
   429 /** Start a previously queued state machine.
       
   430 */  
       
   431 void CNetLocStateMachine::StartQueuedMachine()
       
   432 	{
       
   433 	LBSLOG(ELogP2, "CNetLocStateMachine::StartQueuedMachine()\n");
       
   434 	NetLocReq(iQueueSessionId);
       
   435 	}
       
   436 
       
   437 
       
   438 /** Handle LBS Location response
       
   439 @param aReason Location response error reason.
       
   440 @param aPosInfo The location information response from LBS.
       
   441 */
       
   442 void CNetLocStateMachine::LocationResp(TInt aReason, const TPositionInfoBase& aPosInfo)
       
   443 	{
       
   444 	LBSLOG(ELogP2, "CNetLocStateMachine::LocationResp()\n");
       
   445 	// Store location response data
       
   446 	StoreLocationResp(aReason, aPosInfo);
       
   447 
       
   448 	// Kill the timer related to location response expected by network
       
   449 	iLocRespTimer->Cancel();
       
   450 
       
   451 	// Is the state machine inactive?
       
   452 	if (!IsActive())
       
   453 		{
       
   454 		// Perform a state transition
       
   455 		PerformStateTransition();
       
   456 		}
       
   457 	else
       
   458 		{
       
   459 		// Queue the request
       
   460 		iQueue->AddRequest(EQueueLocResponse);
       
   461 		}
       
   462 	}
       
   463 
       
   464 
       
   465 /** Handle Network Measurement Control indication.
       
   466 A measurement control indication has been received from the network.
       
   467 Note: At this stage the assistance data has already been stored by the
       
   468 protocol manager and is thus not passed into this method.
       
   469 
       
   470 @param aPosInfo Reference location information provided in the measurement control
       
   471 @param aQuality Location request quality specified in the measuerment control
       
   472 */
       
   473 void CNetLocStateMachine::MeasurementControlInd(const TPositionInfoBase& aPosInfo,
       
   474 	const TLbsNetPosRequestQuality& aQuality, const TLbsNetPosRequestMethod& aPosMethod)
       
   475 	{
       
   476 	LBSLOG(ELogP2, "CNetLocStateMachine::MeasurementControlInd()\n");
       
   477 	// Kill timer related to the Network Based Location request
       
   478 	iNetLocReqIssuedTimer->Cancel();
       
   479 
       
   480 	// Perform base class actions
       
   481 	CStateMachineBase::MeasurementControlInd(aPosInfo, aQuality, aPosMethod);
       
   482 
       
   483 	// Is the state machine inactive?
       
   484 	if (!IsActive())
       
   485 		{
       
   486 		// Perform a state transition
       
   487 		PerformStateTransition();
       
   488 		}
       
   489 	else
       
   490 		{
       
   491 		// Queue the request
       
   492 		iQueue->AddRequest(EQueueMeasurementControl);
       
   493 		}
       
   494 	}
       
   495 
       
   496 
       
   497 /** Handle Network Measurement Control Error indication
       
   498 This is called by the protocol manager durinq an active NETLOC when
       
   499 a measurement control error is received from the network.
       
   500 */
       
   501 void CNetLocStateMachine::MeasurementControlErrorInd(TInt aReason)
       
   502 	{
       
   503 	LBSLOG(ELogP2, "CNetLocStateMachine::MeasurementControlErrorInd()\n");	
       
   504 	TBool cancelRequired = EFalse;
       
   505 	TBool assistActionRequired = ETrue;
       
   506 
       
   507 	// If there is no outstanding assistance data request then 
       
   508 	// inhibit assistance data error responses.
       
   509 	if (!iAssistDataTimer->IsActive())
       
   510 		{
       
   511 		assistActionRequired = EFalse;
       
   512 		}
       
   513 
       
   514 	// If this is the first measurement control received
       
   515 	// Then we shall need to cancel the state machine
       
   516 	if (!IsLocReqReceived() || (KErrCancel == aReason))
       
   517 		{
       
   518 		// Kill timer related to the Network Based Location request
       
   519 		iNetLocReqIssuedTimer->Cancel();
       
   520 		cancelRequired = ETrue;
       
   521 		}
       
   522 
       
   523 	// Perform base class actions
       
   524 	CStateMachineBase::HandleMeasureControlError(cancelRequired, aReason);
       
   525 
       
   526 	// Ensure assistance data action only happens if necessary
       
   527 	iAssistanceDataActionRequired = assistActionRequired;
       
   528 	}
       
   529 
       
   530 
       
   531 /** Handle a network error indication.
       
   532 */  
       
   533 void CNetLocStateMachine::NetworkErrorInd()
       
   534 	{
       
   535 	LBSLOG(ELogP2, "CNetLocStateMachine::NetworkErrorInd()\n");
       
   536 	// Do we need to report assistance data errors?
       
   537 	if (!IsLocReqReceived())
       
   538 		{
       
   539 		iAssistanceDataActionRequired = ETrue;
       
   540 		}
       
   541 
       
   542 	// Perform base class actions
       
   543 	CStateMachineBase::NetworkErrorInd();
       
   544 	}
       
   545