|
1 // Copyright (c) 2005-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 |
|
18 // INCLUDE FILES |
|
19 #include <e32base.h> |
|
20 #include <lbs/epos_cposmodules.h> |
|
21 #include <lbs/epos_cposmoduleidlist.h> |
|
22 #include "epos_mposmodulestatuslistener.h" |
|
23 |
|
24 #include "EPos_CPosModulesStatus.h" |
|
25 #include "EPos_Global.h" |
|
26 #include "EPos_ServerPanic.h" |
|
27 |
|
28 // CONSTANTS |
|
29 #ifdef _DEBUG |
|
30 _LIT(KTraceFileName, "EPos_CPosModulesStatus.cpp"); |
|
31 #endif |
|
32 |
|
33 const TInt KParamModuleStatusEvent = 0; |
|
34 const TInt KParamModuleId = 1; |
|
35 |
|
36 const TTimeIntervalMicroSeconds32 KTimerInterval = 5000000; // microseconds |
|
37 const TInt KSequenceNoStartValue = 1; |
|
38 |
|
39 const TInt KStatusInactive = TPositionModuleStatus::EDeviceInactive; |
|
40 const TInt KStatusDisabled = TPositionModuleStatus::EDeviceDisabled; |
|
41 const TInt KStatusError = TPositionModuleStatus::EDeviceError; |
|
42 |
|
43 const TInt KEventInstalled = TPositionModuleStatusEvent::ESystemModuleInstalled; |
|
44 const TInt KEventRemoved = TPositionModuleStatusEvent::ESystemModuleRemoved; |
|
45 const TInt KEventStatus = TPositionModuleStatusEvent::EEventDeviceStatus; |
|
46 const TInt KEventSystem = TPositionModuleStatusEvent::EEventSystemModuleEvent; |
|
47 const TInt KEventQuality = TPositionModuleStatusEvent::EEventDataQualityStatus; |
|
48 |
|
49 |
|
50 // LOCAL FUNCTION PROTOTYPES |
|
51 TBool MatchModuleStatus(const CPosModulesStatus::TPosModule& aFirst, const CPosModulesStatus::TPosModule& aSecond); |
|
52 |
|
53 TIdentityRelation<CPosModulesStatus::TPosModule> moduleMatcher(MatchModuleStatus); |
|
54 |
|
55 TBool MatchSubscriber(const CPosModulesStatus::TPosSubscriber& aFirst, const CPosModulesStatus::TPosSubscriber& aSecond); |
|
56 |
|
57 TIdentityRelation<CPosModulesStatus::TPosSubscriber> subscriberMatcher(MatchSubscriber); |
|
58 |
|
59 TBool EventMatchesRequested(const TPositionModuleStatusEvent& aOccurredEvent, const CPosModulesStatus::TPosSubscriber& aSubscriber); |
|
60 |
|
61 // ==================== LOCAL FUNCTIONS ==================== |
|
62 |
|
63 TBool MatchModuleStatus(const CPosModulesStatus::TPosModule& aFirst, const CPosModulesStatus::TPosModule& aSecond) |
|
64 { |
|
65 return (aFirst.iModuleId == aSecond.iModuleId); |
|
66 } |
|
67 |
|
68 TBool MatchSubscriber(const CPosModulesStatus::TPosSubscriber& aFirst, const CPosModulesStatus::TPosSubscriber& aSecond) |
|
69 { |
|
70 return (aFirst.iClient == aSecond.iClient); |
|
71 } |
|
72 |
|
73 TBool EventMatchesRequested(const TPositionModuleStatusEvent& aOccurredEvent, const CPosModulesStatus::TPosSubscriber& aSubscriber) |
|
74 { |
|
75 // Does module id match? |
|
76 if ((aSubscriber.iModuleId != KPositionNullModuleId) && |
|
77 (aSubscriber.iModuleId != aOccurredEvent.ModuleId())) |
|
78 { |
|
79 return EFalse; |
|
80 } |
|
81 |
|
82 // Does requested event match occurred event? |
|
83 if (!(aSubscriber.iEvent.RequestedEvents() & |
|
84 aOccurredEvent.OccurredEvents())) |
|
85 { |
|
86 return EFalse; |
|
87 } |
|
88 |
|
89 return ETrue; |
|
90 } |
|
91 |
|
92 // ================= MEMBER FUNCTIONS ======================= |
|
93 |
|
94 /** |
|
95 * C++ default constructor. |
|
96 */ |
|
97 CPosModulesStatus::CPosModulesStatus( CPosModules& aModules, const TTimeIntervalMicroSeconds32& aTimerInterval) |
|
98 : iModules(aModules), |
|
99 iSequenceNo(KSequenceNoStartValue), |
|
100 iTimerInterval(aTimerInterval) |
|
101 { |
|
102 } |
|
103 |
|
104 /** |
|
105 * Symbian constructor |
|
106 */ |
|
107 void CPosModulesStatus::ConstructL() |
|
108 { |
|
109 CPosModuleIdList* idList = iModules.ModuleIdListLC(); |
|
110 TInt count = idList->Count(); |
|
111 for (TInt i = 0; i < count; i++) |
|
112 { |
|
113 // Set module id |
|
114 TPosModule module; |
|
115 module.iModuleId = (*idList)[i]; |
|
116 |
|
117 // Set device status |
|
118 TPositionModuleInfo moduleInfo; |
|
119 TRAPD(err, iModules.GetModuleInfoL((*idList)[i], moduleInfo)); |
|
120 if (err == KErrNone) |
|
121 { |
|
122 module.iStatus.SetDeviceStatus( moduleInfo.IsAvailable() ? |
|
123 KStatusInactive : KStatusDisabled); |
|
124 } |
|
125 else |
|
126 { |
|
127 module.iStatus.SetDeviceStatus(KStatusError); |
|
128 } |
|
129 |
|
130 // Store module status |
|
131 User::LeaveIfError(iModuleStatusArray.Append(module)); |
|
132 } |
|
133 CleanupStack::PopAndDestroy(idList); |
|
134 |
|
135 iTimer = CPeriodic::NewL(EPriorityLow); |
|
136 } |
|
137 |
|
138 /** |
|
139 * Two-phased constructor. |
|
140 */ |
|
141 CPosModulesStatus* CPosModulesStatus::NewL(CPosModules& aModules) |
|
142 { |
|
143 return NewL(aModules, KTimerInterval); |
|
144 } |
|
145 |
|
146 /** |
|
147 * Two-phased constructor. |
|
148 */ |
|
149 CPosModulesStatus* CPosModulesStatus::NewL(CPosModules& aModules, const TTimeIntervalMicroSeconds32& aTimerInterval) |
|
150 { |
|
151 CPosModulesStatus* self = new (ELeave) CPosModulesStatus(aModules, aTimerInterval); |
|
152 CleanupStack::PushL(self); |
|
153 self->ConstructL(); |
|
154 CleanupStack::Pop(self); |
|
155 return self; |
|
156 } |
|
157 |
|
158 /** |
|
159 * Destructor. |
|
160 */ |
|
161 CPosModulesStatus::~CPosModulesStatus() |
|
162 { |
|
163 iListenerArray.Close(); |
|
164 iModuleStatusArray.Close(); |
|
165 iSubscribers.Close(); |
|
166 delete iTimer; |
|
167 } |
|
168 |
|
169 /** |
|
170 * From MPosModuleStatusManager |
|
171 */ |
|
172 void CPosModulesStatus::AddListenerL(MPosModuleStatusListener& aListener) |
|
173 { |
|
174 User::LeaveIfError( iListenerArray.Append( &aListener ) ); |
|
175 } |
|
176 |
|
177 /** |
|
178 * From MPosModuleStatusManager |
|
179 */ |
|
180 void CPosModulesStatus::RemoveListener(MPosModuleStatusListener& aListener) |
|
181 { |
|
182 TInt count = iListenerArray.Count(); |
|
183 for ( TInt i = count-1; i >= 0; i-- ) |
|
184 { |
|
185 if ( iListenerArray[i] == &aListener ) |
|
186 { |
|
187 iListenerArray.Remove( i ); |
|
188 } |
|
189 } |
|
190 } |
|
191 |
|
192 |
|
193 /** |
|
194 * From MPosModuleStatusManager |
|
195 */ |
|
196 TInt CPosModulesStatus::GetModuleStatus(const TPositionModuleId& aModuleId, TPositionModuleStatusBase& aStatus) const |
|
197 { |
|
198 if (!(aStatus.PositionClassType() == EPositionModuleStatusClass)) |
|
199 { |
|
200 return KErrNotSupported; |
|
201 } |
|
202 |
|
203 // Set the module status |
|
204 TPositionModuleStatus& status = |
|
205 static_cast<TPositionModuleStatus&>(aStatus); |
|
206 |
|
207 // Find our stored module status |
|
208 TPosModule module; |
|
209 module.iModuleId = aModuleId; |
|
210 TInt index = iModuleStatusArray.Find(module, moduleMatcher); |
|
211 if (index == KErrNotFound) |
|
212 { |
|
213 return KErrNotFound; |
|
214 } |
|
215 |
|
216 TPosModule storedModule = iModuleStatusArray[index]; |
|
217 |
|
218 status.SetDeviceStatus(storedModule.iStatus.DeviceStatus()); |
|
219 status.SetDataQualityStatus(storedModule.iStatus.DataQualityStatus()); |
|
220 |
|
221 return KErrNone; |
|
222 } |
|
223 |
|
224 /** |
|
225 * Requests for status change notification. |
|
226 * |
|
227 * @param aMessage The message that will be completed when the |
|
228 * requested event occurs. The message also contains |
|
229 * all the request information. |
|
230 * @param aClient A pointer to the client that handles the request. |
|
231 */ |
|
232 void CPosModulesStatus::NotifyModuleStatusEventL(const RMessage2& aMessage, TAny* aClient) |
|
233 { |
|
234 TPositionModuleId id; |
|
235 TPositionModuleStatusEvent event; |
|
236 |
|
237 ValidateRequestL(aMessage, id, event); |
|
238 |
|
239 TPosSubscriber subscriber; |
|
240 subscriber.iClient = aClient; |
|
241 |
|
242 // Is the client previously known? |
|
243 TInt index = iSubscribers.Find(subscriber, subscriberMatcher); |
|
244 if (index == KErrNotFound) |
|
245 { |
|
246 subscriber.iToBeRemoved = EFalse; |
|
247 subscriber.iHasRequest = ETrue; |
|
248 subscriber.iMsg = aMessage; |
|
249 subscriber.iModuleId = id; |
|
250 subscriber.iEvent = event; |
|
251 User::LeaveIfError(iSubscribers.Append(subscriber)); |
|
252 } |
|
253 else |
|
254 { |
|
255 TPosSubscriber& storedSubscriber = iSubscribers[index]; |
|
256 if (storedSubscriber.iHasRequest) |
|
257 { |
|
258 iSubscribers.Remove(index); |
|
259 aMessage.Panic(KPosClientFault, EPositionDuplicateRequest); |
|
260 return; |
|
261 } |
|
262 storedSubscriber.iToBeRemoved = EFalse; |
|
263 storedSubscriber.iMsg = aMessage; |
|
264 storedSubscriber.iModuleId = id; |
|
265 storedSubscriber.iEvent = event; |
|
266 if (!HasValidEventsQueued(storedSubscriber)) |
|
267 { |
|
268 storedSubscriber.iHasRequest = ETrue; |
|
269 } |
|
270 } |
|
271 } |
|
272 |
|
273 /** |
|
274 * Cancels a requested status change notification. |
|
275 * |
|
276 * @param aClient A pointer to the client to cancel. |
|
277 */ |
|
278 void CPosModulesStatus::CancelNotifyModuleStatusEventL(TAny* aClient) |
|
279 { |
|
280 TPosSubscriber subscriber; |
|
281 subscriber.iClient = aClient; |
|
282 |
|
283 TInt index = iSubscribers.Find(subscriber, subscriberMatcher); |
|
284 if (index == KErrNotFound) |
|
285 { |
|
286 User::Leave(KErrNotFound); |
|
287 } |
|
288 |
|
289 TPosSubscriber storedSubscriber = iSubscribers[index]; |
|
290 |
|
291 iSubscribers.Remove(index); |
|
292 |
|
293 if (!storedSubscriber.iHasRequest) |
|
294 { |
|
295 User::Leave(KErrNotFound); |
|
296 } |
|
297 |
|
298 RequestComplete(storedSubscriber.iMsg, KErrCancel); |
|
299 } |
|
300 |
|
301 /** |
|
302 * This function is called by a session when it is closed. It panics the |
|
303 * client if it has any open request. A request subscriber to the |
|
304 * closing session is removed. |
|
305 * |
|
306 * @param aClient A pointer to the client to cancel. |
|
307 */ |
|
308 void CPosModulesStatus::NotifySessionClosed(TAny* aClient) |
|
309 { |
|
310 TPosSubscriber subscriber; |
|
311 subscriber.iClient = aClient; |
|
312 |
|
313 TInt index = iSubscribers.Find(subscriber, subscriberMatcher); |
|
314 if (index == KErrNotFound) |
|
315 { |
|
316 return; |
|
317 } |
|
318 |
|
319 TPosSubscriber storedSubscriber = iSubscribers[index]; |
|
320 |
|
321 iSubscribers.Remove(index); |
|
322 |
|
323 if (storedSubscriber.iHasRequest) |
|
324 { |
|
325 storedSubscriber.iMsg.Panic(KPosClientFault, EPositionRequestsNotCancelled); |
|
326 } |
|
327 } |
|
328 |
|
329 /** |
|
330 * Called when a change has been detected in the location settings. |
|
331 * @param aEvent Event information |
|
332 */ |
|
333 void CPosModulesStatus::HandleSettingsChangeL(TPosModulesEvent aEvent) |
|
334 { |
|
335 DEBUG_TRACE("HandleSettingsChange", __LINE__) |
|
336 |
|
337 TPosModule module; |
|
338 module.iModuleId = aEvent.iModuleId; |
|
339 |
|
340 TPositionModuleStatusEvent event; |
|
341 event.SetModuleId(aEvent.iModuleId); |
|
342 |
|
343 switch (aEvent.iType) |
|
344 { |
|
345 case EPosModulesEventModuleInstalled: |
|
346 { |
|
347 module.iStatus.SetDeviceStatus(KStatusInactive); |
|
348 module.iDeviceTimeStamp = iSequenceNo; |
|
349 module.iDataQualityTimeStamp = iSequenceNo++; |
|
350 |
|
351 User::LeaveIfError(iModuleStatusArray.Append(module)); |
|
352 |
|
353 event.SetSystemModuleEvent(KEventInstalled); |
|
354 event.SetOccurredEvents(KEventSystem | KEventStatus); |
|
355 event.SetModuleStatus(module.iStatus); |
|
356 break; |
|
357 } |
|
358 case EPosModulesEventModuleRemoved: |
|
359 { |
|
360 TInt pos = iModuleStatusArray.Find(module, moduleMatcher); |
|
361 if (pos != KErrNotFound) |
|
362 { |
|
363 iModuleStatusArray.Remove(pos); |
|
364 |
|
365 event.SetSystemModuleEvent(KEventRemoved); |
|
366 event.SetOccurredEvents(KEventSystem); |
|
367 } |
|
368 break; |
|
369 } |
|
370 case EPosModulesEventAvailabilityChanged: |
|
371 { |
|
372 TPositionModuleInfo moduleInfo; |
|
373 iModules.GetModuleInfoL(aEvent.iModuleId, moduleInfo); |
|
374 |
|
375 TInt pos = iModuleStatusArray.Find(module, moduleMatcher); |
|
376 if (pos != KErrNotFound) |
|
377 { |
|
378 TPosModule& storedModule = iModuleStatusArray[pos]; |
|
379 |
|
380 if (moduleInfo.IsAvailable() && |
|
381 storedModule.iStatus.DeviceStatus() == KStatusDisabled) |
|
382 { |
|
383 storedModule.iStatus.SetDeviceStatus(KStatusInactive); |
|
384 event.SetOccurredEvents(KEventStatus); |
|
385 } |
|
386 else if (!moduleInfo.IsAvailable() && |
|
387 storedModule.iStatus.DeviceStatus() != KStatusDisabled) |
|
388 { |
|
389 storedModule.iStatus.SetDeviceStatus(KStatusDisabled); |
|
390 event.SetOccurredEvents(KEventStatus); |
|
391 } |
|
392 else |
|
393 { |
|
394 } |
|
395 |
|
396 if (event.OccurredEvents()) |
|
397 { |
|
398 storedModule.iDeviceTimeStamp = iSequenceNo++; |
|
399 event.SetModuleStatus(storedModule.iStatus); |
|
400 } |
|
401 } |
|
402 |
|
403 break; |
|
404 } |
|
405 |
|
406 case EPosModulesEventVisibilityChanged: |
|
407 case EPosModulesEventPrioritiesChanged: |
|
408 case EPosModulesEventCostChanged: |
|
409 break; |
|
410 |
|
411 default: |
|
412 DebugPanic(EPosServerPanicUnexpectedEvent); |
|
413 break; |
|
414 } |
|
415 |
|
416 // Has any event occurred? |
|
417 if (event.OccurredEvents()) |
|
418 { |
|
419 NotifySubscribers(event); |
|
420 NotifyListeners( event ); |
|
421 } |
|
422 } |
|
423 |
|
424 /** |
|
425 * From MPosStatusObserver. |
|
426 * |
|
427 * Reports that the positioner status has changed. |
|
428 * |
|
429 * @param aStatus The new status. |
|
430 */ |
|
431 void CPosModulesStatus::ReportStatus( |
|
432 const TPositionModuleId& aImplementationUid, |
|
433 const TPositionModuleStatus& aStatus) |
|
434 { |
|
435 #ifdef _DEBUG |
|
436 _LIT(KTracePoint, "ReportStatus()"); |
|
437 Global::Trace(KTracePoint, KTraceFileName, __LINE__); |
|
438 #endif |
|
439 |
|
440 TPosModule module; |
|
441 module.iModuleId = aImplementationUid; |
|
442 TInt index = iModuleStatusArray.Find(module, moduleMatcher); |
|
443 if (index == KErrNotFound) |
|
444 { |
|
445 // This should never happen if PSYs are implemented correctly. |
|
446 // Ignore the event. |
|
447 return; |
|
448 } |
|
449 |
|
450 TPosModule& storedModule = iModuleStatusArray[index]; |
|
451 TPositionModuleStatus::TDeviceStatus storedDeviceStatus = |
|
452 storedModule.iStatus.DeviceStatus(); |
|
453 if (storedDeviceStatus == KStatusDisabled) |
|
454 { |
|
455 // Ignore event if module is disabled |
|
456 return; |
|
457 } |
|
458 |
|
459 TPositionModuleStatusEvent event; |
|
460 TPositionModuleStatus::TDeviceStatus newDeviceStatus = |
|
461 aStatus.DeviceStatus(); |
|
462 if (storedDeviceStatus != newDeviceStatus) |
|
463 { |
|
464 storedModule.iStatus.SetDeviceStatus(newDeviceStatus); |
|
465 storedModule.iDeviceTimeStamp = iSequenceNo; |
|
466 event.SetOccurredEvents(KEventStatus); |
|
467 } |
|
468 if (storedModule.iStatus.DataQualityStatus() != |
|
469 aStatus.DataQualityStatus()) |
|
470 { |
|
471 storedModule.iStatus.SetDataQualityStatus(aStatus.DataQualityStatus()); |
|
472 storedModule.iDataQualityTimeStamp = iSequenceNo; |
|
473 event.SetOccurredEvents(KEventQuality | (event.OccurredEvents())); |
|
474 } |
|
475 |
|
476 // Has any event occurred? |
|
477 if (event.OccurredEvents()) |
|
478 { |
|
479 // In order to get the same time stamp on both device status and data |
|
480 // quality status, the counter is not incremented until here. |
|
481 iSequenceNo++; |
|
482 event.SetModuleId(aImplementationUid); |
|
483 event.SetModuleStatus(storedModule.iStatus); |
|
484 NotifySubscribers(event); |
|
485 NotifyListeners( event ); |
|
486 } |
|
487 } |
|
488 |
|
489 /** |
|
490 * Validate request |
|
491 */ |
|
492 void CPosModulesStatus::ValidateRequestL( |
|
493 const RMessage2& aMessage, |
|
494 TPositionModuleId& aId, |
|
495 TPositionModuleStatusEvent& aEvent) |
|
496 { |
|
497 DEBUG_TRACE("ValidateRequestL in", __LINE__); |
|
498 HBufC8* buffer = Global::CopyClientBuffer8LC(aMessage, KParamModuleStatusEvent); |
|
499 |
|
500 // Read module status event |
|
501 const TPositionModuleStatusEventBase* moduleStatusEventBase = |
|
502 reinterpret_cast<const TPositionModuleStatusEventBase*>(buffer->Ptr()); |
|
503 |
|
504 Global::ValidatePositionClassBufferL(*moduleStatusEventBase, buffer->Des()); |
|
505 Global::ValidatePositionClassTypeL(*moduleStatusEventBase, EPositionModuleStatusEventClass); |
|
506 |
|
507 CleanupStack::PopAndDestroy(buffer); |
|
508 |
|
509 DEBUG_TRACE("Reading event object", __LINE__); |
|
510 // Event type is ok so store the client data |
|
511 TPckg<TPositionModuleStatusEvent> eventBuf(aEvent); |
|
512 User::LeaveIfError(Global::Read(aMessage, KParamModuleStatusEvent, eventBuf)); |
|
513 |
|
514 DEBUG_TRACE("Reading module id", __LINE__); |
|
515 // Unpack the module id |
|
516 TPckg<TPositionModuleId> moduleId(aId); |
|
517 User::LeaveIfError(Global::Read(aMessage, KParamModuleId, moduleId)); |
|
518 |
|
519 // Is module id valid? |
|
520 if (aId != KPositionNullModuleId) |
|
521 { |
|
522 TPosModule module; |
|
523 module.iModuleId = aId; |
|
524 |
|
525 TInt index = iModuleStatusArray.Find(module, moduleMatcher); |
|
526 if (index == KErrNotFound) |
|
527 { |
|
528 User::Leave(KErrNotFound); |
|
529 } |
|
530 } |
|
531 DEBUG_TRACE("ValidateRequestL out", __LINE__); |
|
532 } |
|
533 |
|
534 /** |
|
535 * Check if valid event queued |
|
536 */ |
|
537 TBool CPosModulesStatus::HasValidEventsQueued(TPosSubscriber& aSubscriber) |
|
538 { |
|
539 if (aSubscriber.iClientTimeStamp == (iSequenceNo - 1)) |
|
540 { |
|
541 // No event has occurred |
|
542 return EFalse; |
|
543 } |
|
544 |
|
545 if (aSubscriber.iModuleId != KPositionNullModuleId) |
|
546 { |
|
547 // Only one module needs to be checked |
|
548 TPosModule module; |
|
549 module.iModuleId = aSubscriber.iModuleId; |
|
550 TInt index = iModuleStatusArray.Find(module, moduleMatcher); |
|
551 TPosModule storedModule = iModuleStatusArray[index]; |
|
552 |
|
553 TPositionModuleStatusEvent event; |
|
554 if ((aSubscriber.iEvent.RequestedEvents() & KEventStatus) && |
|
555 (storedModule.iDeviceTimeStamp > aSubscriber.iClientTimeStamp)) |
|
556 { |
|
557 event.SetOccurredEvents(KEventStatus); |
|
558 } |
|
559 if ((aSubscriber.iEvent.RequestedEvents() & KEventQuality) && |
|
560 (storedModule.iDataQualityTimeStamp > aSubscriber.iClientTimeStamp)) |
|
561 { |
|
562 event.SetOccurredEvents(KEventQuality | event.OccurredEvents()); |
|
563 } |
|
564 |
|
565 if (event.OccurredEvents()) |
|
566 { |
|
567 aSubscriber.iClientTimeStamp = |
|
568 Max(storedModule.iDeviceTimeStamp, |
|
569 storedModule.iDataQualityTimeStamp); |
|
570 |
|
571 event.SetModuleId(storedModule.iModuleId); |
|
572 event.SetModuleStatus(storedModule.iStatus); |
|
573 |
|
574 NotifyEventToSubscriber(event, aSubscriber); |
|
575 |
|
576 return ETrue; |
|
577 } |
|
578 |
|
579 return EFalse; |
|
580 } |
|
581 |
|
582 // Search all matching modules for lowest time stamp later than client |
|
583 TInt lowestValidTimeStamp = iSequenceNo; |
|
584 TPositionModuleStatusEvent lowestValidEvent; |
|
585 TInt count = iModuleStatusArray.Count(); |
|
586 for (TInt j = 0; j < count; j++) |
|
587 { |
|
588 TPosModule storedModule = iModuleStatusArray[j]; |
|
589 |
|
590 TPositionModuleStatusEvent event; |
|
591 if ((aSubscriber.iEvent.RequestedEvents() & KEventStatus) && |
|
592 (storedModule.iDeviceTimeStamp > aSubscriber.iClientTimeStamp) && |
|
593 (storedModule.iDeviceTimeStamp < lowestValidTimeStamp)) |
|
594 { |
|
595 event.SetOccurredEvents(KEventStatus); |
|
596 lowestValidTimeStamp = storedModule.iDeviceTimeStamp; |
|
597 |
|
598 // Check if data quality status change occurred at the same time |
|
599 if ((aSubscriber.iEvent.RequestedEvents() & KEventQuality) && |
|
600 (storedModule.iDataQualityTimeStamp == storedModule.iDeviceTimeStamp)) |
|
601 { |
|
602 event.SetOccurredEvents(KEventQuality | event.OccurredEvents()); |
|
603 } |
|
604 } |
|
605 |
|
606 if ((aSubscriber.iEvent.RequestedEvents() & KEventQuality) && |
|
607 (storedModule.iDataQualityTimeStamp > aSubscriber.iClientTimeStamp) && |
|
608 (storedModule.iDataQualityTimeStamp < lowestValidTimeStamp)) |
|
609 { |
|
610 event.SetOccurredEvents(KEventQuality); |
|
611 lowestValidTimeStamp = storedModule.iDataQualityTimeStamp; |
|
612 } |
|
613 |
|
614 if (event.OccurredEvents()) |
|
615 { |
|
616 lowestValidEvent = event; |
|
617 |
|
618 lowestValidEvent.SetModuleId(storedModule.iModuleId); |
|
619 lowestValidEvent.SetModuleStatus(storedModule.iStatus); |
|
620 } |
|
621 } |
|
622 |
|
623 if (lowestValidEvent.OccurredEvents()) |
|
624 { |
|
625 aSubscriber.iClientTimeStamp = lowestValidTimeStamp; |
|
626 |
|
627 NotifyEventToSubscriber(lowestValidEvent, aSubscriber); |
|
628 |
|
629 return ETrue; |
|
630 } |
|
631 |
|
632 return EFalse; |
|
633 } |
|
634 |
|
635 /** |
|
636 * Notify subscribers |
|
637 */ |
|
638 void CPosModulesStatus::NotifySubscribers( |
|
639 TPositionModuleStatusEvent& aOccurredEvent) |
|
640 { |
|
641 TInt count = iSubscribers.Count(); |
|
642 for (TInt i = 0; i < count; i++) |
|
643 { |
|
644 TPosSubscriber& subscriber = iSubscribers[i]; |
|
645 if (subscriber.iHasRequest) |
|
646 { |
|
647 if (EventMatchesRequested(aOccurredEvent, subscriber)) |
|
648 { |
|
649 NotifyEventToSubscriber(aOccurredEvent, subscriber); |
|
650 |
|
651 subscriber.iClientTimeStamp = iSequenceNo++; |
|
652 subscriber.iHasRequest = EFalse; |
|
653 subscriber.iToBeRemoved = EFalse; |
|
654 |
|
655 if (!iTimer->IsActive()) |
|
656 { |
|
657 iTimer->Start(iTimerInterval, iTimerInterval, |
|
658 TCallBack(TimerCallback, this)); |
|
659 } |
|
660 } |
|
661 } |
|
662 } |
|
663 } |
|
664 |
|
665 /** |
|
666 * Notify listener |
|
667 */ |
|
668 void CPosModulesStatus::NotifyListeners(TPositionModuleStatusEvent& aOccurredEvent) |
|
669 { |
|
670 TInt count = iListenerArray.Count(); |
|
671 for ( TInt i = 0; i < count; i++ ) |
|
672 { |
|
673 iListenerArray[i]->HandleModuleStatusChanged( |
|
674 aOccurredEvent ); |
|
675 } |
|
676 } |
|
677 |
|
678 /** |
|
679 * Notify event to subscriber |
|
680 */ |
|
681 void CPosModulesStatus::NotifyEventToSubscriber(TPositionModuleStatusEvent& aOccurredEvent, const CPosModulesStatus::TPosSubscriber& aSubscriber) |
|
682 { |
|
683 aOccurredEvent.SetRequestedEvents(aSubscriber.iEvent.RequestedEvents()); |
|
684 |
|
685 DEBUG_TRACE("Writing event object in", __LINE__); |
|
686 // Write back to client |
|
687 TPckgC<TPositionModuleStatusEvent> eventPckg(aOccurredEvent); |
|
688 TInt res = Global::Write(aSubscriber.iMsg, KParamModuleStatusEvent, eventPckg); |
|
689 if (res == KErrNone) |
|
690 { |
|
691 RequestComplete(aSubscriber.iMsg, KErrNone); |
|
692 } |
|
693 DEBUG_TRACE("Writing event object out", __LINE__); |
|
694 } |
|
695 |
|
696 /** |
|
697 * Timer callback |
|
698 */ |
|
699 TInt CPosModulesStatus::TimerCallback(TAny* aModulesStatus) |
|
700 { |
|
701 CPosModulesStatus* moduleStatus = |
|
702 reinterpret_cast<CPosModulesStatus*> (aModulesStatus); |
|
703 return moduleStatus->DoTimerCallback(); |
|
704 } |
|
705 |
|
706 /** |
|
707 * timer callback handler function |
|
708 */ |
|
709 TInt CPosModulesStatus::DoTimerCallback() |
|
710 { |
|
711 TBool timerIsNeeded = EFalse; |
|
712 for (TInt i = iSubscribers.Count() - 1; i >= 0; i--) |
|
713 { |
|
714 TPosSubscriber& subscriber = iSubscribers[i]; |
|
715 if (!subscriber.iHasRequest) |
|
716 { |
|
717 if (subscriber.iToBeRemoved) |
|
718 { |
|
719 iSubscribers.Remove(i); |
|
720 } |
|
721 else |
|
722 { |
|
723 subscriber.iToBeRemoved = ETrue; |
|
724 timerIsNeeded = ETrue; |
|
725 } |
|
726 } |
|
727 } |
|
728 |
|
729 if (!timerIsNeeded) |
|
730 { |
|
731 iTimer->Cancel(); |
|
732 return EFalse; |
|
733 } |
|
734 |
|
735 return ETrue; |
|
736 } |
|
737 |
|
738 /** |
|
739 * Complete request |
|
740 */ |
|
741 void CPosModulesStatus::RequestComplete(const RMessage2& aMessage, TInt aCompleteCode) |
|
742 { |
|
743 if (!aMessage.IsNull()) |
|
744 { |
|
745 aMessage.Complete(aCompleteCode); |
|
746 } |
|
747 } |
|
748 |
|
749 // End of File |