|
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 "ASSrvStaticUtils.h" |
|
17 |
|
18 // System includes |
|
19 |
|
20 // User includes |
|
21 #include "ASShdOpCodes.h" |
|
22 // |
|
23 #include "ASSrvAlarm.h" |
|
24 |
|
25 // Type definitions |
|
26 |
|
27 // Constants |
|
28 const TInt KReturnFirstObjectLessThanSecond = -1; |
|
29 const TInt KReturnFirstObjectGreaterThanSecond = 1; |
|
30 const TInt KReturnObjectsAreEqual = 0; |
|
31 const TInt KNumberOfSecondsInMinute = 60; |
|
32 |
|
33 // Enumerations |
|
34 |
|
35 // Classes referenced |
|
36 |
|
37 |
|
38 // |
|
39 // ----> ASSrvStaticUtils (source) |
|
40 // |
|
41 |
|
42 //************************************************************************************* |
|
43 /** |
|
44 * Validate the alarm. Checks the characteristics applied to the alarm |
|
45 * are valid. |
|
46 */ |
|
47 TInt ASSrvStaticUtils::ValidateAlarm(TASSrvAlarm& aAlarm) |
|
48 { |
|
49 if (aAlarm.Message().Length() < 0 || aAlarm.Message().Length() > KMaxAlarmMessageLength) |
|
50 return KErrArgument; |
|
51 else if (aAlarm.SoundName().Length() < 0 || aAlarm.SoundName().Length() > KMaxAlarmSoundNameLength) |
|
52 return KErrArgument; |
|
53 |
|
54 // Check repeat flags in conjunction with session alarms |
|
55 if (aAlarm.Characteristics().IsSet(EAlarmCharacteristicsSessionSpecific) && aAlarm.RepeatDefinition() != EAlarmRepeatDefintionRepeatOnce) |
|
56 return KErrArgument; |
|
57 |
|
58 const TTimeIntervalSeconds KAllowNoWindow = 0; |
|
59 const TBool KAllowBlanketInThePastOnceOnlyAlarms = ETrue; |
|
60 |
|
61 // The only valid return types are KErrNone (everything is fine) or |
|
62 // KErrLocked (repeat workdays alarm, but no workdays are defined). |
|
63 const TInt error = aAlarm.ValidateAndEnable(KAllowNoWindow, KAllowBlanketInThePastOnceOnlyAlarms); |
|
64 if (!(error == KErrNone || error == KErrLocked)) |
|
65 return error; |
|
66 |
|
67 // Even if the alarm is locked (because there aren't any workdays |
|
68 // defined), its still valid. |
|
69 return KErrNone; |
|
70 } |
|
71 |
|
72 |
|
73 //************************************************************************************* |
|
74 /** |
|
75 * Check that the sound play intervals are valid. Performs basic boundary |
|
76 * checking to ensure that the start time + interval duration does not overlap |
|
77 * with a subsequent definition. |
|
78 * |
|
79 * @return An error value indicating whether or not the array is valid. KErrNone |
|
80 * for a valid array or KErrGeneral if the array is inappropriate. |
|
81 */ |
|
82 TInt ASSrvStaticUtils::ValidateSoundPlayIntervals(RArray<TASSrvAlarmSoundDetails>& aIntervals) |
|
83 { |
|
84 const TUint KOffsetZero = 0; |
|
85 |
|
86 // Sort array of alarm sound details by start time |
|
87 TLinearOrder<TASSrvAlarmSoundDetails> order(ASSrvStaticUtils::CompareSoundPlayIntervalStartTimes); |
|
88 aIntervals.Sort(order); |
|
89 |
|
90 // Compare entries - there must be at least one. |
|
91 const TInt count = aIntervals.Count(); |
|
92 if (!count) |
|
93 return KErrGeneral; |
|
94 |
|
95 // The first item in any array must always have an interval of 0 minutes before |
|
96 // the alarm will sound (i.e. the client will be audibly notified as soon as the |
|
97 // alarm fires). |
|
98 if (aIntervals[0].OffsetInMinutes() != KOffsetZero) |
|
99 return KErrArgument; |
|
100 |
|
101 for(TInt ii=0; ii < count-1; ii++) |
|
102 { |
|
103 const TASSrvAlarmSoundDetails& interval1 = aIntervals[ii]; |
|
104 const TASSrvAlarmSoundDetails& interval2 = aIntervals[ii + 1]; |
|
105 // |
|
106 if (SoundPlayIntervalsOverlap(interval1, interval2)) |
|
107 return KErrGeneral; |
|
108 } |
|
109 |
|
110 return KErrNone; |
|
111 } |
|
112 |
|
113 |
|
114 //************************************************************************************* |
|
115 /** |
|
116 * Fault the server |
|
117 */ |
|
118 void ASSrvStaticUtils::Fault(TASSrvFault aFault) |
|
119 { |
|
120 _LIT(KAlarmServerFault, "ALARMSERVER-FAULT"); |
|
121 User::Panic(KAlarmServerFault, aFault); |
|
122 } |
|
123 |
|
124 |
|
125 //************************************************************************************* |
|
126 /** |
|
127 * Panic the server |
|
128 */ |
|
129 void ASSrvStaticUtils::Panic(TASSrvPanic aPanic) |
|
130 { |
|
131 _LIT(KAlarmServerPanic, "ALARMSERVER-INTERNAL"); |
|
132 User::Panic(KAlarmServerPanic, aPanic); |
|
133 } |
|
134 |
|
135 |
|
136 //************************************************************************************* |
|
137 /** |
|
138 * Compare two alarm categories and return a value indicating which is less. |
|
139 */ |
|
140 TInt ASSrvStaticUtils::CompareCategories(const TAlarmCategory& aCategory1, const TAlarmCategory& aCategory2) |
|
141 { |
|
142 // |
|
143 // Semantics - returns: |
|
144 // |
|
145 // 1) zero, if the two objects are equal |
|
146 // 2) a negative value, if the first object is less than the second. |
|
147 // 3) a positive value, if the first object is greater than the second. |
|
148 // |
|
149 if (aCategory1.iUid < aCategory2.iUid) |
|
150 return KReturnFirstObjectLessThanSecond; |
|
151 else if (aCategory1.iUid > aCategory2.iUid) |
|
152 return KReturnFirstObjectGreaterThanSecond; |
|
153 // |
|
154 return KReturnObjectsAreEqual; |
|
155 } |
|
156 |
|
157 |
|
158 //************************************************************************************* |
|
159 /** |
|
160 * Compare two alarm ids and return a value indicating which is less. |
|
161 */ |
|
162 TInt ASSrvStaticUtils::CompareAlarmIds(const TAlarmId& aId1, const TAlarmId& aId2) |
|
163 { |
|
164 if (aId1 < aId2) |
|
165 return KReturnFirstObjectLessThanSecond; |
|
166 else if (aId1 > aId2) |
|
167 return KReturnFirstObjectGreaterThanSecond; |
|
168 // |
|
169 return KReturnObjectsAreEqual; |
|
170 } |
|
171 |
|
172 |
|
173 //************************************************************************************* |
|
174 /** |
|
175 * Compare two alarms and return a value indicating which is less. |
|
176 */ |
|
177 TInt ASSrvStaticUtils::CompareAlarms(const TASSrvAlarm& aAlarm1, const TASSrvAlarm& aAlarm2) |
|
178 { |
|
179 if (aAlarm1.NextDueTime() < aAlarm2.NextDueTime()) |
|
180 { |
|
181 return KReturnFirstObjectLessThanSecond; |
|
182 } |
|
183 else if (aAlarm1.NextDueTime() > aAlarm2.NextDueTime()) |
|
184 { |
|
185 return KReturnFirstObjectGreaterThanSecond; |
|
186 } |
|
187 // If you're reading this comment in the year 2141 and you've been adding an |
|
188 // alarm every second since 2005, you may begin to experience problems as we are |
|
189 // now making the assumption that the alarm id counter will never roll-over. |
|
190 return ASSrvStaticUtils::CompareAlarmIds(aAlarm1.Id(), aAlarm2.Id()); |
|
191 } |
|
192 |
|
193 |
|
194 //************************************************************************************* |
|
195 /** |
|
196 * Compare two alarms and return a boolean if they are the same |
|
197 */ |
|
198 TBool ASSrvStaticUtils::CompareAlarmsExact(const TASSrvAlarm& aAlarm1, const TASSrvAlarm& aAlarm2) |
|
199 { |
|
200 return (CompareAlarmIds(aAlarm1.Id(), aAlarm2.Id()) == KReturnObjectsAreEqual); |
|
201 } |
|
202 |
|
203 |
|
204 //************************************************************************************* |
|
205 /** |
|
206 * Return the version of the Alarm Server |
|
207 */ |
|
208 TVersion ASSrvStaticUtils::ASVersion() |
|
209 { |
|
210 return TVersion(KAlarmServerMajorVN, KAlarmServerMinorVN, KAlarmServerBuildVN); |
|
211 } |
|
212 |
|
213 |
|
214 //************************************************************************************* |
|
215 /** |
|
216 * Return the name of the Alarm Server |
|
217 */ |
|
218 const TDesC& ASSrvStaticUtils::ASName() |
|
219 { |
|
220 return KAlarmServerName; |
|
221 } |
|
222 |
|
223 |
|
224 //************************************************************************************* |
|
225 /** |
|
226 * Rounds any time down to the minute |
|
227 */ |
|
228 void ASSrvStaticUtils::RoundTimeDownToTheMinute(TTime& aTime) |
|
229 { |
|
230 TDateTime time(aTime.DateTime()); |
|
231 time.SetSecond(0); |
|
232 time.SetMicroSecond(0); |
|
233 aTime = time; |
|
234 } |
|
235 |
|
236 |
|
237 //************************************************************************************* |
|
238 /** |
|
239 * Panic the client |
|
240 */ |
|
241 void ASSrvStaticUtils::PanicClient(const RMessage2& aMessage, TAlarmServerInitiatedClientPanic aPanic) |
|
242 { |
|
243 _LIT(KServerIntiatedSessionPanic, "ALARMSERVER"); |
|
244 aMessage.Panic(KServerIntiatedSessionPanic, aPanic); |
|
245 } |
|
246 |
|
247 |
|
248 //************************************************************************************* |
|
249 /** |
|
250 * Return the current utc time, to the nearest second |
|
251 */ |
|
252 TTime ASSrvStaticUtils::UtcTimeNow() |
|
253 { |
|
254 TTime NowInUTC; |
|
255 NowInUTC.UniversalTime(); |
|
256 TDateTime dateTime(NowInUTC.DateTime()); |
|
257 dateTime.SetMicroSecond(0); // Remove microsecond element. |
|
258 NowInUTC = dateTime; |
|
259 return NowInUTC; |
|
260 } |
|
261 |
|
262 //************************************************************************************* |
|
263 /** |
|
264 * Return the current local time, to the nearest second |
|
265 */ |
|
266 TTime ASSrvStaticUtils::LocalTimeNow() |
|
267 { |
|
268 TTime now; |
|
269 now.HomeTime(); |
|
270 TDateTime dateTime(now.DateTime()); |
|
271 dateTime.SetMicroSecond(0); |
|
272 return dateTime; |
|
273 } |
|
274 |
|
275 //************************************************************************************* |
|
276 /** |
|
277 * Return (via reference) today's date at the specified time. |
|
278 */ |
|
279 void ASSrvStaticUtils::TodayAtTheSpecifiedTime(const TTime& aTime, TTime& aReturn) |
|
280 { |
|
281 // Reset the cycle and sound state ready to start playing |
|
282 const TDateTime todaysDate = ASSrvStaticUtils::UtcTimeNow().DateTime(); |
|
283 TDateTime baselineDateTime = aTime.DateTime(); |
|
284 // |
|
285 baselineDateTime.SetYear(todaysDate.Year()); |
|
286 baselineDateTime.SetMonth(todaysDate.Month()); |
|
287 baselineDateTime.SetDay(todaysDate.Day()); |
|
288 baselineDateTime.SetMicroSecond(0); |
|
289 aReturn = baselineDateTime; |
|
290 } |
|
291 |
|
292 |
|
293 //************************************************************************************* |
|
294 /** |
|
295 * Internalize the sound play intervals from the specified stream and return |
|
296 * them on the cleanup stack. |
|
297 */ |
|
298 RArray<TASSrvAlarmSoundDetails>* ASSrvStaticUtils::InternalizeSoundPlayIntervalsLC(RReadStream& aStream) |
|
299 { |
|
300 const TInt count = aStream.ReadInt32L(); |
|
301 if (!count) |
|
302 User::Leave(KErrArgument); |
|
303 // |
|
304 RArray<TASSrvAlarmSoundDetails>* newIntervals = new(ELeave) RArray<TASSrvAlarmSoundDetails>(count); |
|
305 CleanupStack::PushL(TCleanupItem(ASSrvStaticUtils::CleanupCloseDeleteSoundDetailsArray, newIntervals)); |
|
306 // |
|
307 for(TInt i=0; i<count; i++) |
|
308 { |
|
309 const TUint offset = aStream.ReadUint32L(); |
|
310 const TUint duration = aStream.ReadUint32L(); |
|
311 // |
|
312 User::LeaveIfError(newIntervals->Append(TASSrvAlarmSoundDetails(offset, duration))); |
|
313 } |
|
314 // |
|
315 return newIntervals; |
|
316 } |
|
317 //************************************************************************************* |
|
318 /** |
|
319 This method will return a descriptor created in such a way that |
|
320 it holds the path to the directory containing the Alarm Servers private data. |
|
321 */ |
|
322 void ASSrvStaticUtils::GetPrivateDirL(RFs& aFsSession, TDes& aDirName) |
|
323 { |
|
324 //Sets the session path to the process's private directory |
|
325 User::LeaveIfError(aFsSession.PrivatePath(aDirName)); |
|
326 //Alarmserver.ini is supposed to be on drive C: |
|
327 TDriveName driveName(TDriveUnit(EDriveC).Name()); |
|
328 aDirName.Insert(0,driveName); //drive name goes before the path |
|
329 } |
|
330 |
|
331 //************************************************************************************* |
|
332 /** |
|
333 This method will return a descriptor created in such a way that |
|
334 it holds the whole search path to the Alarmserver.ini file. |
|
335 */ |
|
336 void ASSrvStaticUtils::GetServerPathL(RFs& aFsSession, TDes& aFileName) |
|
337 { |
|
338 //Sets the session path to the process's private directory on C: |
|
339 GetPrivateDirL(aFsSession, aFileName); |
|
340 aFileName.Append(KAlarmServerBackupFile); //filename goes after the path |
|
341 } |
|
342 |
|
343 //************************************************************************************* |
|
344 /** |
|
345 * Calculate days until the next active alarm day. |
|
346 */ |
|
347 void ASSrvStaticUtils::DaysUntilNextActiveAlarmDay( |
|
348 TTimeIntervalDays& aDaysFromNow, |
|
349 TTimeIntervalDays& aRollOverDays, |
|
350 TDay aCurrentDayInWeek, |
|
351 TUint aActiveDays) |
|
352 { |
|
353 TInt daysToAddFromNow = 7; |
|
354 TInt daysForRollOver = 0; |
|
355 |
|
356 for(TInt i=6; i>=0; --i) |
|
357 { |
|
358 daysForRollOver = daysToAddFromNow; |
|
359 |
|
360 const TInt day = (aCurrentDayInWeek + i) % 7; |
|
361 const TInt dayMask = (1 << day); |
|
362 |
|
363 if (dayMask & aActiveDays) |
|
364 { |
|
365 daysToAddFromNow = i; |
|
366 } |
|
367 } |
|
368 |
|
369 aDaysFromNow = daysToAddFromNow; |
|
370 aRollOverDays = daysForRollOver; |
|
371 } |
|
372 |
|
373 |
|
374 //************************************************************************************* |
|
375 /** |
|
376 * Update the specified alarm for next 24 hours repeat. Depending on the current |
|
377 * time the alarm may repeat within the next day, or it may repeat tomorrow. |
|
378 */ |
|
379 void ASSrvStaticUtils::CalculateNext24HoursRepeat(TASShdAlarm& aAlarm, TTimeIntervalSeconds aAllowableWindow) |
|
380 { |
|
381 __ASSERT_DEBUG(aAlarm.RepeatDefinition() == EAlarmRepeatDefintionRepeatNext24Hours, ASSrvStaticUtils::Panic(ASSrvStaticUtils::EASSrvPanicInvalidAlarmRepeat)); |
|
382 |
|
383 // Get the current due time. |
|
384 const TDateTime alarmTimeAsDateTime = aAlarm.NextDueTime().DateTime(); |
|
385 |
|
386 // Get the current time. |
|
387 TTime timeNow(UtcTimeNow()); |
|
388 |
|
389 // Set the new due time. |
|
390 TDateTime nextDueTimeAsDateTime = timeNow.DateTime(); // Take the current date. |
|
391 nextDueTimeAsDateTime.SetHour(alarmTimeAsDateTime.Hour()); |
|
392 nextDueTimeAsDateTime.SetMinute(alarmTimeAsDateTime.Minute()); |
|
393 nextDueTimeAsDateTime.SetSecond(0); |
|
394 nextDueTimeAsDateTime.SetMicroSecond(0); |
|
395 |
|
396 TTime nextDueTime(nextDueTimeAsDateTime); |
|
397 |
|
398 // Allow for the startup window. This ensures that any alarm which causes the |
|
399 // device to be brought out of standby isn't silently ignored. |
|
400 timeNow -= aAllowableWindow; |
|
401 |
|
402 // If the due time has passed then set it for the next day. |
|
403 if (nextDueTime < timeNow) |
|
404 { |
|
405 nextDueTime += TTimeIntervalDays(1); |
|
406 } |
|
407 // |
|
408 aAlarm.NextDueTime()=nextDueTime; |
|
409 } |
|
410 |
|
411 |
|
412 //************************************************************************************* |
|
413 /** |
|
414 * Cleanup an RArray<TAlarmId>* |
|
415 */ |
|
416 void ASSrvStaticUtils::CleanupCloseDeleteAlarmIdArray(TAny* aArray) |
|
417 { |
|
418 RArray<TAlarmId>* array = reinterpret_cast<RArray<TAlarmId>*>(aArray); |
|
419 array->Close(); |
|
420 delete array; |
|
421 } |
|
422 |
|
423 |
|
424 //************************************************************************************* |
|
425 /** |
|
426 * Cleanup an RArray<TAlarmCategory>* |
|
427 */ |
|
428 void ASSrvStaticUtils::CleanupCloseDeleteCategoryArray(TAny* aArray) |
|
429 { |
|
430 RArray<TAlarmCategory>* array = reinterpret_cast<RArray<TAlarmCategory>*>(aArray); |
|
431 array->Close(); |
|
432 delete array; |
|
433 } |
|
434 |
|
435 |
|
436 //************************************************************************************* |
|
437 /** |
|
438 * Cleanup an RArray<TASSrvAlarmSoundDetails>* |
|
439 */ |
|
440 void ASSrvStaticUtils::CleanupCloseDeleteSoundDetailsArray(TAny* aArray) |
|
441 { |
|
442 RArray<TASSrvAlarmSoundDetails>* array = reinterpret_cast<RArray<TASSrvAlarmSoundDetails>*>(aArray); |
|
443 array->Close(); |
|
444 delete array; |
|
445 } |
|
446 |
|
447 |
|
448 // |
|
449 // |
|
450 // |
|
451 |
|
452 |
|
453 //************************************************************************************* |
|
454 /** |
|
455 * Compare two alarm sound play interval start times and return a value indicating which is less. |
|
456 */ |
|
457 TInt ASSrvStaticUtils::CompareSoundPlayIntervalStartTimes(const TASSrvAlarmSoundDetails& aAlarmSound1, const TASSrvAlarmSoundDetails& aAlarmSound2) |
|
458 { |
|
459 if (aAlarmSound1.OffsetInMinutes() < aAlarmSound2.OffsetInMinutes()) |
|
460 return KReturnFirstObjectLessThanSecond; |
|
461 else if (aAlarmSound1.OffsetInMinutes() > aAlarmSound2.OffsetInMinutes()) |
|
462 return KReturnFirstObjectGreaterThanSecond; |
|
463 // |
|
464 return KReturnObjectsAreEqual; |
|
465 } |
|
466 |
|
467 |
|
468 //************************************************************************************* |
|
469 /** |
|
470 * Compare two alarm sound play intervals return ETrue if they overlap, else EFalse. |
|
471 */ |
|
472 TBool ASSrvStaticUtils::SoundPlayIntervalsOverlap(const TASSrvAlarmSoundDetails& aDetails1, const TASSrvAlarmSoundDetails& aDetails2) |
|
473 { |
|
474 TInt offsetInSeconds = aDetails1.OffsetInMinutes() * KNumberOfSecondsInMinute; |
|
475 offsetInSeconds += aDetails1.DurationInSeconds(); |
|
476 // |
|
477 const TInt offsetOfOtherItemInSeconds = aDetails2.OffsetInMinutes() * KNumberOfSecondsInMinute; |
|
478 // |
|
479 return (offsetInSeconds > offsetOfOtherItemInSeconds); |
|
480 } |
|
481 |
|
482 |