os/ossrv/genericservices/taskscheduler/SCHSVR/SchTimer.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/ossrv/genericservices/taskscheduler/SCHSVR/SchTimer.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,656 @@
     1.4 +// Copyright (c) 2004-2010 Nokia Corporation and/or its subsidiary(-ies).
     1.5 +// All rights reserved.
     1.6 +// This component and the accompanying materials are made available
     1.7 +// under the terms of "Eclipse Public License v1.0"
     1.8 +// which accompanies this distribution, and is available
     1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.10 +//
    1.11 +// Initial Contributors:
    1.12 +// Nokia Corporation - initial contribution.
    1.13 +//
    1.14 +// Contributors:
    1.15 +//
    1.16 +// Description:
    1.17 +//
    1.18 +
    1.19 +// User includes
    1.20 +#include "SchTimer.h"
    1.21 +#include "SCHMAN.H"
    1.22 +#include "SCHEDULE.H"
    1.23 +#include "schlogger.h"
    1.24 +
    1.25 +// system includes
    1.26 +#include <e32property.h>
    1.27 +
    1.28 +/**
    1.29 +An instance of this class is used for each different time that a
    1.30 +schedule needs to be run. It is created solely in the 
    1.31 +CScheduleCriteriaManager class.  The timer is updated via the 
    1.32 +SetNext method.  When the time has been reached it notifies the schedule
    1.33 +manager via the CScheduleCriteriaManager::DueSchedule() method.
    1.34 +
    1.35 +@internalComponent
    1.36 +*/
    1.37 +_LIT(KTaskSchedulerPanic, "TaskScheduler ");
    1.38 +
    1.39 +NONSHARABLE_CLASS(CScheduleTimer) : public CTimer
    1.40 +	{
    1.41 +public:
    1.42 +	~CScheduleTimer();
    1.43 +	static CScheduleTimer* NewL(TInt aSchedule, CScheduleCriteriaManager& aManager);
    1.44 +	
    1.45 +	void SetNext(const TTsTime& aNextTime);
    1.46 +	TInt Id();
    1.47 +
    1.48 +	//list capability
    1.49 +	static TInt Offset();
    1.50 +private:
    1.51 +	// From CTimer
    1.52 +	void RunL();
    1.53 +
    1.54 +	CScheduleTimer(TInt aSchedule, CScheduleCriteriaManager& aManager);
    1.55 +	void ConstructL();
    1.56 +	
    1.57 +private:
    1.58 +	TTsTime iDueTime;
    1.59 +	TInt iScheduleHandle;
    1.60 +	TSglQueLink iLink;
    1.61 +	CScheduleCriteriaManager& iConditonManager;
    1.62 +	};
    1.63 +
    1.64 +CScheduleTimer* CScheduleTimer::NewL(TInt aSchedule, CScheduleCriteriaManager& aManager)
    1.65 +	{
    1.66 +	CScheduleTimer* self = new(ELeave) CScheduleTimer(aSchedule, aManager);
    1.67 +	CleanupStack::PushL(self);
    1.68 +	self->ConstructL();
    1.69 +	CleanupStack::Pop(self);
    1.70 +	return self;
    1.71 +	}
    1.72 +
    1.73 +CScheduleTimer::CScheduleTimer(TInt aSchedule, CScheduleCriteriaManager& aManager)
    1.74 +:	CTimer(EPriorityStandard),
    1.75 +	iScheduleHandle(aSchedule),
    1.76 +	iConditonManager(aManager)
    1.77 +	{
    1.78 +	}
    1.79 +
    1.80 +CScheduleTimer::~CScheduleTimer()
    1.81 +	{
    1.82 +	Cancel();
    1.83 +	}
    1.84 +
    1.85 +void CScheduleTimer::ConstructL()
    1.86 +	{
    1.87 +	CTimer::ConstructL();
    1.88 +	CActiveScheduler::Add(this);
    1.89 +	}
    1.90 +
    1.91 +void CScheduleTimer::SetNext(const TTsTime& aNewTime)
    1.92 +	{
    1.93 +	// Can't handle (unlikely but theoretical) situation when year is BC (not AD)
    1.94 +	__ASSERT_ALWAYS(aNewTime.GetUtcTime().DateTime().Year()>0,User::Invariant());
    1.95 +	if (IsActive())
    1.96 +		Cancel();
    1.97 +
    1.98 +	iDueTime=aNewTime;
    1.99 +	TTime currentTime;
   1.100 +	currentTime.UniversalTime();
   1.101 +
   1.102 +	if	(aNewTime.GetUtcTime()>currentTime)
   1.103 +		AtUTC(aNewTime.GetUtcTime());
   1.104 +	else
   1.105 +		AtUTC(currentTime);
   1.106 +	}
   1.107 +
   1.108 +//	Respond to an task being due.  RunL is only called once!
   1.109 +void CScheduleTimer::RunL()
   1.110 +	{
   1.111 +	if(iStatus != KErrAbort)
   1.112 +		iConditonManager.DueSchedule(iScheduleHandle);
   1.113 +
   1.114 +	// RunL() will also be triggered if the system time is changed, with iStatus
   1.115 +	// set to KErrAbort. In this case DueSchedule() should not be called.
   1.116 +	// If the system time has been changed, the schedule needs to be requeued. 
   1.117 +	// This has already been done automatically by CTaskScheduler::HandleEnvironmentChange()
   1.118 +	// [called by the AO CEnvironmentChangeNotifier],
   1.119 +	// as the active object CEnvironmentChangeNotifier has a higher priority than CScheduleTimer.
   1.120 +	}	
   1.121 +
   1.122 +TInt CScheduleTimer::Offset()
   1.123 +	{
   1.124 +	return (_FOFF(CScheduleTimer, iLink));
   1.125 +	}
   1.126 +
   1.127 +TInt CScheduleTimer::Id()
   1.128 +	{
   1.129 +	return iScheduleHandle;
   1.130 +	}
   1.131 +
   1.132 +//		
   1.133 +// class CPropertyNotifier
   1.134 +// This class handles changes to P&S variables and notifies the
   1.135 +// CConditionManager class when a condition is satisfied.
   1.136 +NONSHARABLE_CLASS(CPropertyNotifier) : public CActive
   1.137 +	{
   1.138 +public:
   1.139 +	~CPropertyNotifier();
   1.140 +	static CPropertyNotifier* NewL(CConditionManager& aManager);
   1.141 +	
   1.142 +private:	
   1.143 +	CPropertyNotifier(CConditionManager& aManager);
   1.144 +	void AttachL();
   1.145 +	// From CActive
   1.146 +	void RunL();
   1.147 +	void DoCancel();
   1.148 +	TInt RunError(TInt aError);
   1.149 +
   1.150 +public:
   1.151 +	void SetPropertyL(const TUid& aCategory, TUint aKey);
   1.152 +
   1.153 +private:
   1.154 +	TUid iCategory;
   1.155 +	TUint iKey;
   1.156 +	RProperty iProperty;
   1.157 +	CConditionManager& iConditionManager;
   1.158 +	};
   1.159 +
   1.160 +//		
   1.161 +// class CConditionManager
   1.162 +// This class manages a set of conditions for each schedule.  It is used
   1.163 +// solely by the CScheduleCriteriaManager class. When the set of conditions 
   1.164 +// is met, a the schedule manager is notified.
   1.165 +NONSHARABLE_CLASS(CConditionManager) : public CActive
   1.166 +	{
   1.167 +public:
   1.168 +	~CConditionManager();
   1.169 +	static CConditionManager* NewL(TInt aSchedule, CScheduleCriteriaManager& aManager);
   1.170 +	
   1.171 +private:	
   1.172 +	CConditionManager(TInt aSchedule, CScheduleCriteriaManager& aManager);
   1.173 +	TBool MatchAllConditionsL() const;
   1.174 +	TBool HasVariable(const TUid& aCategory, TUint aKey) const;
   1.175 +	void CompleteRequest();
   1.176 +	// From CActive
   1.177 +	void RunL();
   1.178 +	void DoCancel();
   1.179 +
   1.180 +public:
   1.181 +	void ReplaceL(const RArray<TTaskSchedulerCondition>& aConditions);
   1.182 +	TInt Id();
   1.183 +	void VariableChangedL(const TUid& aCategory, TUint aKey);
   1.184 +	//list capability
   1.185 +	static TInt Offset();	
   1.186 +	
   1.187 +private:
   1.188 +	RArray<TTaskSchedulerCondition> iConditions;
   1.189 +	RPointerArray<CPropertyNotifier> iPropertyNotifiers;
   1.190 +	TInt iScheduleHandle;
   1.191 +	TSglQueLink iLink;
   1.192 +	CScheduleCriteriaManager& iManager;
   1.193 +	};
   1.194 +
   1.195 +CConditionManager* CConditionManager::NewL(TInt aSchedule, CScheduleCriteriaManager& aManager)
   1.196 +	{
   1.197 +	CConditionManager* self = new(ELeave) CConditionManager(aSchedule, aManager);
   1.198 +	return self;
   1.199 +	}
   1.200 +
   1.201 +CConditionManager::CConditionManager(TInt aSchedule, CScheduleCriteriaManager& aManager)
   1.202 +:	CActive(EPriorityStandard+1), //make priority higher that propertynotifier AO
   1.203 +	iScheduleHandle(aSchedule),
   1.204 +	iManager(aManager)
   1.205 +	{
   1.206 +	CActiveScheduler::Add(this);
   1.207 +	}
   1.208 +
   1.209 +CConditionManager::~CConditionManager()
   1.210 +	{
   1.211 +	Cancel();
   1.212 +	iPropertyNotifiers.ResetAndDestroy();
   1.213 +	iConditions.Reset();		
   1.214 +	}
   1.215 +
   1.216 +//This function evaluates (aValue <op> aState) expression, where "op" could be
   1.217 +//"==", "!=", ">", "<", depending on aType value, and returns the result of expression.
   1.218 +static TBool DoMatchCondition(TTaskSchedulerCondition::TConditionType aType,
   1.219 +							  TInt aValue, 
   1.220 +							  TInt aState)
   1.221 +	{
   1.222 +	if(aType == TTaskSchedulerCondition::EEquals)
   1.223 +		{
   1.224 +		if(aValue == aState)
   1.225 +			{
   1.226 +			return ETrue;
   1.227 +			}
   1.228 +		}
   1.229 +	else if(aType == TTaskSchedulerCondition::ENotEquals)
   1.230 +		{
   1.231 +		if(aValue != aState)
   1.232 +			{
   1.233 +			return ETrue;
   1.234 +			}
   1.235 +		}
   1.236 +	else if(aType == TTaskSchedulerCondition::EGreaterThan)
   1.237 +		{
   1.238 +		if(aValue > aState)
   1.239 +			{
   1.240 +			return ETrue;
   1.241 +			}
   1.242 +		}
   1.243 +	else if(aType == TTaskSchedulerCondition::ELessThan)
   1.244 +		{
   1.245 +		if(aValue < aState)
   1.246 +			{
   1.247 +			return ETrue;
   1.248 +			}
   1.249 +		}
   1.250 +	else
   1.251 +		{
   1.252 +		__ASSERT_ALWAYS(0, User::Invariant());
   1.253 +		}
   1.254 +	return EFalse;
   1.255 +	}
   1.256 +
   1.257 +void CConditionManager::ReplaceL(const RArray<TTaskSchedulerCondition>& aConditions)
   1.258 +	{
   1.259 +	// Ensure any active requests are cancelled
   1.260 +	if(IsActive()) 
   1.261 +	{ 
   1.262 +		Cancel(); 
   1.263 +	}
   1.264 +
   1.265 +	//destroying existing ones will cancel outstanding requests
   1.266 +	iPropertyNotifiers.ResetAndDestroy(); 
   1.267 +	iConditions.Reset();
   1.268 +	const TInt count = aConditions.Count();
   1.269 +	TInt i;
   1.270 +	//Check that the properties already exist
   1.271 +	for(i=0;i<count;++i)
   1.272 +		{
   1.273 +		TInt value;
   1.274 +		TInt err = RProperty::Get(aConditions[i].iCategory, aConditions[i].iKey, value);
   1.275 +		if(err != KErrNone)
   1.276 +			{
   1.277 +			if(err == KErrNotFound)
   1.278 +				{
   1.279 +				err = KErrArgument; //use KErrArgument error code to signify bad conditions.
   1.280 +				}
   1.281 +			User::Leave(err);	
   1.282 +			}
   1.283 +		}
   1.284 +	//Add the new conditions and notifiers.
   1.285 +	for(i=0;i<count;++i)
   1.286 +		{
   1.287 +		//Create local CPropertyNotifier object
   1.288 +		CPropertyNotifier* notifier = CPropertyNotifier::NewL(*this);
   1.289 +		CleanupStack::PushL(notifier);
   1.290 +		const TTaskSchedulerCondition& condition = aConditions[i];
   1.291 +		notifier->SetPropertyL(condition.iCategory, condition.iKey); 
   1.292 +		//Add condition
   1.293 +		User::LeaveIfError(iConditions.Append(condition));
   1.294 +		//Add notifier
   1.295 +		TInt err = iPropertyNotifiers.Append(notifier);
   1.296 +		if(err != KErrNone)
   1.297 +			{
   1.298 +			iConditions.Remove(iConditions.Count() - 1);//Remove the condition we've just added
   1.299 +			User::Leave(err);
   1.300 +			}
   1.301 +		CleanupStack::Pop(notifier);
   1.302 +		}
   1.303 +	//Check to see that conditions are not already satisfied.
   1.304 +	if(MatchAllConditionsL())
   1.305 +		{
   1.306 +		SetActive(); //we need to set AO active here, otherwise RunL wont be called.	
   1.307 +		CompleteRequest();
   1.308 +		}
   1.309 +	}
   1.310 +
   1.311 +void CConditionManager::CompleteRequest()
   1.312 +	{
   1.313 +	TRequestStatus *status = &iStatus;
   1.314 +	User::RequestComplete(status, KErrNone); // now compete request so RunL is triggered
   1.315 +	}
   1.316 +	
   1.317 +//Respond to a condition changing.
   1.318 +//Called from CPropertyNotifier::RunL().
   1.319 +void CConditionManager::VariableChangedL(const TUid& aCategory, TUint aKey)
   1.320 +	{
   1.321 +	//We have been notified that the value of one of the variables has been changed.
   1.322 +	//It is not enough to check that the variable's value satisfies its condition!
   1.323 +	//We have to check that all CConditionManager::iPropertyNotifiers satisfy their conditions.
   1.324 +	//----------------
   1.325 +	//If this is a variable, which is a part of the variables, monitored by the 
   1.326 +	//current CConditionManager object, only then do check variables values against
   1.327 +	//requested conditions	
   1.328 +	if(HasVariable(aCategory, aKey))
   1.329 +		{
   1.330 +		if(MatchAllConditionsL())
   1.331 +			{
   1.332 +			SetActive(); //we need to set AO active here, otherwise RunL wont be called.	
   1.333 +			CompleteRequest();
   1.334 +			}
   1.335 +		}
   1.336 +	}
   1.337 +	
   1.338 +void CConditionManager::RunL()
   1.339 +	{
   1.340 +	// cancel outstanding notification requests by destroying AO's
   1.341 +	iPropertyNotifiers.ResetAndDestroy();
   1.342 +	iManager.DueSchedule(iScheduleHandle);		
   1.343 +	}
   1.344 +
   1.345 +void CConditionManager::DoCancel()
   1.346 +	{
   1.347 +	CompleteRequest();  		
   1.348 +	}
   1.349 +
   1.350 +//The method returns ETrue, if all monitored variables (aConditions array) 
   1.351 +//satisfy their conditions, EFalse otherwise.
   1.352 +TBool CConditionManager::MatchAllConditionsL() const
   1.353 +	{
   1.354 +	TInt satisfiedConditionsCnt = 0;
   1.355 +	TInt count = iConditions.Count();
   1.356 +	for(TInt i=0;i<count;++i)
   1.357 +		{
   1.358 +		const TTaskSchedulerCondition& condition = iConditions[i];
   1.359 +		TInt value;
   1.360 +		// errors here typically indicate that the P&S variables is not of 
   1.361 +		// integer type (ie its changed) or its been deleted
   1.362 +		User::LeaveIfError(RProperty::Get(condition.iCategory, condition.iKey, value));
   1.363 +		if(::DoMatchCondition(condition.iType, value, condition.iState))
   1.364 +			{
   1.365 +			++satisfiedConditionsCnt;
   1.366 +			}
   1.367 +		}
   1.368 +	return satisfiedConditionsCnt == count;
   1.369 +	}
   1.370 +	
   1.371 +//This method checks if the variable, identified by (aCategory, aKey) pair, is a part
   1.372 +//of CConditionManager::iPropertyNotifiers array and returns ETrue, if that's true.
   1.373 +//EFalse otherwise.
   1.374 +TBool CConditionManager::HasVariable(const TUid& aCategory, TUint aKey) const
   1.375 +	{
   1.376 +	for(TInt i=iConditions.Count()-1;i>-1;--i)
   1.377 +		{
   1.378 +		if(iConditions[i].iCategory == aCategory && iConditions[i].iKey == aKey)
   1.379 +			{
   1.380 +			return ETrue;
   1.381 +			}
   1.382 +		}
   1.383 +	return EFalse;
   1.384 +	}
   1.385 +
   1.386 +TInt CConditionManager::Offset()
   1.387 +	{
   1.388 +	return (_FOFF(CConditionManager, iLink));
   1.389 +	}
   1.390 +
   1.391 +TInt CConditionManager::Id()
   1.392 +	{
   1.393 +	return iScheduleHandle;
   1.394 +	}
   1.395 +
   1.396 +//
   1.397 +
   1.398 +CPropertyNotifier* CPropertyNotifier::NewL(CConditionManager& aManager)
   1.399 +	{
   1.400 +	CPropertyNotifier* self = new(ELeave) CPropertyNotifier(aManager);
   1.401 +	return self;
   1.402 +	}
   1.403 +
   1.404 +CPropertyNotifier::CPropertyNotifier(CConditionManager& aManager)
   1.405 +:	CActive(EPriorityStandard),
   1.406 +	iConditionManager(aManager)
   1.407 +	{
   1.408 +	CActiveScheduler::Add(this);
   1.409 +	}
   1.410 +
   1.411 +CPropertyNotifier::~CPropertyNotifier()
   1.412 +	{
   1.413 +	Cancel();
   1.414 +	iProperty.Close();
   1.415 +	}
   1.416 +
   1.417 +void CPropertyNotifier::AttachL()
   1.418 +	{
   1.419 +	User::LeaveIfError(iProperty.Attach(iCategory, iKey));
   1.420 +	iProperty.Subscribe(iStatus);
   1.421 +	SetActive();
   1.422 +	}
   1.423 +
   1.424 +void CPropertyNotifier::SetPropertyL(const TUid& aCategory, TUint aKey)
   1.425 +	{
   1.426 +	if (IsActive())
   1.427 +	    {
   1.428 +		Cancel();
   1.429 +		iProperty.Close();
   1.430 +	    }
   1.431 +	iCategory = aCategory;
   1.432 +	iKey = aKey;
   1.433 +	AttachL();	
   1.434 +	}
   1.435 +
   1.436 +//	Respond to a condition changing
   1.437 +void CPropertyNotifier::RunL()
   1.438 +	{
   1.439 +	if (iStatus.Int() >= KErrNone)
   1.440 +		{
   1.441 +		iConditionManager.VariableChangedL(iCategory, iKey);
   1.442 +		AttachL();
   1.443 +		}
   1.444 +	// if status is KErrNotFound then P&S variable has been deleted!  By 
   1.445 +	// resubscribing we wait for it to be created.  If it never gets
   1.446 +	// created then TRequestStatus never completes so this condition 
   1.447 +	// never gets met and iConditionManager.VariableChanged which 
   1.448 +	// makes sense.
   1.449 +	else if (iStatus.Int() == KErrNotFound)
   1.450 +		AttachL();			
   1.451 +	// If status is another error we have a problem!!! Whatever the case 
   1.452 +	// we should just ignore this condition from now on by doing nothing.
   1.453 +	}
   1.454 +
   1.455 +void CPropertyNotifier::DoCancel()
   1.456 +	{
   1.457 +	iProperty.Cancel();
   1.458 +	}
   1.459 +	
   1.460 +TInt CPropertyNotifier::RunError(TInt aError)
   1.461 +    {
   1.462 +    if (aError)
   1.463 +        {
   1.464 +        LOGSTRING("CPropertyNotifier::RunL() leaves.");
   1.465 +        User::Panic(KTaskSchedulerPanic, aError);
   1.466 +        }
   1.467 +    return KErrNone;
   1.468 +    }
   1.469 +	
   1.470 +//
   1.471 +
   1.472 +CScheduleCriteriaManager* CScheduleCriteriaManager::NewL(CTaskScheduler& aOwner)
   1.473 +	{
   1.474 +	CScheduleCriteriaManager* self = new(ELeave) CScheduleCriteriaManager(aOwner);
   1.475 +	return self;
   1.476 +	}
   1.477 +
   1.478 +CScheduleCriteriaManager::~CScheduleCriteriaManager()
   1.479 +	{
   1.480 +	Cancel();
   1.481 +	RemoveTimers();
   1.482 +	RemoveConditions();
   1.483 +	}
   1.484 +
   1.485 +CScheduleCriteriaManager::CScheduleCriteriaManager(CTaskScheduler& aOwner)
   1.486 +:	CActive(EPriorityStandard+2), //make priority higher than condition AO
   1.487 +	iTaskScheduler(aOwner),
   1.488 +	iTimers(CScheduleTimer::Offset()),
   1.489 +	iConditions(CConditionManager::Offset())	
   1.490 +	{
   1.491 +	CActiveScheduler::Add(this);
   1.492 +	}
   1.493 +
   1.494 +void CScheduleCriteriaManager::CompleteRequest()
   1.495 +	{
   1.496 +	TRequestStatus *status = &iStatus;
   1.497 +	User::RequestComplete(status, KErrNone); // now compete request so RunL is triggered	
   1.498 +	}
   1.499 +	
   1.500 +void CScheduleCriteriaManager::DueSchedule(TInt aScheduleHandle)
   1.501 +	{
   1.502 +	iDueScheduleHandle = aScheduleHandle;
   1.503 +	SetActive(); // need to set AO active so RunL will subsequently be called.
   1.504 +	CompleteRequest();
   1.505 +	}
   1.506 +
   1.507 +void CScheduleCriteriaManager::RunL()
   1.508 +	{
   1.509 +	// remove schedule and then notify task scheduler manager	
   1.510 +	RemoveSchedule(iDueScheduleHandle);
   1.511 +	iTaskScheduler.DueTaskNotifyL(iDueScheduleHandle);
   1.512 +	}
   1.513 +
   1.514 +void CScheduleCriteriaManager::DoCancel()
   1.515 +	{
   1.516 +	CompleteRequest();
   1.517 +	}
   1.518 +	
   1.519 +// If schedule timer for this ID doesnt exist then create and add new timer.  If schedule 
   1.520 +// timer does exist then just amend existing timer.
   1.521 +//When one of the schedule entries in this schedule has become due,
   1.522 +//this function will be called with aNotFirstTime = ETrue
   1.523 +//If this function is called because of environment changes then aSchChange   = EOnlyTime and only update time based schedule
   1.524 +void CScheduleCriteriaManager::ReplaceScheduleL(CSchedule& aSchedule, TSchChangeType aSchChange , TBool aNotFirstTime)
   1.525 +	{
   1.526 +	aSchedule.CalculateDueTime(aNotFirstTime);
   1.527 +
   1.528 +	TInt  scheduleId 		=  	aSchedule.Id();
   1.529 +	const TTsTime nextTime 	= 	aSchedule.DueTime();
   1.530 +	ReplaceScheduleL(nextTime,scheduleId);
   1.531 +	
   1.532 +	//If this function is called because of environment changes then
   1.533 +	//leave conditions unchanged
   1.534 +	if(aSchChange == EOnlyTime)
   1.535 +		return;
   1.536 +	CConditionManager* condition = FindCondition(scheduleId);
   1.537 +	// no point in doing work for 
   1.538 +	if(aSchedule.Conditions().Count() > 0)
   1.539 +		{
   1.540 +		if(!condition)
   1.541 +			{
   1.542 +			condition = CConditionManager::NewL(scheduleId, *this);
   1.543 +			iConditions.AddLast(*condition);
   1.544 +			}
   1.545 +		condition->ReplaceL(aSchedule.Conditions());
   1.546 +		}
   1.547 +	else if(condition)
   1.548 +		RemoveCondition(condition);		
   1.549 +	}
   1.550 +	
   1.551 +// If schedule timer for this ID doesnt exist then create and add new timer.  If schedule 
   1.552 +// timer does exist then just amend existing timer.
   1.553 +void CScheduleCriteriaManager::ReplaceScheduleL(const TTsTime& aNextTime, 
   1.554 +								TInt aSchedule)
   1.555 +	{
   1.556 +	CScheduleTimer* timer = Find(aSchedule);
   1.557 +	// if time is set to MaxTTime then we don't want to set a timer
   1.558 +	// off as it will complete straight away.
   1.559 +	if((aNextTime.GetUtcTime() != Time::MaxTTime())
   1.560 +	&& 	(aNextTime.GetLocalTime() != Time::MaxTTime()))
   1.561 +		{
   1.562 +		if(!timer)
   1.563 +			{	
   1.564 +			timer = CScheduleTimer::NewL(aSchedule, *this);
   1.565 +			iTimers.AddLast(*timer);
   1.566 +			}
   1.567 +		timer->SetNext(aNextTime);
   1.568 +		}
   1.569 +	else if(timer)	
   1.570 +		{
   1.571 +		RemoveTimer(timer); // make sure we remove the old one!
   1.572 +		}
   1.573 +	}
   1.574 +
   1.575 +void CScheduleCriteriaManager::RemoveSchedule(TInt aSchedule)
   1.576 +	{
   1.577 +	CScheduleTimer* timer = Find(aSchedule);
   1.578 +	if(timer)
   1.579 +		RemoveTimer(timer); // remove timer also terminates AO
   1.580 +
   1.581 +	CConditionManager* condition = FindCondition(aSchedule);
   1.582 +	if(condition)
   1.583 +		RemoveCondition(condition); // remove condition also terminates AO
   1.584 +	
   1.585 +	}
   1.586 +
   1.587 +//Timer methods	
   1.588 +void CScheduleCriteriaManager::RemoveTimers()
   1.589 +	{
   1.590 +	CScheduleTimer* timer;
   1.591 +	TSglQueIter<CScheduleTimer> timerIter(iTimers);
   1.592 +    timerIter.SetToFirst();
   1.593 +    while ((timer = timerIter++) != NULL)
   1.594 +		{
   1.595 +		RemoveTimer(timer);
   1.596 +		}
   1.597 +	}
   1.598 +
   1.599 +void CScheduleCriteriaManager::RemoveTimer(CScheduleTimer* aTimer)
   1.600 +	{
   1.601 +	iTimers.Remove(*aTimer);
   1.602 +	delete aTimer;
   1.603 +	}
   1.604 +	
   1.605 +CScheduleTimer* CScheduleCriteriaManager::Find(TInt aSchedule)
   1.606 +	{
   1.607 +	CScheduleTimer* timer = NULL;
   1.608 +	TSglQueIter<CScheduleTimer> timerIter(iTimers);
   1.609 +    timerIter.SetToFirst();
   1.610 +    while ((timer = timerIter++) != NULL)
   1.611 +		{
   1.612 +		if	(timer->Id() == aSchedule)
   1.613 +			break;
   1.614 +		}	
   1.615 +	return timer;
   1.616 +	}	
   1.617 +
   1.618 +// condition methods
   1.619 +void CScheduleCriteriaManager::RemoveConditions()
   1.620 +	{
   1.621 +	CConditionManager* condition;
   1.622 +	TSglQueIter<CConditionManager> conditionIter(iConditions);
   1.623 +    conditionIter.SetToFirst();
   1.624 +    while ((condition = conditionIter++) != NULL)
   1.625 +		{
   1.626 +		RemoveCondition(condition);
   1.627 +		}
   1.628 +	}
   1.629 +
   1.630 +void CScheduleCriteriaManager::RemoveCondition(CConditionManager* aCondition)
   1.631 +	{
   1.632 +	iConditions.Remove(*aCondition);
   1.633 +	delete aCondition;
   1.634 +	}
   1.635 +	
   1.636 +CConditionManager* CScheduleCriteriaManager::FindCondition(TInt aSchedule)
   1.637 +	{
   1.638 +	CConditionManager* condition = NULL;
   1.639 +	TSglQueIter<CConditionManager> conditionIter(iConditions);
   1.640 +    conditionIter.SetToFirst();
   1.641 +    while ((condition = conditionIter++) != NULL)
   1.642 +		{
   1.643 +		if	(condition->Id() == aSchedule)
   1.644 +			break;
   1.645 +		}	
   1.646 +	return condition;
   1.647 +	}	
   1.648 +	
   1.649 +TInt CScheduleCriteriaManager::RunError(TInt aError)
   1.650 +    {
   1.651 +    if (aError)
   1.652 +        {
   1.653 +        LOGSTRING("CScheduleCriteriaManager::RunL() leaves.");
   1.654 +        User::Panic(KTaskSchedulerPanic, aError);
   1.655 +        }    
   1.656 +    return KErrNone;
   1.657 +    }
   1.658 +
   1.659 +