|
1 // Copyright (c) 2002-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 // Contains method implementations for the Active Object classes used by the Phonebook |
|
15 // Synchroniser. |
|
16 // |
|
17 // |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalComponent |
|
22 */ |
|
23 |
|
24 #include "common.h" |
|
25 #include "Phonebook.h" |
|
26 #include "PhonebookManager.h" |
|
27 #include "SyncContactICCEntry.h" |
|
28 #include "phbksynclog.h" |
|
29 #include "phbksyncsvr.h" |
|
30 #include "SyncEngineSession.h" |
|
31 #include "SyncEngineServer.h" |
|
32 #include "phbksyncsess.h" |
|
33 #include "SyncContactsWithICC.h" |
|
34 |
|
35 |
|
36 /** |
|
37 * Number of retries to read the ICC in an ICC multiple read operation. |
|
38 */ |
|
39 const TInt KMaxICCReadRetryCnt = 1; |
|
40 |
|
41 |
|
42 /** |
|
43 * Delay for retry (will be multiplied by an increasing factor). |
|
44 */ |
|
45 const TInt KReadRetryDelayBase = 100000; |
|
46 |
|
47 |
|
48 |
|
49 /** |
|
50 * Static factory method used to create a CSyncContactsWithICC object. |
|
51 * |
|
52 * @param aSession Reference to the engine session. |
|
53 * @param aPhonebookManager Reference to the Phonebook Manager which stores |
|
54 * all the phonebook parameters. |
|
55 * @param aDb Reference to the database. |
|
56 * @param aPhone Handle to the phone object. |
|
57 * @param aPhonebookUid Phonebook UID for the contact to be deleted from. |
|
58 * @param aClientMessage Handle to the engine message request. |
|
59 */ |
|
60 CSyncContactsWithICC* CSyncContactsWithICC::NewL(CSyncEngineSession& aSession, |
|
61 CPhoneBookManager& aPhoneBookManager, |
|
62 CContactDatabase& aDb, |
|
63 RMobilePhone& aPhone, |
|
64 TUid aPhonebookUid, |
|
65 const RMessage2& aClientMessage) |
|
66 { |
|
67 CSyncContactsWithICC* self = new(ELeave) CSyncContactsWithICC(aSession, |
|
68 aPhoneBookManager, |
|
69 aDb, |
|
70 aPhone, |
|
71 aPhonebookUid, |
|
72 aClientMessage); |
|
73 CleanupStack::PushL(self); |
|
74 self->ConstructL(); |
|
75 CleanupStack::Pop(self); |
|
76 |
|
77 return self; |
|
78 } // CSyncContactsWithICC::NewL |
|
79 |
|
80 |
|
81 /** |
|
82 * Standard constructor. |
|
83 * |
|
84 * @param aSession Reference to the engine session. |
|
85 * @param aPhonebookManager Reference to the Phonebook Manager which stores |
|
86 * all the phonebook parameters. |
|
87 * @param aDb Reference to the database. |
|
88 * @param aPhone Handle to the phone object. |
|
89 * @param aPhonebookUid Phonebook UID for the contact to be deleted from. |
|
90 * @param aClientMessage Handle to the engine message request. |
|
91 */ |
|
92 CSyncContactsWithICC::CSyncContactsWithICC(CSyncEngineSession& aSession, |
|
93 CPhoneBookManager& aPhonebookManager, |
|
94 CContactDatabase& aDb, |
|
95 RMobilePhone& aPhone, |
|
96 TUid aPhonebookUid, |
|
97 const RMessage2& aClientMessage) |
|
98 : CActive(EPriorityNormal), |
|
99 iSession(aSession), |
|
100 iPhonebookManager(aPhonebookManager), |
|
101 iDb(aDb), |
|
102 iPhone(aPhone), |
|
103 iPhonebookUid(aPhonebookUid), |
|
104 iClientMessage(aClientMessage), |
|
105 iState(ESyncContactsWithICCStateIdle), |
|
106 iPhonebookDataPtr(NULL,0), |
|
107 iNumOfEntries(1), |
|
108 iSlotNum(1) |
|
109 { |
|
110 // NOP |
|
111 } // CSyncContactsWithICC::CSyncContactsWithICC |
|
112 |
|
113 |
|
114 /** |
|
115 * Standard destructor. This will cancel any pending active requests. |
|
116 */ |
|
117 CSyncContactsWithICC::~CSyncContactsWithICC() |
|
118 { |
|
119 LOGACTIVE1(_L8("~CSyncContactsWithICC()")); |
|
120 |
|
121 Cancel(); |
|
122 |
|
123 delete iPhonebookData; |
|
124 iUnconfirmedEntries.Close(); |
|
125 iTimer.Close(); |
|
126 } // CSyncContactsWithICC::~CSyncContactsWithICC |
|
127 |
|
128 |
|
129 /** |
|
130 * Second phase constructor. |
|
131 */ |
|
132 void CSyncContactsWithICC::ConstructL() |
|
133 { |
|
134 LOGACTIVE1(_L8("CSyncContactsWithICC::ConstructL()")); |
|
135 |
|
136 // |
|
137 // Create the phonebook data buffer. |
|
138 // |
|
139 iPhonebookData = HBufC8::NewL(KPBDataClientHeap); |
|
140 iPhonebookDataPtr.Set(const_cast<unsigned char*>(iPhonebookData->Ptr()), 0, KPBDataClientHeap); |
|
141 |
|
142 // |
|
143 // Obtain a few bits of info now to save time later... |
|
144 // |
|
145 User::LeaveIfError(iPhonebookManager.GetPhoneBookInfo(iPhonebookUid, iPhBkInfo)); |
|
146 User::LeaveIfError(iPhonebookManager.GetPhoneBookStore(iPhonebookUid, iPhone, iPhonebookStore)); |
|
147 |
|
148 // |
|
149 // Create a timer for use later if needed... |
|
150 // |
|
151 iTimer.CreateLocal(); |
|
152 |
|
153 CActiveScheduler::Add(this); |
|
154 } // CSyncContactsWithICC::ConstructL |
|
155 |
|
156 |
|
157 /** |
|
158 * Begin synchronising the ICC phonebook into the Contacts Database. This |
|
159 * function begins the process be ensuring the Look-Up Table is upto date |
|
160 * with the information from the Contacts DB. Any contact entires that are |
|
161 * stored outside the slot range of the ICC (e.g. entries from previous ICCs) |
|
162 * are removed. |
|
163 */ |
|
164 void CSyncContactsWithICC::SyncContactsWithICCL() |
|
165 { |
|
166 LOGACTIVE1(_L8("CSyncContactsWithICC::SyncContactsWithICCL()")); |
|
167 |
|
168 // |
|
169 // Check that we are not in use! |
|
170 // |
|
171 if (iState != ESyncContactsWithICCStateIdle) |
|
172 { |
|
173 PhBkSyncPanic(EPhBkSyncPanicDoMultipleReadError); |
|
174 } |
|
175 |
|
176 // |
|
177 // Fetch all current database entries into the Look-Up Table. Also we |
|
178 // need to delete all entires outside the size of the phonebook. Start by |
|
179 // getting the size of the phonebook and clearing the current table data. |
|
180 // |
|
181 TInt phonebookSize; |
|
182 |
|
183 User::LeaveIfError(iPhonebookManager.GetLookUpTableSize(iPhonebookUid, |
|
184 phonebookSize)); |
|
185 User::LeaveIfError(iPhonebookManager.ClearLookUpTable(iPhonebookUid)); |
|
186 |
|
187 // |
|
188 // Get the Group ID to search for entries. If no ID exists then the |
|
189 // database does not contain any entries. |
|
190 // |
|
191 TContactItemId groupId; |
|
192 |
|
193 User::LeaveIfError(iPhonebookManager.GetGroupId(iPhonebookUid, groupId)); |
|
194 |
|
195 |
|
196 // |
|
197 // Populate the lookup table with entries from the contacts database... |
|
198 // |
|
199 if (groupId != KNullContactId && groupId != KGoldenTemplateId) |
|
200 { |
|
201 CContactItem* group = iDb.ReadContactLC(groupId); |
|
202 const CContactIdArray* members = static_cast<CContactGroup*>(group)->ItemsContained(); |
|
203 const TInt count = members->Count(); |
|
204 |
|
205 TContactTextDefItem iccSlotFieldType(KUidContactFieldICCSlot); |
|
206 CContactTextDef* iccSlotFieldTextDef = CContactTextDef::NewLC(); |
|
207 iccSlotFieldTextDef->AppendL(iccSlotFieldType); |
|
208 |
|
209 for (TInt item = 0; item < count; item++) |
|
210 { |
|
211 // |
|
212 // Read the item from the database and add to the Look-Up Table. |
|
213 // The state is unconfirmed until the synchronisation is complete. |
|
214 // |
|
215 TBuf<KTemplateNumberLength> iccSlotField; |
|
216 |
|
217 iDb.ReadContactTextDefL((*members)[item], iccSlotField, |
|
218 iccSlotFieldTextDef); |
|
219 TLex input(iccSlotField); |
|
220 TInt slotNum = 0; |
|
221 input.Val(slotNum); |
|
222 |
|
223 // |
|
224 // Delete entries that are in slots exceeding the ICC slot range, |
|
225 // otherwise add them to the Look Up Table. |
|
226 // |
|
227 if (slotNum > phonebookSize) |
|
228 { |
|
229 iDb.DeleteContactL((*members)[item]); |
|
230 } |
|
231 else |
|
232 { |
|
233 User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid, |
|
234 slotNum, |
|
235 (*members)[item], |
|
236 ESlotUnconfirmed)); |
|
237 } |
|
238 } |
|
239 |
|
240 CleanupStack::PopAndDestroy(2, group); |
|
241 } |
|
242 |
|
243 // |
|
244 // Now begin the process of reading entries and writting them to the database. |
|
245 // |
|
246 ReadICCEntries(); |
|
247 } // CSyncContactsWithICC::SyncContactsWithICCL |
|
248 |
|
249 |
|
250 /** |
|
251 * Issues a read of one or more ICC entries. |
|
252 */ |
|
253 void CSyncContactsWithICC::ReadICCEntries() |
|
254 { |
|
255 LOGACTIVE1(_L8("CSyncContactsWithICC::ReadICCEntries()")); |
|
256 |
|
257 // |
|
258 // Now issue the ICC read and set the object Active... |
|
259 // |
|
260 iPhonebookStore.Read(iStatus, iSlotNum, 1, iPhonebookDataPtr); |
|
261 iState = ESyncContactsWithICCStateWaitForRead; |
|
262 iDbAccessRetryCount=0; |
|
263 iICCReadRetryCount=0; |
|
264 SetActive(); |
|
265 |
|
266 LOGACTIVETIMESTAMP(); |
|
267 } // CSyncContactsWithICC::ReadICCEntries |
|
268 |
|
269 |
|
270 /** |
|
271 * Standard Active Object RunL() method to process the various sync requests. |
|
272 */ |
|
273 void CSyncContactsWithICC::RunL() |
|
274 { |
|
275 LOGACTIVE2(_L8("CSyncContactsWithICC::RunL() iStatus=%d)"), |
|
276 iStatus.Int()); |
|
277 |
|
278 switch (iState) |
|
279 { |
|
280 case ESyncContactsWithICCStateWaitForRead: |
|
281 { |
|
282 // |
|
283 // If the request was completed, cancelled or no more entries were found... |
|
284 // |
|
285 if (iStatus.Int() == KErrNone || |
|
286 iStatus.Int() == KErrCancel || |
|
287 iStatus.Int() == KErrNotFound) |
|
288 { |
|
289 TInt ret(iStatus.Int()); |
|
290 |
|
291 iICCReadRetryCount=0; |
|
292 |
|
293 // |
|
294 // Now decode received phonebook data and store it in Contacts DB... |
|
295 // |
|
296 TRAPD(decodeErr, DecodeICCAndStoreToDbL(iSlotNum, iReceivedEntries)); |
|
297 if (decodeErr != KErrNone) |
|
298 { |
|
299 iSession.Server().RollbackIccTransaction(); |
|
300 |
|
301 if (iDbAccessRetryCount < KMaxDbAccessRetryCount && |
|
302 (decodeErr == KErrInUse || decodeErr == KErrLocked)) |
|
303 { |
|
304 iDbAccessRetryCount++; |
|
305 LOGACTIVE2(_L8("iDbAccessErrorCount is %d"),iDbAccessRetryCount); |
|
306 |
|
307 iTimer.After(iStatus, KReadRetryDelayBase*iDbAccessRetryCount);//increase the delay each time |
|
308 SetActive(); |
|
309 LOGACTIVETIMESTAMP(); |
|
310 } |
|
311 else |
|
312 { |
|
313 iSession.Server().CompleteDoSync(decodeErr); |
|
314 } |
|
315 |
|
316 return; |
|
317 } |
|
318 |
|
319 iDbAccessRetryCount = 0; // reset the DB retry counter |
|
320 |
|
321 // |
|
322 // Have we finished reading yet? |
|
323 // |
|
324 if ((iPhBkInfo.iUsedEntries < 0 || iReceivedEntries < iPhBkInfo.iUsedEntries) && |
|
325 iSlotNum < iPhBkInfo.iTotalEntries) |
|
326 { |
|
327 // |
|
328 // Increment the slot number and read some more... |
|
329 // |
|
330 iSlotNum++; |
|
331 ReadICCEntries(); |
|
332 } |
|
333 else |
|
334 { |
|
335 // |
|
336 // All entries have been read. It is okay to not find an |
|
337 // entry in the case where the TSY could not tell you how |
|
338 // many entries were used. If there was an error return now. |
|
339 // |
|
340 if (ret != KErrNone && ret != KErrNotFound) |
|
341 { |
|
342 iState = ESyncContactsWithICCStateIdle; |
|
343 iSession.Server().CompleteDoSync(ret); |
|
344 return; |
|
345 } |
|
346 |
|
347 // |
|
348 // Request the list of unconfirmed entries to remove... |
|
349 // |
|
350 TInt result; |
|
351 |
|
352 result = iPhonebookManager.GetMatchingEntries(iPhonebookUid, |
|
353 ESlotUnconfirmed, |
|
354 iUnconfirmedEntries); |
|
355 if (result != KErrNone) |
|
356 { |
|
357 iSession.Server().CompleteDoSync(result); |
|
358 return; |
|
359 } |
|
360 |
|
361 // |
|
362 // Yield and continue processing in the next RunL call. |
|
363 // |
|
364 iState = ESyncContactsWithICCStateRemoveUnconfirmedEntries; |
|
365 YieldToOtherActiveObjects(); |
|
366 } |
|
367 } |
|
368 else |
|
369 { |
|
370 if (iICCReadRetryCount < KMaxICCReadRetryCnt) |
|
371 { |
|
372 iICCReadRetryCount++; |
|
373 iPhonebookDataPtr.Zero(); |
|
374 iPhonebookStore.Read(iStatus, iSlotNum, 1, iPhonebookDataPtr); |
|
375 SetActive(); |
|
376 LOGACTIVETIMESTAMP(); |
|
377 } |
|
378 else |
|
379 { |
|
380 iSession.Server().CompleteDoSync(iStatus.Int()); |
|
381 return; |
|
382 } |
|
383 } |
|
384 } |
|
385 break; |
|
386 |
|
387 case ESyncContactsWithICCStateRemoveUnconfirmedEntries: |
|
388 { |
|
389 // |
|
390 // If we have unconfirmed entries to remove, then delete one of |
|
391 // them before yielding to the scheduler (so we don't spend too |
|
392 // much time in the RunL() in one go). Otherwise we have finished. |
|
393 // |
|
394 if (iUnconfirmedEntries.Count() > 0) |
|
395 { |
|
396 // |
|
397 // Get the contact ID for the entry we are going to delete... |
|
398 // |
|
399 TContactItemId contactId; |
|
400 TInt result; |
|
401 |
|
402 result = iPhonebookManager.GetContactIdFromSlotNum(iPhonebookUid, |
|
403 iUnconfirmedEntries[0], |
|
404 contactId); |
|
405 if (result != KErrNone) |
|
406 { |
|
407 iSession.Server().CompleteDoSync(result); |
|
408 return; |
|
409 } |
|
410 |
|
411 // |
|
412 // Delete the entry... |
|
413 // |
|
414 TRAP(result, iDb.DeleteContactL(contactId)); |
|
415 if (result != KErrNone) |
|
416 { |
|
417 iSession.Server().CompleteDoSync(result); |
|
418 return; |
|
419 } |
|
420 |
|
421 // |
|
422 // Reset the Look-Up Table entry... |
|
423 // |
|
424 result = iPhonebookManager.UpdateEntryInTable(iPhonebookUid, |
|
425 iUnconfirmedEntries[0], |
|
426 KNullContactId, |
|
427 ESlotEmpty); |
|
428 if (result != KErrNone) |
|
429 { |
|
430 iSession.Server().CompleteDoSync(result); |
|
431 return; |
|
432 } |
|
433 |
|
434 // |
|
435 // Remove this entry from the list and yield... |
|
436 // |
|
437 iUnconfirmedEntries.Remove(0); |
|
438 YieldToOtherActiveObjects(); |
|
439 } |
|
440 else |
|
441 { |
|
442 // |
|
443 // Compress the database if needed and we are finished! |
|
444 // |
|
445 if (iDb.CompressRequired()) |
|
446 { |
|
447 TRAP_IGNORE(iDb.CompactL()); |
|
448 } |
|
449 |
|
450 iState = ESyncContactsWithICCStateIdle; |
|
451 |
|
452 iSession.Server().CompleteDoSync(KErrNone); |
|
453 } |
|
454 } |
|
455 break; |
|
456 |
|
457 case ESyncContactsWithICCStateWaitForCancel: |
|
458 { |
|
459 iState = ESyncContactsWithICCStateIdle; |
|
460 iSession.Server().CompleteDoSync(iStatus.Int()); |
|
461 } |
|
462 break; |
|
463 |
|
464 default: |
|
465 { |
|
466 PhBkSyncPanic(EPhBkSyncPanicDoMultipleReadError); |
|
467 } |
|
468 break; |
|
469 } |
|
470 } // CSyncContactsWithICC::RunL |
|
471 |
|
472 |
|
473 /** |
|
474 * Simple function that causes the Active Object to yield to the scheduler |
|
475 * and let any other Active Objects (such as the engine) run if they want. |
|
476 */ |
|
477 void CSyncContactsWithICC::YieldToOtherActiveObjects() |
|
478 { |
|
479 LOGACTIVE1(_L8("CSyncContactsWithICC::YieldToOtherActiveObjects()")); |
|
480 |
|
481 // |
|
482 // Post a dummy request... |
|
483 // |
|
484 iStatus = KRequestPending; |
|
485 SetActive(); |
|
486 LOGACTIVETIMESTAMP(); |
|
487 |
|
488 // |
|
489 // Now complete the dummy request... |
|
490 // |
|
491 TRequestStatus* reqStatusPtr = &iStatus; |
|
492 |
|
493 User::RequestComplete(reqStatusPtr, KErrNone); |
|
494 } // CSyncContactsWithICC::YieldToOtherActiveObjects |
|
495 |
|
496 |
|
497 /** |
|
498 * Decode the phonebook entries supplied in iPhoneData. The entries are |
|
499 * converted from TLV (Tag-Length-Value) format into the phonebook server internal |
|
500 * (CSyncContactICCEntry) format and then written to the Contacts Database. |
|
501 * Once they are written to the DB, the server's look-up table is updated |
|
502 * accordingly. |
|
503 * |
|
504 * @param aIndex Returns the slot number of the last decoded |
|
505 * phonebook entry. |
|
506 * @param aReceivedEntries Returns the number of the received entries. |
|
507 */ |
|
508 void CSyncContactsWithICC::DecodeICCAndStoreToDbL(TInt& aIndex, |
|
509 TInt& aReceivedEntries) |
|
510 { |
|
511 LOGACTIVE1(_L8("CSyncContactsWithICC::DecodeICCAndStoreToDbL()")); |
|
512 |
|
513 TBuf16<KPBDataClientBuf> buffer; |
|
514 TPtrC16 bufPtr(buffer); |
|
515 |
|
516 TUint8 tagValue(0); |
|
517 TInt entryCount(0); |
|
518 CPhoneBookBuffer::TPhBkTagType dataType; |
|
519 |
|
520 TBool isAdditionalNumber(EFalse); // Used to indicate beginning of an Additional Number |
|
521 CSyncContactICCEntry::TSyncAdditionalNumber additionalNumber; |
|
522 |
|
523 // |
|
524 // Allocate an ICC Entry... |
|
525 // |
|
526 CSyncContactICCEntry* iccEntry = CSyncContactICCEntry::NewL(); |
|
527 CleanupStack::PushL(iccEntry); |
|
528 |
|
529 // |
|
530 // Create a CPhoneBookBuffer ready to decode the entries... |
|
531 // |
|
532 CPhoneBookBuffer* pbBuffer = new(ELeave) CPhoneBookBuffer(); |
|
533 CleanupStack::PushL(pbBuffer); |
|
534 pbBuffer->Set(&iPhonebookDataPtr); |
|
535 |
|
536 // |
|
537 // Now start decoding the phonebook data received in TLV format... |
|
538 // |
|
539 pbBuffer->StartRead(); |
|
540 |
|
541 while (pbBuffer->GetTagAndType(tagValue, dataType) == KErrNone) |
|
542 { |
|
543 switch (tagValue) |
|
544 { |
|
545 case RMobilePhoneBookStore::ETagPBAdnIndex: |
|
546 { |
|
547 entryCount++; // Don't increment this until we find the index |
|
548 // So that we wait for whole entry to be received |
|
549 TUint16 index; |
|
550 pbBuffer->GetValue(index); |
|
551 iccEntry->iSlotNum = (TInt) index; |
|
552 aIndex = iccEntry->iSlotNum; |
|
553 } |
|
554 break; |
|
555 |
|
556 case RMobilePhoneBookStore::ETagPBTonNpi: |
|
557 { |
|
558 TUint8 tonNpi; |
|
559 |
|
560 pbBuffer->GetValue(tonNpi); |
|
561 if (isAdditionalNumber) |
|
562 { |
|
563 additionalNumber.iTON = ConvertTypeOfNumber(tonNpi); // TON associated with additional number |
|
564 |
|
565 // We have rearched to the end of one additional number. So, |
|
566 // we add the complete additionNumber into the list and set |
|
567 // the flag as EFalse. Note we will get a ETagPBAnrStart for |
|
568 // each additional number. |
|
569 iccEntry->iNumberList->AppendL(additionalNumber); |
|
570 isAdditionalNumber = EFalse; |
|
571 } |
|
572 else |
|
573 { |
|
574 // TON associated with first (default) number |
|
575 iccEntry->iTON = ConvertTypeOfNumber(tonNpi); |
|
576 } |
|
577 } |
|
578 break; |
|
579 |
|
580 case RMobilePhoneBookStore::ETagPBText: |
|
581 { |
|
582 pbBuffer->GetValue(bufPtr); |
|
583 if (isAdditionalNumber) |
|
584 { |
|
585 // For additional number bufPtr contains number alpha string |
|
586 additionalNumber.iNumberString.Copy(bufPtr); |
|
587 } |
|
588 else |
|
589 { |
|
590 iccEntry->iName.Copy(bufPtr); |
|
591 } |
|
592 } |
|
593 break; |
|
594 |
|
595 case RMobilePhoneBookStore::ETagPBSecondName: |
|
596 { |
|
597 pbBuffer->GetValue(bufPtr); |
|
598 iccEntry->iSecondName.Copy(bufPtr); |
|
599 } |
|
600 break; |
|
601 |
|
602 case RMobilePhoneBookStore::ETagPBNumber: |
|
603 { |
|
604 pbBuffer->GetValue(bufPtr); |
|
605 if (isAdditionalNumber) |
|
606 { |
|
607 additionalNumber.iNumber.Copy(bufPtr); |
|
608 } |
|
609 else |
|
610 { |
|
611 // First number so this will be used as default number |
|
612 iccEntry->iNumber.Append(bufPtr); |
|
613 } |
|
614 } |
|
615 break; |
|
616 |
|
617 case RMobilePhoneBookStore::ETagPBAnrStart: |
|
618 { |
|
619 // This tag should precede every additional number entry |
|
620 isAdditionalNumber = ETrue; |
|
621 } |
|
622 break; |
|
623 |
|
624 case RMobilePhoneBookStore::ETagPBGroupName: |
|
625 { |
|
626 pbBuffer->GetValue(bufPtr); |
|
627 iccEntry->iGroupList->AppendL(bufPtr); |
|
628 } |
|
629 break; |
|
630 |
|
631 case RMobilePhoneBookStore::ETagPBEmailAddress: |
|
632 { |
|
633 pbBuffer->GetValue(bufPtr); |
|
634 iccEntry->iEmailList->AppendL(bufPtr); |
|
635 } |
|
636 break; |
|
637 |
|
638 case RMobilePhoneBookStore::ETagPBHiddenInfo: |
|
639 { |
|
640 TUint8 hidden; |
|
641 |
|
642 pbBuffer->GetValue(hidden); |
|
643 if (hidden != 0) |
|
644 { |
|
645 iccEntry->iIsHidden = ETrue; |
|
646 } |
|
647 } |
|
648 break; |
|
649 |
|
650 case RMobilePhoneBookStore::ETagPBNewEntry: |
|
651 { |
|
652 // |
|
653 // This signals the end of the entry and is a special case |
|
654 // which will be handled below. |
|
655 // |
|
656 } |
|
657 break; |
|
658 |
|
659 default: |
|
660 { |
|
661 // |
|
662 // An unsupported field type - just skip this value |
|
663 // |
|
664 pbBuffer->SkipValue(dataType); |
|
665 } |
|
666 break; |
|
667 } |
|
668 |
|
669 // |
|
670 // Has the whole entry been extracted? |
|
671 // |
|
672 if ((tagValue == RMobilePhoneBookStore::ETagPBNewEntry && entryCount > 0) || |
|
673 (pbBuffer->RemainingReadLength() == 0 && entryCount > 0)) |
|
674 { |
|
675 iccEntry->iPhonebookUid = iPhonebookUid; |
|
676 |
|
677 #ifdef _DEBUG |
|
678 iccEntry->LogSyncContactICCEntry(); |
|
679 #endif |
|
680 |
|
681 // |
|
682 // Write the entry to the Contacts Database... |
|
683 // |
|
684 TContactItemId id(KNullContactId); |
|
685 TPhonebookSlotState slotState(ESlotUsedAvailable); |
|
686 if (iccEntry->iIsHidden) |
|
687 // Hidden entry so ignore all fields for that entry, since they will not |
|
688 // be stored in Contacts database |
|
689 { |
|
690 slotState = ESlotHiddenNotAvailable; |
|
691 // remove any existing entry for this slot from database |
|
692 TInt result = iPhonebookManager.GetContactIdFromSlotNum(iPhonebookUid, |
|
693 iccEntry->iSlotNum, |
|
694 id); |
|
695 if (result == KErrNone) |
|
696 { |
|
697 iDb.DeleteContactL(id); |
|
698 id = KNullContactId; |
|
699 // Populate the phonebook look-up table |
|
700 User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid, |
|
701 iccEntry->iSlotNum, |
|
702 id, slotState)); |
|
703 } |
|
704 } |
|
705 else // Not hidden entry or it used to be hidden but its not anymore |
|
706 { |
|
707 // So add this entry to Contacts database |
|
708 |
|
709 id = iSession.Server().WriteICCContactToDBL(*iccEntry); |
|
710 } |
|
711 |
|
712 // ICC entry successfully written Contacts DB, so update look-up table |
|
713 if((id!=KNullContactId) || (iccEntry->iIsHidden)) |
|
714 { |
|
715 // Populate the phonebook look-up table |
|
716 User::LeaveIfError(iPhonebookManager.UpdateEntryInTable(iPhonebookUid, |
|
717 iccEntry->iSlotNum, |
|
718 id, slotState)); |
|
719 } |
|
720 |
|
721 // |
|
722 // Loop again... |
|
723 // |
|
724 iccEntry->Reset(); |
|
725 aReceivedEntries++; |
|
726 } |
|
727 } |
|
728 |
|
729 iPhonebookDataPtr.Zero(); |
|
730 |
|
731 CleanupStack::PopAndDestroy(2, iccEntry); |
|
732 } // CSyncContactsWithICC::DecodeICCAndStoreToDbL |
|
733 |
|
734 |
|
735 /** |
|
736 * Converts an ETSI Type-Of-Number value to a RMobilePhone::TMobileTON. |
|
737 * |
|
738 * @param aValue An ETSI Type-Of-Number field. |
|
739 * |
|
740 * @return The equivalent RMobilePhone::TMobileTON value. |
|
741 */ |
|
742 RMobilePhone::TMobileTON CSyncContactsWithICC::ConvertTypeOfNumber(TUint8 aValue) const |
|
743 { |
|
744 // |
|
745 // Mask off NPI and move TON to least-sig byte... |
|
746 // |
|
747 TUint8 aTon = (aValue & KEtsiTonPosition) >> 4; |
|
748 |
|
749 // |
|
750 // The below 'magic numbers' come from the ETSI 03.40 |
|
751 // specification for Address Fields (section 9.1.2.5) |
|
752 // |
|
753 RMobilePhone::TMobileTON result; |
|
754 |
|
755 switch(aTon) |
|
756 { |
|
757 case 0: |
|
758 { |
|
759 result = RMobilePhone::EUnknownNumber; |
|
760 } |
|
761 break; |
|
762 |
|
763 case 1: |
|
764 { |
|
765 result = RMobilePhone::EInternationalNumber; |
|
766 } |
|
767 break; |
|
768 |
|
769 case 2: |
|
770 { |
|
771 result = RMobilePhone::ENationalNumber; |
|
772 } |
|
773 break; |
|
774 |
|
775 case 3: |
|
776 { |
|
777 result = RMobilePhone::ENetworkSpecificNumber; |
|
778 } |
|
779 break; |
|
780 |
|
781 case 4: |
|
782 { |
|
783 result = RMobilePhone::ESubscriberNumber; |
|
784 } |
|
785 break; |
|
786 |
|
787 default: |
|
788 { |
|
789 result = RMobilePhone::EUnknownNumber; |
|
790 } |
|
791 break; |
|
792 } |
|
793 |
|
794 return result; |
|
795 } // CSyncContactsWithICC::ConvertTypeOfNumber |
|
796 |
|
797 |
|
798 /** |
|
799 * Standard Active Object DoCancel method called when the objects Cancel() |
|
800 * method is called. |
|
801 */ |
|
802 void CSyncContactsWithICC::DoCancel() |
|
803 { |
|
804 if (iState == ESyncContactsWithICCStateWaitForRead) |
|
805 { |
|
806 iPhonebookStore.CancelAsyncRequest(EMobilePhoneBookStoreRead); |
|
807 iState = ESyncContactsWithICCStateWaitForCancel; |
|
808 } |
|
809 } // CSyncContactsWithICC::DoCancel |
|
810 |
|
811 |
|
812 /** |
|
813 * Standard Active Object RunError method called when the objects RunL() |
|
814 * method leaves. |
|
815 * |
|
816 * Hopefully this method should never be called. |
|
817 * |
|
818 * @param aError Leave code from the RunL(). |
|
819 * |
|
820 * @return KErrNone is returned although the server will panic first. |
|
821 */ |
|
822 TInt CSyncContactsWithICC::RunError(TInt aError) |
|
823 { |
|
824 #ifdef _DEBUG |
|
825 LOGACTIVE2(_L8("CSyncContactsWithICC::RunError(%d)"), aError); |
|
826 #else |
|
827 (void) aError; |
|
828 #endif |
|
829 |
|
830 PhBkSyncPanic(EPhBkSyncPanicUnexpectedLeave); |
|
831 |
|
832 return KErrNone; |
|
833 } // CSyncContactsWithICC::RunError |