|
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 // Implements the CSmsEventLogerClass |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @file |
|
20 */ |
|
21 |
|
22 #include "smsulog.h" |
|
23 #include "smsumain.h" |
|
24 #include "smsstacklog.h" |
|
25 #include "gsmubuf.h" |
|
26 #include "Gsmumsg.h" |
|
27 #include "Gsmuelem.h" |
|
28 #include <logwrap.h> |
|
29 #include <logwraplimits.h> |
|
30 |
|
31 |
|
32 /** |
|
33 * Allocates and creates a logger. |
|
34 * |
|
35 * @param aFs File server handle |
|
36 * @param aPriority Active object priority |
|
37 * @return New CSmsEventLogger object |
|
38 * @capability None |
|
39 */ |
|
40 EXPORT_C CSmsEventLogger* CSmsEventLogger::NewL(RFs& aFs,TInt aPriority) |
|
41 { |
|
42 LOGSMSU1("CSmsEventLogger::NewL()"); |
|
43 |
|
44 CSmsEventLogger* smseventlogger = new(ELeave) CSmsEventLogger(aPriority); |
|
45 CleanupStack::PushL(smseventlogger); |
|
46 smseventlogger->ConstructL(aFs); |
|
47 CleanupStack::Pop(); |
|
48 return smseventlogger; |
|
49 } // CSmsEventLogger::NewL |
|
50 |
|
51 |
|
52 /** |
|
53 * Destructor. |
|
54 * @capability None |
|
55 */ |
|
56 EXPORT_C CSmsEventLogger::~CSmsEventLogger() |
|
57 { |
|
58 Cancel(); |
|
59 delete iLogEvent; |
|
60 delete iLogWrapper; |
|
61 } // CSmsEventLogger::~CSmsEventLogger |
|
62 |
|
63 |
|
64 /** |
|
65 * Adds an event to the log database. |
|
66 * |
|
67 * @param aStatus Asynchronous status word to signal when the operation is complete |
|
68 * @param aSmsMessage The SMS message that the event concerns |
|
69 * @param aData SMS PDU information for the event |
|
70 * @param aStatusId Optional string to include in the log message, specified by |
|
71 * resource ID |
|
72 * @capability WriteUserData |
|
73 */ |
|
74 EXPORT_C void CSmsEventLogger::AddEvent(TRequestStatus& aStatus,const CSmsMessage& aSmsMessage,const TLogSmsPduData& aData,TInt* aStatusId) |
|
75 { |
|
76 LOGSMSU1("CSmsEventLogger::AddEvent"); |
|
77 |
|
78 __ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState)); |
|
79 |
|
80 iState=ESmsEventLoggerAddingEvent; |
|
81 |
|
82 Queue(aStatus); |
|
83 |
|
84 iSmsPDUData=aData; |
|
85 iSmsPDUData.iType=aSmsMessage.Type(); |
|
86 |
|
87 TRAPD(ret,DoAddEventL(aSmsMessage,aStatusId)); |
|
88 if (ret!=KErrNone) |
|
89 { |
|
90 CompleteMyself(ret); |
|
91 } |
|
92 else |
|
93 { |
|
94 iLogWrapper->Log().AddEvent(*iLogEvent,iStatus); |
|
95 SetActive(); |
|
96 } |
|
97 } // CSmsEventLogger::AddEvent |
|
98 |
|
99 |
|
100 /** |
|
101 * Gets the specified event from the log. |
|
102 * |
|
103 * The event itself can be obtained using a subsequent call to Event(). |
|
104 * |
|
105 * @param aStatus Asynchronous status word to signal when the operation is complete |
|
106 * @param aId Log event ID for the event |
|
107 * @capability ReadUserData |
|
108 */ |
|
109 EXPORT_C void CSmsEventLogger::GetEvent(TRequestStatus& aStatus,TLogId aId) |
|
110 { |
|
111 LOGSMSU1("CSmsEventLogger::GetEvent"); |
|
112 |
|
113 __ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState)); |
|
114 iState=ESmsEventLoggerGettingEvent; |
|
115 Queue(aStatus); |
|
116 iLogEvent->SetId(aId); |
|
117 iLogWrapper->Log().GetEvent(*iLogEvent,iStatus); |
|
118 SetActive(); |
|
119 } // CSmsEventLogger::GetEvent |
|
120 |
|
121 /** Changes the details of an existing event. |
|
122 |
|
123 Use GetEvent() to specify the event. |
|
124 |
|
125 @param aStatus Asynchronous status word to signal when the operation is complete |
|
126 @param aSmsMessage The SMS message that the event concerns |
|
127 @param aTime SMS delivery time |
|
128 @param aData SMS PDU information for the event |
|
129 @param aStatusId Optional string to include in the log message, specified by |
|
130 resource ID |
|
131 @capability WriteUserData |
|
132 */ |
|
133 EXPORT_C void CSmsEventLogger::ChangeEvent(TRequestStatus& aStatus,const CSmsMessage& aSmsMessage, const TTime* aTime, const TLogSmsPduData& aData, TInt* aStatusId) |
|
134 { |
|
135 LOGSMSU1("CSmsEventLogger::ChangeEvent"); |
|
136 |
|
137 __ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState)); |
|
138 __ASSERT_DEBUG(aSmsMessage.LogServerId()==iLogEvent->Id(),SmsuPanic(KSmsuPanicWrongLogServerId)); |
|
139 __ASSERT_DEBUG(iSmsPDUData.iType==aSmsMessage.Type(),SmsuPanic(ESmsuUnexpectedSmsPDUType)); |
|
140 iState=ESmsEventLoggerChangingEvent; |
|
141 Queue(aStatus); |
|
142 iSmsPDUData=aData; |
|
143 iSmsPDUData.iType=aSmsMessage.Type(); |
|
144 |
|
145 TRAPD(ret,SetDataL(aSmsMessage,aStatusId, aTime)); |
|
146 if (ret!=KErrNone) |
|
147 { |
|
148 Complete(ret); |
|
149 } |
|
150 else |
|
151 { |
|
152 iLogWrapper->Log().ChangeEvent(*iLogEvent,iStatus); |
|
153 SetActive(); |
|
154 } |
|
155 } |
|
156 |
|
157 /** |
|
158 * Changes the details of an existing event. |
|
159 * |
|
160 * Use GetEvent() to specify the event. |
|
161 * |
|
162 * @param aStatus Asynchronous status word to signal when the operation is complete |
|
163 * @param aSmsMessage The SMS message that the event concerns |
|
164 * @param aData SMS PDU information for the event |
|
165 * @param aStatusId Optional string to include in the log message, specified by |
|
166 * resource ID |
|
167 * @capability WriteUserData |
|
168 */ |
|
169 EXPORT_C void CSmsEventLogger::ChangeEvent(TRequestStatus& aStatus, const CSmsMessage& aSmsMessage, const TLogSmsPduData& aData, TInt* aStatusId) |
|
170 { |
|
171 ChangeEvent(aStatus, aSmsMessage, NULL, aData, aStatusId); |
|
172 } // CSmsEventLogger::ChangeEvent |
|
173 |
|
174 /** |
|
175 * Deletes an event. |
|
176 * |
|
177 * Use GetEvent() to specify the event. |
|
178 * |
|
179 * @param aStatus Asynchronous status word to signal when the operation is complete |
|
180 * @capability WriteUserData |
|
181 */ |
|
182 EXPORT_C void CSmsEventLogger::DeleteEvent(TRequestStatus& aStatus) |
|
183 { |
|
184 // Ignore in code coverage - not used within the SMS stack. |
|
185 BULLSEYE_OFF |
|
186 LOGSMSU1("CSmsEventLogger::DeleteEvent"); |
|
187 |
|
188 __ASSERT_DEBUG(iState==ESmsEventLoggerIdle,SmsuPanic(KSmsuPanicUnexpectedState)); |
|
189 |
|
190 iState=ESmsEventLoggerDeletingEvent; |
|
191 |
|
192 Queue(aStatus); |
|
193 |
|
194 iLogWrapper->Log().DeleteEvent(iLogEvent->Id(),iStatus); |
|
195 SetActive(); |
|
196 BULLSEYE_RESTORE |
|
197 } |
|
198 |
|
199 void CSmsEventLogger::DoCancel() |
|
200 { |
|
201 // Ignore in code coverage - in order to test would need to cancel |
|
202 // event logger request; as these called when receiving/sending SMS |
|
203 // message would need to cancel these activities during event the |
|
204 // logger request - too difficult to test. Need to add unit test. |
|
205 BULLSEYE_OFF |
|
206 LOGSMSU3("CSmsEventLogger::DoCancel [iStatus=%d, iState=%d]", iStatus.Int(), iState); |
|
207 |
|
208 switch( iState ) |
|
209 { |
|
210 case ESmsEventLoggerGettingEvent: |
|
211 case ESmsEventLoggerAddingEvent: |
|
212 case ESmsEventLoggerChangingEvent: |
|
213 case ESmsEventLoggerDeletingEvent: |
|
214 { |
|
215 iLogWrapper->Log().Cancel(); |
|
216 } break; |
|
217 default: |
|
218 { |
|
219 SmsuPanic(KSmsuPanicUnexpectedState); |
|
220 } break; |
|
221 } |
|
222 // Handle completion of this Active Object. Note that the object |
|
223 // may well still be active at this point... |
|
224 if( TimedOut() ) |
|
225 { |
|
226 Complete(KErrTimedOut); |
|
227 } |
|
228 else |
|
229 { |
|
230 Complete(KErrCancel); |
|
231 } |
|
232 BULLSEYE_RESTORE |
|
233 } |
|
234 |
|
235 CSmsEventLogger::CSmsEventLogger(TInt aPriority): |
|
236 CSmsuActiveBase(aPriority), |
|
237 iState(ESmsEventLoggerIdle) |
|
238 { |
|
239 // NOP |
|
240 } |
|
241 |
|
242 |
|
243 void CSmsEventLogger::ConstructL(RFs& aFs) |
|
244 { |
|
245 LOGSMSU1("CSmsEventLogger::ConstructL()"); |
|
246 |
|
247 iLogWrapper=CLogWrapper::NewL(aFs); |
|
248 iLogEvent=CLogEvent::NewL(); |
|
249 } // CSmsEventLogger::ConstructL |
|
250 |
|
251 |
|
252 void CSmsEventLogger::DoRunL() |
|
253 { |
|
254 LOGSMSU2("CSmsEventLogger::DoRunL [iStatus=%d]", iStatus.Int() ); |
|
255 |
|
256 switch (iState) |
|
257 { |
|
258 case ESmsEventLoggerGettingEvent: |
|
259 { |
|
260 if (iStatus.Int() == KErrNone) |
|
261 { |
|
262 TPckg<TLogSmsPduData> packeddata(iSmsPDUData); |
|
263 packeddata.Copy(iLogEvent->Data()); |
|
264 } |
|
265 } |
|
266 break; |
|
267 |
|
268 case ESmsEventLoggerAddingEvent: |
|
269 case ESmsEventLoggerChangingEvent: |
|
270 case ESmsEventLoggerDeletingEvent: |
|
271 { |
|
272 // NOP |
|
273 } |
|
274 break; |
|
275 |
|
276 default: |
|
277 { |
|
278 User::Leave(KErrGeneral); |
|
279 //SmsuPanic(KSmsuPanicUnexpectedState); |
|
280 } |
|
281 break; |
|
282 } |
|
283 |
|
284 // |
|
285 // DoRunL() will now return to CSmsuActiveBase which if the object |
|
286 // is not active, will call Complete(). |
|
287 // |
|
288 } // CSmsEventLogger::DoRunL |
|
289 |
|
290 |
|
291 void CSmsEventLogger::DoAddEventL(const CSmsMessage& aSmsMessage,TInt* aStatusId) |
|
292 { |
|
293 LOGSMSU2("CSmsEventLogger::DoAddEventL [statusID*=%d]", aStatusId); |
|
294 |
|
295 // Reset event |
|
296 CLogEvent* logevent=CLogEvent::NewL(); |
|
297 delete iLogEvent; |
|
298 iLogEvent=logevent; |
|
299 TBuf<KLogMaxDirectionLength> direction; |
|
300 switch (aSmsMessage.Type()) |
|
301 { |
|
302 // Incoming SMS |
|
303 case CSmsPDU::ESmsDeliver: |
|
304 { |
|
305 LOGSMSU1("DoAddEventL ESmsDeliver"); |
|
306 GetStringL(direction,R_LOG_DIR_IN); |
|
307 break; |
|
308 } |
|
309 case CSmsPDU::ESmsStatusReport: |
|
310 { |
|
311 LOGSMSU1("DoAddEventL ESmsStatusReport"); |
|
312 GetStringL(direction,R_LOG_DIR_IN); |
|
313 break; |
|
314 } |
|
315 // Outgoing SMS |
|
316 case CSmsPDU::ESmsSubmit: |
|
317 { |
|
318 LOGSMSU1("DoAddEventL ESmsSubmit"); |
|
319 GetStringL(direction,R_LOG_DIR_OUT); |
|
320 break; |
|
321 } |
|
322 case CSmsPDU::ESmsCommand: |
|
323 { |
|
324 LOGSMSU1("DoAddEventL ESmsCommand"); |
|
325 GetStringL(direction,R_LOG_DIR_OUT); |
|
326 break; |
|
327 } |
|
328 default: |
|
329 { |
|
330 LOGSMSU1("DoAddEventL ESmsuUnexpectedSmsPDUType"); |
|
331 SmsuPanic(ESmsuUnexpectedSmsPDUType); |
|
332 } |
|
333 } |
|
334 |
|
335 Event().SetDirection(direction); |
|
336 Event().SetEventType(KLogShortMessageEventTypeUid); |
|
337 |
|
338 TGsmSmsTelNumber address; |
|
339 aSmsMessage.ParsedToFromAddress(address); |
|
340 |
|
341 if (address.IsInstanceOf(TGsmSmsTelNumber::EVoiceMessageWaitingIndicator)) |
|
342 { |
|
343 Event().SetNumber(_L("CPHS")); |
|
344 } |
|
345 else |
|
346 { |
|
347 Event().SetNumber(aSmsMessage.ToFromAddress()); |
|
348 } |
|
349 |
|
350 SetDataL(aSmsMessage,aStatusId, NULL); |
|
351 } // CSmsEventLogger::DoAddEventL |
|
352 |
|
353 |
|
354 void CSmsEventLogger::SetDataL(const CSmsMessage& aSmsMessage,TInt* aStatusId, const TTime* aDischargeTime) |
|
355 { |
|
356 |
|
357 __ASSERT_DEBUG(iSmsPDUData.iType==aSmsMessage.Type(),SmsuPanic(ESmsuUnexpectedSmsPDUType)); |
|
358 TBuf<KLogMaxStatusLength> status; |
|
359 #ifdef _DEBUG |
|
360 if (aStatusId!=NULL) |
|
361 LOGSMSU2("CSmsEventLogger::SetDataL StatusID = %d", *aStatusId); |
|
362 #endif |
|
363 if (aStatusId==NULL) |
|
364 { |
|
365 CSmsPDU::TSmsPDUType type=aSmsMessage.Type(); |
|
366 switch (type) |
|
367 { |
|
368 // Incoming SMS |
|
369 case CSmsPDU::ESmsDeliver: |
|
370 { |
|
371 if (iSmsPDUData.iTotal==iSmsPDUData.iReceived) |
|
372 { |
|
373 LOGSMSU1("SetDataL ESmsDeliver R_LOG_DEL_DONE"); |
|
374 GetStringL(status,R_LOG_DEL_DONE); |
|
375 } |
|
376 else if (iSmsPDUData.iTotal>iSmsPDUData.iReceived) |
|
377 { |
|
378 LOGSMSU1("SetDataL ESmsDeliver R_LOG_DEL_PENDING"); |
|
379 GetStringL(status,R_LOG_DEL_PENDING); |
|
380 } |
|
381 break; |
|
382 } |
|
383 case CSmsPDU::ESmsStatusReport: |
|
384 { |
|
385 if (iSmsPDUData.iTotal==iSmsPDUData.iReceived) |
|
386 { |
|
387 LOGSMSU1("SetDataL ESmsStatusReport R_LOG_DEL_DONE"); |
|
388 GetStringL(status,R_LOG_DEL_DONE); |
|
389 } |
|
390 else if (iSmsPDUData.iTotal>iSmsPDUData.iReceived) |
|
391 { |
|
392 LOGSMSU1("SetDataL ESmsStatusReport R_LOG_DEL_PENDING"); |
|
393 GetStringL(status,R_LOG_DEL_PENDING); |
|
394 } |
|
395 break; |
|
396 } |
|
397 // Outgoing SMS |
|
398 case CSmsPDU::ESmsSubmit: |
|
399 case CSmsPDU::ESmsCommand: |
|
400 { |
|
401 TBool statusreportrequest=EFalse; |
|
402 if (type==CSmsPDU::ESmsSubmit) |
|
403 { |
|
404 CSmsSubmit& submit=(CSmsSubmit&) aSmsMessage.SmsPDU(); |
|
405 statusreportrequest=submit.StatusReportRequest(); |
|
406 } |
|
407 else |
|
408 { |
|
409 CSmsCommand& command=(CSmsCommand&) aSmsMessage.SmsPDU(); |
|
410 statusreportrequest=command.StatusReportRequest(); |
|
411 } |
|
412 if (statusreportrequest) |
|
413 { |
|
414 if (iSmsPDUData.iSent==0) |
|
415 { |
|
416 // None sent yet |
|
417 GetStringL(status,R_LOG_DEL_NOT_SENT); |
|
418 LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_NOT_SENT SR"); |
|
419 } |
|
420 else if (iSmsPDUData.iTotal==iSmsPDUData.iDelivered) |
|
421 { |
|
422 // All have been delivered |
|
423 LOGSMSU2("SetDataL ESmsSubmit R_LOG_DEL_DONE SR iSmsPDUData.iDelivered=%d", iSmsPDUData.iDelivered); |
|
424 GetStringL(status,R_LOG_DEL_DONE); |
|
425 } |
|
426 else if (iSmsPDUData.iSent<=iSmsPDUData.iTotal && iSmsPDUData.iFailed==0) |
|
427 { |
|
428 // One or more sent but not all, no failures |
|
429 LOGSMSU3("SetDataL ESmsSubmit R_LOG_DEL_PENDING SR iSmsPDUData.iSent==%d, iSmsPDUData.iTotal==%d, iFailed==0", iSmsPDUData.iSent, iSmsPDUData.iTotal); |
|
430 GetStringL(status,R_LOG_DEL_PENDING); |
|
431 } |
|
432 else |
|
433 { |
|
434 // One or more failures or corruption of iSmsPDUData values |
|
435 LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_FAILED SR"); |
|
436 LOGSMSU3(" Total: %d, Sent: %d",iSmsPDUData.iTotal, iSmsPDUData.iSent ); |
|
437 LOGSMSU3(" Failed: %d, Delivered: %d",iSmsPDUData.iFailed, iSmsPDUData.iDelivered ); |
|
438 GetStringL(status,R_LOG_DEL_FAILED); |
|
439 } |
|
440 if (aDischargeTime != NULL) |
|
441 { |
|
442 iLogEvent->SetTime(*aDischargeTime); |
|
443 } |
|
444 } |
|
445 else |
|
446 { |
|
447 if (iSmsPDUData.iSent<iSmsPDUData.iTotal) |
|
448 { |
|
449 // IF not all PDUs sent, state is "NOT SENT". |
|
450 LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_NOT_SENT NOSR"); |
|
451 LOGSMSU3(" Total: %d, Sent: %d", iSmsPDUData.iTotal, iSmsPDUData.iSent ); |
|
452 GetStringL(status,R_LOG_DEL_NOT_SENT); |
|
453 } |
|
454 else if (iSmsPDUData.iTotal==iSmsPDUData.iSent) |
|
455 { |
|
456 // All sent |
|
457 LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_SENT NOSR"); |
|
458 GetStringL(status,R_LOG_DEL_SENT); |
|
459 } |
|
460 else |
|
461 { |
|
462 // The iSmsPDUData values have become corrupt |
|
463 LOGSMSU1("SetDataL ESmsSubmit R_LOG_DEL_FAILED NOSR"); |
|
464 LOGSMSU3(" Total: %d, Sent: %d",iSmsPDUData.iTotal, iSmsPDUData.iSent ); |
|
465 LOGSMSU3(" Failed: %d, Delivered: %d",iSmsPDUData.iFailed, iSmsPDUData.iDelivered ); |
|
466 GetStringL(status,R_LOG_DEL_FAILED); |
|
467 } |
|
468 } |
|
469 LOGSMSU2("SetDataL [status string=%S]",&status); |
|
470 break; |
|
471 } |
|
472 default: |
|
473 { |
|
474 LOGSMSU1("SetDataL ESmsuUnexpectedSmsPDUType"); |
|
475 SmsuPanic(ESmsuUnexpectedSmsPDUType); |
|
476 } |
|
477 } |
|
478 } |
|
479 else |
|
480 GetStringL(status,*aStatusId); |
|
481 |
|
482 TBuf<KLogMaxSubjectLength> subject; |
|
483 // |
|
484 // EDNAVSA-4VA9FQ Incoming SMSes with special chars are entered in the log as "data messages" |
|
485 // only 8 bit messages are displayed as data message in the log viewer |
|
486 // |
|
487 if (aSmsMessage.SmsPDU().DataCodingSchemePresent() && aSmsMessage.SmsPDU().Alphabet() == TSmsDataCodingScheme::ESmsAlphabet8Bit) |
|
488 { |
|
489 GetStringL(subject, R_LOG_SUBJECT_DATA_MESSAGE); |
|
490 } |
|
491 else if (aSmsMessage.TextPresent()) |
|
492 { |
|
493 const TInt length= Min(KLogMaxSubjectLength, aSmsMessage.Buffer().Length()); |
|
494 aSmsMessage.Buffer().Extract(subject, 0, length); |
|
495 subject.Trim(); |
|
496 } |
|
497 if (subject.Length() == 0) |
|
498 { |
|
499 GetStringL(subject, R_LOG_SUBJECT_NONE); |
|
500 } |
|
501 iLogEvent->SetSubject(subject); |
|
502 |
|
503 iLogEvent->SetStatus(status); |
|
504 TPckg<TLogSmsPduData> packeddata(iSmsPDUData); |
|
505 iLogEvent->SetDataL(packeddata); |
|
506 } // CSmsEventLogger::SetDataL |
|
507 |
|
508 |
|
509 void CSmsEventLogger::DoComplete(TInt& aStatus) |
|
510 { |
|
511 LOGSMSU3("CSmsEventLogger::DoComplete(): aStatus=%d, iState=%d", aStatus, iState); |
|
512 |
|
513 // |
|
514 // Check the state is valid and finish up... |
|
515 // |
|
516 __ASSERT_DEBUG(iState == ESmsEventLoggerGettingEvent || |
|
517 iState == ESmsEventLoggerAddingEvent || |
|
518 iState == ESmsEventLoggerChangingEvent || |
|
519 iState == ESmsEventLoggerDeletingEvent, SmsuPanic(KSmsuPanicUnexpectedState)); |
|
520 |
|
521 aStatus = -aStatus; |
|
522 iState = ESmsEventLoggerIdle; |
|
523 } // CSmsEventLogger::Complete |
|
524 |