commonappservices/alarmserver/Server/Source/ASSrvTimer.cpp
changeset 0 2e3d3ce01487
equal deleted inserted replaced
-1:000000000000 0:2e3d3ce01487
       
     1 // Copyright (c) 1999-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 "ASSrvTimer.h"
       
    17 
       
    18 // System includes
       
    19 #include <e32base.h>
       
    20 
       
    21 // User includes
       
    22 #include "ASSrvStaticUtils.h"
       
    23 #include "ASSrvAlarmQueue.h"
       
    24 #include "ASSrvTimerObserver.h"
       
    25 #include "ASSrvServerWideData.h"
       
    26 #include "ASSrvAnyEventManager.h"
       
    27 
       
    28 //
       
    29 // ----> CASSrvAlarmTimer (source)
       
    30 //
       
    31 
       
    32 //*************************************************************************************
       
    33 CASSrvAlarmTimer::CASSrvAlarmTimer(CASSrvServerWideData& aServerWideData)
       
    34 :	CTimer(CActive::EPriorityStandard), iServerWideData(aServerWideData), iNextDueAlarmId(KNullAlarmId),
       
    35 	iInvalidatedByInternalize(EFalse)
       
    36 	{
       
    37 	CActiveScheduler::Add(this);
       
    38 	}
       
    39 
       
    40 
       
    41 //*************************************************************************************
       
    42 CASSrvAlarmTimer::~CASSrvAlarmTimer()
       
    43 	{
       
    44 	ServerData().Queue().NotificationPoolChangeCancel(*this);
       
    45 	iNotificationList.Close();
       
    46 	}
       
    47 
       
    48 
       
    49 //*************************************************************************************
       
    50 void CASSrvAlarmTimer::ConstructL()
       
    51 	{
       
    52 	CTimer::ConstructL();
       
    53 	ServerData().Queue().NotificationPoolChangeL(*this);
       
    54 	}
       
    55 
       
    56 
       
    57 //*************************************************************************************
       
    58 CASSrvAlarmTimer* CASSrvAlarmTimer::NewL(CASSrvServerWideData& aServerWideData)
       
    59 	{
       
    60 	CASSrvAlarmTimer* self = new(ELeave) CASSrvAlarmTimer(aServerWideData);
       
    61 	CleanupStack::PushL(self);
       
    62 	self->ConstructL();
       
    63 	CleanupStack::Pop(self);
       
    64 	return self;
       
    65 	}
       
    66 
       
    67 
       
    68 //
       
    69 //
       
    70 //
       
    71 
       
    72 
       
    73 //*************************************************************************************
       
    74 /**
       
    75  * Request notifications when an alarm expires
       
    76  */
       
    77 void CASSrvAlarmTimer::NotifyAlarmExpiredL(MASSrvAlarmTimerObserver& aObserver)
       
    78 	{
       
    79 	User::LeaveIfError(iNotificationList.InsertInAddressOrder(&aObserver));
       
    80 	}
       
    81 
       
    82 
       
    83 //*************************************************************************************
       
    84 /**
       
    85  * Cancel a previous notification request
       
    86  */
       
    87 void CASSrvAlarmTimer::NotifyAlarmExpiredCancel(MASSrvAlarmTimerObserver& aObserver)
       
    88 	{
       
    89 	TInt index = KErrNotFound;
       
    90 	const TInt error = iNotificationList.FindInAddressOrder(&aObserver, index);
       
    91 	if	(error != KErrNotFound)
       
    92 		iNotificationList.Remove(index);
       
    93 	}
       
    94 
       
    95 
       
    96 //
       
    97 //
       
    98 //
       
    99 
       
   100 
       
   101 //*************************************************************************************
       
   102 /**
       
   103  * @see MASSrvAlarmQueueObserver
       
   104  */
       
   105 void CASSrvAlarmTimer::MAlarmQueueObserverHandleEvent(TASSrvAlarmQueueEvent aEvent, TAlarmId aAlarmId)
       
   106 	{
       
   107 	const TAlarmId previousDueAlarmId = iNextDueAlarmId;
       
   108 
       
   109 	/* There two interesting events that we should look for:
       
   110 	 * Alarm Queue Start Internalize - everything we know is now invalid
       
   111 	 * Alarm Queue Head Item Changed - stop what we are doing, and see if/when
       
   112 	 *   the next alarm is due.
       
   113 	 */
       
   114 	switch (aEvent)
       
   115 		{
       
   116 	case EASSrvAlarmQueueEventAlarmStartInternalize:
       
   117 		// stop processing alarm queue, (until a new head alarm appears)
       
   118 		Cancel();
       
   119 		// RunL could have started already (it waits for an Access Token)
       
   120 		// and would be processing an invalid head alarm!
       
   121 		iInvalidatedByInternalize = ETrue;
       
   122 		break;
       
   123 
       
   124 	case EASSrvAlarmQueueEventHeadItemChanged:
       
   125 		{
       
   126 	// The next alarm has changed.
       
   127 	Cancel();
       
   128 
       
   129 		// head alarm is valid
       
   130 		iInvalidatedByInternalize = EFalse;
       
   131 
       
   132 	// Set ourselves up for the next alarm, assuming there is one.
       
   133 	CASSrvAlarmQueue& queue = ServerData().Queue();
       
   134 	const TASSrvAlarm* nextDueAlarm = queue.HeadAlarm();
       
   135 	if	(nextDueAlarm && aAlarmId != KNullAlarmId)
       
   136 		{
       
   137 		__ASSERT_DEBUG(nextDueAlarm->Id() != KNullAlarmId, ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicQueueAlarmIdNull));
       
   138 		
       
   139 		// Convert alarm time to local time
       
   140 		TTime dueTime = nextDueAlarm->NextDueTime();
       
   141 		
       
   142 		// Get current time
       
   143 		const TTime now(ASSrvStaticUtils::UtcTimeNow());
       
   144 		
       
   145 		// Expire now (if the alarm is in the past), or when the alarm
       
   146 		// is really due (if it's in the future).
       
   147 		TTime t = dueTime > now? dueTime : now;
       
   148 
       
   149 
       
   150 		AtUTC(t);					
       
   151 
       
   152 		// Update next due alarm id and original due time
       
   153 		iOriginalExpiryTimeForAlarm = dueTime;
       
   154 		iNextDueAlarmId = aAlarmId;
       
   155 		}
       
   156 		}
       
   157 		break;
       
   158 
       
   159 	default: // don't care about other events
       
   160 		return;
       
   161 		}
       
   162 
       
   163 	// Notify change
       
   164 	if	(iNextDueAlarmId != previousDueAlarmId)
       
   165 		ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventHeadQueueItemChanged, iNextDueAlarmId);
       
   166 	}
       
   167 
       
   168 
       
   169 //
       
   170 //
       
   171 //
       
   172 
       
   173 
       
   174 //*************************************************************************************
       
   175 /**
       
   176  * @see CActive
       
   177  */
       
   178 void CASSrvAlarmTimer::RunL()
       
   179 	{
       
   180 	// Cache this, so that notifications can queue the next alarm with the
       
   181 	// timer.
       
   182 	const TAlarmId justExpiredAlarmId = iNextDueAlarmId;
       
   183 
       
   184 	// Set this back to KNullAlarmId indicating that we don't (yet) have another
       
   185 	// alarm to notify about. We must do this just in case there aren't any more
       
   186 	// suitable alarms in the queue, otherwise we will always indicate that we
       
   187 	// are notifying about an (already) notified alarm.
       
   188 	iNextDueAlarmId = KNullAlarmId;
       
   189 
       
   190 	// check that Internalize hasn't invalidated the head alarm
       
   191 	if (!iInvalidatedByInternalize && (iNextDueAlarmId == KNullAlarmId))
       
   192 		{
       
   193 	const TInt errorStatus = iStatus.Int();
       
   194 	switch(errorStatus)
       
   195 		{
       
   196 	// Time changed - RChangeNotifier for time changes only used if no alarm is set.
       
   197 	case KErrAbort:
       
   198 		NotifyEvent(MASSrvAlarmTimerObserver::EAlarmTimerEventTimeOrDateChanged, KNullAlarmId);
       
   199 		break;
       
   200 	
       
   201 	// Ignore times set in the past
       
   202 	case KErrUnderflow:
       
   203 	case KErrNone:
       
   204 			if (!iInvalidatedByInternalize)
       
   205 		NotifyEvent(MASSrvAlarmTimerObserver::EAlarmTimerEventAlarmExpired, justExpiredAlarmId);
       
   206 		break;
       
   207 
       
   208 	// No timer reset if the date is close to the overflow range. 
       
   209 	// This means that agenda will not get notified of time changes
       
   210 	case KErrOverflow:
       
   211 
       
   212 	// Fall through to error handler
       
   213 	default:
       
   214 		HandleTimerError(justExpiredAlarmId, errorStatus);
       
   215 		NotifyEvent(MASSrvAlarmTimerObserver::EAlarmTimerEventTimingError, justExpiredAlarmId);
       
   216 		break;
       
   217 		}
       
   218 
       
   219 	// Notify change
       
   220 	ServerData().AnyEventManager().MASAnyEventManagerObserverNotifyChanges(EAlarmChangeEventTimerExpired, justExpiredAlarmId);
       
   221 		}
       
   222 	}
       
   223 
       
   224 
       
   225 //*************************************************************************************
       
   226 /**
       
   227  * @see CActive
       
   228  */
       
   229 void CASSrvAlarmTimer::Cancel()
       
   230 	{
       
   231 	CTimer::Cancel();
       
   232 	//
       
   233 	iNextDueAlarmId = KNullAlarmId;
       
   234 	iOriginalExpiryTimeForAlarm = Time::NullTTime();
       
   235 	}
       
   236 
       
   237 
       
   238 //*************************************************************************************
       
   239 /**
       
   240  * @see CActive
       
   241  */
       
   242 TInt CASSrvAlarmTimer::RunError(TInt /*aError*/)
       
   243 	{
       
   244 	// Ignore erorrs
       
   245 	return KErrNone;
       
   246 	}
       
   247 
       
   248 
       
   249 //
       
   250 //
       
   251 //
       
   252 
       
   253 
       
   254 //*************************************************************************************
       
   255 /**
       
   256  * Notify observers about the specified event
       
   257  */
       
   258 void CASSrvAlarmTimer::NotifyEvent(MASSrvAlarmTimerObserver::TAlarmTimerEvent aEvent, TAlarmId aId)
       
   259 	{
       
   260   	for(TInt i=iNotificationList.Count(); i>0; --i)
       
   261    		// Notify observers
       
   262 		// TASSrvAlarm::MATimerHandleAlarmExpired() removes itself from the list
       
   263    		iNotificationList[i-1]->MATimerHandleAlarmExpired(aEvent, aId);
       
   264 	}
       
   265 
       
   266 
       
   267 //*************************************************************************************
       
   268 /**
       
   269  * Handle an error returned in CTimer::iStatus 
       
   270  */
       
   271 void CASSrvAlarmTimer::HandleTimerError(TAlarmId aIdOfJustExpiredAlarm, TInt aErrorCode)
       
   272 	{
       
   273 	CASSrvAlarmQueue& queue = ServerData().Queue();
       
   274 	TASSrvAlarm* expiredAlarm = queue.QueueAlarmById(aIdOfJustExpiredAlarm);
       
   275 	expiredAlarm->HandleTimerError(aErrorCode);
       
   276 	}