sysstatemgmt/systemstatemgr/ssm/src/ssmswptransitionengine.cpp
changeset 0 4e1aa6a622a0
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2008-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 <ssm/ssmswppolicy.h>
       
    17 #include <ssm/ssmcommandlist.h>
       
    18 
       
    19 #include "ssmdebug.h"
       
    20 #include "ssmserverpanic.h"
       
    21 #include "ssmswppolicyframe.h"
       
    22 #include "ssmswptransitionengine.h"
       
    23 #include "ssmswppolicyframe.h"
       
    24 #include "clesessionproxy.h"
       
    25 #include "ssmcommandlistutils.h"
       
    26 
       
    27 
       
    28 //
       
    29 //Construction/Destruction
       
    30 //
       
    31 
       
    32 /**
       
    33 Create an engine using the swp value supplied
       
    34 
       
    35 @param aSwp Associated swp value
       
    36 @return A new instance of CSsmSwpTransitionEngine
       
    37 */
       
    38 CSsmSwpTransitionEngine* CSsmSwpTransitionEngine::NewL(const TSsmSwp& aSwp)
       
    39 	{
       
    40 	CSsmSwpTransitionEngine* self = new (ELeave) CSsmSwpTransitionEngine(aSwp);
       
    41 	CleanupStack::PushL (self);
       
    42 	self->ConstructL ();
       
    43 	CleanupStack::Pop (self);
       
    44 	return self;
       
    45 	}
       
    46 
       
    47 /**
       
    48 Empty Construct
       
    49 */
       
    50 void CSsmSwpTransitionEngine::ConstructL()
       
    51 	{
       
    52 	}
       
    53 
       
    54 /**
       
    55 Construct engine
       
    56 
       
    57 @param aSwp Associated swp value
       
    58 
       
    59 */
       
    60 CSsmSwpTransitionEngine::CSsmSwpTransitionEngine(const TSsmSwp& aSwp) :
       
    61 	CActive(CActive::EPriorityStandard), iClientStatus(NULL),
       
    62 			iCurrentSwpValue(aSwp), iNextAction(EIdle), iPerformCommandListValidation(ETrue)
       
    63 	{
       
    64 	CActiveScheduler::Add (this);
       
    65 	}
       
    66 
       
    67 /**
       
    68 Destruct engine and destroy owned frame
       
    69 
       
    70 */
       
    71 CSsmSwpTransitionEngine::~CSsmSwpTransitionEngine()
       
    72 	{
       
    73 	__ASSERT_DEBUG(KNullHandle == iClientMessage.Handle(), PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError18));
       
    74 	Cancel();
       
    75 	delete iPolicyFrame; // owned by me
       
    76     delete iCommandList;
       
    77     }
       
    78 
       
    79 /**
       
    80 Give the engine a client message
       
    81 If a client message is supplied, it will be completed when the engine starts running
       
    82 or if an error occurs
       
    83 
       
    84 @param aMessage Client message
       
    85 
       
    86 */
       
    87 void CSsmSwpTransitionEngine::SetClientMessage(const RMessage2* aMessage)
       
    88 	{
       
    89 	if(aMessage)
       
    90 		{
       
    91 		iClientMessage = *aMessage;
       
    92 		}
       
    93 	}
       
    94 
       
    95 CSession2* CSsmSwpTransitionEngine::OriginatingSesssion() const
       
    96 	{
       
    97 	return iClientMessage.Session();
       
    98 	}
       
    99 
       
   100 void CSsmSwpTransitionEngine::PerformCommandListValidation(TBool aSetting)
       
   101 	{
       
   102 	iPerformCommandListValidation = aSetting;
       
   103 	}
       
   104 
       
   105 /**
       
   106 Give the engine a cle session
       
   107 
       
   108 @param aCleSession Object that implements CLE Session proxy interface
       
   109 
       
   110 */
       
   111 void CSsmSwpTransitionEngine::SetCleSessionProxy(MCleSessionProxy* aCleSession)
       
   112 	{
       
   113 	__ASSERT_DEBUG(NULL != aCleSession, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError1));
       
   114 	iCleSession = aCleSession;
       
   115 	}
       
   116 
       
   117 
       
   118 /**
       
   119 Give the engine a ssmSwpPolicy session
       
   120 
       
   121 @param aSsmSwpPolicySession Object that has RSsmSwpPolicySession Session
       
   122 */
       
   123 void CSsmSwpTransitionEngine::SetSsmSwpPolicySession(CSsmSwpPolicyCliSession* aSsmSwpPolicySession)
       
   124 	{
       
   125 	__ASSERT_DEBUG(NULL != aSsmSwpPolicySession, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError21));
       
   126 	iSsmSwpPolicySession = aSsmSwpPolicySession;
       
   127 	}
       
   128 
       
   129 /**
       
   130 Give the engine a policy frame
       
   131 Note: the engine takes ownership of the frame
       
   132 
       
   133 @param aPolicyFrame Policy frame
       
   134 
       
   135 */
       
   136 void CSsmSwpTransitionEngine::SetSwpPolicyFrame(CSsmSwpPolicyFrame* aPolicyFrame)
       
   137 	{
       
   138 	__ASSERT_DEBUG(NULL != aPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError2));
       
   139 	iPolicyFrame = aPolicyFrame;
       
   140 	}
       
   141 
       
   142 #ifdef TEST_SSM_SERVER
       
   143 /**
       
   144 Start a transition without completion notification
       
   145 This method is for testcode only
       
   146 */
       
   147 void CSsmSwpTransitionEngine::Submit()
       
   148 	{
       
   149 	__ASSERT_DEBUG(!IsActive(), PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError3));
       
   150 	__ASSERT_DEBUG(iClientStatus == NULL, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError5));
       
   151 	iClientStatus=NULL;
       
   152 	DoSubmit ();
       
   153 	}
       
   154 #endif
       
   155 
       
   156 /**
       
   157 Start a transition with completion notification
       
   158 
       
   159 @param aClientStatus - the client status to complete
       
   160 
       
   161 */
       
   162 void CSsmSwpTransitionEngine::Submit(TRequestStatus& aClientStatus)
       
   163 	{
       
   164 	__ASSERT_ALWAYS(!IsActive(), PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError4));
       
   165 	__ASSERT_ALWAYS(iClientStatus == NULL, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError5));
       
   166 
       
   167 	aClientStatus = KRequestPending;
       
   168 	iClientStatus = &aClientStatus;
       
   169 	DoSubmit ();
       
   170 	}
       
   171 
       
   172 /**
       
   173 Start transition engine running
       
   174 */
       
   175 void CSsmSwpTransitionEngine::DoSubmit()
       
   176 	{
       
   177 	// Submit can only be called on a brand new engine
       
   178 	__ASSERT_DEBUG(EIdle == iNextAction, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError6));
       
   179 	__ASSERT_ALWAYS(NULL != iCleSession, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError14));
       
   180 	__ASSERT_ALWAYS(NULL != iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError15));
       
   181 	__ASSERT_ALWAYS(NULL != iSsmSwpPolicySession, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError23));
       
   182 
       
   183 	TInt err = KErrNone;
       
   184 	// Before this transition engine can be used, we need to connect to (and probably start) the Ssmswppolicysrv.
       
   185 	// The session remains connected as long as SsmSwpPolicySrv does not disconnect itself (due to a panic for example)
       
   186 	if (!iSsmSwpPolicySession->IsConnected())
       
   187 		{
       
   188 		TRAP(err, iSsmSwpPolicySession->ConnectL());
       
   189 		DEBUGPRINT2(_L("CSsmSwpTransitionEngine iSsmSwpPolicySession->ConnectL called with err: %d"), err);
       
   190 		}
       
   191 	if (err != KErrNone)
       
   192 		{
       
   193 		// Call DoRunError() to handle the error.
       
   194 		DoRunError(err);
       
   195 		}
       
   196 	else
       
   197 		{
       
   198 		// Sets the SsmSwpPolicySession in the policyframe
       
   199 		iPolicyFrame->SetSsmSwpPolicySession(iSsmSwpPolicySession);
       
   200 
       
   201 		iNextAction = iCleSession->IsConnected() ? ESetSwpPolicyDllHandleAndInitialize : EUnConnected;
       
   202 		Start ();
       
   203 		}
       
   204 	}
       
   205 
       
   206 /**
       
   207 Start active scheduler running it's state machine
       
   208 */
       
   209 void CSsmSwpTransitionEngine::Start()
       
   210 	{
       
   211 	SetActive ();
       
   212 	TRequestStatus* status = &iStatus;
       
   213 	User::RequestComplete (status, KErrNone);
       
   214 	}
       
   215 
       
   216 /**
       
   217 Cancel the running of the engine
       
   218 Cancel any running command lists
       
   219 Complete the client request if supplied
       
   220 */
       
   221 void CSsmSwpTransitionEngine::DoCancel()
       
   222 	{
       
   223 	__ASSERT_DEBUG(iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError7));
       
   224 
       
   225 	TInt err = KErrCancel;
       
   226 	//Cancel any request this engine is waiting for
       
   227 	if( iNextAction == EIdle)
       
   228 		{
       
   229 		__ASSERT_DEBUG(iClientStatus==NULL, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError17));
       
   230 		return;
       
   231 		}
       
   232 	else if( iPolicyFrame && (iNextAction == ETransitionAllowed) )
       
   233 		{
       
   234 		err = iPolicyFrame->CallInitializeCancel();
       
   235 		}
       
   236 	else if( iPolicyFrame && (iNextAction == EExecuteCommandList) )
       
   237 		{
       
   238 		err = iPolicyFrame->CallPrepareCommandListCancel();
       
   239 		}
       
   240 	else if( iCleSession && (iNextAction == EWaitForCommandListExecute) )
       
   241 		{
       
   242 		iCleSession->ExecuteCommandListCancel();
       
   243 		}
       
   244 	else if( iPolicyFrame && (iNextAction == EWaitForHandleCleReturnValue) )
       
   245 		{
       
   246 		err = iPolicyFrame->CallHandleCleReturnValueCancel();
       
   247 		//iCommandList needs to be deleted when cancel has been called before completion of command 
       
   248         if (iCommandList)
       
   249             {
       
   250             delete iCommandList;
       
   251             iCommandList = NULL;
       
   252             }
       
   253 		}
       
   254 
       
   255 	//Then complete the transition-scheduler's TRequestStatus
       
   256 	if( NULL != iClientStatus )
       
   257 		{
       
   258 		User::RequestComplete (iClientStatus, err);
       
   259 		iClientStatus = NULL;
       
   260 		}
       
   261 
       
   262 	//And let the end-user know
       
   263 	CompleteClientMessage (err);
       
   264 
       
   265 	iNextAction = EIdle;
       
   266 	}
       
   267 
       
   268 /**
       
   269 The engine runs through a fixed sequence of steps, most of which require an asynchronous reply from
       
   270 another component in the system
       
   271 
       
   272 @leave One of the system-wide error codes
       
   273 */
       
   274 
       
   275 void CSsmSwpTransitionEngine::RunL()
       
   276 	{
       
   277 	if(iNextAction != EWaitForCommandListExecute)
       
   278 		{
       
   279 		//Propagate all problems except CleSrv's return code to RunError
       
   280 		SSMLOGLEAVEIFERROR(iStatus.Int()); //will leave in release builds as well
       
   281 		}
       
   282 
       
   283 	switch (iNextAction)
       
   284 		{
       
   285 		case EUnConnected:
       
   286 			DoConnectCleSessionL();
       
   287 			iNextAction = ESetSwpPolicyDllHandleAndInitialize;
       
   288 			break;
       
   289 
       
   290 		case ESetSwpPolicyDllHandleAndInitialize:
       
   291 			DoInitialize();
       
   292 			iNextAction = ETransitionAllowed;
       
   293 			break;
       
   294 
       
   295 		case ETransitionAllowed:
       
   296 			iNextAction = DoTransitionAllowed() ? EPrepareCommandList : EIdle;
       
   297 			break;
       
   298 
       
   299 		case EPrepareCommandList:
       
   300 			DoPrepareCommandList();
       
   301 			iNextAction = EExecuteCommandList;
       
   302 			break;
       
   303 
       
   304 		case EExecuteCommandList:
       
   305 			DoExecuteCommandList();
       
   306 			iNextAction = EWaitForCommandListExecute;
       
   307 			break;
       
   308 
       
   309 		case EWaitForCommandListExecute:
       
   310             if (iCommandList)
       
   311                 {
       
   312                 delete iCommandList;
       
   313                 iCommandList = NULL;
       
   314                 }
       
   315 			DoHandleCleReturnValue();
       
   316 			iNextAction = EWaitForHandleCleReturnValue;
       
   317 			break;
       
   318 
       
   319 		case EWaitForHandleCleReturnValue:
       
   320 			if(NULL != iClientStatus)
       
   321 				{
       
   322 				User::RequestComplete(iClientStatus, KErrNone);
       
   323 				iClientStatus = NULL;
       
   324 				}
       
   325 			iNextAction = ETransitionComplete;
       
   326 			break;
       
   327 
       
   328 		case EIdle:
       
   329 		default:
       
   330 			__ASSERT_DEBUG(EFalse, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError19));
       
   331 			break;
       
   332 		}
       
   333 	}
       
   334 
       
   335 TBool CSsmSwpTransitionEngine::InTransition() const
       
   336 	{
       
   337 	return (iNextAction > ETransitionAllowed);
       
   338 	}
       
   339 
       
   340 /**
       
   341  * Returns the current SwP value for this transition engine.
       
   342  */
       
   343 const TSsmSwp& CSsmSwpTransitionEngine::TransitionValue() const
       
   344 	{
       
   345 	return iCurrentSwpValue;
       
   346 	}
       
   347 
       
   348 /**
       
   349  * Returns the MCleSessionProxy currently associated with this engine
       
   350  */
       
   351 MCleSessionProxy* CSsmSwpTransitionEngine::CleSessionProxy()
       
   352 	{
       
   353 	return iCleSession;
       
   354 	}
       
   355 
       
   356 /**
       
   357  Most errors cause a Panic followed by Kernel fault. The rationale behind this is that all
       
   358  swp policies placed on the rom by the device manufacturer must be free from errors when
       
   359  a device is shipped. There is no case for graceful handling of missing commandlists,
       
   360  bad resource files or an unknown swp.
       
   361  In case there is low memory condition then we are completing the client request status with KErrNoMemory,
       
   362  instead of panicking the client.
       
   363 
       
   364  Note: Both the return value from CleSrv (which is forwarded to the Swp Policy DLL) and the error resulting
       
   365  	   from a transition not allowed do NOT cause this RunError() to be called.
       
   366 */
       
   367 TInt CSsmSwpTransitionEngine::RunError(TInt aError)
       
   368 	{
       
   369 	DoRunError(aError);
       
   370 	return KErrNone;
       
   371 	}
       
   372 
       
   373 void CSsmSwpTransitionEngine::DoRunError(TInt aError)
       
   374 	{
       
   375 	if(NULL != iClientStatus && aError == KErrNoMemory)
       
   376 		{
       
   377 		User::RequestComplete(iClientStatus, aError);
       
   378 		iClientStatus = NULL;
       
   379 
       
   380 		//And let the end-user know
       
   381 		CompleteClientMessage (aError);
       
   382 		}
       
   383 	else
       
   384 		{
       
   385 		DEBUGPRINT3(_L("CSsmSwpTransitionEngine RunError called with aError: %d when iNextAction had the value of: %d"), aError, iNextAction);
       
   386 		PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError20);
       
   387 		}
       
   388 	}
       
   389 
       
   390 /**
       
   391  Before this transition engine can be used, we need to connect to (and probably start) the CleSrv.
       
   392  The session remains connected as long as Cle does not disconnect itself (due to a panic for example)
       
   393  */
       
   394 void CSsmSwpTransitionEngine::DoConnectCleSessionL()
       
   395 	{
       
   396 	iCleSession->ConnectL();
       
   397 	Start();
       
   398 	}
       
   399 
       
   400 /**
       
   401 Call the policy's Initialize method
       
   402 Wait asynchronously for completion
       
   403 */
       
   404 void CSsmSwpTransitionEngine::DoInitialize()
       
   405 	{
       
   406 	__ASSERT_DEBUG(iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError8));
       
   407 	//Let the swp policy do whatever it needs to do e.g. initialize its CSsmCommandListResourceReader
       
   408 	iPolicyFrame->CallInitialize (iStatus);
       
   409 	SetActive ();
       
   410 	}
       
   411 
       
   412 /**
       
   413 Call the policy's TransitionAllowed method and handle return value appropriately
       
   414 Continue with sequence if allowed
       
   415 Complete message and request with correct status if not allowed
       
   416 */
       
   417 TBool CSsmSwpTransitionEngine::DoTransitionAllowed()
       
   418 	{
       
   419 	__ASSERT_DEBUG(iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError9));
       
   420 
       
   421 	MSsmSwpPolicy::TResponse response = iPolicyFrame->CallTransitionAllowed(iCurrentSwpValue, iClientMessage);
       
   422 
       
   423 	if( MSsmSwpPolicy::EAllowed == response) // continue as normal
       
   424 		{
       
   425 		CompleteClientMessage(KErrNone);	// tell the caller we were accepted
       
   426 
       
   427 		Start();
       
   428 		return ETrue;
       
   429 		}
       
   430 	else // complete with error status
       
   431 		{
       
   432 		CompleteClientMessage (KErrNotSupported); // tell the caller we were rejected
       
   433 
       
   434 		if ( NULL != iClientStatus)
       
   435 			{
       
   436 			User::RequestComplete (iClientStatus, KErrNotSupported);
       
   437 			iClientStatus = NULL;
       
   438 			}
       
   439 		return EFalse;
       
   440 		}
       
   441 	}
       
   442 
       
   443 /**
       
   444 Call the policy's PrepareCommandList method and wait for completion
       
   445 */
       
   446 void CSsmSwpTransitionEngine::DoPrepareCommandList()
       
   447 	{
       
   448 	__ASSERT_DEBUG(iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError10));
       
   449 	iPolicyFrame->CallPrepareCommandList (iCurrentSwpValue, iStatus);
       
   450 	SetActive ();
       
   451 	}
       
   452 
       
   453 /**
       
   454 Retrieve the prepared command list
       
   455 Request execution of the command list
       
   456 Wait asynchronously for execution to complete
       
   457 
       
   458 @leave KErrNoMemory if the list is NULL
       
   459 */
       
   460 void CSsmSwpTransitionEngine::DoExecuteCommandList()
       
   461 	{
       
   462 	__ASSERT_DEBUG(iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError11));
       
   463 	__ASSERT_DEBUG(iCleSession, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError13));
       
   464 
       
   465 	iCommandList = iPolicyFrame->CallCommandList();
       
   466 	if(iPerformCommandListValidation)
       
   467 		{
       
   468 		DoValidation();
       
   469 		}
       
   470 
       
   471 	if(iCommandList)
       
   472 		{
       
   473 		iCleSession->ExecuteCommandList(*iCommandList, iStatus, iSeverity);
       
   474 		SetActive ();
       
   475 		}
       
   476 	else
       
   477 		{
       
   478 		Start();
       
   479 		}
       
   480 	}
       
   481 
       
   482 void CSsmSwpTransitionEngine::DoValidation()
       
   483 	{
       
   484 	TBool valid = EFalse;
       
   485 	if(!iCommandList)
       
   486 		{
       
   487 		DEBUGPRINT1(_L ("System-Wide-Property DLL's CommandList() function returned NULL"));
       
   488 		}
       
   489 	else
       
   490 		{
       
   491 		valid = CSsmCommandListUtils::IsValidSwpList(*iCommandList);
       
   492 		if(!valid)
       
   493 			{
       
   494 			DEBUGPRINT1(_L("System-Wide-Property DLL's CommandList() function returned an invalid CommandList()"));
       
   495 			}
       
   496 		}
       
   497 	__ASSERT_ALWAYS( iCommandList && valid, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError16));
       
   498 	}
       
   499 
       
   500 /**
       
   501 Pass the request status returned by the CLE to the policy
       
   502 Wait asynchronously for the policy to complete the handling
       
   503 */
       
   504 
       
   505 void CSsmSwpTransitionEngine::DoHandleCleReturnValue()
       
   506 	{
       
   507 	__ASSERT_DEBUG(iPolicyFrame, PanicNow(KPanicSysStateMgr,ESwpTransitionEngineError12));
       
   508 	const TInt error = iStatus.Int ();
       
   509 
       
   510 	// In case the server is no longer present
       
   511 	if(error == KErrServerTerminated)
       
   512 		{
       
   513 		// Close cle handle and mark it as disconnected
       
   514 		iCleSession->Close();
       
   515 		}
       
   516 
       
   517 	// Severity must be obtained from CLE somehow. This needs proper implementation.
       
   518 	TCmdErrorSeverity severity = ECmdIgnoreFailure;
       
   519 	if(KErrNone != error)
       
   520 		{
       
   521 		DEBUGPRINT3(_L("Commandlist execution reported error: %d, with severity %d."), error, severity);
       
   522 		severity = ECmdCriticalSeverity;
       
   523 		}
       
   524 
       
   525 	iPolicyFrame->CallHandleCleReturnValue(iCurrentSwpValue, error, severity, iStatus);
       
   526 	SetActive ();
       
   527 	}
       
   528 
       
   529 /**
       
   530 Complete the client message if not already done.
       
   531 This should be done only for the first time.
       
   532 After that the client message is invalid
       
   533 */
       
   534 void CSsmSwpTransitionEngine::CompleteClientMessage(TInt aError)
       
   535 	{
       
   536 	if( iClientMessage.Handle() )
       
   537 		{
       
   538 		iClientMessage.Complete (aError);
       
   539 		}
       
   540 	}