os/ossrv/genericservices/taskscheduler/SCHSVR/SCHEDULE.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200 (2014-06-10)
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2004-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 // User includes
    17 #include "SchLogger.h"
    18 #include "SCHEDULE.H"
    19 #include <schtask.h>
    20 #include "SCHCLI.H"
    21 #include "SCHENTRY.H"
    22 #include "SchTimer.h"
    23 #include "SCHEXEC.H"
    24 // Constants
    25 const TInt KMaxTasksPerSchedule = 9999;
    26 
    27 //TScheduledTask
    28 TScheduledTask::TScheduledTask(CScheduledTask& aTask, CClientProxy& aClient)
    29 	:	iTask(aTask), 
    30 		iClient(aClient)
    31 	{
    32 	}
    33 
    34 void TScheduledTask::OnDue(const TTsTime& aValidUntil)
    35 	{
    36 	LOGSTRING("TScheduledTask::OnDue - start");
    37 	iTask.OnDue(aValidUntil);
    38 	iClient.ReadyToExecute();
    39 	LOGSTRING("TScheduledTask::OnDue - end");
    40 	}
    41 
    42 const HBufC& TScheduledTask::Data() const
    43 	{
    44 	return iTask.Data();
    45 	}
    46 
    47 const TTaskInfo& TScheduledTask::Info() const
    48 	{
    49 	return iTask.Info();
    50 	}
    51 
    52 const CClientProxy& TScheduledTask::Client() const
    53 	{
    54 	return iClient;
    55 	}
    56 
    57 void TScheduledTask::RemoveInfo()
    58 	{
    59 	LOGSTRING("TScheduledTask::RemoveInfo - start");
    60 	iClient.RemoveTask(&iTask);
    61 	LOGSTRING("TScheduledTask::RemoveInfo - end");
    62 	}
    63 	
    64 void TScheduledTask::DecRepeat()
    65 	{
    66 	iTask.DecRepeat();
    67 	}
    68 
    69 TInt TScheduledTask::Offset()
    70 	{
    71 	return (_FOFF(TScheduledTask, iLink));
    72 	}
    73 /*************************************************************************/
    74 //CSchedule functions
    75 /*************************************************************************/
    76 CSchedule* CSchedule::NewLC(TInt aHandle, 
    77 						const TDesC& aName, 
    78 						TBool aPersists, 
    79 						const CArrayFixFlat<TScheduleEntryInfo2>& aEntries,
    80 						const TSecurityInfo& aSecurityInfo)
    81 	{
    82 	CSchedule* self = new(ELeave) CSchedule(aSecurityInfo, aHandle, aPersists);
    83 	CleanupStack::PushL(self);
    84 	self->ConstructL(aName, aEntries);
    85 	return self;
    86 	}
    87 
    88 CSchedule* CSchedule::NewLC(TInt aHandle, 
    89 						const TDesC& aName, 
    90 						TBool aPersists, 
    91 						const CArrayFixFlat<TTaskSchedulerCondition>& aEntries,
    92 						const TTsTime& aDefaultRunTime,
    93 						const TSecurityInfo& aSecurityInfo)
    94 	{
    95 	CSchedule* self = new(ELeave) CSchedule(aSecurityInfo, aHandle, aPersists);
    96 	CleanupStack::PushL(self);
    97 	self->ConstructL(aName, aEntries,aDefaultRunTime);
    98 	return self;
    99 	}
   100 	
   101 CSchedule* CSchedule::NewL(CFileStore& aStore, TStreamId& aStreamId)
   102 	{
   103 	CSchedule* self = new(ELeave) CSchedule;
   104 	CleanupStack::PushL(self);
   105 	self->RestoreL(aStore, aStreamId);//get self from root
   106 	CleanupStack::Pop();//self
   107 	return self;
   108 	}
   109 
   110 CSchedule::CSchedule(const TSecurityInfo& aSecurityInfo, TInt aHandle, TBool aPersists)
   111 :	iId(aHandle), 
   112 	iPersists(aPersists), 
   113 	iEnabled(ETrue),
   114 	iTaskList(TScheduledTask::Offset()),
   115 	iEntryList(TScheduleEntry::Offset()),
   116 	iSecurityInfo(aSecurityInfo)
   117 	{
   118 	}
   119 
   120 CSchedule::CSchedule()
   121 :	iTaskList(TScheduledTask::Offset()),
   122 	iEntryList(TScheduleEntry::Offset())
   123 	{
   124 	}
   125 
   126 CSchedule::~CSchedule()
   127 	{
   128 	LOGSTRING("CSchedule::~CSchedule - start");
   129 		
   130 	delete iName;
   131 	RemoveTasks(EFalse);
   132 	RemoveEntries();
   133 	RemoveConditions();
   134 
   135 	LOGSTRING("CSchedule::~CSchedule - end");
   136 	}
   137 
   138 void CSchedule::ConstructL(const TDesC& aName,
   139 						const CArrayFixFlat<TScheduleEntryInfo2>& aEntries)
   140 	{
   141 	iName = aName.AllocL();
   142 	AddEntriesL(aEntries);
   143 	}
   144 	
   145 void CSchedule::ConstructL(const TDesC& aName,
   146 					const CArrayFixFlat<TTaskSchedulerCondition>& aEntries,
   147 					const TTsTime& aDefaultRunTime)
   148 	{
   149 	iName = aName.AllocL();
   150 	AddConditionsL(aEntries);
   151 	
   152 	// we plug the default time in as the start time of a schedule entry
   153 	TScheduleEntryInfo2 info(aDefaultRunTime, EDaily, 1, 60*24);
   154 	TScheduleEntry* entry = ScheduleEntryFactory::CreateL(info);
   155 	iEntryList.AddLast(*entry);		
   156 	}	
   157 	
   158 void CSchedule::RestoreL(CFileStore& aStore, TStreamId& aId)
   159 	{
   160 	RStoreReadStream scheduleStream;
   161 	scheduleStream.OpenLC(aStore, aId);
   162 	InternalizeL(scheduleStream);
   163 	CleanupStack::PopAndDestroy(&scheduleStream);
   164 	}
   165 	
   166 TInt CSchedule::Offset()
   167 	{
   168 	return (_FOFF(CSchedule, iLink));
   169 	}
   170 	
   171 TBool CSchedule::ClientInSchedule(const TDesC& aClientName)
   172 //
   173 // returns true if the client is part of a task associated with this schedule
   174 //
   175 	{
   176 	TSglQueIter<TScheduledTask> tasks(iTaskList);
   177 	tasks.SetToFirst();
   178 	//
   179 	TScheduledTask* task;
   180 	while ((task=tasks++)!=NULL)
   181 		{
   182 		if (task->Client().ExecutorFileName().MatchF(aClientName) == 0)
   183 			return ETrue;
   184 		}
   185 	return EFalse;
   186 	}
   187 	
   188 //
   189 //Task methods
   190 //
   191 
   192 void CSchedule::AddTask(TScheduledTask& aTask)
   193 	{
   194 	iTaskList.AddFirst(aTask);
   195 	}
   196 
   197 void CSchedule::RemoveTasks(TBool aFromClient)
   198 	{
   199 	LOGSTRING("CSchedule::RemoveTasks - start");
   200 
   201 	TScheduledTask*  task;
   202 	TSglQueIter<TScheduledTask> taskIter(iTaskList);
   203     taskIter.SetToFirst();
   204     while ((task = taskIter++) != NULL)
   205 		{
   206 		if (aFromClient)
   207 			{
   208 			task->RemoveInfo();
   209 			}
   210 		RemoveTask(task);
   211 		}
   212 
   213 	LOGSTRING("CSchedule::RemoveTasks - end");
   214 	}
   215 
   216 void CSchedule::RemoveTask(TScheduledTask* aTask)
   217 	{
   218 	LOGSTRING("CSchedule::RemoveTask - start");
   219 
   220 	LOGSTRING2("CSchedule::RemoveTask - Schedule id: %d", iId);
   221 	iTaskList.Remove(*aTask);
   222 	delete aTask;
   223 	LOGSTRING("CSchedule::RemoveTask - end");
   224 	}
   225 
   226 void CSchedule::NotifyTasks()
   227 	{
   228 	LOGSTRING("CSchedule::NotifyTasks - start");
   229 
   230 	TScheduledTask*  task;
   231 	TSglQueIter<TScheduledTask> taskIter(iTaskList);
   232     taskIter.SetToFirst();
   233     TTsTime time;
   234     while((task = taskIter++) != NULL)
   235 		{
   236 		if (iDueTime.IsUtc())
   237 			time.SetUtcTime(iDueTime.GetUtcTime() + iValidityPeriod);
   238 		else
   239 			time.SetLocalTime(iDueTime.GetLocalTime()+iValidityPeriod);
   240 		
   241 		task->OnDue(time);
   242 		if	(task->Info().iRepeat > 0)
   243 			task->DecRepeat();
   244 		if	(task->Info().iRepeat == 0)
   245 			RemoveTask(task);
   246 		}
   247 
   248 	LOGSTRING("CSchedule::NotifyTasks - end");
   249 	}
   250 
   251 TInt CSchedule::GenerateTaskId()
   252 	{
   253 	LOGSTRING("CSchedule::GenerateTaskId - start");
   254 
   255 	TInt id = iId;
   256 	TScheduledTask* task = Task(id);
   257 	while (task!=NULL) 
   258 		{
   259 		if	((id-iId) > KMaxTasksPerSchedule)
   260 			return KErrOverflow;
   261 		id++;
   262 		task = Task(id);
   263 		}
   264 	LOGSTRING("CSchedule::GenerateTaskId - end");
   265 	return id;
   266 	}
   267 
   268 TScheduledTask* CSchedule::Task(const TInt aTaskId)
   269 	{
   270 	TSglQueIter<TScheduledTask> tasks(iTaskList);
   271 	tasks.SetToFirst();
   272 	//
   273 	TScheduledTask* task;
   274 	while ((task=tasks++)!=NULL)
   275 		{
   276 		if	(task->Info().iTaskId == aTaskId)
   277 			return task;
   278 		}
   279 	return NULL;
   280 	}
   281 
   282 void CSchedule::TasksL(CArrayFixFlat<TTaskInfo>& aTasks)
   283 	{
   284 	LOGSTRING("CSchedule::TasksL - start");
   285 	TSglQueIter<TScheduledTask> taskIter(iTaskList);
   286 	taskIter.SetToFirst();
   287 	TScheduledTask* task;
   288 	while ((task = taskIter++) != NULL)
   289 		{
   290 		aTasks.AppendL(task->Info());
   291 		}
   292 	LOGSTRING("CSchedule::TasksL - end");
   293 	}
   294 
   295 //
   296 //Externalize/Internalize methods
   297 //
   298 void CSchedule::ExternalizeL(RWriteStream& aWriteStream) const
   299 	{
   300 	LOGSTRING("CSchedule::ExternalizeL - start");
   301 
   302 	aWriteStream.WriteInt32L(iId);
   303 	aWriteStream << *iName;
   304 	aWriteStream.WriteInt32L(iPersists);
   305 	aWriteStream.WriteInt32L(iEnabled);
   306 
   307 	TInt count=0;
   308 	// Count the number of schedule entries so that
   309 	// we can write the count (in the stream) in advance
   310 	// of the entries themselves.
   311 	TSglQueIter<TScheduleEntry> iter(iEntryList);
   312 	iter.SetToFirst();
   313 
   314 	TScheduleEntry* entry;
   315 	while((entry=iter++)!=NULL)
   316 		count++;
   317 	aWriteStream.WriteInt32L(count);
   318 
   319 	// Write the entries
   320 	iter.SetToFirst();
   321 	while((entry=iter++)!=NULL)
   322 		{
   323 		entry->Info().ExternalizeL(aWriteStream);
   324 		}
   325 	
   326 	//write conditions
   327 	count = iConditions.Count();
   328 	aWriteStream.WriteInt32L(count);
   329 	for(TInt ii = 0; ii<count; ++ii)
   330 		{
   331 		aWriteStream.WriteInt32L(iConditions[ii].iCategory.iUid);
   332 		aWriteStream.WriteUint32L(iConditions[ii].iKey);
   333 		aWriteStream.WriteInt32L(iConditions[ii].iState);
   334 		aWriteStream.WriteInt32L(iConditions[ii].iType);		
   335 		}		
   336 		
   337 	//write security Info
   338 	aWriteStream << iSecurityInfo;
   339 		
   340 	LOGSTRING("CSchedule::ExternalizeL - end");
   341 	}
   342 
   343 void CSchedule::InternalizeL(RReadStream& aReadStream)
   344 	{
   345 	LOGSTRING("CSchedule::InternalizeL - start");
   346 	iId = aReadStream.ReadInt32L();
   347 	HBufC* name = HBufC::NewL(aReadStream, KMaxName);
   348 	delete iName;
   349 	iName = name;
   350 	iPersists = aReadStream.ReadInt32L();
   351 	iEnabled = aReadStream.ReadInt32L();
   352 
   353 	//Make sure we remove the entries first!
   354 	RemoveEntries();
   355 
   356 	TInt entries = aReadStream.ReadInt32L();
   357 	for (TInt i=0; i<entries;i++)
   358 		{
   359 		TScheduleEntryInfo2 info;
   360 		info.InternalizeL(aReadStream);		
   361 		TScheduleEntry* entry = ScheduleEntryFactory::CreateL(info);
   362 		iEntryList.AddLast(*entry);
   363 		}
   364 	
   365 	// now read in conditions
   366 	RemoveConditions();
   367 	TInt conditions = aReadStream.ReadInt32L();
   368 	for (TInt ii=0; ii<conditions;++ii)
   369 		{
   370 		TUid category;
   371 		category.iUid = aReadStream.ReadInt32L();
   372 		TUint key = aReadStream.ReadUint32L();
   373 		TInt state = aReadStream.ReadInt32L();
   374 		TTaskSchedulerCondition::TConditionType type 
   375 			= static_cast<TTaskSchedulerCondition::TConditionType>(aReadStream.ReadInt32L());
   376 		TTaskSchedulerCondition condition(category, key, state, type);
   377 		User::LeaveIfError(iConditions.Append(condition));
   378 		}
   379 	
   380 	// read in security Info
   381 	aReadStream >> iSecurityInfo;
   382 	
   383 	LOGSTRING("CSchedule::InternalizeL - end");
   384 	}
   385 	
   386 //
   387 //Entries methods
   388 //
   389 
   390 void CSchedule::EntriesL(CArrayFixFlat<TScheduleEntryInfo2>& aEntries)
   391 	{
   392 	LOGSTRING("CSchedule::EntriesL - start");
   393 	TSglQueIter<TScheduleEntry> entryIter(iEntryList);
   394 	entryIter.SetToFirst();
   395 	TScheduleEntry* entry;
   396 	while ((entry = entryIter++) != NULL)
   397 		{
   398 		aEntries.AppendL(entry->Info());
   399 		}
   400 	LOGSTRING("CSchedule::EntriesL - end");
   401 	}
   402 
   403 void CSchedule::AddEntriesL(const CArrayFixFlat<TScheduleEntryInfo2>& aEntries)
   404 	{
   405 	LOGSTRING("CSchedule::AddEntriesL - start");
   406 	TInt count = aEntries.Count();
   407 	TScheduleEntryInfo2 entryInfo2;
   408 	TTsTime ttsTime;	//temporary needed due to gccxml compiler
   409 	TDateTime dateTime;
   410 	
   411 	for (TInt i = 0;i<count;i++)
   412 		{
   413 		entryInfo2 = aEntries.At(i);
   414 		
   415 		// Zero out time to the nearest ms.
   416 		if(entryInfo2.StartTime().IsUtc())
   417 			{
   418 			dateTime = entryInfo2.StartTime().GetUtcTime().DateTime();
   419 			dateTime.SetMicroSecond(0);
   420 			ttsTime.SetUtcTime(dateTime);
   421 			entryInfo2.SetStartTime(ttsTime);
   422 			}
   423 		else
   424 			{
   425 			dateTime = entryInfo2.StartTime().GetLocalTime().DateTime();
   426 			dateTime.SetMicroSecond(0);
   427 			ttsTime.SetLocalTime(dateTime);
   428 			entryInfo2.SetStartTime(ttsTime);
   429 			}
   430 			
   431 		TScheduleEntry* entry = ScheduleEntryFactory::CreateL(entryInfo2);
   432 		iEntryList.AddLast(*entry);
   433 		}
   434 
   435 	LOGSTRING("CSchedule::AddEntriesL - end");
   436 	}
   437 
   438 void CSchedule::ReplaceEntriesL(const CArrayFixFlat<TScheduleEntryInfo2>& aEntries)
   439 	{
   440 	// remove the original entries
   441 	RemoveEntries();
   442 	AddEntriesL(aEntries);
   443 	}
   444 
   445 void CSchedule::RemoveEntries()
   446 	{
   447 	LOGSTRING("CSchedule::RemoveEntries - start");
   448 
   449 	TScheduleEntry* entry;
   450     TSglQueIter<TScheduleEntry> iter(iEntryList);
   451 	iter.SetToFirst();
   452     while ((entry = iter++) != NULL)
   453 		{
   454 		iEntryList.Remove(*entry);
   455 		delete entry;
   456 		}
   457 
   458 	LOGSTRING("CSchedule::RemoveEntries - end");
   459 	}
   460 	
   461 //Condition methods
   462 void CSchedule::AddConditionsL(const CArrayFixFlat<TTaskSchedulerCondition>& aConditions)
   463 	{
   464 	TInt count = aConditions.Count();
   465 	for (TInt i = 0;i<count;++i)
   466 		User::LeaveIfError(iConditions.Append(aConditions[i]));
   467 	}
   468 	
   469 void CSchedule::ReplaceConditionsL(const CArrayFixFlat<TTaskSchedulerCondition>& aConditions)
   470 	{
   471 	// remove the original conditions
   472 	RemoveConditions();
   473 	AddConditionsL(aConditions);
   474 	}
   475 
   476 void CSchedule::ConditionsL(CArrayFixFlat<TTaskSchedulerCondition>& aConditions)
   477 	{
   478 	TInt count = iConditions.Count();
   479 	for (TInt i = 0;i<count;++i)
   480 		{
   481 		aConditions.AppendL(iConditions[i]);
   482 		}
   483 	}
   484 
   485 void CSchedule::RemoveConditions()
   486 	{
   487 	iConditions.Reset();
   488 	}
   489 
   490 const TTsTime& CSchedule::DefaultRunTimeL() const
   491 	{
   492 	TSglQueIter<TScheduleEntry> entryIter(iEntryList);
   493 	entryIter.SetToFirst();
   494 	TScheduleEntry* entry = entryIter;
   495 	if (entry == NULL)
   496 		User::Leave(KErrArgument);
   497 	return entry->DueTime();
   498 	}	
   499 	
   500 // This method is called when ever a new task is scheduled or a change to an 
   501 // existing schedule is made. When one of the schedule entries in this schedule 
   502 // has become due, this is called with aNotFirstTime = ETrue.  All this does is
   503 // move the next due time into the next time frame.
   504 void CSchedule::CalculateDueTime(TBool aNotFirstTime)
   505 	{
   506 	// Sort the list of entries
   507 	TSglQueIter<TScheduleEntry> iter(iEntryList);
   508 	iter.SetToFirst();
   509 	TScheduleEntry* entry;
   510 	TTime currentTTime;
   511 	TTsTime currentTTsTime;
   512 	//make sure we reset iDueTime to max so that only the minimum is calculated.
   513 	TTsTime maxTime(Time::MaxTTime(), ETrue);
   514 	TTsTime dueTime;
   515 	iDueTime = maxTime; 
   516 	while ((entry = iter++)!=NULL)
   517 		{
   518 		currentTTime.UniversalTime();
   519 		currentTTsTime.SetUtcTime(currentTTime);
   520 		// This works out when the schedule is next due based on the input time
   521 		// and also updates the due time if it is home time based
   522 		dueTime = entry->NextScheduledTime(currentTTsTime);
   523 		if(aNotFirstTime && dueTime.GetUtcTime() <= currentTTime) 
   524 			{
   525 			// We don't want this schedule to run straight away so seed the 
   526 			// next due initial time-frame by incrementing the validity
   527 			currentTTime += entry->Info().ValidityPeriod();
   528 			currentTTime += TTimeIntervalMicroSeconds32(1); // push into the next boundary
   529 				
   530 			if (dueTime.IsUtc())
   531 				currentTTsTime.SetUtcTime(currentTTime);
   532 			else
   533 				currentTTsTime.SetLocalTime(currentTTime + dueTime.GetOffset());
   534 				
   535 			dueTime = entry->NextScheduledTime(currentTTsTime);
   536 			}
   537 		if(dueTime.GetUtcTime() < iDueTime.GetUtcTime()) //find earliest due time from all entries
   538 			{	
   539 			iDueTime = dueTime;
   540 			iValidityPeriod = entry->Info().ValidityPeriod();
   541 			}	 
   542 		}
   543 	}
   544 
   545 // if aCalculateForConditions is true then entrycount corresponds
   546 // to number of conditions;
   547 void CSchedule::GetInfo(TScheduleInfo& aInfo, TBool aCalculateForConditions) 
   548 	{
   549 	aInfo.iState.SetName(Name());
   550 	aInfo.iState.SetDueTime(iDueTime);
   551 	aInfo.iState.SetPersists(Persists());
   552 	aInfo.iState.SetEnabled(Enabled());
   553 	TInt taskCount = 0;
   554 
   555 	TSglQueIter<TScheduledTask> taskIter(*Tasks());
   556 	taskIter.SetToFirst();
   557 	while (taskIter++ != NULL)
   558 		{
   559 		taskCount++;
   560 		}
   561 	aInfo.iTaskCount = taskCount;
   562 	TInt entryCount = 0;
   563 	if(!aCalculateForConditions)
   564 		{
   565 		TSglQueIter<TScheduleEntry> entryIter(iEntryList);
   566 		entryIter.SetToFirst();
   567 		while (entryIter++ != NULL)
   568 			{
   569 			entryCount++;
   570 			}
   571 		}
   572 	else
   573 		entryCount = iConditions.Count();	
   574 	aInfo.iEntryCount = entryCount;
   575 	}
   576 
   577 const RArray<TTaskSchedulerCondition>& CSchedule::Conditions() const
   578 	{
   579 	return iConditions;
   580 	}
   581 	
   582 TBool CSchedule::IsAccessAllowed(const RMessagePtr2& aMessage) const
   583 	{
   584 	// Access allowed if message SID is the same as the schedule creator
   585 	// or if client has WriteDeviceData
   586 	return aMessage.SecureId()==iSecurityInfo.iSecureId 
   587 		|| aMessage.HasCapability(ECapabilityWriteDeviceData)
   588 		|| PlatSec::ConfigSetting(PlatSec::EPlatSecEnforcement)==0; // Enforcement off
   589 	}
   590 	
   591 const TSecurityInfo& CSchedule::SecurityInfo() const
   592 	{
   593 	return iSecurityInfo;
   594 	}
   595 
   596 TBool CSchedule::IsUpdatable()
   597 	{
   598 	if(HasTasks() && Enabled() )
   599 		return 	ETrue;	
   600 	else
   601 		return EFalse;	
   602 	}