sysstatemgmt/systemstatemgr/cmd/src/cmdmultiplewait.cpp
changeset 0 4e1aa6a622a0
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2007-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 //
       
    15 
       
    16 #include <s32strm.h>
       
    17 #include <barsread2.h>
       
    18 
       
    19 #include "ssmcommandparameters.h"
       
    20 #include "cmdmultiplewait.h"
       
    21 #include "ssmdebug.h"
       
    22 #include "ssmpanic.h"
       
    23 
       
    24 const TInt KMultipleWaitMilliToMicro = 1000;
       
    25 
       
    26 /**
       
    27 Used to create an instance of CCmdMultipleWait class from given parameters.
       
    28 This method is used by SsmCommandFactory to create a command.
       
    29 
       
    30 Creating multiple wait command with timeout value and 
       
    31 Timer will be constructed only when command is executed through CLE
       
    32 
       
    33 @param aTimeout Timeout specified for MULTIPLE_WAIT command
       
    34 @return	A pointer to an object of type CCmdMultipleWait.
       
    35 */
       
    36 CCmdMultipleWait* CCmdMultipleWait::NewL(TInt32 aTimeout)
       
    37 	{
       
    38 	CCmdMultipleWait* self = new (ELeave) CCmdMultipleWait(aTimeout);
       
    39 	return self;
       
    40 	}
       
    41 
       
    42 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
    43 /**
       
    44 Used to create an instance of CCmdMultipleWait class from given parameters.
       
    45 This method is used by SsmCommandFactory to create a command.
       
    46 
       
    47 Creating multiple wait command with timeout value and Priority
       
    48 Timer will be constructed only when command is executed through CLE
       
    49 
       
    50 @param aTimeout Timeout specified for MULTIPLE_WAIT command
       
    51 @param aPriority The priority of command in the list
       
    52 @return	A pointer to an object of type CCmdMultipleWait.
       
    53 */
       
    54 CCmdMultipleWait* CCmdMultipleWait::NewL(TInt32 aTimeout, const TUint16 aPriority)
       
    55 	{
       
    56 	CCmdMultipleWait* self = new (ELeave) CCmdMultipleWait(aTimeout, aPriority);
       
    57 	return self;
       
    58 	}
       
    59 #endif //SYMBIAN_SSM_FLEXIBLE_MERGE
       
    60 
       
    61 /**
       
    62 Used to create an instance of CCmdMultipleWait class from a read stream.
       
    63 CSsmCommandList::InternalizeL() uses this method to construct a command from stream.
       
    64 
       
    65 Creating multiple wait command with ReadStream and DeferredCommands 
       
    66 Timer will be constructed only when command is executed through CLE
       
    67 
       
    68 @param aReadStream Read stream containing data through which object can be created
       
    69 @param aDeferredCommands List of deferred commands
       
    70 @return	A pointer to an object of type CCmdMultipleWait.
       
    71 */
       
    72 CCmdMultipleWait* CCmdMultipleWait::NewL(RReadStream& aReadStream, TArray<MSsmCommand*>& aDeferredCommands)
       
    73 	{
       
    74 	CCmdMultipleWait* self = new (ELeave) CCmdMultipleWait();
       
    75 	CleanupStack::PushL(self);
       
    76 	self->ConstructL(aDeferredCommands, aReadStream);
       
    77 	CleanupStack::Pop(self);
       
    78 	return self;
       
    79 	}
       
    80 
       
    81 /**
       
    82 Used to create an instance of CCmdMultipleWait class from resource.
       
    83 
       
    84 Creating multiple wait command with CommandParameters and 
       
    85 Timer will be constructed only when command is executed through CLE
       
    86 
       
    87 @param aCommandParameters Object data from a resource file
       
    88 @return	A pointer to an object of type CCmdMultipleWait.
       
    89 */
       
    90 CCmdMultipleWait* CCmdMultipleWait::NewL(TSsmCommandParameters& aCommandParameters)
       
    91 	{
       
    92 	CCmdMultipleWait* self = new (ELeave) CCmdMultipleWait();
       
    93 	CleanupStack::PushL(self);
       
    94 	self->ConstructL(aCommandParameters);
       
    95 	CleanupStack::Pop(self);
       
    96 	return self;
       
    97 	}
       
    98 
       
    99 /**
       
   100 Used to create an instance of CCmdMultipleWait class from CCmdMultipleWait object
       
   101 Must be used only by CLE
       
   102 @param aCmdMultipleWait CCmdMultipleWait reference 
       
   103 @param aDeferredCommands TArray<MSsmCommand*> reference 
       
   104 @return A pointer to an object of type CCmdMultipleWait.
       
   105 */
       
   106 CCmdMultipleWait* CCmdMultipleWait::NewLC(const CCmdMultipleWait& aCmdMultipleWait, TArray<MSsmCommand*>& aDeferredCommands)
       
   107     {
       
   108 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   109     CCmdMultipleWait* self = new (ELeave) CCmdMultipleWait(aCmdMultipleWait.Timeout(),aCmdMultipleWait.Priority());
       
   110 #else
       
   111     CCmdMultipleWait* self = new (ELeave) CCmdMultipleWait(aCmdMultipleWait.Timeout());
       
   112 #endif
       
   113     CleanupStack::PushL(self);
       
   114     self->ConstructL(aCmdMultipleWait, aDeferredCommands);
       
   115     return self;
       
   116     }
       
   117 
       
   118 void CCmdMultipleWait::ConstructL(const CCmdMultipleWait& aCmdMultipleWait, TArray<MSsmCommand*>& aDeferredCommands)
       
   119     {
       
   120     iConditionalResourceId = aCmdMultipleWait.ConditionalInformation();
       
   121 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   122 	if (iConditionalResourceId != 0)
       
   123         {
       
   124         SetCommandResourceFileNameL(aCmdMultipleWait.GetCommandResourceFileName());
       
   125         } 
       
   126 #endif
       
   127     const TInt count = aDeferredCommands.Count();
       
   128     for (TInt i = 0; i < count; i++)
       
   129         {
       
   130         iDeferredCommands.AppendL(aDeferredCommands[i]);
       
   131         }
       
   132     ConstructL();   // Constructs the timer
       
   133     }
       
   134 
       
   135 /**
       
   136 Returns the version of the BIC
       
   137 @return		The maximum supported version of the BIC
       
   138 */
       
   139 TInt CCmdMultipleWait::MaxSupportedVersion()
       
   140 	{
       
   141 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   142 	return (static_cast<TInt>(ECmdMultipleWaitVersionWithPriority));
       
   143 #else
       
   144 	return (static_cast<TInt>(ECmdMultipleWaitInitialVersion));
       
   145 #endif //SYMBIAN_SSM_FLEXIBLE_MERGE
       
   146 	}
       
   147 
       
   148 /**
       
   149 Destructor
       
   150 */
       
   151 CCmdMultipleWait::~CCmdMultipleWait()
       
   152 	{
       
   153 	Cancel();
       
   154 	iDeferredCommands.Close();
       
   155 	delete iMultipleWaitTimer;
       
   156 	}
       
   157 
       
   158 /**
       
   159 Execute this command
       
   160 @param aStatus 	The TRequestStatus which is completed when value is set either 
       
   161 				with KErrNone or with error value.
       
   162 */
       
   163 void CCmdMultipleWait::Execute(TRequestStatus& aStatus)
       
   164 	{
       
   165 	aStatus = KRequestPending;
       
   166 	iExecuteRequest = &aStatus;
       
   167 
       
   168 	if (0 == iDeferredCommands.Count())
       
   169 		{
       
   170 		DEBUGPRINT1A("Deferred command list is empty, Multiple wait completing request with KErrNone");
       
   171 		CompleteExecuteRequest(KErrNone);
       
   172 		}
       
   173 	else 
       
   174 		{
       
   175 		iCommandIndex = 0;	// start processing with first command in deferred command list
       
   176 		MoveToNextState(EStateCheckCompletionStatus);
       
   177 		}
       
   178 	}
       
   179 
       
   180 /**
       
   181 Releases resources associated with this BIC
       
   182 */
       
   183 void CCmdMultipleWait::Release()
       
   184 	{
       
   185 	delete this;
       
   186 	}
       
   187 
       
   188 /**
       
   189 Cancels the BIC
       
   190 */
       
   191 void CCmdMultipleWait::ExecuteCancel()
       
   192 	{
       
   193 	//cancel the outstanding request
       
   194 	Cancel();
       
   195 	//and complete the request with KErrCancel
       
   196 	CompleteExecuteRequest(KErrCancel);
       
   197 	}
       
   198 
       
   199 /**
       
   200 Returns the type of the BIC
       
   201 @return Type of BIC
       
   202 */
       
   203 TSsmCommandType CCmdMultipleWait::Type() const
       
   204 	{
       
   205 	return (ESsmCmdMultipleWait);
       
   206 	}
       
   207 
       
   208 /**
       
   209 Externalises the configuration of the BIC
       
   210 @param aWriteStream A write stream to write BIC data to
       
   211 */
       
   212 void CCmdMultipleWait::ExternalizeL(RWriteStream& aWriteStream) const
       
   213 	{
       
   214 	aWriteStream.WriteInt32L(iTimeout);
       
   215 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   216 	aWriteStream.WriteUint16L(iPriority);
       
   217 #endif //SYMBIAN_SSM_FLEXIBLE_MERGE
       
   218 	}
       
   219 
       
   220 /**
       
   221 Handles command's request completion event.
       
   222 @panic EInvalidRunLAction if the RunL action is invalid
       
   223 */
       
   224 void CCmdMultipleWait::RunL()
       
   225 	{
       
   226 	switch (iInternalState)
       
   227 		{
       
   228 		case EStateCheckCompletionStatus:
       
   229 			{
       
   230 			CheckCompletion();
       
   231 			break;
       
   232 			}
       
   233 		case EStateTakeAction:
       
   234 			{
       
   235 			// pending command is completed so take the proper action
       
   236 			TakeProperAction();
       
   237 			// and process remaining deferred commands
       
   238 			iCommandIndex++;
       
   239 			MoveToNextState(EStateCheckCompletionStatus);
       
   240 			break;
       
   241 			}
       
   242 		case EStateTimerExpired:
       
   243 			{
       
   244 			// multiple wait will not consider the severity in this case,
       
   245 			// it will just complete the request with KErrTimedOut.
       
   246 			if (iExecuteRequest && (iExecuteRequest->Int() == KRequestPending))
       
   247 				{
       
   248 				CompleteRequest(*iExecuteRequest, KErrTimedOut);
       
   249 				}
       
   250 			iExecuteRequest = NULL;
       
   251 
       
   252 			break;
       
   253 			}
       
   254 		default:
       
   255 			{
       
   256 			PanicNow(KPanicCmdMultipleWait, EInvalidRunLAction);
       
   257 			break;
       
   258 			}
       
   259 		}
       
   260 	}
       
   261 
       
   262 /**
       
   263 Cancellation of an outstanding request.
       
   264 */
       
   265 void CCmdMultipleWait::DoCancel()
       
   266 	{
       
   267 	Cleanup();
       
   268 	}
       
   269 
       
   270 /**
       
   271 Complete the command request with aError. It gets called when RunL leaves.
       
   272 
       
   273 @param aError Error code with which RunL has left.
       
   274 @return KErrNone as error is handled in this function.
       
   275 */
       
   276 TInt CCmdMultipleWait::RunError(TInt aError)
       
   277 	{
       
   278 	DEBUGPRINT2A("CCmdMultipleWait::RunError called with reason %d", aError);
       
   279 	CompleteExecuteRequest(aError);
       
   280 	return KErrNone;
       
   281 	}
       
   282 
       
   283 /**
       
   284 Helper function to check the completion code of a deferred command and move to the next state.
       
   285 */
       
   286 void CCmdMultipleWait::CheckCompletion()
       
   287 	{
       
   288 	TInt count = iDeferredCommands.Count();
       
   289 	for ( ; iCommandIndex < count; iCommandIndex++)
       
   290 		{
       
   291 		DEBUGPRINT2A("Processing command %d", iCommandIndex);
       
   292 		MSsmCommand* cmd = iDeferredCommands[iCommandIndex];
       
   293 		// Severity of multiple wait should be same as the current command,
       
   294 		iSeverity = cmd->Severity();
       
   295 		if (cmd->CompletionStatus() == KSsmCommandPending)
       
   296 			{
       
   297 			// Register for the command completion and wait for command to complete
       
   298 			DEBUGPRINT2A("Command %d is pending, Register for completion", iCommandIndex);
       
   299 			SetActive();
       
   300 			iInternalState = EStateTakeAction;
       
   301 			cmd->RegisterCompletionObserver(iStatus);
       
   302 			//start timer if not yet started
       
   303 			if (iMultipleWaitTimer && !iMultipleWaitTimer->IsActive())
       
   304 				{
       
   305 				if (iTimeout > 0)
       
   306 					{
       
   307 					DEBUGPRINT2A("Timer started for %d milliseconds", iTimeout);
       
   308 					iMultipleWaitTimer->StartTimer(iTimeout * KMultipleWaitMilliToMicro);
       
   309 					}
       
   310 				}
       
   311 			break;
       
   312 			}
       
   313 		else 
       
   314 			{
       
   315 			TakeProperAction();
       
   316 			}
       
   317 		}
       
   318 	// processed all deferred command so complete the request
       
   319 	if (iCommandIndex == count)
       
   320 		{
       
   321 		DEBUGPRINT1A("All commands processed!!!");
       
   322 		CompleteExecuteRequest(iCommandError);
       
   323 		}
       
   324 	}
       
   325 
       
   326 /**
       
   327 Helper function to take the proper action and move to the next state.
       
   328 */
       
   329 void CCmdMultipleWait::TakeProperAction()
       
   330 	{
       
   331 	MSsmCommand* cmd = iDeferredCommands[iCommandIndex];
       
   332 	iCommandError = cmd->CompletionStatus();
       
   333 	DEBUGPRINT4A("Pending command %d completed with error %d and Severity is %d", iCommandIndex, iCommandError, cmd->Severity());
       
   334 	if (iCommandError != KErrNone && iSeverity != ECmdIgnoreFailure)
       
   335 		{
       
   336 		// means command has failed which has severity other then ECmdIgnoreFailure
       
   337 		//cancel all pending commands if any
       
   338 		Cleanup();
       
   339 		CompleteExecuteRequest(iCommandError);
       
   340 		}
       
   341 	else 
       
   342 		{
       
   343 		// ignore the error if command has ECmdIgnoreFailure severity
       
   344 		iCommandError = KErrNone;
       
   345 		}
       
   346 	}
       
   347 
       
   348 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   349 /**
       
   350 Overloaded CTOR
       
   351 @param aTimeout Timeout for this command
       
   352 @param aPriority The priority for the command
       
   353 */
       
   354 CCmdMultipleWait::CCmdMultipleWait( TInt32 aTimeout, const TUint16 aPriority)
       
   355 	:iTimeout(aTimeout)
       
   356 	{
       
   357 	iPriority = aPriority;
       
   358 	}
       
   359 #endif //SYMBIAN_SSM_FLEXIBLE_MERGE
       
   360 
       
   361 /**
       
   362 Overloaded CTOR
       
   363 @param aTimeout Timeout for this command
       
   364 */
       
   365 CCmdMultipleWait::CCmdMultipleWait( TInt32 aTimeout)
       
   366 	: iTimeout(aTimeout)
       
   367 	{
       
   368 	}
       
   369 
       
   370 /**
       
   371 Default CTOR
       
   372 */
       
   373 CCmdMultipleWait::CCmdMultipleWait()
       
   374 	{
       
   375 	}
       
   376 
       
   377 /**
       
   378 Construct the command object with deferred commands and readstream.
       
   379 @param aDeferredCommands List of deferred commands.
       
   380 @param aReadStream Readstream containing data for this BIC.
       
   381 */
       
   382 void CCmdMultipleWait::ConstructL(TArray<MSsmCommand*>&  aDeferredCommands, RReadStream& aReadStream)
       
   383 	{
       
   384 	TInt count = aDeferredCommands.Count();
       
   385 	
       
   386 	for (TInt i = 0; i < count; i++)
       
   387 		{
       
   388 		iDeferredCommands.AppendL(aDeferredCommands[i]);
       
   389 		}
       
   390 	InternalizeL(aReadStream);
       
   391 	}
       
   392 
       
   393 /**
       
   394 Constructs an object from resource file.
       
   395 @param aCommandParameters Object data from a resource file
       
   396 */
       
   397 void CCmdMultipleWait::ConstructL(TSsmCommandParameters& aCommandParameters)
       
   398 	{
       
   399 	RResourceReader& reader = aCommandParameters.MainReader();
       
   400 	const TSsmCommandType type = static_cast<TSsmCommandType>(reader.ReadInt16L());
       
   401 	SSMLOGLEAVEIFFALSE(type == Type(), KErrNotSupported);
       
   402 	const TInt version = reader.ReadInt16L();
       
   403 	SSMLOGLEAVEIFFALSE(__COMPARE_VERSION(version, CCmdMultipleWait::MaxSupportedVersion()), KErrNotSupported);
       
   404 	iTimeout = reader.ReadInt32L();
       
   405 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   406 	iPriority = (version > ECmdMultipleWaitInitialVersion) ? reader.ReadUint16L() : KDefaultCommandPriority;
       
   407 #endif
       
   408 	}
       
   409 
       
   410 void CCmdMultipleWait::ConstructL()
       
   411 	{
       
   412 	iMultipleWaitTimer = CMultipleWaitTimer::NewL(*this);
       
   413 	}
       
   414 /**
       
   415 Helper function to move to the next action.
       
   416 @param aNextState Next action to be taken.
       
   417 */
       
   418 void CCmdMultipleWait::MoveToNextState(TStates aNextState)
       
   419 	{
       
   420 	DEBUGPRINT2A("CCmdMultipleWait Moving to next state : %d", aNextState);
       
   421 	iInternalState = aNextState;
       
   422 
       
   423 	TRequestStatus* status = &iStatus;
       
   424 	User::RequestComplete(status, KErrNone);
       
   425 	SetActive();
       
   426 	}
       
   427 
       
   428 /**
       
   429 Helper function to handle the timeout.
       
   430 */
       
   431 void CCmdMultipleWait::HandleTimeoutCallback()
       
   432 	{
       
   433 	DEBUGPRINT1A("Timer has expired");
       
   434 	Cleanup();
       
   435 
       
   436 	iInternalState = EStateTimerExpired;
       
   437 	if (iMultipleWaitTimer)
       
   438 		{
       
   439 		iMultipleWaitTimer->Cancel();
       
   440 		}
       
   441 	}
       
   442 
       
   443 void CCmdMultipleWait::Cleanup()
       
   444 	{
       
   445 	// cancel all pending deferred commands, 
       
   446 	// starting from the current command in the list
       
   447 	TInt count = iDeferredCommands.Count();
       
   448 	if (iCommandIndex < count && iCommandIndex >= 0)
       
   449 		{
       
   450 		MSsmCommand* cmd = iDeferredCommands[iCommandIndex];
       
   451 		if (cmd)
       
   452 			{
       
   453 			DEBUGPRINT1A("Cancel  completion observer");
       
   454 			cmd->RegisterCompletionObserverCancel();
       
   455 			}
       
   456 
       
   457 		for (; iCommandIndex < count; iCommandIndex++)
       
   458 			{
       
   459 			cmd = iDeferredCommands[iCommandIndex];
       
   460 			if (KSsmCommandPending == cmd->CompletionStatus())
       
   461 				{
       
   462 				DEBUGPRINT2A("Cancelling command %d ", iCommandIndex);
       
   463 				iDeferredCommands[iCommandIndex]->ExecuteCancel();				
       
   464 				}
       
   465 			}		
       
   466 		}
       
   467 	}
       
   468 
       
   469 /**
       
   470 Configures the BIC using data contained in a ReadStream
       
   471 @param aReadStream 	A read stream containing BIC data
       
   472 */
       
   473 void CCmdMultipleWait::InternalizeL(RReadStream& aReadStream)
       
   474 	{
       
   475 	iTimeout = aReadStream.ReadInt32L();
       
   476 #ifdef SYMBIAN_SSM_FLEXIBLE_MERGE
       
   477 	iPriority = aReadStream.ReadUint16L();
       
   478 #endif
       
   479 	}
       
   480 
       
   481 CCmdMultipleWait::CMultipleWaitTimer* CCmdMultipleWait::CMultipleWaitTimer::NewL(CCmdMultipleWait& aMultipleWaitCmd)
       
   482 	{
       
   483 	CMultipleWaitTimer* self = new (ELeave) CMultipleWaitTimer(aMultipleWaitCmd);
       
   484 	CleanupStack::PushL(self);
       
   485 	self->ConstructL();
       
   486 	CleanupStack::Pop(self);
       
   487 	return self;
       
   488 	}
       
   489 
       
   490 CCmdMultipleWait::CMultipleWaitTimer::~CMultipleWaitTimer()
       
   491 	{
       
   492 	Cancel();
       
   493 	}
       
   494 
       
   495 void CCmdMultipleWait::CMultipleWaitTimer::StartTimer(TInt32 aTimeout)
       
   496 	{
       
   497 	After(aTimeout);
       
   498 	}
       
   499 
       
   500 void CCmdMultipleWait::CMultipleWaitTimer::RunL()
       
   501 	{
       
   502 	iMultipleWaitCmd.HandleTimeoutCallback();
       
   503 	}
       
   504 
       
   505 void CCmdMultipleWait::CMultipleWaitTimer::ConstructL()
       
   506 	{
       
   507 	CTimer::ConstructL();
       
   508 	}
       
   509 
       
   510 CCmdMultipleWait::CMultipleWaitTimer::CMultipleWaitTimer(CCmdMultipleWait& aMultipleWaitCmd)
       
   511 	: CTimer(EPriorityStandard), iMultipleWaitCmd(aMultipleWaitCmd)
       
   512 	{
       
   513 	CActiveScheduler::Add(this);
       
   514 	}
       
   515