sysstatemgmt/systemstatemgr/ss/src/ssmstartsafe.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 
       
    17 #include <ssm/ssmstartsafe.h>
       
    18 
       
    19 #include <ssm/ssmstartupproperties.h>
       
    20 #include "startandretry.h"
       
    21 #include "rvobserver.h"
       
    22 #include "fireandforget.h"
       
    23 #include "activewaiter.h"
       
    24 #include <ssm/ssmcmd.hrh>
       
    25 #include <ssm/ssmloadsysmon.h>
       
    26 #include <apastarter.h>
       
    27 
       
    28 _LIT(KApStartDLL, "apstart.dll");
       
    29 _LIT( KSysMonProxyDLL, "loadsysmon.dll" );
       
    30 typedef CApaStarter* (*TFuncNewL)( void );
       
    31 typedef MSsmLoadSysMon* (*TFuncCreateL)( void );
       
    32 
       
    33 
       
    34 
       
    35 /**
       
    36 Used to start a process or application and initiate monitoring. 
       
    37 Use this for ESsmWaitForSignal or ESsmDeferredWaitForSignal. 
       
    38 The number-of-retries parameter in aStartupProperties applies to the startup procedure.
       
    39 If monitoring is not successfully setup, the started process is killed and this function
       
    40 leaves with the error code supplied by the system-monitor.
       
    41 
       
    42 @param aStartupProperties Startup properties provided by the caller.
       
    43 @param aProcess Handle on the process to be created.
       
    44 @leave KErrArgument if the monitor flag is not set in aStartupProperties, or if the execution behaviour is ESsmFireandForget.
       
    45 @leave KErrNotSupported if the system monitor sub-system is not installed. 
       
    46 @leave Another of the system-wide error codes @see StartL
       
    47 
       
    48 @internalTechnology
       
    49 @released
       
    50 */
       
    51 EXPORT_C void CSsmStartSafe::StartAndMonitorL( const CSsmStartupProperties& aStartupProperties, RProcess& aProcess )
       
    52 	{
       
    53 	
       
    54 	if( !aStartupProperties.IsMonitoringRequired() )
       
    55 		{
       
    56 		User::Leave( KErrArgument );	
       
    57 		}
       
    58 	
       
    59 	if( !iSysMonCli )
       
    60 		{
       
    61 		User::Leave( KErrNotSupported );
       
    62 		}
       
    63 	
       
    64 	StartL( aStartupProperties, aProcess );
       
    65 	
       
    66 	// Monitor the process only if the behavior is not EFireAndForget
       
    67 	// The monitor for process/app with EFireAndForget behavior is started only after the process/app is started
       
    68 	// Hence the monitor is started in the CFireAndForget object
       
    69 	if (ESsmFireAndForget != aStartupProperties.ExecutionBehaviour())
       
    70 		{
       
    71 		iSysMonCli->OpenL();
       
    72 		TRAPD( err, iSysMonCli->MonitorL( aStartupProperties, aProcess ) );
       
    73 		iSysMonCli->Close();
       
    74 		if( KErrNone != err )
       
    75 			{
       
    76 			aProcess.Terminate( err );
       
    77 			User::Leave( err );	
       
    78 			}
       
    79 		}
       
    80 
       
    81 	}
       
    82 
       
    83 
       
    84 
       
    85 /**
       
    86  Synchronous function to start a process or application.
       
    87  Note: This API should be used only if one synchronous call to StartL at any one time can be assured.
       
    88  
       
    89 @param aStartupProperties Startup properties provided by the caller.
       
    90 @param aProcess Handle on the process to be created.
       
    91 @leave KErrNoMemory if no memory. 
       
    92 @leave KErrArgument if the TStartMethod enumeration in aStartupProperties is out of range. 
       
    93 @leave KErrTimedOut if the Application or process failed to rendezvous within the interval specified in aStartupProperties. 
       
    94 @leave Or one of the system-wide error codes
       
    95 @internalTechnology
       
    96 @released
       
    97 */
       
    98 EXPORT_C void CSsmStartSafe::StartL( const CSsmStartupProperties &aStartupProperties, RProcess& aProcess )	
       
    99 	{
       
   100 	// The index is not required as a parameter because this function is synchronous and must only be used consecutively.
       
   101 	TInt callerIndex = 0;
       
   102 	CActiveWaiter* waiter = new(ELeave) CActiveWaiter;
       
   103 	CleanupStack::PushL( waiter );
       
   104 	
       
   105 	Start( aStartupProperties, aProcess, waiter->iStatus, callerIndex );
       
   106 	waiter->WaitActive();
       
   107 	
       
   108 	User::LeaveIfError(waiter->iStatus.Int());
       
   109 	
       
   110 	CleanupStack::PopAndDestroy( waiter );
       
   111 	}
       
   112 	
       
   113 	
       
   114 
       
   115 /**
       
   116  Asynchronous function to start a process or application.
       
   117 
       
   118 @param aStartupProperties The startup-properties defining the app or process to be started. 
       
   119 @param aProcess Handle on the process to be created.
       
   120 @param aCommandTrs The TRequestStatus which is completed as a result of the process rendezvous or any error arising from the attempt.
       
   121 @param aCallerIndex The index integer supplied by this call. This value should be perserved and passed in the case of a call to StartCancel()
       
   122 @internalTechnology
       
   123 @released 
       
   124 */
       
   125 EXPORT_C void CSsmStartSafe::Start( const CSsmStartupProperties& aStartupProperties, RProcess& aProcess, TRequestStatus& aCommandTrs, TInt& aCallerIndex )
       
   126 	{	
       
   127 	
       
   128 	aCommandTrs = KRequestPending;
       
   129 	
       
   130 	if (ESsmFireAndForget == aStartupProperties.ExecutionBehaviour())
       
   131 		{
       
   132 		TRequestStatus* status = &aCommandTrs;
       
   133 	
       
   134 		CFireAndForget* fireAndForget = NULL;
       
   135 		// F&F destroys itself.
       
   136 		TRAPD(err,fireAndForget = CFireAndForget::NewL(aStartupProperties));
       
   137 		
       
   138 		if(KErrNone == err)
       
   139 			{
       
   140 			fireAndForget->FireD();
       
   141 			}
       
   142 		User::RequestComplete(status, err);
       
   143 		}
       
   144 	else
       
   145 		{
       
   146 		TInt err = RegisterCall( aCallerIndex, aCommandTrs );
       
   147 
       
   148 		if (err != KErrNone)
       
   149 			{
       
   150 			aCallerIndex = KErrNotFound;
       
   151 			TRequestStatus* status = &aCommandTrs;
       
   152 			User::RequestComplete( status, err );
       
   153 			return;
       
   154 			}
       
   155 
       
   156 		TRAP( err, iStartSafeEntryArray[ aCallerIndex ].iStartAndRetry = CStartAndRetry::NewL( *this, aStartupProperties, aProcess, aCallerIndex, iApaStarter ));
       
   157 		if (err != KErrNone)
       
   158 			{
       
   159 			DeRegisterCall( aCallerIndex );	//should complete the request with KErrCancel
       
   160 			return;
       
   161 			}
       
   162 		iStartSafeEntryArray[ aCallerIndex ].iStartAndRetry->Actuate();
       
   163 		}
       
   164 	}
       
   165 
       
   166 /**
       
   167 Waits for AppArc Server to initialise.
       
   168 @return KErrNotSupported if AppArc is not installed
       
   169 @return TInt system error code
       
   170 @internalTechnology
       
   171 @released 
       
   172 */			
       
   173 EXPORT_C TInt CSsmStartSafe::InitAppArcServer()
       
   174 	{
       
   175 	
       
   176 	// Guard against the case of no Apparc.
       
   177 	if( !iApaStarter )
       
   178 		{
       
   179 		return KErrNotSupported;	
       
   180 		}
       
   181 		
       
   182 	TRAPD( err, iApaStarter->WaitForApparcToInitialiseL() );
       
   183 	
       
   184 	return err;
       
   185 	}
       
   186 
       
   187 /**
       
   188 Async call to wait for Apparc Server to initialise.
       
   189 @param aCommandTrs The TRequestStatus which is completed when applist is populated.
       
   190 @internalTechnology
       
   191 @released 
       
   192 */			
       
   193 EXPORT_C void CSsmStartSafe::InitApparcServer(TRequestStatus& aStatus)
       
   194 	{
       
   195 	aStatus = KRequestPending;
       
   196 	// Guard against the case of no Apparc.
       
   197 	if( !iApaStarter )
       
   198 		{
       
   199 		TRequestStatus* status = &aStatus;
       
   200 		User::RequestComplete(status, KErrNotSupported);
       
   201 		return;
       
   202 		}
       
   203 
       
   204 	iApaStarter->InitApparcServer(aStatus);
       
   205 	}
       
   206 
       
   207 /**
       
   208 Cancel Apparc Server initialization.
       
   209 @internalTechnology
       
   210 @released 
       
   211 */			
       
   212 EXPORT_C void CSsmStartSafe::InitApparcServerCancel()
       
   213 	{
       
   214 	if (iApaStarter)
       
   215 		{
       
   216 		iApaStarter->InitApparcServerCancel();
       
   217 		}
       
   218 	}
       
   219 
       
   220 /**
       
   221  Calling cancel precipitates the destruction of the rendezvous-observer/timeoutwaiter.
       
   222  These are AOs and so cancellation of any outstanding rendezvous is implied.
       
   223  @param aCallerIndex the index value supplied by the async CSsmStartSafe::StartL(). This is set to a large negative value upon completion
       
   224  of the operation to guard against multiple calls, or KErrArgument if the index is out of range.
       
   225 */
       
   226 EXPORT_C void CSsmStartSafe::StartCancel( TInt& aCallerIndex )
       
   227 	{
       
   228 	
       
   229 	const TInt KSsNegValue = -9999;
       
   230 	
       
   231 	if( KErrNone != DeRegisterCall(aCallerIndex) )
       
   232 		{
       
   233 		aCallerIndex = KErrArgument;
       
   234 		}
       
   235 	else
       
   236 		{
       
   237 		aCallerIndex = KSsNegValue;
       
   238 		}
       
   239 
       
   240 	}
       
   241 
       
   242 /**
       
   243  Inherited from MStartAndRetryNotifications
       
   244 */
       
   245 void CSsmStartSafe::RendezvousComplete( TInt aComplete, TInt aCallerIndex )
       
   246 	{
       
   247 	
       
   248 	User::RequestComplete( iStartSafeEntryArray[ aCallerIndex ].iCallerTrs, aComplete );
       
   249 
       
   250 	DeRegisterCall( aCallerIndex );
       
   251 	}
       
   252 
       
   253 
       
   254 
       
   255 void CSsmStartSafe::CancellationComplete( TInt aComplete, TInt aCallerIndex )
       
   256 	{
       
   257 	User::RequestComplete( iStartSafeEntryArray[ aCallerIndex ].iCallerTrs, aComplete );
       
   258 	}
       
   259 
       
   260 
       
   261 
       
   262 /**
       
   263  Add the caller to the array of callers. Supply an index which identifies the caller. 
       
   264  In the case a call to one of the cancel functions, the caller identifies themselves 
       
   265  by this index.
       
   266 */
       
   267 TInt CSsmStartSafe::RegisterCall( TInt& aCallerIndex, TRequestStatus& aStatus )
       
   268 	{
       
   269 	const TInt count = iStartSafeEntryArray.Count();
       
   270 	TBool slotFound = EFalse;	
       
   271 	for(TInt i = 0; i < count; i++ )
       
   272 		{
       
   273 		if( !iStartSafeEntryArray[ i ].iInUse )
       
   274 			{
       
   275 			iStartSafeEntryArray[ i ].iInUse = ETrue;
       
   276 			iStartSafeEntryArray[ i ].iStartAndRetry = NULL;
       
   277 			iStartSafeEntryArray[ i ].iCallerTrs = &aStatus;
       
   278 			iStartSafeEntryArray[ i ].iCallerIndex = aCallerIndex;
       
   279 			aCallerIndex = i;
       
   280 			slotFound = ETrue;
       
   281 			iCallerCount++;
       
   282 			break;
       
   283 			}		
       
   284 		}
       
   285 	TInt err = KErrNone;
       
   286 	if( !slotFound )
       
   287 		{
       
   288 		TSsmStartSafeEntry entry;
       
   289 		entry.iStartAndRetry = NULL;
       
   290 		entry.iCallerTrs = &aStatus;
       
   291 		entry.iInUse = ETrue;
       
   292 		err = iStartSafeEntryArray.Append( entry );
       
   293 		if( KErrNone == err )
       
   294 			{
       
   295 			aCallerIndex = iCallerCount++;
       
   296 			}
       
   297 		}
       
   298 	return err;
       
   299 	}
       
   300 
       
   301 
       
   302 
       
   303 TInt CSsmStartSafe::DeRegisterCall(TInt aCallerIndex )
       
   304 	{	
       
   305 	if( !__IN_RANGE(aCallerIndex, iStartSafeEntryArray.Count()) )
       
   306 		{
       
   307 		return KErrArgument;
       
   308 		}
       
   309 	
       
   310 	if( iStartSafeEntryArray[ aCallerIndex ].iInUse )
       
   311 		{
       
   312 		delete iStartSafeEntryArray[ aCallerIndex ].iStartAndRetry;
       
   313 		iStartSafeEntryArray[ aCallerIndex ].iStartAndRetry = NULL;	
       
   314 		iStartSafeEntryArray[ aCallerIndex ].iInUse = EFalse;
       
   315 		
       
   316 		// In case of call from destructor. Actually, the other classes look after themselves
       
   317 		// so this conditional shouldn't evaluate to true.
       
   318 		TRequestStatus* trs = iStartSafeEntryArray[ aCallerIndex ].iCallerTrs;
       
   319 		
       
   320 		if( trs && (*trs == KRequestPending) )
       
   321 			{
       
   322 			User::RequestComplete( iStartSafeEntryArray[ aCallerIndex ].iCallerTrs, KErrCancel );
       
   323 			}
       
   324 		
       
   325 		iCallerCount--;
       
   326 
       
   327 	   // Remove unused elements at the end of the array, so iStartSafeEntryArray can be (granular)shrunk
       
   328 		const TInt count = iStartSafeEntryArray.Count();
       
   329 		TBool slotRemoved = EFalse;
       
   330 		for(TInt i = count-1; i >= 0 ; i-- )
       
   331 			{
       
   332 			if( !iStartSafeEntryArray[ i ].iInUse )
       
   333 				{
       
   334 	      		iStartSafeEntryArray.Remove(i);
       
   335 	      		slotRemoved = ETrue;
       
   336 				}
       
   337 			else
       
   338 				{
       
   339 				break;
       
   340 				}
       
   341 			}
       
   342 		if (slotRemoved)
       
   343 			{
       
   344 			iStartSafeEntryArray.GranularCompress();
       
   345 			}
       
   346 		}
       
   347 	
       
   348 	return KErrNone;
       
   349 	}
       
   350 
       
   351 
       
   352 
       
   353 /**
       
   354 Load the library. Locate and call the ordinal corresponding to CApStart::NewL().
       
   355 
       
   356 Note: We do not leave in the case of being unable to load the libray, but assume Apparc is not present.
       
   357       iApaStarter is checked for NULL before use passim and appropriate error code supplied if it is. 
       
   358       The return code is derived from the loader-server (Base) and not closely specified in RLibrary docs or code.
       
   359 */
       
   360 void CSsmStartSafe::LoadApStartLibL()
       
   361 	{	
       
   362 	 if( KErrNone != iApStartLib.Load(KApStartDLL) )
       
   363 	 	{
       
   364 	 	return;	
       
   365 	 	}
       
   366 	 
       
   367 	TFuncNewL apStartNewL = reinterpret_cast<TFuncNewL>( iApStartLib.Lookup(1) );
       
   368 	iApaStarter = apStartNewL();
       
   369 	}
       
   370 
       
   371 
       
   372 
       
   373 /**
       
   374  Load the dll interfacing between us and the System Monitor component, if installed.
       
   375 */
       
   376 void CSsmStartSafe::LoadMonitorProxyLibL()
       
   377 	{
       
   378 	if( KErrNone != iSysMonProxyLib.Load(KSysMonProxyDLL) )
       
   379 	 	{
       
   380 	 	return;	
       
   381 	 	}
       
   382 
       
   383 	TFuncCreateL sysMonProxyCreateL = reinterpret_cast<TFuncCreateL>( iSysMonProxyLib.Lookup(1) );
       
   384 	iSysMonCli = sysMonProxyCreateL();
       
   385 	}
       
   386 
       
   387 
       
   388 
       
   389 /**
       
   390 Used to create an instance of CSsmStartSafe class
       
   391 @return A pointer to an instance of CSsmStartSafe
       
   392 @internalTechnology
       
   393 @released
       
   394 */
       
   395 EXPORT_C CSsmStartSafe* CSsmStartSafe::NewL()
       
   396 	{
       
   397 	CSsmStartSafe* self = NewLC();
       
   398 	CleanupStack::Pop( self );
       
   399 	
       
   400 	return self;	
       
   401 	}
       
   402 
       
   403 
       
   404 
       
   405 EXPORT_C CSsmStartSafe* CSsmStartSafe::NewLC()
       
   406 	{
       
   407 	CSsmStartSafe* self = new(ELeave) CSsmStartSafe();
       
   408 	CleanupStack::PushL( self );
       
   409 	self->ConstructL();
       
   410 	return self;	
       
   411 	}
       
   412 
       
   413 
       
   414 
       
   415 CSsmStartSafe::CSsmStartSafe()
       
   416 	{
       
   417 	}
       
   418 
       
   419  
       
   420 
       
   421 void CSsmStartSafe::ConstructL()
       
   422 	{
       
   423 	LoadApStartLibL();		
       
   424 	LoadMonitorProxyLibL();
       
   425 	}
       
   426 	
       
   427 
       
   428 
       
   429 CSsmStartSafe::~CSsmStartSafe()
       
   430 	{
       
   431 	const TInt count = iStartSafeEntryArray.Count();	
       
   432 	for(TInt i = 0; i < count; i++ )
       
   433 		{
       
   434 		DeRegisterCall( i );
       
   435 		}
       
   436 	
       
   437 	delete iApaStarter;
       
   438 	delete iSysMonCli;
       
   439 	iStartSafeEntryArray.Close();
       
   440 	iApStartLib.Close();
       
   441 	iSysMonProxyLib.Close();
       
   442 	}
       
   443