networkprotocolmodules/networkprotocolmodule/LbsProtocolModule/src/cstatemachinebase.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 base class for
       
    15 // protocol state machines used in the Test Protocol Module.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21  @internalTechnology
       
    22  @released
       
    23 */
       
    24 
       
    25 #include "cstatemachinebase.h"
       
    26 #include "cstatehandlerbase.h"
       
    27 #include "lbsdevloggermacros.h"
       
    28 
       
    29 //-----------------------------------------------------------------------------
       
    30 // State Machine Base Class
       
    31 //-----------------------------------------------------------------------------
       
    32 
       
    33 /** Standard constructor.
       
    34 @param aObserver A reference to the state machine observer. 
       
    35 */  
       
    36 CStateMachineBase::CStateMachineBase(MStateMachineObserver& aObserver)
       
    37 : CActive(EPriorityLow), iObserver(aObserver), iProtocolState(EStateReady)
       
    38 	{
       
    39 	ResetSessionId();
       
    40 	}
       
    41 
       
    42 
       
    43 /** Standard destructor.
       
    44 */  
       
    45 CStateMachineBase::~CStateMachineBase()
       
    46 	{
       
    47 	iCancelSource = ECancelClosing;
       
    48 	Cancel();
       
    49 	delete iAssistDataTimer;
       
    50 	delete iQueue;
       
    51 	delete iStateHandler;
       
    52 	}
       
    53 
       
    54 
       
    55 /** Retrieve reference to state machine observer.
       
    56 @return MStateMachineObserver A reference to the observer. 
       
    57 */  
       
    58 MStateMachineObserver& CStateMachineBase::Observer()
       
    59 	{
       
    60 	return iObserver;
       
    61 	}
       
    62 
       
    63 /** Set session ID
       
    64 @param aSessionId Identifier to be used by the state machine whenever
       
    65 	the session ID is to be used.
       
    66 */
       
    67 void CStateMachineBase::SessionId(const TLbsNetSessionId& aSessionId)
       
    68 	{
       
    69 	iSessionId = aSessionId;
       
    70 	}
       
    71 
       
    72 /** Reset session ID
       
    73 */
       
    74 void CStateMachineBase::ResetSessionId()
       
    75 	{
       
    76 	iSessionId.SetSessionOwner(TUid::Uid(0));
       
    77 	iSessionId.SetSessionNum(0);
       
    78 	}
       
    79 
       
    80 /** Get session ID
       
    81 @return const TLbsNetSessionId& The session ID currently used by the state machine.
       
    82 */
       
    83 const TLbsNetSessionId& CStateMachineBase::SessionId() const
       
    84 	{
       
    85 	return iSessionId;
       
    86 	}
       
    87 
       
    88 /** Set ID for queued session
       
    89 @param aSessionId Identifier to be used for a queued session.
       
    90 */
       
    91 void CStateMachineBase::QueueSessionId(const TLbsNetSessionId& aSessionId)
       
    92 	{
       
    93 	iQueueSessionId = aSessionId;
       
    94 	}
       
    95 
       
    96 /** Get ID of queued session
       
    97 @return const TLbsNetSessionId& The session ID of the queued session
       
    98 */
       
    99 const TLbsNetSessionId& CStateMachineBase::QueueSessionId() const
       
   100 	{
       
   101 	return iQueueSessionId;
       
   102 	}
       
   103 
       
   104 
       
   105 /** Retrieve current general protocol state.
       
   106 @return CStateMachineBase::TProtocolState The current general 
       
   107 	protocol state for this state machine.
       
   108 
       
   109 @see CStateMachineBase::TProtocolState
       
   110 */  
       
   111 CStateMachineBase::TProtocolState CStateMachineBase::State() const
       
   112 	{
       
   113 	return iProtocolState;
       
   114 	}
       
   115 
       
   116 	
       
   117 /** Start additional assistance data timer.
       
   118 The state machine calls this when it has issued a request for additional
       
   119 assistance data from the network.
       
   120 */
       
   121 void CStateMachineBase::StartAssistDataTimer()
       
   122 	{
       
   123 	if (iAssistDataTimer->IsActive())
       
   124 		{
       
   125 		iAssistDataTimer->Cancel();
       
   126 		}
       
   127 	iAssistDataTimer->EventAfter(TTimeIntervalSeconds(KAssistDataTimerDurationInSec), KAssistDataTimerEvent);
       
   128 	}
       
   129 
       
   130 
       
   131 /** Indicates if location request has been received.
       
   132 @return TBool ETrue if location request has been received.
       
   133 */  
       
   134 TBool CStateMachineBase::IsLocReqReceived() const
       
   135 	{
       
   136 	return iIsLocReqReceived;
       
   137 	}
       
   138 	
       
   139 /** Indicates if location response has been sent to network.
       
   140 @return TBool ETrue if location response has been sent.
       
   141 */ 
       
   142 TBool CStateMachineBase::IsLocRespSent() const
       
   143 	{
       
   144 	return iIsLocRespSent;
       
   145 	}
       
   146 
       
   147 /** Indicates if Measurement Control has been handled.
       
   148 @return TBool ETrue if Measurement Control has been handled.
       
   149 */  
       
   150 TBool CStateMachineBase::IsMeasureControlHandled() const
       
   151 	{
       
   152 	return iIsMeasureControlHandled;
       
   153 	}
       
   154 
       
   155 
       
   156 /** Indicates if assistance data action is required.
       
   157 @return TBool ETrue if assistance data action is required.
       
   158 */  
       
   159 TBool CStateMachineBase::IsAssistanceDataActionReq() const
       
   160 	{
       
   161 	return iAssistanceDataActionRequired;
       
   162 	}
       
   163 
       
   164 
       
   165 /** Client close reason.
       
   166 This is called by state handlers to determine what reason to
       
   167 provide to the client for the client session closing.
       
   168 @return TInt Reason value.
       
   169 */
       
   170 TInt CStateMachineBase::ClientCloseReason()  const
       
   171 	{
       
   172 	TInt reason = KErrNone;
       
   173 
       
   174 	if (KErrPositionHighPriorityReceive == iClientCancelReason)
       
   175 		{
       
   176 		reason = iClientCancelReason;
       
   177 		}
       
   178 	else if (KErrNone == iNetworkCancelReason)
       
   179 		{
       
   180 		switch (iCancelSource)
       
   181 			{
       
   182 		case ECancelNetworkCancel:
       
   183 			reason = KErrCancel;
       
   184 			break;
       
   185 
       
   186 		case ECancelNetworkError:
       
   187 			reason = KErrDisconnected;
       
   188 			break;
       
   189 
       
   190 		case ECancelClientTimeout:
       
   191 		case ECancelNetworkTimeout:
       
   192 			reason = KErrTimedOut;
       
   193 			break;
       
   194 
       
   195 		case ECancelNone:
       
   196 			{
       
   197 			// The reson returned from here is used for teht Session Complete Message from the 
       
   198 			// Network Gateway to the NRH, so use the value which was received with the location
       
   199 			// response
       
   200 			reason = LocRespReason();
       
   201 			if(reason == KErrCancel || reason == KErrPermissionDenied)
       
   202 				{
       
   203 				reason = KErrNone;
       
   204 				}
       
   205 			}
       
   206 			break;
       
   207  		
       
   208 		case ECancelClientCancel:
       
   209 			reason = iClientCancelReason;
       
   210 			break;
       
   211 			
       
   212 		case ECancelClientCancelSilent:
       
   213 		case ECancelClosing:
       
   214 			break;
       
   215 
       
   216 		default:
       
   217 			User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
       
   218 			break;
       
   219 			};
       
   220 		}
       
   221 	else
       
   222 		{
       
   223 		reason = iNetworkCancelReason;
       
   224 		}
       
   225 
       
   226 	return reason;
       
   227 	}
       
   228 
       
   229 
       
   230 /** Network close reason.
       
   231 This is called by state handlers to determine what reason to
       
   232 provide to the network for the network session closing.
       
   233 @return TInt Reason value.
       
   234 */
       
   235 TInt CStateMachineBase::NetworkCloseReason() const
       
   236 	{
       
   237 	TInt reason = KErrNone;
       
   238 
       
   239 	if (KErrPositionHighPriorityReceive == iNetworkCancelReason)
       
   240 		{
       
   241 		reason = iNetworkCancelReason;
       
   242 		}
       
   243 	else if (KErrNone == iClientCancelReason)
       
   244 		{
       
   245 		switch (iCancelSource)
       
   246 			{
       
   247 		case ECancelClientCancel:
       
   248 		case ECancelClientCancelSilent:
       
   249 			reason = KErrCancel;
       
   250 			break;
       
   251 
       
   252 		case ECancelClientTimeout:
       
   253 		case ECancelNetworkTimeout:
       
   254 			reason = KErrTimedOut;
       
   255 			break;
       
   256 
       
   257 		case ECancelNone:
       
   258 		case ECancelNetworkCancel:
       
   259 		case ECancelNetworkError:
       
   260 		case ECancelClosing:
       
   261 			break;
       
   262 
       
   263 		default:
       
   264 			User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
       
   265 			break;
       
   266 			};
       
   267 		}
       
   268 	else
       
   269 		{
       
   270 		reason = iClientCancelReason;
       
   271 		}
       
   272 
       
   273 	return reason;
       
   274 	}
       
   275 
       
   276 
       
   277 /** Silent cancellation of LBS client is taking place.
       
   278 This is called by state handlers to determine if there is a silent cancellation
       
   279 of the LBS client session taking place, which means that LBS does not receive
       
   280 any cancel-related messages for this session.
       
   281 @return TBool A value of ETrue indicates silent client cancellation is taking place.
       
   282 */
       
   283 TBool CStateMachineBase::IsSilentClientCancel() const
       
   284 	{
       
   285 	return (ECancelClientCancelSilent == iCancelSource);
       
   286 	}
       
   287 
       
   288 
       
   289 /** Network connection error indication.
       
   290 This is called by state handlers to determine if a network connection error
       
   291 has been experienced. In this situation the state handlers should not attempt
       
   292 to send responses to the network.
       
   293 @return TBool A value of ETrue indicates a network connection error exists.
       
   294 */
       
   295 TBool CStateMachineBase::IsNetworkConnectionError() const
       
   296 	{
       
   297 	return ((EStateCancelling == iProtocolState) && (ECancelNetworkError == iCancelSource));
       
   298 	}
       
   299 
       
   300 
       
   301 /** Location request type.
       
   302 This is called by state handlers to determine what type of location
       
   303 request is to be specified to LBS. This is usually fixed for a given
       
   304 state machine, but there is scope to support more than type of request
       
   305 within a single state machine.
       
   306 @return MLbsNetworkProtocolObserver::TLbsNetProtocolService request type.
       
   307 */
       
   308 MLbsNetworkProtocolObserver::TLbsNetProtocolService CStateMachineBase::LocReqType() const
       
   309 	{
       
   310 	return iLocReqType;
       
   311 	}
       
   312 
       
   313 
       
   314 /** Location response reason.
       
   315 This is called by state handlers to determine what reason to
       
   316 provide to the network for the location response failure.
       
   317 @return TInt Reason value.
       
   318 */
       
   319 TInt CStateMachineBase::LocRespReason() const
       
   320 	{
       
   321 	TInt reason = KErrNone;
       
   322 	// Was a Location response error provided?
       
   323 	if (KErrNone != iLocRespReason)
       
   324 		{
       
   325 		reason = iLocRespReason;
       
   326 		}
       
   327 	// Are we cancelling?
       
   328 	else if (Cancelling())
       
   329 		{
       
   330 		switch (iCancelSource)
       
   331 			{
       
   332 		case ECancelClientCancel:
       
   333 		case ECancelClientCancelSilent:
       
   334 			if (KErrPositionHighPriorityReceive == iClientCancelReason)
       
   335 				{
       
   336 				reason = iClientCancelReason;
       
   337 				}
       
   338 			else
       
   339 				{
       
   340 				reason = KErrCancel;
       
   341 				}
       
   342 			break;
       
   343 
       
   344 		case ECancelClientTimeout:
       
   345 			reason = KErrGeneral;
       
   346 			break;
       
   347 
       
   348 		case ECancelNone:
       
   349 		case ECancelNetworkError:
       
   350 		case ECancelNetworkTimeout:
       
   351 		case ECancelNetworkCancel:
       
   352 		case ECancelClosing:
       
   353 			break;
       
   354 
       
   355 		default:
       
   356 			User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
       
   357 			break;
       
   358 
       
   359 			};
       
   360 		}
       
   361 	return reason;
       
   362 	}
       
   363 
       
   364 
       
   365 /** Location response position.
       
   366 This is called by state handlers to retrieve the most
       
   367 recent reported position.
       
   368 @return TPositionInfoBase Currently held location response position
       
   369 */
       
   370 const TPositionInfoBase& CStateMachineBase::LocRespPosition() const
       
   371 	{
       
   372 	return iLocRespPosInfo;
       
   373 	}
       
   374 
       
   375 
       
   376 /** Reference Location.
       
   377 This is called by state handlers to retrieve the most
       
   378 recent reported reference location.
       
   379 @return TPositionInfoBase Currently held reference position
       
   380 */
       
   381 const TPositionInfoBase& CStateMachineBase::ReferenceLoc() const
       
   382 	{
       
   383 	return iReferenceLoc;
       
   384 	}
       
   385 
       
   386 
       
   387 /** Location request quality.
       
   388 This is called by state handlers to retrieve the most
       
   389 recent location request quality.
       
   390 @return TLbsNetPosRequestQuality Currently held location request quality
       
   391 */ 
       
   392 const TLbsNetPosRequestQuality& CStateMachineBase::LocReqQuality() const
       
   393 	{
       
   394 	return iLocReqQuality;
       
   395 	}
       
   396 
       
   397 
       
   398 /** Location request positioning method.
       
   399 This is called by state handlers to retrieve the most
       
   400 recent location request positioning method.
       
   401 @return TLbsNetPosRequestMethod Currently held location request positioning method
       
   402 */ 
       
   403 const TLbsNetPosRequestMethod& CStateMachineBase::PosMethod() const
       
   404 	{
       
   405 	return iPosMethod;
       
   406 	}
       
   407 
       
   408 
       
   409 /** Initialise internal state machine attributes.
       
   410 This is used when a new protocol procedure commences.
       
   411 */
       
   412 void CStateMachineBase::InitialiseMachineBase()
       
   413 	{
       
   414 	iTransitionState = ETransitionNull;
       
   415 	iIsCancelPending = EFalse;
       
   416 	iCancelSource = ECancelNone;
       
   417 	iClientCancelReason = KErrNone;
       
   418 	iNetworkCancelReason = KErrNone;
       
   419 	iIsLocReqReceived = EFalse;
       
   420 	iIsLocRespSent = EFalse;
       
   421 	iIsMeasureControlHandled = EFalse;
       
   422 	iIsAdditionalDataExpected = EFalse;
       
   423 	iAssistanceDataActionRequired = EFalse;
       
   424 	iLocRespReason = KErrNone;
       
   425 
       
   426 	LBSLOG(ELogP2, "CStateMachineBase::InitialiseMachineBase() protocol state ---> EStateActive \n");
       
   427 	iProtocolState = EStateActive;
       
   428 	iIsMachineQueued = EFalse;
       
   429 	}
       
   430 
       
   431 
       
   432 /** Complete state machine attributes.
       
   433 This is used when a protocol procedure completes.
       
   434 */
       
   435 void CStateMachineBase::CompleteMachineBase()
       
   436 	{
       
   437 	LBSLOG(ELogP2, "CStateMachineBase::CompleteMachineBase() protocol state ---> EStateReady\n");
       
   438 	iProtocolState = EStateReady;
       
   439 	// Inform Protocol Manager that procedure is complete
       
   440 	Observer().ProcedureCompleteInd();
       
   441 	}
       
   442 
       
   443 
       
   444 /** Store location response.
       
   445 @param aPosInfo Location information response
       
   446 */
       
   447 void CStateMachineBase::StoreLocationResp(TInt aReason, const TPositionInfoBase& aPosInfo)
       
   448 	{
       
   449 	iLocRespReason = aReason;
       
   450 	iLocRespPosInfo = reinterpret_cast <const TPositionInfo&> (aPosInfo);
       
   451 	}
       
   452 
       
   453 
       
   454 /** Store network location cancel reason.
       
   455 @param aReason The reason for cancelling network location
       
   456 */
       
   457 void CStateMachineBase::StoreNetLocCancelReason(TInt aReason)
       
   458 	{
       
   459 	iNetLocCancelReason = aReason;
       
   460 	}
       
   461 
       
   462 
       
   463 /** Store location request quality
       
   464 @param aQuality Location request quality
       
   465 */
       
   466 void CStateMachineBase::StoreLocReqQuality(const TLbsNetPosRequestQuality& aQuality)
       
   467 	{
       
   468 	iLocReqQuality = aQuality;
       
   469 	}
       
   470 
       
   471 
       
   472 /** Store location request positioning method
       
   473 @param aPosMethod Location request positioning method
       
   474 */
       
   475 void CStateMachineBase::StorePosMethod(const TLbsNetPosRequestMethod& aPosMethod)
       
   476 	{
       
   477 	iPosMethod = aPosMethod;
       
   478 	}
       
   479 
       
   480 
       
   481 /** Store reference location
       
   482 @param aPosInfo Network reference location information
       
   483 */
       
   484 void CStateMachineBase::StoreRefLoc(const TPositionInfoBase& aPosInfo)
       
   485 	{
       
   486 	iReferenceLoc = reinterpret_cast <const TPositionInfo&> (aPosInfo);
       
   487 	}
       
   488 
       
   489 
       
   490 /** Enter new state.
       
   491 This asks the state handler to perform the actions required when
       
   492 entering a new state.
       
   493 */  
       
   494 void CStateMachineBase::EnterNewState()
       
   495 	{
       
   496 	ASSERT(iStateHandler != NULL);
       
   497 
       
   498 	// Perform entry actions for the new state
       
   499 	iStateHandler->EntryActions();
       
   500 	}
       
   501 
       
   502 
       
   503 /** Exit current state.
       
   504 This asks the state handler to perform the actions required when
       
   505 exiting from a state.
       
   506 */  
       
   507 void CStateMachineBase::ExitCurrentState()
       
   508 	{
       
   509 	ASSERT(iStateHandler != NULL);
       
   510 
       
   511 	// Perform exit actions for the current state
       
   512 	iStateHandler->ExitActions();
       
   513 	}
       
   514 
       
   515 
       
   516 /** Perform a state transition.
       
   517 This initiates a state transition and performs the first stage of
       
   518 this by exiting from the current state.
       
   519 */  
       
   520 void CStateMachineBase::PerformStateTransition()
       
   521 	{
       
   522 	if (!IsActive())
       
   523 		{
       
   524 		iTransitionState = ETransitionExit;
       
   525 		DoStateTransitionStage();
       
   526 		}
       
   527 	}
       
   528 
       
   529 
       
   530 /** Do one stage of the state transition.
       
   531 This employs a self-completion mechanism to perform one stage of
       
   532 a state transition. The state machine object is set active and then its
       
   533 own status is completed, which results in its RunL being called.
       
   534 */  
       
   535 void CStateMachineBase::DoStateTransitionStage()
       
   536 	{
       
   537 	TRequestStatus* localStatus = &iStatus;
       
   538 	iStatus = KRequestPending;
       
   539 	SetActive();
       
   540 	User::RequestComplete(localStatus, KErrNone);
       
   541 	}
       
   542 
       
   543 
       
   544 /** Indicates if state machine is cancelling
       
   545 @return TBool ETrue if machine is cancelling
       
   546 */  
       
   547 TBool CStateMachineBase::Cancelling() const
       
   548 	{
       
   549 	return (EStateCancelling == iProtocolState) ? ETrue : EFalse;
       
   550 	}
       
   551 
       
   552 
       
   553 /** Indicates if state machine is to be cancelled
       
   554 @return TBool ETrue if machine is to be cancelled
       
   555 */  
       
   556 TBool CStateMachineBase::CancelPending() const
       
   557 	{
       
   558 	return iIsCancelPending;
       
   559 	}
       
   560 
       
   561 
       
   562 /** Cancel state machine
       
   563 @param aCancelSource The source that decided to cancel.
       
   564 */  
       
   565 void CStateMachineBase::CancelMachine(const TCancelSource& aCancelSource)
       
   566 	{
       
   567 	iIsCancelPending = ETrue;
       
   568 	iCancelSource = aCancelSource;
       
   569 
       
   570 	// Cancel the active procedure
       
   571 	CancelProcedure();
       
   572 
       
   573 	// Perform state transition
       
   574 	if (!IsActive() && (ETransitionNull == iTransitionState))
       
   575 		{
       
   576 		PerformStateTransition();
       
   577 		}
       
   578 	}
       
   579 
       
   580 
       
   581 /** Sets state machine attributes to represent cancelling
       
   582 */  
       
   583 void CStateMachineBase::SetMachineAsCancelling()
       
   584 	{
       
   585 	LBSLOG(ELogP2, "CStateMachineBase::SetMachineAsCancelling() protocol state ---> EStateCancelling \n");
       
   586 	iIsCancelPending = EFalse;
       
   587 	iProtocolState = CStateMachineBase::EStateCancelling;
       
   588 	}
       
   589 
       
   590 
       
   591 /** Cancel state machine
       
   592 @param aCancelSource The source that decided to cancel.
       
   593 @param aReason The reason for the cancellation.
       
   594 */  
       
   595 void CStateMachineBase::CancelMachine(const TCancelSource& aCancelSource,
       
   596 										TInt aReason)
       
   597 	{
       
   598 	// Store the specific cancel reason
       
   599 	switch (aCancelSource)
       
   600 		{
       
   601 	case ECancelNetworkCancel:
       
   602 	case ECancelNetworkError:
       
   603 	case ECancelNetworkTimeout:
       
   604 		iNetworkCancelReason = aReason;
       
   605 		break;
       
   606 
       
   607 	case ECancelClientTimeout:
       
   608 	case ECancelClientCancel:
       
   609 	case ECancelClientCancelSilent:
       
   610 		iClientCancelReason = aReason;
       
   611 		break;
       
   612 
       
   613 	case ECancelNone:
       
   614 	case ECancelClosing:
       
   615 		break;
       
   616 
       
   617 	default:
       
   618 		User::Panic(KProtocolModulePanic, EProtocolModuleCancelSource);
       
   619 		break;
       
   620 		};
       
   621 
       
   622 	// Cancel the machine
       
   623 	CancelMachine(aCancelSource);
       
   624 	}
       
   625 
       
   626 
       
   627 /** Set state machine as queued.
       
   628 This is called by individual derived state machines when they need
       
   629 to enter into a queued state.
       
   630 */  
       
   631 void CStateMachineBase::SetMachineAsQueued()
       
   632 	{
       
   633 	iIsMachineQueued = ETrue;
       
   634 	}
       
   635 
       
   636 
       
   637 /** Set state machine as queued.
       
   638 This is called by individual derived state machines when they need
       
   639 to enter into a queued state.
       
   640 */  
       
   641 TBool CStateMachineBase::IsMachineQueued() const
       
   642 	{
       
   643 	return iIsMachineQueued;
       
   644 	}
       
   645 
       
   646 
       
   647 /** Check for a queued request.
       
   648 Determine if there is a queued request and, if so, handle it.
       
   649 */
       
   650 void CStateMachineBase::CheckForQueuedRequest()
       
   651 	{
       
   652 	// Check for a pending request
       
   653 	if (!IsActive() && iQueue->IsRequestPending())
       
   654 		{
       
   655 		// Perform the required action
       
   656 		DoQueuedRequest(iQueue->PopRequest());
       
   657 		}
       
   658 	}
       
   659 
       
   660 	
       
   661 /** Active object completion handler
       
   662 */
       
   663 void CStateMachineBase::RunL()
       
   664 	{
       
   665 	// Check we have completed ok
       
   666 	if (KErrNone == iStatus.Int())
       
   667 		{
       
   668 		// Which stage of the transition is this?
       
   669 		switch (iTransitionState)
       
   670 			{
       
   671 
       
   672 		// About to exit from a state
       
   673 		case ETransitionExit:
       
   674 			// Prepare state machine prior to the transition.
       
   675 			PreStateTransition();
       
   676 
       
   677 			// Exit current state.
       
   678 			ExitCurrentState();
       
   679 
       
   680 			// Do transition to next stage
       
   681 			iTransitionState = ETransitionEnter;
       
   682 			DoStateTransitionStage();
       
   683 			break;
       
   684 
       
   685 		// About to enter a state
       
   686 		case ETransitionEnter:
       
   687 			// Reset transition state value
       
   688 			iTransitionState = ETransitionNull;
       
   689 
       
   690 			// Perform state machine transition.
       
   691 			StateTransition();
       
   692 
       
   693 			// Enter new state.
       
   694 			EnterNewState();
       
   695 
       
   696 			// If an assistance data action is required then do it now.
       
   697 			// Note: Deferred until first measurement & control is handled.
       
   698 			if (iAssistanceDataActionRequired)
       
   699 				{
       
   700 				iAssistanceDataActionRequired = EFalse;
       
   701 				iObserver.DoAssistanceDataActions();
       
   702 				}
       
   703 
       
   704 			// Perform state machine post-transition actions
       
   705 			// Note: This may initiate another state transition
       
   706 			PostStateTransition();
       
   707 
       
   708 			// If the state machine is not active then we can see if there 
       
   709 			// are any queued requests to be handled
       
   710 			if (!IsActive())
       
   711 				{
       
   712 				CheckForQueuedRequest();
       
   713 				}
       
   714 			break;
       
   715 
       
   716 		// Not changing state just performing asynchronous activities
       
   717 		case ETransitionNull:
       
   718 		default:
       
   719 			// If an assistance data action is required then do it now.
       
   720 			if (iAssistanceDataActionRequired)
       
   721 				{
       
   722 				iAssistanceDataActionRequired = EFalse;
       
   723 				iObserver.DoAssistanceDataActions();
       
   724 				}
       
   725 			break;
       
   726 			};
       
   727 
       
   728 		}
       
   729 
       
   730 	}
       
   731 
       
   732 
       
   733 /** Active object cancellation handler
       
   734 */
       
   735 void CStateMachineBase::DoCancel()
       
   736 	{
       
   737 	iStatus = KErrCancel;
       
   738 	}
       
   739 
       
   740 
       
   741 /** Handle Network Measurement Control indication
       
   742 A measurement control indication has been received and the associated content
       
   743 must be stored. Note: At this stage the assistance data has already been handled 
       
   744 by the protocol manager and is thus not passed into this method.
       
   745 
       
   746 @param aPosInfo The network reference location
       
   747 @param aQuality The location request quality
       
   748 @param aMethod Positioning method to adopt
       
   749 */
       
   750 void CStateMachineBase::MeasurementControlInd(const TPositionInfoBase& aPosInfo,
       
   751 							const TLbsNetPosRequestQuality& aQuality,
       
   752 							const TLbsNetPosRequestMethod& aPosMethod)
       
   753 	{
       
   754 	// Ensure assistance data action is performed when appropriate
       
   755 	iAssistanceDataActionRequired = ETrue;
       
   756 
       
   757 	// Store ref location and location request criteria
       
   758 	StoreRefLoc(aPosInfo);
       
   759 	StoreLocReqQuality(aQuality);
       
   760 	StorePosMethod(aPosMethod);
       
   761 
       
   762 	iIsLocReqReceived = ETrue;
       
   763 	iIsMeasureControlHandled = EFalse;
       
   764 	}
       
   765 
       
   766 
       
   767 /** Handle LBS request for additional Assistance Data
       
   768 This is called by the protocol manager during an active procedure when
       
   769 a request has been made by LBS for further assistance data.
       
   770 */
       
   771 void CStateMachineBase::AssistanceDataReq()
       
   772 	{
       
   773 	// Ensure assistance data action is performed when appropriate
       
   774 	iAssistanceDataActionRequired = ETrue;
       
   775 	iIsAdditionalDataExpected = ETrue;
       
   776 
       
   777 	// If not already active then we must get the state machine to
       
   778 	// perform asynchronous assistance data actions
       
   779 	if (!IsActive())
       
   780 		{
       
   781 		DoStateTransitionStage();
       
   782 		}
       
   783 	}
       
   784 
       
   785 
       
   786 /** Handle Network Additional Assistance data indication
       
   787 This is called by the protocol manager during an active procedure when
       
   788 an additional assistance data response is received from the network.
       
   789 */
       
   790 void CStateMachineBase::AdditionalAssistDataInd()
       
   791 	{
       
   792 	// Stop the related timer
       
   793 	iAssistDataTimer->Cancel();
       
   794 
       
   795 	// Ensure assistance data action is performed when appropriate
       
   796 	iAssistanceDataActionRequired = ETrue;
       
   797 	iIsAdditionalDataExpected = EFalse;
       
   798 
       
   799 	// If not already active then we must get the state machine to
       
   800 	// perform asynchronous assistance data actions
       
   801 	if (!IsActive())
       
   802 		{
       
   803 		DoStateTransitionStage();
       
   804 		}
       
   805 	}
       
   806 
       
   807 
       
   808 /** Handle Network Measurement Control Error indication
       
   809 This is called by the protocol manager during an active procedure when
       
   810 a measurement control error is received from the network.
       
   811 @param aCancelRequired Indicates if the derived state machine requires
       
   812 	the state machine to be cancelled as a result of this error.
       
   813 */
       
   814 void CStateMachineBase::HandleMeasureControlError(
       
   815 			const TBool& aCancelRequired, TInt aReason)
       
   816 	{
       
   817 	// Stop the related timer
       
   818 	iAssistDataTimer->Cancel();
       
   819 
       
   820 	// Ensure assistance data action is performed
       
   821 	iAssistanceDataActionRequired = ETrue;
       
   822 
       
   823 	// Do we have to cancel the state machine?
       
   824 	if (aCancelRequired)
       
   825 		{
       
   826 		iIsMeasureControlHandled = ETrue;
       
   827 		CancelMachine(ECancelNetworkCancel, aReason);
       
   828 	}
       
   829 	else
       
   830 		{
       
   831 		// If not already active then we must get the state machine to
       
   832 		// perform asynchronous assistance data actions
       
   833 		if (!IsActive())
       
   834 			{
       
   835 			DoStateTransitionStage();
       
   836 			}
       
   837 		}
       
   838 	}
       
   839 
       
   840 
       
   841 /** Network Measurement Control Error indication
       
   842 This implements the default actions to be taken if a derived class
       
   843 does not override this method.
       
   844 @param aReason The reason for network error
       
   845 */
       
   846 void CStateMachineBase::MeasurementControlErrorInd(TInt aReason)
       
   847 	{
       
   848 	HandleMeasureControlError(EFalse, aReason);
       
   849 	}
       
   850 
       
   851 
       
   852 /** Handle a network error indication.
       
   853 */  
       
   854 void CStateMachineBase::NetworkErrorInd()
       
   855 	{
       
   856 	// Only handle this the first time
       
   857 	if (ECancelNetworkError != iCancelSource)
       
   858 		{
       
   859 		// Ensure assistance data actions are performed
       
   860 		if (iIsAdditionalDataExpected)
       
   861 			{
       
   862 			iAssistanceDataActionRequired = ETrue;
       
   863 			iIsAdditionalDataExpected = EFalse;
       
   864 			}
       
   865 		// Cancel state machine
       
   866 		CancelMachine(ECancelNetworkError);
       
   867 		}
       
   868 	}
       
   869 
       
   870 
       
   871 //-----------------------------------------------------------------------------
       
   872 // State Machine Request Queue Class
       
   873 //-----------------------------------------------------------------------------
       
   874 
       
   875 /** Static constructor
       
   876 @param aMaxEntries Maximum requests to be held in the queue.
       
   877 @return A new instance of the CStateQueue class.
       
   878 */
       
   879 CStateQueue* CStateQueue::NewL(TInt aMaxEntries)
       
   880 	{
       
   881 	CStateQueue* self = new (ELeave) CStateQueue(aMaxEntries);
       
   882 	CleanupStack::PushL(self);
       
   883 	self->ConstructL(aMaxEntries);
       
   884 	CleanupStack::Pop(self);
       
   885 	return self;
       
   886 	}
       
   887 
       
   888 
       
   889 /** Default private constructor
       
   890 @param aMaxEntries Maximum requests to be held in the queue.
       
   891 */
       
   892 CStateQueue::CStateQueue(TInt aMaxEntries)
       
   893  : iMaxEntries(aMaxEntries)
       
   894 	{
       
   895 	}
       
   896 
       
   897 
       
   898 /** Destructor
       
   899 */
       
   900 CStateQueue::~CStateQueue()
       
   901 	{
       
   902 	iQueue.Reset();
       
   903 	}
       
   904 	
       
   905 	
       
   906 /** Private second stage constructor
       
   907 @param aMaxEntries Maximum requests to be held in the queue.
       
   908 */
       
   909 void CStateQueue::ConstructL(TInt aMaxEntries) 
       
   910 	{
       
   911 	iQueue.ReserveL(aMaxEntries);
       
   912 	}
       
   913 
       
   914 
       
   915 /** Check if there is a pending request
       
   916 @return TBool ETrue if there is a pending request in the queue
       
   917 */
       
   918 TBool CStateQueue::IsRequestPending()
       
   919 	{
       
   920 	return (0 < iQueue.Count()) ? ETrue : EFalse;
       
   921 	}
       
   922 
       
   923 
       
   924 /** Add a request to the queue
       
   925 The new request is inserted at the start of the internal array
       
   926 because this makes it easier to pop the oldest request out of
       
   927 the array, @see CStateQueue::PopRequest()
       
   928 @param aNewRequest A number identifying the request to be queued.
       
   929 @return TInt KErrNone if there is no error queueing the request.
       
   930 */
       
   931 TInt CStateQueue::AddRequest(TInt aNewRequest)
       
   932 	{
       
   933 	TInt err = KErrOverflow;
       
   934 	if (iMaxEntries > iQueue.Count())
       
   935 		{
       
   936 		TRAP(err, iQueue.InsertL(aNewRequest, 0));
       
   937 		}
       
   938 
       
   939 	return err;
       
   940 	}
       
   941 
       
   942 
       
   943 /** Pop the oldest request off the queue
       
   944 The entry at the end of the array represents the oldest queued request.
       
   945 @return TInt The number identifying the popped request
       
   946 */
       
   947 TInt CStateQueue::PopRequest()
       
   948 	{
       
   949 	TInt request = 0;
       
   950 	if (0 < iQueue.Count())
       
   951 		{
       
   952 		request = iQueue[iQueue.Count() - 1];
       
   953 		iQueue.Remove(iQueue.Count() - 1);
       
   954 		}
       
   955 
       
   956 	return request;
       
   957 	}
       
   958